[
  {
    "path": ".gitignore",
    "content": ".DS_Store\nnode_modules/\nrelease-builds/"
  },
  {
    "path": "HOWTO.md",
    "content": "# Wick Editor v16\n\n**Note:** The `Modifier` key in this document refers to the `Control` key in Windows, and the `Command` key on MacOS.\n\n## Brower Support\n\n- All features of the Wick Editor are supported in Firefox and Chrome.\n- All features of the Wick Player are supported by most major browsers, including mobile browsers.\n\n## Canvas\n\n - Pan canvas with `Spacebar`\n - Zoom in and out with `+` and `-` keys\n - Zoom in and out with `Modifier` + `Scroll`\n - You can also zoom in and out with the plus and minus buttons below the timeline. This is also where you can select the percent at which to zoom.\n - Reset canvas zoom level to 100% with `Modifier` + `0`\n - Canvas color can be changed in project settings\n - Canvas dimensions (width/height) can be changed in project settings\n\n### Undo/Redo\n\n- Undo any action by clicking `Edit` -> `Undo` or by pressing `Modifier` + `Z`\n- Redo any action by clicking `Edit` -> `Redo` or by pressing `Modifier` + `Shift` + `Z`\n\n### Copy/Cut/Paste/Delete\n\n- Copy object(s) by pressing `Modifier`+`C` or by clicking `Edit` -> `Copy` in the menu bar\n- Cut object(s) by pressing `Modifier`+`X` or by clicking `Edit` -> `Cut` in the menu bar\n- Paste object(s) by pressing `Modifier`+`V` or by clicking `Edit` -> `Paste` in the menu bar\n- Cut object(s) by pressing `Delete` or `Backspace`, or by clicking `Edit` -> `Delete` in the menu bar\n- Duplicate object(s) by pressing `Modifier` + `D` or or right clicking and selecting `Duplicate Object(s)`.\n\n### Ordering\n\n- Move object(s) forward by right clicking and selecting `Move Forwards` or pressing `Modifier` + `Up`\n- Move object(s) backwards by right clicking and selecting `Move Backwards` or pressing `Modifier` + `Down`\n- Move object(s) to the front by right clicking and selecting `Move To Front` or pressing `Modifier` + `Shift` + `Up`\n- Move object(s) to the back by right clicking and selecting `Move To Back` or pressing `Modifier` + `Shift` + `Down`\n\n## Toolbar\n\n### Color Picker\n\n- Click either box to change the current fill or stroke color.\n- The filled box changes the fill color, and the unfilled box changes the stroke color.\n- The default pallete contains twelve basic colors.\n- The color picker saves the last six colors used below the default pallete.\n- Click and drag the largest square to change the saturation and lightness of the current color.\n- Click and drag the vertical rectangle to change the hue of the current color.\n- Click and drag the horizontal rectangle to change to opacity of the current color.\n\n### Selection Cursor\n\n_Making selections_\n\n- Click to select object\n- `Shift` + click to select multiple objects\n- Click and drag to select objects touching the selection box\n- `Alt` + click and drag to select objects strictly inside the selection box\n\n_Modifying selections_\n\n- Scale by dragging handles on corners and sides\n- Scale and keep aspect ratio of object(s) by holding `Shift` and dragging handles on corners\n- Rotate by dragging corners\n- Move object(s) by 1 pixel in any direction using the arrow keys\n- Move object(s) by 10 pixels in any direction using `Shift` + arrow keys\n- Select all objects on the canvas by clicking `Edit` -> `Select All` in the menu bar, or by pressing `Modifier` + `A`\n- Deselect all objects on the canvas by clicking `Edit` -> `Deselect All` in the menu bar, or by using `Modifier` + `Shift` + `A`\n\n### Path Cursor\n\n_Making selections_\n\n- Click any path to select it\n- Drag to select paths touching the selection box\n- Alt+drag to select objects strictly inside the selection box\n\n_Modifying Path Segments_\n\n- Click and drag points to move them\n- Click on a stroke to add a point on that part of the stroke\n- Hold `Modifier` and click a point to remove it\n\n_Modifying Path Curves_\n\n- Double click a path to straighten and smooth its curves\n- Drag handles to change curvature of strokes\n\n### Brush\n\n_Brush Options_\n\n- Color\n\t- The brush uses the current fill color as its drawing color.\n- Size\n- Smoothness\n- Stabilizer Level\n- Pressure Sensitivity Enabled\n- Pressure Sensitivity Level\n   - A higher Pressure Sensitivity level makes the pressure from a tablet have more impact on the size of the brush.\n- Blob Detail\n\t- A higher Blob Detail value will give your strokes more detail when they are converted to paths, but will make drawing strokes slower.\n\n### Pencil\n\n_Pencil Options_\n\n- Color\n\t- The pencil uses the current stroke color as its drawing color.\n- Stroke width\n- Smoothness\n\n### Fill Bucket\n\n- Click any path to change it's fill or stroke color\n- Click any holes created by paths to fill that hole\n\n### Rectangle\n\n- Click and drag to draw a rectangle\n- Hold shift while dragging to draw a perfect square\n- Change corner roundness in inspector\n\n### Ellipse\n\n- Click and drag to draw an ellipse\n- Hold shift while dragging to draw a perfect circle\n\n### Line\n\n- Click and drag to draw a line\n- Hold shift while dragging to draw horizontal/vertical/diagonal line\n\n### Pen\n\n- Click to create a new point\n- Click and drag to create a new point and change it's curvature\n- Click first point to close shape\n- Click the ends of an existing shape to add more curves to that shape\n\n### Eyedropper\n\n- Click any path to set the current fill or stroke color to that path's color.\n\n### Text\n\n- Click and drag to create a text box\n- Click text objects to edit them\n\n### Zoom\n\n- Click to zoom in\n- Hold `Alt` and click to zoom out\n- Click and drag, draw a rectangle, and release to zoom into a section of the screen\n\n### Pan\n\n- Click and drag to pan\n\n## Timeline\n\n### Frames\n\n**DESIGN TODO**\n\n- To add a frame, double click an empty space on the timeline or right click and select `Add Frame`\n- Change the length of frame(s) by dragging the edges left or right.\n- Select frames by clicking and dragging, all frames inside the selection box will be selected.\n- Delete selected frames by pressing `Delete` or right clicking and selecting `Delete Frame`\n\n### Playhead\n\n- Move the playhead by dragging it, or by using the `<` and `>` keys.\n- Clicking on a frame will jump the playhead to that frame.\n- Play the whole timeline by clicking the `Play Preview` button, or by pressing `Enter`\n- Loop the timeline by holding `Shift` and clicking the `Play Preview` button, or by pressing `Shift` + `Enter`\n- Change the framerate that the timeline is played at in project settings\n\n### Layers\n\n- Create a layer with the `Add Layer` button\n- Delete the current layer with the `Delete Layer` button\n- Rename a layer by clicking on its name\n- Layers can be locked by clicking the lock icon on that layer\n- Layers can be hidden by clicking the eye icon in that layer\n- Layers can be reordered by dragging them by the three lines icon on the left\n\n### Tweens\n\n- Create a motion tween on a frame by right clicking a frame and selecting `Create Motion Tween`.\n- If there are multiple objects on the frame when a motion tween is created, they will be automatically grouped into a single object.\n- Create keyframes by right clicking and selecting `Insert Keyframe`.\n- Copy and paste keyframes by right clicking a keyframe and selecting `Copy Keyframe` or `Paste Keyframe`.\n- Keyframes will be automatically added if an object is modified while the playhead is over a point on the frame without a keyframe.\n- You can change the \"easing\" of a tween in the Inspector. The current options are `None`, `Ease In`, `Ease Out`, and `Ease In-Out`.\n- If you want to rotate an object 360 degrees or more in a tween, use the `Number of Rotations` value in the Inspector. _Note: You can rotate objects counter-clockwise by using a negative value here._\n- Tweening of all transformations (x, y, scale, rotation) is possible, as well as opacity.\n\n### Sounds\n\n- Add a sound to a frame by dragging it from the asset library onto a frame, or by selecing a frame and choosing a sound from the dropdown menu in the Inspector.\n\n### Onion Skinning\n\n- Click the onion icon to enable onion skinning\n- Control how many frames are shown in onion skin by dragging the edges of the box near the playhead.\n\n## Import\n\n### Images\n\nImport images by dragging them into the editor or by selecting `Import` -> `Image` in the menu bar.\n\n_Supported image types:_\n\n- `png`\n- `jpeg`\n- `bmp`\n- `gif` (_Animated GIFs are converted into clips with all the frames of the original GIF_)\n\n### Sounds\n\nImport sounds by dragging them into the editor or by selecting `Import` -> `Sound` in the menu bar.\n\n_Supported sound file types:_\n\n- `mp3`\n- `wav`\n- `ogg`\n\n### SVG\n\nImport SVGs by dragging them into the editor or by selecting `Import` -> `SVG` in the menu bar.\n\n### Asset Library\n\n- All assets used in the project are stored in the Asset Library.\n- Reorganize assets by clicking and dragging them.\n- Rename assets by selecting an asset and clicking the `Rename Asset` button.\n- Delete assets by selecting an asset and clicking the `Delete Asset` button.\n\n## Wick Objects\n\nAll Wick Objects have the following attributes:\n\n- Position (x,y)\n- Width\n- Height\n- Scale (x,y)\n- Rotation (angle, 0-360)\n- Opacity\n\n### Paths\n\n_Attributes:_\n\n- Fill color\n- Stroke color\n- Stroke width\n- Boolean Operations\n - Unite: Combines two or more paths into one path.\n - Subtract: Uses the topmost path to cut out a portion of other selected paths.\n\n### Images\n\n_Attributes:_\n\n- Asset source\n\n### Text\n\n_Attributes:_\n\n- Font family\n- Font size\n- Font color\n- Text align\n- Bold\n- Italic\n\n### Groups\n\n- Create a group by right clicking wick object(s) and selecting `Group Objects` or by pressing `Modifier` + `G`.\n- Edit group by double clicking or right clicking and selecting `Edit Group`.\n- Leave group by using breadcrumbs or by double clicking\n- Break apart a group by right clicking and selecting `Break Apart` or by pressing `Modifier` + `B`\n\n### Buttons\n\n- Right click a selection of wick object(s) and select `Create Clip from Objects`.\n- A dialog box will open up prompting you to name the new Clip\n- An asset will be created out of the new Clip, and the new Clip will use that asset as its source. _(to change this later, select a different \"clip resource\" in the inspector)_\n\n_Button Appearance_\n\n- To change how a button appears when it interacts with the mouse, right click the button and select `Edit Button`.\n- Create frames in the places where the timeline is labeled `Up`, `Over`, and `Down`.\n\n### Clips\n\n_Creating a Clip_\n\n- Right click a selection of wick object(s) and select `Create Clip from Objects`.\n- A dialog box will open up prompting you to name the new Clip\n- An asset will be created out of the new Clip, and the new Clip will use that asset as its source. _(to change this later, select a different \"clip resource\" in the inspector)_\n\n_Clip timelines_\n\n- Clips have their own timelines.\n- Clip timelines run independently of the main timeline.\n- Edit the timeline of a Clip by double clicking or right clicking the Clip and selecting `Edit Timeline`.\n- Leave the timeline of the clip by using breadcrumbs or by double clicking the canvas.\n\n_Clip attributes_\n\n- Name (used in scripting - see `Writing Scripts` section.)\n- Start frame\n- Autoplay\n\n__Note__ that the \"root object\" is actually a Clip that contains everything in the project. You can never leave the root object.\n\n## Writing Scripts\n\nScripts can be added to Clips, Buttons, and Frames.\n\nWith an Clip, Button, or Frame selected, open the Scripting Window by clicking the bar along the bottom of the editor.\n\n### Object Access\n\n- You can access any named Clip by using its name. For example, to set some value of a Clip named \"player\", you would use a line of code like this:\n\n`player.rotation = 90`\n\n- You can access the object that the script belongs to using the keyword `this`.\n\n- You can access the root object of the project by using the keyword `root`.\n\n- You can access the parent object of the current object by using the keyword `parent`.\n\n### Moving the Timeline Programmatically\n\n- While a project is running, the playhead will automatically move forward once per \"tick\". Projects \"tick\" at the rate of the framerate \n- (e.g. a project with a framerate of 12 will tick 12 times per second.)\n\nAll timeline functions can be used on objects, such as: \n \n- `root.play()` \n- `this.stop()`\n- `yourOwnObject.gotoAndPlay(2)`\n\nas well as by themselves, where they will refer to the timeline where the script was added:\n\n- `play()`\n- `gotoAndStop(2)`\n\n### Variables\n\n- Store information in an object by using variables as shown:\n - `this.level = 5`\n - `player.isAlive = true`\n - `player.name = \"Slombo\"`\n - `root.numberOfBees = 10000`\n- See all builtin variables below in the `Script Reference` section\n- Tip: Put variables that you want to access everywhere in `root`.\n\n### Events\n\n- Use events to run code when a certain event happens, such as when an object is clicked, or when an object first appears onscreen.\n\n### Creating Objects Programmatically\n\n- You can create instances of Clips from the Asset Library programmatically by using `createInstanceOf()` with the name of the asset to use. Example:\n\n`enemy = createInstanceOf(\"Enemy\")`\n\n### Errors\n\n- If your script contains a syntax error, the project will not run until it is fixed. The Scripting Window will highlight the line that contains the syntax error.\n- If a runtime error occurs while the project is running, the player will close, and the line that caused the error will be highlighted in the Scripting Window.\n\n## Script Reference\n\n### Scope\n\nName | Description\n--- | ---\n`this` | Refers to the Wick Object running the script.\n`parent` | Refers to the parent of the Wick Object running the script. (This is `null` for the root object.)\n`root` | Refers to the root object of the project.\n\n### Timeline\n\nName | Description\n--- | ---\n`play()` | Plays the timeline. \n`stop()` | Stops the timeline.\n`gotoAndStop(frame)` | Moves the timeline to the specified frame and stops the timeline. You can use a number to move the timeline to a certain position, or a string to move the timeline to a named frame.\n`gotoAndPlay(frame)` | Moves the timeline to the specified frame and plays the timeline. You can use a number to move the timeline to a certain position, or a string to move the timeline to a named frame.\n`gotoNextFrame()` | Moves the timeline to the next frame.\n`gotoPrevFrame()` | Moves the timeline to the previous frame.\n`currentFrameNumber` | The current frame number that the timeline is currently on.\n`currentFrameName` | The current name of the frame that the timeline is currently on. If the timeline is on an unnamed frame, this value will be `null`.\n\n### Events\n\nName | Description\n--- | ---\n`on(load)` | Runs once when the object/frame first appears onscreen.\n`on(update)` | Runs once per tick that the object/frame is onscreen.\n`on(click)` | Runs when the object/frame is clicked (i.e. a full press and release)\n`on(mousedown)` | Runs when the object/frame is first pressed by the mouse.\n`on(mouseup)` | Runs when mouse is released over the frame/object.\n`on(mouseenter)` | Runs when the mouse first rolls over the frame/object.\n`on(mouseleave)` | Runs when the mouse leaves the frame/object.\n`on(mousehover)` | Runs every tick that the mouse is hovered over the frame/object.\n`on(mousedrag)` | Runs every tick that the mouse is hovered over the frame/object while held down.\n`on(keypressed)` | Runs when a key is pressed.\n`on(keydown)` | Runs every tick that a key is held down.\n`on(keyup)` | Runs when a key is released.\n\n### Wick Object Attributes\n\nName | Description\n--- | ---\n`x` | The horizontal position of the object on the x-axis.\n`y` | The vertical position of the object on the y-axis.\n`scaleX` | The horizontal scale of the object.\n`scaleY` | The vertical scale of the object.\n`rotation` | The rotation of the object, in angles.\n`flipX` | True if the object is mirrored horizontally, false otherwise.\n`flipY` | True if the object is mirrored vertically, false otherwise.\n`opacity` | Value from 0.0 to 1.0 where 0.0 is completely transparent, and 1.0 is completely opaque.\n\n### Wick Object Methods\n\nName | Description\n--- | ---\n`hitTest(object)` | Returns `true` if the object collides with the speicified object.\n`delete()` | Deletes the object.\n\n### Mouse Input\n\nName | Description\n--- | ---\n`mouseX` | The position of the mouse on the x-axis.\n`mouseY` | The position of the mouse on the y-axis.\n`mouseMoveX` | The amount the mouse has moved on the x-axis.\n`mouseMoveY` | The amount the mouse has moved on the y-axis.\n\n### Keyboard Input\n\nName | Description\n--- | ---\n`key` | The last key that was pressed/released/held down.\n`keyIsDown(key)` | Returns true if the specified key is currently held down.\n`keyJustPressed(key)` | Returns true if the specified key was pressed.\n\n### Sound\n\nName | Description\n--- | ---\n`playSound(filename)` | Plays the specified sound from the Asset Library.\n`stopAllSounds()` | Stops all currently playing sounds.\n\n### Creating Objects\n\nName | Description\n--- | ---\n`createInstanceOf(assetName)` | Creates a Clip using the specified asset as its source.\n`getAllInstancesOf(assetName)` | Returns an array containing all objects onscreen that are instances of the specified asset.\n\n## Saving Projects\n\n### Autosave\n\n- Projects are \"autosaved\" every time you run your project.\n- You can also force an autosave by clicking on the title of the project in the top-left corner of the screen, or by pressing `Modifier` + `Shift` + `S`.\n- __Autosaved projects are deleted when you clear your browser cache.__ It is recommended to save your projects as .wick files as often as possible.\n\n### .wick file format\n\n- A .wick file is the native filetype for Wick projects.\n- .wick files can be opened in the editor by dragging them into the browser window, or by clicking `File` -> `Open Project` and selecting them.\n\n## Exporting Projects\n\n### .zip archive\n\n- `File` -> `Export ZIP Archive`\n- The exported .zip archive will contain the Wick Player bundled into an html file named `index.html`, as well as your project named `wick-project.wick`.\n- Most Flash/HTML5 game websites accept `.zip` files in this format.\n\n### Video\n\n- `File` -> `Export Video`\n- Choose quality (Low, Medium, High, or Ultra)\n- Videos are exported as `mp4` files using the `mpeg4` codec.\n\n## Builtin Player\n\n- Play your project in the builtin player by clicking the `Run` button in the menu bar or by pressing `Modifier` + `Enter`.\n- Close the builtin player by clicking the X in the top right corner or by pressing `Escape`.\n- If script errors happen inside the builtin player, the player will close and the editor will show you where the error happened by selecting the object or frame that caused the error.\n- You can run the builtin player in a new window by pressing `Modifier` + `Shift` + `Enter`, but errors will not be shown in the editor.\n\n## Embedding Projects\n\nTo embed a .wick file, you will need the Wick Player html file. Download it **TODO** here.\n\nThen, embed the player in an iframe and add the filename of your project with an `#` after `player.html` as shown here:\n\n`<iframe width=\"720\" height=\"480\" src=\"player.html#myproject.wick\"></iframe>`"
  },
  {
    "path": "LICENSE.txt",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n"
  },
  {
    "path": "README.md",
    "content": "This repo is no longer active, please go to the new one: https://github.com/wicklets/wick-editor\n"
  },
  {
    "path": "code-of-conduct.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, gender identity and expression, level of experience,\neducation, socio-economic status, nationality, personal appearance, race,\nreligion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\n  advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n  address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at *contact@wickeditor.com*. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n"
  },
  {
    "path": "index.html",
    "content": "<!-- Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli -->\n\n<!-- This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. -->\n\n<!DOCTYPE html>\n<html>\n\n<head>\n    <title>Wick Editor</title>\n\n    <!-- Google analytics -->\n    <!-- THIS IS TEMPORARY DONT KILL ME PLZ -->\n    <script>\n      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n      })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');\n\n      ga('create', 'UA-88233944-1', 'auto');\n      ga('send', 'pageview');\n    </script>\n\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"styles/editor.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"styles/timeline.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"styles/scriptingide.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"lib/skin-win8/ui.fancytree.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"styles/library.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"styles/inspector.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"styles/toolbar.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"styles/colorpicker.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"styles/textBox.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"lib/rangeslider.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"lib/nouislider.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"lib/spectrum.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"styles/progressBar.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"styles/videoExporter.css\">\n\n    <script src=\"lib/jquery.min.js\"></script>\n    <script src=\"lib/jquery-ui.custom.min.js\"></script>\n    <script src=\"lib/jquery.fancytree.js\"></script>\n    <script src=\"lib/jquery.fancytree.filter.js\"></script>\n    <script src=\"lib/potrace.js\"></script>\n    <script src=\"lib/paper-full.js\"></script>\n    <script src=\"lib/paperholefinder.js\"></script>\n    <script src=\"lib/beautify.js\"></script>\n    <script src=\"lib/FileSaver.min.js\"></script>\n    <script src=\"lib/jscolor.js\"></script>\n    <script src=\"lib/libgif.js\"></script>\n    <script src=\"lib/lz-string.min.js\"></script>\n    <script src=\"lib/jszip.min.js\"></script>\n    <script src=\"lib/screenfull.js\"></script>\n    <script src=\"lib/rangeslider.min.js\"></script>\n    <script src=\"lib/gif.js\"></script>\n    <script src=\"lib/gif.worker.js\"></script>\n    <script src=\"lib/whammy.js\"></script>\n    <script src=\"lib/filedownloader.js\"></script>\n    <script src=\"lib/URLParameterUtils.js\"></script>\n    <script src=\"lib/keyCharToCode.js\"></script>\n    <script src=\"lib/timer.js\"></script>\n    <script src=\"lib/canvasutils.js\"></script>\n    <script src=\"lib/polyfills.js\"></script>\n    <script src=\"lib/fpscounter.js\"></script>\n    <script src=\"lib/base64-arraybuffer.js\"></script>\n    <script src=\"lib/random.js\"></script>\n    <script src=\"lib/Tween.js\"></script>\n    <script src=\"lib/lerp.js\"></script>\n    <script src=\"lib/bowser.js\"></script>\n    <script src=\"lib/howler.min.js\"></script>\n    <script src=\"lib/pixi.4.5.6.min.js\"></script>\n    <script src=\"lib/scrollbar.js\"></script>\n    <script src=\"lib/nouislider.js\"></script>\n    <script src=\"lib/soundcloud-waveform.js\"></script>\n    <script src=\"lib/html2canvas.js\"></script>\n    <script src=\"lib/localstoragewrapper.js\"></script>\n    <script src=\"lib/ace/ace.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n    <script src=\"lib/ace/ext-language_tools.min.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n    <script src=\"lib/spectrum.js\"></script>\n    <script src=\"lib/pressure.min.js\"></script>\n    <script src=\"lib/WickEditorInputs.js\"></script>\n    <script src=\"lib/idb-keyval-min.js\"></script>\n    <script src=\"lib/offset.js\"></script>\n    <script src=\"lib/floodfill.min.js\" type=\"text/javascript\"></script>\n    <script src=\"lib/webfont.js\" type=\"text/javascript\"></script>\n    <script src=\"lib/video-export/videoExporter.js\" type=\"text/javascript\"></script>\n    <script src=\"lib/croquis.js\"></script>\n\n    <script src=\"src/project/WickDocs.js\"></script>\n    <script src=\"src/project/WickFrame.js\"></script>\n    <script src=\"src/project/WickLayer.js\"></script>\n    <script src=\"src/project/WickObject.js\"></script>\n    <script src=\"src/project/WickAsset.js\"></script>\n    <script src=\"src/project/WickProject.js\"></script>\n    <script src=\"src/project/WickProject.Exporter.js\"></script>\n    <script src=\"src/project/WickProject.Compressor.js\"></script>\n    <script src=\"src/project/WickProject.AssetLibrary.js\"></script>\n    <script src=\"src/project/WickTween.js\"></script>\n\n    <script src=\"src/editor/interfaces/Interfaces.Canvas.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.Canvas.Interactive.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.Canvas.Backdrop.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.Canvas.Fast.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.Canvas.ImageRenderer.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.Library.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.BuiltinPlayer.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.RightClickMenu.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.ScriptingIDE.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.ScriptingIDE.Reference.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.Timeline.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.Timeline.FramesContainer.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.Timeline.Interactions.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.Timeline.LayersContainer.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.Toolbar.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.Inspector.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.Inspector.Properties.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.Inspector.InputTypes.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.MenuBar.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.Breadcrumbs.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.AlertBox.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.CursorIcon.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.EditorSettings.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.Credits.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.ColorPicker.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.TextEditBox.js\"></script>\n    <script src=\"src/editor/interfaces/Interfaces.VideoExporter.js\"></script>\n\n    <script src=\"src/editor/tools/Tools.SelectionCursor.js\"></script>\n    <script src=\"src/editor/tools/Tools.VectorCursor.js\"></script>\n    <script src=\"src/editor/tools/Tools.FillBucket.js\"></script>\n    <script src=\"src/editor/tools/Tools.Pencil.js\"></script>\n    <script src=\"src/editor/tools/Tools.Paintbrush.js\"></script>\n    <script src=\"src/editor/tools/Tools.Eraser.js\"></script>\n    <script src=\"src/editor/tools/Tools.Rectangle.js\"></script>\n    <script src=\"src/editor/tools/Tools.Ellipse.js\"></script>\n    <script src=\"src/editor/tools/Tools.Line.js\"></script>\n    <script src=\"src/editor/tools/Tools.Pen.js\"></script>\n    <script src=\"src/editor/tools/Tools.Dropper.js\"></script>\n    <script src=\"src/editor/tools/Tools.Text.js\"></script>\n    <script src=\"src/editor/tools/Tools.Zoom.js\"></script>\n    <script src=\"src/editor/tools/Tools.Pan.js\"></script>\n\n    <script src=\"src/editor/WickEditor.js\"></script>\n    <script src=\"src/editor/WickEditor.Settings.js\"></script>\n    <script src=\"src/editor/WickEditor.WickActionHandler.js\"></script>\n    <script src=\"src/editor/WickEditor.GuiActionHandler.js\"></script>\n    <script src=\"src/editor/WickEditor.InputHandler.js\"></script>  \n\n    <script src=\"src/player/WickPlayer.js\"></script>\n    <script src=\"src/player/WickPlayer.PixiRenderer.js\"></script>\n    <script src=\"src/player/WickPlayer.HowlerAudioPlayer.js\"></script>\n    <script src=\"src/player/WickPlayer.InputHandler.js\"></script>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"https://fonts.googleapis.com/css?family=Anonymous+Pro\" />\n\n    <script>\n        $(document).ready(function() {\n            window.wickEditor = new WickEditor();\n        });\n    </script>\n</head>\n\n<body>\n<div class=\"alpha-warning\">\n    <script>function hideWarning () { var e = document.getElementsByClassName('alpha-warning')[0];e.style.pointerEvents='none';e.style.display='none'; }; if (localStorage.hideWarning) { hideWarning(); };</script>\n    <div class=\"alpha-warning-text\">\n        NOTE: The Wick Editor is currently in open beta!<hr class=\"alpha-warning-hr\" />Please report all bugs on <a class=\"forums-link\" href=\"http://forum.wickeditor.com/\" target=\"_blank\">the forums</a>!!\n    </div>\n    <div class=\"alpha-warning-closebutton\" onclick=\"localStorage.hideWarning='true';hideWarning();\"></div>\n</div>\n\n<div class=\"noselect\">\n    <!-- Hidden element to always be selected so browser always fires copy/paste events -->\n    <input id=\"hidden-input\" class=\"hidden\" type=\"text\" value=\"\" />\n\n    <!-- Hidden element that gets clicked by other divs to open file dialog -->\n    <input type=\"file\" class=\"hidden\" id=\"importButton\" /> \n\n    <div id=\"alert-box\" class=\"GUIBox\">\n        <div class=\"alert-box-icon\"></div>\n        <div class=\"alert-box-text\"></div>\n    </div>\n\n    <div id=\"editor\">\n\n        <div tabindex=\"1\" id=\"editorCanvasContainer\">\n            <div id=\"previewRenderContainer\"></div>\n        </div>\n\n        <div id=\"cursorIcon\" class=\"GUIBox\"></div>\n\n        <div id=\"timelineGUI\" class=\"GUIBox\"></div>\n\n        <div id=\"breadcrumbsGUI\" class=\"GUIBox\"></div>\n\n        <div id=\"editorSettingsGUI\" class=\"GUIBox\">\n            <div class=\"editorSettingsGUITitle\">Hotkeys</div>\n            <div class=\"editorSettingsGUICloseButton\"></div>\n            <div class=\"editorSettingsGUIHotkeys\"></div>\n        </div>\n\n        <div id=\"videoExportGUI\" class=\"GUIBox\">  \n        </div>\n\n        <div id=\"editorCreditsGUI\" class=\"GUIBox\">\n            <div class=\"editorCreditsCloseButton\"></div>\n            <div class=\"editorCreditsContent\"></div>\n        </div>\n\n        <div id=\"toolbarGUI\" class=\"GUIBox\">\n            <div id=\"tools\"></div>\n        </div>\n\n        <div id=\"inspectorGUI\" class=\"GUIBox\">\n            <div id=\"inspector-title\">Inspector</div>\n            <div class=\"inspector-title-bar\">\n                <div class=\"inspector-selection-icon\"></div>\n                <div class=\"inspector-selection-title\"></div>\n            </div>\n            <div class=\"inspector-allitems-container\">\n                <div class=\"inspector-properties-container\"></div>\n                <div class=\"inspector-buttons-container\"></div>\n            </div>\n            <div id=\"treeContainer\">\n                <div id=\"inspector-title\">Asset Library</div>\n                <div id=\"treeFilterContainer\">\n                    <input id=\"treeFilterInput\" type=\"text\" placeholder=\"filter...\">\n                </div>\n                <div id=\"tree\"><ul></ul></div>\n                <div id=\"treeOptionsContainer\">\n                    <div class=\"tooltipElem assetLibraryButton\" id=\"deleteAssetButton\" alt=\"Delete Asset\"></div>\n                    <div class=\"tooltipElem assetLibraryButton\" id=\"renameAssetButton\" alt=\"Rename Asset\"></div>\n                </div>\n            </div>\n        </div>\n\n        <div id=\"scriptingGUI\" class=\"GUIBox\">\n            <div id=\"scriptObjectDiv\">\n                <div id=\"scriptEditor\"></div>\n                <div id=\"scriptEditorSidebar\">\n                    <!--<div id=\"scriptEditorObjectName\"></div>\n                    <img id=\"scriptEditorObjectThumbnail\" />-->\n                    <div id=\"scriptEditorReference\"></div>\n                </div>\n            </div>\n            <div id=\"noSelectionDiv\">\n                <div id=\"noSelectionText\"></div>\n            </div>\n            <div id=\"scriptingIDEHeader\"></div>\n            <div id=\"resizeScriptingGUIBar\"></div>\n            <div class=\"elemInRow\">\n                <div class=\"button buttonInRow tooltipElem\" id=\"beautifyButton\" alt=\"Beautify Code\"></div>\n                <div class=\"button buttonInRow tooltipElem\" id=\"expandScriptingGUIButton\" alt=\"Expand Scripting IDE\"></div>\n                <div class=\"button buttonInRow tooltipElem\" id=\"minimizeScriptingGUIButton\" alt=\"Collapse Scripting GUI\"></div>\n                <div class=\"button buttonInRow tooltipElem\" id=\"closeScriptingGUIButton\" alt=\"Close Code Tab\"></div>\n                <div class=\"button buttonInRow tooltipElem\" id=\"openScriptingGUIButton\" alt=\"Open Code Tab\"></div>\n            </div>\n        </div>\n\n        <div id=\"colorPickerGUI\" class=\"GUIBox\"></div>\n\n        <div id=\"dropFileMessage\"><div id=\"dropFileMessageImage\"></div></div>\n\n    </div>\n\n    <div id=\"builtinPlayer\">\n        <div id=\"builtinPlayerGUI\" class=\"GUIBox\">\n            <div class=\"tooltipElem\" id=\"closeBuiltinPlayerButton\" alt=\"Close project\"></div>\n            <div id=\"builtinPlayerProjectInfo\"></div>\n        </div>\n    </div>\n\n    <div id=\"tooltipGUI\" class=\"GUIBox tooltip\"></div>\n\n    <div onclick=\"window.open('http://forum.wickeditor.com/t/wick-0-15-update-thread-video-export/461')\" id=\"wick-editor-version\"></div>\n\n</div>\n</body>\n\n</html>\n"
  },
  {
    "path": "lib/SAT.js",
    "content": "/* SAT.js - Version 0.6.0 - Copyright 2012 - 2016 - Jim Riecken <jimr@jimr.ca> - released under the MIT License. https://github.com/jriecken/sat-js */\nfunction x(){function c(a,e){this.x=a||0;this.y=e||0}function B(a,e){this.pos=a||new c;this.r=e||0}function n(a,e){this.pos=a||new c;this.angle=0;this.offset=new c;this.u(e||[])}function q(a,e,b){this.pos=a||new c;this.w=e||0;this.h=b||0}function w(){this.b=this.a=null;this.overlapN=new c;this.overlapV=new c;this.clear()}function C(a,e,b){for(var h=Number.MAX_VALUE,c=-Number.MAX_VALUE,k=a.length,g=0;g<k;g++){var d=a[g].f(e);d<h&&(h=d);d>c&&(c=d)}b[0]=h;b[1]=c}function y(a,e,b,h,c,k){var g=r.pop(),\nd=r.pop();a=m.pop().c(e).sub(a);e=a.f(c);C(b,c,g);C(h,c,d);d[0]+=e;d[1]+=e;if(g[0]>d[1]||d[0]>g[1])return m.push(a),r.push(g),r.push(d),!0;k&&(g[0]<d[0]?(k.aInB=!1,g[1]<d[1]?(b=g[1]-d[0],k.bInA=!1):(b=g[1]-d[0],h=d[1]-g[0],b=b<h?b:-h)):(k.bInA=!1,g[1]>d[1]?(b=g[0]-d[1],k.aInB=!1):(b=g[1]-d[0],h=d[1]-g[0],b=b<h?b:-h)),h=Math.abs(b),h<k.overlap&&(k.overlap=h,k.overlapN.c(c),0>b&&k.overlapN.reverse()));m.push(a);r.push(g);r.push(d);return!1}function z(a,e){var b=a.g(),c=e.f(a);return 0>c?-1:c>b?1:0}\nfunction D(a,e,b){for(var c=m.pop().c(e.pos).sub(a.pos),l=e.r,k=l*l,g=a.calcPoints,d=g.length,u=m.pop(),f=m.pop(),n=0;n<d;n++){var v=n===d-1?0:n+1,r=0===n?d-1:n-1,q=0,t=null;u.c(a.edges[n]);f.c(c).sub(g[n]);b&&f.g()>k&&(b.aInB=!1);var p=z(u,f);if(-1===p){u.c(a.edges[r]);v=m.pop().c(c).sub(g[r]);p=z(u,v);if(1===p){p=f.j();if(p>l)return m.push(c),m.push(u),m.push(f),m.push(v),!1;b&&(b.bInA=!1,t=f.normalize(),q=l-p)}m.push(v)}else if(1===p){if(u.c(a.edges[v]),f.c(c).sub(g[v]),p=z(u,f),-1===p){p=f.j();\nif(p>l)return m.push(c),m.push(u),m.push(f),!1;b&&(b.bInA=!1,t=f.normalize(),q=l-p)}}else{v=u.m().normalize();p=f.f(v);r=Math.abs(p);if(0<p&&r>l)return m.push(c),m.push(v),m.push(f),!1;b&&(t=v,q=l-p,0<=p||q<2*l)&&(b.bInA=!1)}t&&b&&Math.abs(q)<Math.abs(b.overlap)&&(b.overlap=q,b.overlapN.c(t))}b&&(b.a=a,b.b=e,b.overlapV.c(b.overlapN).scale(b.overlap));m.push(c);m.push(u);m.push(f);return!0}function E(a,e,b){for(var c=a.calcPoints,l=c.length,k=e.calcPoints,g=k.length,d=0;d<l;d++)if(y(a.pos,e.pos,c,\nk,a.normals[d],b))return!1;for(d=0;d<g;d++)if(y(a.pos,e.pos,c,k,e.normals[d],b))return!1;b&&(b.a=a,b.b=e,b.overlapV.c(b.overlapN).scale(b.overlap));return!0}var f={};f.Vector=c;f.V=c;c.prototype.copy=c.prototype.c=function(a){this.x=a.x;this.y=a.y;return this};c.prototype.clone=c.prototype.clone=function(){return new c(this.x,this.y)};c.prototype.perp=c.prototype.m=function(){var a=this.x;this.x=this.y;this.y=-a;return this};c.prototype.rotate=c.prototype.rotate=function(a){var e=this.x,b=this.y;\nthis.x=e*Math.cos(a)-b*Math.sin(a);this.y=e*Math.sin(a)+b*Math.cos(a);return this};c.prototype.reverse=c.prototype.reverse=function(){this.x=-this.x;this.y=-this.y;return this};c.prototype.normalize=c.prototype.normalize=function(){var a=this.j();0<a&&(this.x/=a,this.y/=a);return this};c.prototype.add=c.prototype.add=function(a){this.x+=a.x;this.y+=a.y;return this};c.prototype.sub=c.prototype.sub=function(a){this.x-=a.x;this.y-=a.y;return this};c.prototype.scale=c.prototype.scale=function(a,e){this.x*=\na;this.y*=e||a;return this};c.prototype.project=c.prototype.o=function(a){var e=this.f(a)/a.g();this.x=e*a.x;this.y=e*a.y;return this};c.prototype.projectN=c.prototype.s=function(a){var e=this.f(a);this.x=e*a.x;this.y=e*a.y;return this};c.prototype.reflect=function(a){var e=this.x,b=this.y;this.o(a).scale(2);this.x-=e;this.y-=b;return this};c.prototype.reflectN=function(a){var e=this.x,b=this.y;this.s(a).scale(2);this.x-=e;this.y-=b;return this};c.prototype.dot=c.prototype.f=function(a){return this.x*\na.x+this.y*a.y};c.prototype.len2=c.prototype.g=function(){return this.f(this)};c.prototype.len=c.prototype.j=function(){return Math.sqrt(this.g())};f.Circle=B;B.prototype.getAABB=function(){var a=this.r,e=this.pos.clone().sub(new c(a,a));return(new q(e,2*a,2*a)).l()};f.Polygon=n;n.prototype.setPoints=n.prototype.u=function(a){if(!this.points||this.points.length!==a.length){var e,b=this.calcPoints=[],h=this.edges=[],l=this.normals=[];for(e=0;e<a.length;e++)b.push(new c),h.push(new c),l.push(new c)}this.points=\na;this.i();return this};n.prototype.setAngle=function(a){this.angle=a;this.i();return this};n.prototype.setOffset=function(a){this.offset=a;this.i();return this};n.prototype.rotate=n.prototype.rotate=function(a){for(var e=this.points,b=e.length,c=0;c<b;c++)e[c].rotate(a);this.i();return this};n.prototype.translate=n.prototype.translate=function(a,c){for(var b=this.points,h=b.length,l=0;l<h;l++)b[l].x+=a,b[l].y+=c;this.i();return this};n.prototype.i=function(){var a=this.calcPoints,c=this.edges,b=\nthis.normals,h=this.points,l=this.offset,k=this.angle,g=h.length,d;for(d=0;d<g;d++){var f=a[d].c(h[d]);f.x+=l.x;f.y+=l.y;0!==k&&f.rotate(k)}for(d=0;d<g;d++)h=a[d],h=c[d].c(d<g-1?a[d+1]:a[0]).sub(h),b[d].c(h).m().normalize()};n.prototype.getAABB=function(){for(var a=this.calcPoints,e=a.length,b=a[0].x,h=a[0].y,f=a[0].x,k=a[0].y,g=1;g<e;g++){var d=a[g];d.x<b?b=d.x:d.x>f&&(f=d.x);d.y<h?h=d.y:d.y>k&&(k=d.y)}return(new q(this.pos.clone().add(new c(b,h)),f-b,k-h)).l()};f.Box=q;q.prototype.toPolygon=q.prototype.l=\nfunction(){var a=this.pos,e=this.w,b=this.h;return new n(new c(a.x,a.y),[new c,new c(e,0),new c(e,b),new c(0,b)])};f.Response=w;w.prototype.clear=w.prototype.clear=function(){this.bInA=this.aInB=!0;this.overlap=Number.MAX_VALUE;return this};for(var m=[],t=0;10>t;t++)m.push(new c);for(var r=[],t=0;5>t;t++)r.push([]);var A=new w,F=(new q(new c,1E-6,1E-6)).l();f.isSeparatingAxis=y;f.pointInCircle=function(a,c){var b=m.pop().c(a).sub(c.pos),h=c.r*c.r,f=b.g();m.push(b);return f<=h};f.pointInPolygon=function(a,\nc){F.pos.c(a);A.clear();var b=E(F,c,A);b&&(b=A.aInB);return b};f.testCircleCircle=function(a,c,b){var f=m.pop().c(c.pos).sub(a.pos),l=a.r+c.r,k=f.g();if(k>l*l)return m.push(f),!1;b&&(k=Math.sqrt(k),b.a=a,b.b=c,b.overlap=l-k,b.overlapN.c(f.normalize()),b.overlapV.c(f).scale(b.overlap),b.aInB=a.r<=c.r&&k<=c.r-a.r,b.bInA=c.r<=a.r&&k<=a.r-c.r);m.push(f);return!0};f.testPolygonCircle=D;f.testCirclePolygon=function(a,c,b){if((a=D(c,a,b))&&b){c=b.a;var f=b.aInB;b.overlapN.reverse();b.overlapV.reverse();\nb.a=b.b;b.b=c;b.aInB=b.bInA;b.bInA=f}return a};f.testPolygonPolygon=E;return f}\"function\"===typeof define&&define.amd?define(x):\"object\"===typeof exports?module.exports=x():this.SAT=x();"
  },
  {
    "path": "lib/Tween.js",
    "content": "/**\n * Tween.js - Licensed under the MIT license\n * https://github.com/tweenjs/tween.js\n * ----------------------------------------------\n *\n * See https://github.com/tweenjs/tween.js/graphs/contributors for the full list of contributors.\n * Thank you all, you're awesome!\n */\n\nvar TWEEN = TWEEN || (function () {\n\n\tvar _tweens = [];\n\n\treturn {\n\n\t\tgetAll: function () {\n\n\t\t\treturn _tweens;\n\n\t\t},\n\n\t\tremoveAll: function () {\n\n\t\t\t_tweens = [];\n\n\t\t},\n\n\t\tadd: function (tween) {\n\n\t\t\t_tweens.push(tween);\n\n\t\t},\n\n\t\tremove: function (tween) {\n\n\t\t\tvar i = _tweens.indexOf(tween);\n\n\t\t\tif (i !== -1) {\n\t\t\t\t_tweens.splice(i, 1);\n\t\t\t}\n\n\t\t},\n\n\t\tupdate: function (time, preserve) {\n\n\t\t\tif (_tweens.length === 0) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tvar i = 0;\n\n\t\t\ttime = time !== undefined ? time : TWEEN.now();\n\n\t\t\twhile (i < _tweens.length) {\n\n\t\t\t\tif (_tweens[i].update(time) || preserve) {\n\t\t\t\t\ti++;\n\t\t\t\t} else {\n\t\t\t\t\t_tweens.splice(i, 1);\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn true;\n\n\t\t}\n\t};\n\n})();\n\n\n// Include a performance.now polyfill.\n// In node.js, use process.hrtime.\nif (typeof (window) === 'undefined' && typeof (process) !== 'undefined') {\n\tTWEEN.now = function () {\n\t\tvar time = process.hrtime();\n\n\t\t// Convert [seconds, nanoseconds] to milliseconds.\n\t\treturn time[0] * 1000 + time[1] / 1000000;\n\t};\n}\n// In a browser, use window.performance.now if it is available.\nelse if (typeof (window) !== 'undefined' &&\n         window.performance !== undefined &&\n\t\t window.performance.now !== undefined) {\n\t// This must be bound, because directly assigning this function\n\t// leads to an invocation exception in Chrome.\n\tTWEEN.now = window.performance.now.bind(window.performance);\n}\n// Use Date.now if it is available.\nelse if (Date.now !== undefined) {\n\tTWEEN.now = Date.now;\n}\n// Otherwise, use 'new Date().getTime()'.\nelse {\n\tTWEEN.now = function () {\n\t\treturn new Date().getTime();\n\t};\n}\n\n\nTWEEN.Tween = function (object) {\n\n\tvar _object = object;\n\tvar _valuesStart = {};\n\tvar _valuesEnd = {};\n\tvar _valuesStartRepeat = {};\n\tvar _duration = 1000;\n\tvar _repeat = 0;\n\tvar _repeatDelayTime;\n\tvar _yoyo = false;\n\tvar _isPlaying = false;\n\tvar _reversed = false;\n\tvar _delayTime = 0;\n\tvar _startTime = null;\n\tvar _easingFunction = TWEEN.Easing.Linear.None;\n\tvar _interpolationFunction = TWEEN.Interpolation.Linear;\n\tvar _chainedTweens = [];\n\tvar _onStartCallback = null;\n\tvar _onStartCallbackFired = false;\n\tvar _onUpdateCallback = null;\n\tvar _onCompleteCallback = null;\n\tvar _onStopCallback = null;\n\n\tthis.to = function (properties, duration) {\n\n\t\t_valuesEnd = properties;\n\n\t\tif (duration !== undefined) {\n\t\t\t_duration = duration;\n\t\t}\n\n\t\treturn this;\n\n\t};\n\n\tthis.start = function (time) {\n\n\t\tTWEEN.add(this);\n\n\t\t_isPlaying = true;\n\n\t\t_onStartCallbackFired = false;\n\n\t\t_startTime = time !== undefined ? time : TWEEN.now();\n\t\t_startTime += _delayTime;\n\n\t\tfor (var property in _valuesEnd) {\n\n\t\t\t// Check if an Array was provided as property value\n\t\t\tif (_valuesEnd[property] instanceof Array) {\n\n\t\t\t\tif (_valuesEnd[property].length === 0) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Create a local copy of the Array with the start value at the front\n\t\t\t\t_valuesEnd[property] = [_object[property]].concat(_valuesEnd[property]);\n\n\t\t\t}\n\n\t\t\t// If `to()` specifies a property that doesn't exist in the source object,\n\t\t\t// we should not set that property in the object\n\t\t\tif (_object[property] === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Save the starting value.\n\t\t\t_valuesStart[property] = _object[property];\n\n\t\t\tif ((_valuesStart[property] instanceof Array) === false) {\n\t\t\t\t_valuesStart[property] *= 1.0; // Ensures we're using numbers, not strings\n\t\t\t}\n\n\t\t\t_valuesStartRepeat[property] = _valuesStart[property] || 0;\n\n\t\t}\n\n\t\treturn this;\n\n\t};\n\n\tthis.stop = function () {\n\n\t\tif (!_isPlaying) {\n\t\t\treturn this;\n\t\t}\n\n\t\tTWEEN.remove(this);\n\t\t_isPlaying = false;\n\n\t\tif (_onStopCallback !== null) {\n\t\t\t_onStopCallback.call(_object, _object);\n\t\t}\n\n\t\tthis.stopChainedTweens();\n\t\treturn this;\n\n\t};\n\n\tthis.end = function () {\n\n\t\tthis.update(_startTime + _duration);\n\t\treturn this;\n\n\t};\n\n\tthis.stopChainedTweens = function () {\n\n\t\tfor (var i = 0, numChainedTweens = _chainedTweens.length; i < numChainedTweens; i++) {\n\t\t\t_chainedTweens[i].stop();\n\t\t}\n\n\t};\n\n\tthis.delay = function (amount) {\n\n\t\t_delayTime = amount;\n\t\treturn this;\n\n\t};\n\n\tthis.repeat = function (times) {\n\n\t\t_repeat = times;\n\t\treturn this;\n\n\t};\n\n\tthis.repeatDelay = function (amount) {\n\n\t\t_repeatDelayTime = amount;\n\t\treturn this;\n\n\t};\n\n\tthis.yoyo = function (yoyo) {\n\n\t\t_yoyo = yoyo;\n\t\treturn this;\n\n\t};\n\n\n\tthis.easing = function (easing) {\n\n\t\t_easingFunction = easing;\n\t\treturn this;\n\n\t};\n\n\tthis.interpolation = function (interpolation) {\n\n\t\t_interpolationFunction = interpolation;\n\t\treturn this;\n\n\t};\n\n\tthis.chain = function () {\n\n\t\t_chainedTweens = arguments;\n\t\treturn this;\n\n\t};\n\n\tthis.onStart = function (callback) {\n\n\t\t_onStartCallback = callback;\n\t\treturn this;\n\n\t};\n\n\tthis.onUpdate = function (callback) {\n\n\t\t_onUpdateCallback = callback;\n\t\treturn this;\n\n\t};\n\n\tthis.onComplete = function (callback) {\n\n\t\t_onCompleteCallback = callback;\n\t\treturn this;\n\n\t};\n\n\tthis.onStop = function (callback) {\n\n\t\t_onStopCallback = callback;\n\t\treturn this;\n\n\t};\n\n\tthis.update = function (time) {\n\n\t\tvar property;\n\t\tvar elapsed;\n\t\tvar value;\n\n\t\tif (time < _startTime) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (_onStartCallbackFired === false) {\n\n\t\t\tif (_onStartCallback !== null) {\n\t\t\t\t_onStartCallback.call(_object, _object);\n\t\t\t}\n\n\t\t\t_onStartCallbackFired = true;\n\t\t}\n\n\t\telapsed = (time - _startTime) / _duration;\n\t\telapsed = elapsed > 1 ? 1 : elapsed;\n\n\t\tvalue = _easingFunction(elapsed);\n\n\t\tfor (property in _valuesEnd) {\n\n\t\t\t// Don't update properties that do not exist in the source object\n\t\t\tif (_valuesStart[property] === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tvar start = _valuesStart[property] || 0;\n\t\t\tvar end = _valuesEnd[property];\n\n\t\t\tif (end instanceof Array) {\n\n\t\t\t\t_object[property] = _interpolationFunction(end, value);\n\n\t\t\t} else {\n\n\t\t\t\t// Parses relative end values with start as base (e.g.: +10, -3)\n\t\t\t\tif (typeof (end) === 'string') {\n\n\t\t\t\t\tif (end.charAt(0) === '+' || end.charAt(0) === '-') {\n\t\t\t\t\t\tend = start + parseFloat(end);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tend = parseFloat(end);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Protect against non numeric properties.\n\t\t\t\tif (typeof (end) === 'number') {\n\t\t\t\t\t_object[property] = start + (end - start) * value;\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tif (_onUpdateCallback !== null) {\n\t\t\t_onUpdateCallback.call(_object, value);\n\t\t}\n\n\t\tif (elapsed === 1) {\n\n\t\t\tif (_repeat > 0) {\n\n\t\t\t\tif (isFinite(_repeat)) {\n\t\t\t\t\t_repeat--;\n\t\t\t\t}\n\n\t\t\t\t// Reassign starting values, restart by making startTime = now\n\t\t\t\tfor (property in _valuesStartRepeat) {\n\n\t\t\t\t\tif (typeof (_valuesEnd[property]) === 'string') {\n\t\t\t\t\t\t_valuesStartRepeat[property] = _valuesStartRepeat[property] + parseFloat(_valuesEnd[property]);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (_yoyo) {\n\t\t\t\t\t\tvar tmp = _valuesStartRepeat[property];\n\n\t\t\t\t\t\t_valuesStartRepeat[property] = _valuesEnd[property];\n\t\t\t\t\t\t_valuesEnd[property] = tmp;\n\t\t\t\t\t}\n\n\t\t\t\t\t_valuesStart[property] = _valuesStartRepeat[property];\n\n\t\t\t\t}\n\n\t\t\t\tif (_yoyo) {\n\t\t\t\t\t_reversed = !_reversed;\n\t\t\t\t}\n\n\t\t\t\tif (_repeatDelayTime !== undefined) {\n\t\t\t\t\t_startTime = time + _repeatDelayTime;\n\t\t\t\t} else {\n\t\t\t\t\t_startTime = time + _delayTime;\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\n\t\t\t\tif (_onCompleteCallback !== null) {\n\n\t\t\t\t\t_onCompleteCallback.call(_object, _object);\n\t\t\t\t}\n\n\t\t\t\tfor (var i = 0, numChainedTweens = _chainedTweens.length; i < numChainedTweens; i++) {\n\t\t\t\t\t// Make the chained tweens start exactly at the time they should,\n\t\t\t\t\t// even if the `update()` method was called way past the duration of the tween\n\t\t\t\t\t_chainedTweens[i].start(_startTime + _duration);\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn true;\n\n\t};\n\n};\n\n\nTWEEN.Easing = {\n\n\tLinear: {\n\n\t\tNone: function (k) {\n\n\t\t\treturn k;\n\n\t\t}\n\n\t},\n\n\tQuadratic: {\n\n\t\tIn: function (k) {\n\n\t\t\treturn k * k;\n\n\t\t},\n\n\t\tOut: function (k) {\n\n\t\t\treturn k * (2 - k);\n\n\t\t},\n\n\t\tInOut: function (k) {\n\n\t\t\tif ((k *= 2) < 1) {\n\t\t\t\treturn 0.5 * k * k;\n\t\t\t}\n\n\t\t\treturn - 0.5 * (--k * (k - 2) - 1);\n\n\t\t}\n\n\t},\n\n\tCubic: {\n\n\t\tIn: function (k) {\n\n\t\t\treturn k * k * k;\n\n\t\t},\n\n\t\tOut: function (k) {\n\n\t\t\treturn --k * k * k + 1;\n\n\t\t},\n\n\t\tInOut: function (k) {\n\n\t\t\tif ((k *= 2) < 1) {\n\t\t\t\treturn 0.5 * k * k * k;\n\t\t\t}\n\n\t\t\treturn 0.5 * ((k -= 2) * k * k + 2);\n\n\t\t}\n\n\t},\n\n\tQuartic: {\n\n\t\tIn: function (k) {\n\n\t\t\treturn k * k * k * k;\n\n\t\t},\n\n\t\tOut: function (k) {\n\n\t\t\treturn 1 - (--k * k * k * k);\n\n\t\t},\n\n\t\tInOut: function (k) {\n\n\t\t\tif ((k *= 2) < 1) {\n\t\t\t\treturn 0.5 * k * k * k * k;\n\t\t\t}\n\n\t\t\treturn - 0.5 * ((k -= 2) * k * k * k - 2);\n\n\t\t}\n\n\t},\n\n\tQuintic: {\n\n\t\tIn: function (k) {\n\n\t\t\treturn k * k * k * k * k;\n\n\t\t},\n\n\t\tOut: function (k) {\n\n\t\t\treturn --k * k * k * k * k + 1;\n\n\t\t},\n\n\t\tInOut: function (k) {\n\n\t\t\tif ((k *= 2) < 1) {\n\t\t\t\treturn 0.5 * k * k * k * k * k;\n\t\t\t}\n\n\t\t\treturn 0.5 * ((k -= 2) * k * k * k * k + 2);\n\n\t\t}\n\n\t},\n\n\tSinusoidal: {\n\n\t\tIn: function (k) {\n\n\t\t\treturn 1 - Math.cos(k * Math.PI / 2);\n\n\t\t},\n\n\t\tOut: function (k) {\n\n\t\t\treturn Math.sin(k * Math.PI / 2);\n\n\t\t},\n\n\t\tInOut: function (k) {\n\n\t\t\treturn 0.5 * (1 - Math.cos(Math.PI * k));\n\n\t\t}\n\n\t},\n\n\tExponential: {\n\n\t\tIn: function (k) {\n\n\t\t\treturn k === 0 ? 0 : Math.pow(1024, k - 1);\n\n\t\t},\n\n\t\tOut: function (k) {\n\n\t\t\treturn k === 1 ? 1 : 1 - Math.pow(2, - 10 * k);\n\n\t\t},\n\n\t\tInOut: function (k) {\n\n\t\t\tif (k === 0) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tif (k === 1) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\tif ((k *= 2) < 1) {\n\t\t\t\treturn 0.5 * Math.pow(1024, k - 1);\n\t\t\t}\n\n\t\t\treturn 0.5 * (- Math.pow(2, - 10 * (k - 1)) + 2);\n\n\t\t}\n\n\t},\n\n\tCircular: {\n\n\t\tIn: function (k) {\n\n\t\t\treturn 1 - Math.sqrt(1 - k * k);\n\n\t\t},\n\n\t\tOut: function (k) {\n\n\t\t\treturn Math.sqrt(1 - (--k * k));\n\n\t\t},\n\n\t\tInOut: function (k) {\n\n\t\t\tif ((k *= 2) < 1) {\n\t\t\t\treturn - 0.5 * (Math.sqrt(1 - k * k) - 1);\n\t\t\t}\n\n\t\t\treturn 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1);\n\n\t\t}\n\n\t},\n\n\tElastic: {\n\n\t\tIn: function (k) {\n\n\t\t\tif (k === 0) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tif (k === 1) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\treturn -Math.pow(2, 10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI);\n\n\t\t},\n\n\t\tOut: function (k) {\n\n\t\t\tif (k === 0) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tif (k === 1) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\treturn Math.pow(2, -10 * k) * Math.sin((k - 0.1) * 5 * Math.PI) + 1;\n\n\t\t},\n\n\t\tInOut: function (k) {\n\n\t\t\tif (k === 0) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tif (k === 1) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\tk *= 2;\n\n\t\t\tif (k < 1) {\n\t\t\t\treturn -0.5 * Math.pow(2, 10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI);\n\t\t\t}\n\n\t\t\treturn 0.5 * Math.pow(2, -10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI) + 1;\n\n\t\t}\n\n\t},\n\n\tBack: {\n\n\t\tIn: function (k) {\n\n\t\t\tvar s = 1.70158;\n\n\t\t\treturn k * k * ((s + 1) * k - s);\n\n\t\t},\n\n\t\tOut: function (k) {\n\n\t\t\tvar s = 1.70158;\n\n\t\t\treturn --k * k * ((s + 1) * k + s) + 1;\n\n\t\t},\n\n\t\tInOut: function (k) {\n\n\t\t\tvar s = 1.70158 * 1.525;\n\n\t\t\tif ((k *= 2) < 1) {\n\t\t\t\treturn 0.5 * (k * k * ((s + 1) * k - s));\n\t\t\t}\n\n\t\t\treturn 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2);\n\n\t\t}\n\n\t},\n\n\tBounce: {\n\n\t\tIn: function (k) {\n\n\t\t\treturn 1 - TWEEN.Easing.Bounce.Out(1 - k);\n\n\t\t},\n\n\t\tOut: function (k) {\n\n\t\t\tif (k < (1 / 2.75)) {\n\t\t\t\treturn 7.5625 * k * k;\n\t\t\t} else if (k < (2 / 2.75)) {\n\t\t\t\treturn 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75;\n\t\t\t} else if (k < (2.5 / 2.75)) {\n\t\t\t\treturn 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375;\n\t\t\t} else {\n\t\t\t\treturn 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375;\n\t\t\t}\n\n\t\t},\n\n\t\tInOut: function (k) {\n\n\t\t\tif (k < 0.5) {\n\t\t\t\treturn TWEEN.Easing.Bounce.In(k * 2) * 0.5;\n\t\t\t}\n\n\t\t\treturn TWEEN.Easing.Bounce.Out(k * 2 - 1) * 0.5 + 0.5;\n\n\t\t}\n\n\t}\n\n};\n\nTWEEN.Interpolation = {\n\n\tLinear: function (v, k) {\n\n\t\tvar m = v.length - 1;\n\t\tvar f = m * k;\n\t\tvar i = Math.floor(f);\n\t\tvar fn = TWEEN.Interpolation.Utils.Linear;\n\n\t\tif (k < 0) {\n\t\t\treturn fn(v[0], v[1], f);\n\t\t}\n\n\t\tif (k > 1) {\n\t\t\treturn fn(v[m], v[m - 1], m - f);\n\t\t}\n\n\t\treturn fn(v[i], v[i + 1 > m ? m : i + 1], f - i);\n\n\t},\n\n\tBezier: function (v, k) {\n\n\t\tvar b = 0;\n\t\tvar n = v.length - 1;\n\t\tvar pw = Math.pow;\n\t\tvar bn = TWEEN.Interpolation.Utils.Bernstein;\n\n\t\tfor (var i = 0; i <= n; i++) {\n\t\t\tb += pw(1 - k, n - i) * pw(k, i) * v[i] * bn(n, i);\n\t\t}\n\n\t\treturn b;\n\n\t},\n\n\tCatmullRom: function (v, k) {\n\n\t\tvar m = v.length - 1;\n\t\tvar f = m * k;\n\t\tvar i = Math.floor(f);\n\t\tvar fn = TWEEN.Interpolation.Utils.CatmullRom;\n\n\t\tif (v[0] === v[m]) {\n\n\t\t\tif (k < 0) {\n\t\t\t\ti = Math.floor(f = m * (1 + k));\n\t\t\t}\n\n\t\t\treturn fn(v[(i - 1 + m) % m], v[i], v[(i + 1) % m], v[(i + 2) % m], f - i);\n\n\t\t} else {\n\n\t\t\tif (k < 0) {\n\t\t\t\treturn v[0] - (fn(v[0], v[0], v[1], v[1], -f) - v[0]);\n\t\t\t}\n\n\t\t\tif (k > 1) {\n\t\t\t\treturn v[m] - (fn(v[m], v[m], v[m - 1], v[m - 1], f - m) - v[m]);\n\t\t\t}\n\n\t\t\treturn fn(v[i ? i - 1 : 0], v[i], v[m < i + 1 ? m : i + 1], v[m < i + 2 ? m : i + 2], f - i);\n\n\t\t}\n\n\t},\n\n\tUtils: {\n\n\t\tLinear: function (p0, p1, t) {\n\n\t\t\treturn (p1 - p0) * t + p0;\n\n\t\t},\n\n\t\tBernstein: function (n, i) {\n\n\t\t\tvar fc = TWEEN.Interpolation.Utils.Factorial;\n\n\t\t\treturn fc(n) / fc(i) / fc(n - i);\n\n\t\t},\n\n\t\tFactorial: (function () {\n\n\t\t\tvar a = [1];\n\n\t\t\treturn function (n) {\n\n\t\t\t\tvar s = 1;\n\n\t\t\t\tif (a[n]) {\n\t\t\t\t\treturn a[n];\n\t\t\t\t}\n\n\t\t\t\tfor (var i = n; i > 1; i--) {\n\t\t\t\t\ts *= i;\n\t\t\t\t}\n\n\t\t\t\ta[n] = s;\n\t\t\t\treturn s;\n\n\t\t\t};\n\n\t\t})(),\n\n\t\tCatmullRom: function (p0, p1, p2, p3, t) {\n\n\t\t\tvar v0 = (p2 - p0) * 0.5;\n\t\t\tvar v1 = (p3 - p1) * 0.5;\n\t\t\tvar t2 = t * t;\n\t\t\tvar t3 = t * t2;\n\n\t\t\treturn (2 * p1 - 2 * p2 + v0 + v1) * t3 + (- 3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1;\n\n\t\t}\n\n\t}\n\n};\n\n// UMD (Universal Module Definition)\n(function (root) {\n\n\tif (typeof define === 'function' && define.amd) {\n\n\t\t// AMD\n\t\tdefine([], function () {\n\t\t\treturn TWEEN;\n\t\t});\n\n\t} else if (typeof module !== 'undefined' && typeof exports === 'object') {\n\n\t\t// Node.js\n\t\tmodule.exports = TWEEN;\n\n\t} else if (root !== undefined) {\n\n\t\t// Global variable\n\t\troot.TWEEN = TWEEN;\n\n\t}\n\n})(this);\n"
  },
  {
    "path": "lib/URLParameterUtils.js",
    "content": "var URLParameterUtils = (function () {\n\n\tvar urlParameterUtils = { };\n\n\turlParameterUtils.getParameterByName = function (name, url) {\n\t    if (!url) url = window.location.href;\n\t    name = name.replace(/[\\[\\]]/g, \"\\\\$&\");\n\t    var regex = new RegExp(\"[?&]\" + name + \"(=([^&#]*)|&|#|$)\"),\n\t        results = regex.exec(url);\n\t    if (!results) return null;\n\t    if (!results[2]) return '';\n\t    return decodeURIComponent(results[2].replace(/\\+/g, \" \"));\n\t}\n\n\t//http://stackoverflow.com/questions/1634748/how-can-i-delete-a-query-string-parameter-in-javascript\n\turlParameterUtils.clearURLParam = function (parameter) {\n\t    //prefer to use l.search if you have a location/link object\n\t    var url = window.location.href;\n\t    var urlparts= url.split('?');   \n\t    if (urlparts.length>=2) {\n\n\t        var prefix= encodeURIComponent(parameter)+'=';\n\t        var pars= urlparts[1].split(/[&;]/g);\n\n\t        //reverse iteration as may be destructive\n\t        for (var i= pars.length; i-- > 0;) {    \n\t            //idiom for string.startsWith\n\t            if (pars[i].lastIndexOf(prefix, 0) !== -1) {  \n\t                pars.splice(i, 1);\n\t            }\n\t        }\n\n\t        url= urlparts[0] + (pars.length > 0 ? '?' + pars.join('&') : \"\");\n\t        //console.log(url)\n\t        //window.location.href = url;\n\t        history.pushState(null, null, url);\n\t        return url;\n\t    } else {\n\t        return url;\n\t    }\n\t}\n\n\treturn urlParameterUtils;\n\n})();"
  },
  {
    "path": "lib/WickEditorInputs.js",
    "content": "var SlideyNumberInput = function (args) {\n  var input = document.createElement('input');\n  input.type = 'text';\n  input.value = args.initValue;\n\n  var mouseIsDown = false;\n  var initXY = {};\n  var oldValue;\n\n  input.addEventListener('mousedown', function (e) {\n    mouseIsDown = true;\n    initXY.x = e.screenX - parseFloat(input.value)/args.moveFactor;\n    initXY.y = e.screenY;\n    oldValue = parseFloat(input.value);\n  });\n\n  input.addEventListener('mouseup', function (e) {\n    input.select();\n  });\n\n  window.addEventListener('mousemove', function (e) {\n    if(!mouseIsDown) return;\n    var diffXY = {\n      x:(e.screenX-initXY.x)*args.moveFactor,\n      y:(e.screenY-initXY.y)*args.moveFactor,\n    }\n    if(diffXY.x !== 0) {\n      input.value = roundToHundredths(Math.min(args.max, Math.max(args.min, diffXY.x)));\n      args.onsoftchange(input.value);\n    }\n  });\n\n  window.addEventListener('mouseup', function (e) {\n    if(mouseIsDown) {\n      if(parseFloat(input.value) !== oldValue) {\n        args.onhardchange(parseFloat(input.value) || args.min);\n        document.getElementById('editorCanvasContainer').focus();\n      }\n    }\n    mouseIsDown = false;\n  });\n\n  input.addEventListener('change', function (e) {\n    args.onhardchange(parseFloat(input.value) || args.min);\n  });\n\n  return input;\n}"
  },
  {
    "path": "lib/ace/ace.js",
    "content": "(function(){function o(n){var i=e;n&&(e[n]||(e[n]={}),i=e[n]);if(!i.define||!i.define.packaged)t.original=i.define,i.define=t,i.define.packaged=!0;if(!i.require||!i.require.packaged)r.original=i.require,i.require=r,i.require.packaged=!0}var ACE_NAMESPACE=\"\",e=function(){return this}();!e&&typeof window!=\"undefined\"&&(e=window);if(!ACE_NAMESPACE&&typeof requirejs!=\"undefined\")return;var t=function(e,n,r){if(typeof e!=\"string\"){t.original?t.original.apply(this,arguments):(console.error(\"dropping module because define wasn't a string.\"),console.trace());return}arguments.length==2&&(r=n),t.modules[e]||(t.payloads[e]=r,t.modules[e]=null)};t.modules={},t.payloads={};var n=function(e,t,n){if(typeof t==\"string\"){var i=s(e,t);if(i!=undefined)return n&&n(),i}else if(Object.prototype.toString.call(t)===\"[object Array]\"){var o=[];for(var u=0,a=t.length;u<a;++u){var f=s(e,t[u]);if(f==undefined&&r.original)return;o.push(f)}return n&&n.apply(null,o)||!0}},r=function(e,t){var i=n(\"\",e,t);return i==undefined&&r.original?r.original.apply(this,arguments):i},i=function(e,t){if(t.indexOf(\"!\")!==-1){var n=t.split(\"!\");return i(e,n[0])+\"!\"+i(e,n[1])}if(t.charAt(0)==\".\"){var r=e.split(\"/\").slice(0,-1).join(\"/\");t=r+\"/\"+t;while(t.indexOf(\".\")!==-1&&s!=t){var s=t;t=t.replace(/\\/\\.\\//,\"/\").replace(/[^\\/]+\\/\\.\\.\\//,\"\")}}return t},s=function(e,r){r=i(e,r);var s=t.modules[r];if(!s){s=t.payloads[r];if(typeof s==\"function\"){var o={},u={id:r,uri:\"\",exports:o,packaged:!0},a=function(e,t){return n(r,e,t)},f=s(a,o,u);o=f||u.exports,t.modules[r]=o,delete t.payloads[r]}s=t.modules[r]=o||s}return s};o(ACE_NAMESPACE)})(),define(\"ace/lib/regexp\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";function o(e){return(e.global?\"g\":\"\")+(e.ignoreCase?\"i\":\"\")+(e.multiline?\"m\":\"\")+(e.extended?\"x\":\"\")+(e.sticky?\"y\":\"\")}function u(e,t,n){if(Array.prototype.indexOf)return e.indexOf(t,n);for(var r=n||0;r<e.length;r++)if(e[r]===t)return r;return-1}var r={exec:RegExp.prototype.exec,test:RegExp.prototype.test,match:String.prototype.match,replace:String.prototype.replace,split:String.prototype.split},i=r.exec.call(/()??/,\"\")[1]===undefined,s=function(){var e=/^/g;return r.test.call(e,\"\"),!e.lastIndex}();if(s&&i)return;RegExp.prototype.exec=function(e){var t=r.exec.apply(this,arguments),n,a;if(typeof e==\"string\"&&t){!i&&t.length>1&&u(t,\"\")>-1&&(a=RegExp(this.source,r.replace.call(o(this),\"g\",\"\")),r.replace.call(e.slice(t.index),a,function(){for(var e=1;e<arguments.length-2;e++)arguments[e]===undefined&&(t[e]=undefined)}));if(this._xregexp&&this._xregexp.captureNames)for(var f=1;f<t.length;f++)n=this._xregexp.captureNames[f-1],n&&(t[n]=t[f]);!s&&this.global&&!t[0].length&&this.lastIndex>t.index&&this.lastIndex--}return t},s||(RegExp.prototype.test=function(e){var t=r.exec.call(this,e);return t&&this.global&&!t[0].length&&this.lastIndex>t.index&&this.lastIndex--,!!t})}),define(\"ace/lib/es5-shim\",[\"require\",\"exports\",\"module\"],function(e,t,n){function r(){}function w(e){try{return Object.defineProperty(e,\"sentinel\",{}),\"sentinel\"in e}catch(t){}}function H(e){return e=+e,e!==e?e=0:e!==0&&e!==1/0&&e!==-1/0&&(e=(e>0||-1)*Math.floor(Math.abs(e))),e}function B(e){var t=typeof e;return e===null||t===\"undefined\"||t===\"boolean\"||t===\"number\"||t===\"string\"}function j(e){var t,n,r;if(B(e))return e;n=e.valueOf;if(typeof n==\"function\"){t=n.call(e);if(B(t))return t}r=e.toString;if(typeof r==\"function\"){t=r.call(e);if(B(t))return t}throw new TypeError}Function.prototype.bind||(Function.prototype.bind=function(t){var n=this;if(typeof n!=\"function\")throw new TypeError(\"Function.prototype.bind called on incompatible \"+n);var i=u.call(arguments,1),s=function(){if(this instanceof s){var e=n.apply(this,i.concat(u.call(arguments)));return Object(e)===e?e:this}return n.apply(t,i.concat(u.call(arguments)))};return n.prototype&&(r.prototype=n.prototype,s.prototype=new r,r.prototype=null),s});var i=Function.prototype.call,s=Array.prototype,o=Object.prototype,u=s.slice,a=i.bind(o.toString),f=i.bind(o.hasOwnProperty),l,c,h,p,d;if(d=f(o,\"__defineGetter__\"))l=i.bind(o.__defineGetter__),c=i.bind(o.__defineSetter__),h=i.bind(o.__lookupGetter__),p=i.bind(o.__lookupSetter__);if([1,2].splice(0).length!=2)if(!function(){function e(e){var t=new Array(e+2);return t[0]=t[1]=0,t}var t=[],n;t.splice.apply(t,e(20)),t.splice.apply(t,e(26)),n=t.length,t.splice(5,0,\"XXX\"),n+1==t.length;if(n+1==t.length)return!0}())Array.prototype.splice=function(e,t){var n=this.length;e>0?e>n&&(e=n):e==void 0?e=0:e<0&&(e=Math.max(n+e,0)),e+t<n||(t=n-e);var r=this.slice(e,e+t),i=u.call(arguments,2),s=i.length;if(e===n)s&&this.push.apply(this,i);else{var o=Math.min(t,n-e),a=e+o,f=a+s-o,l=n-a,c=n-o;if(f<a)for(var h=0;h<l;++h)this[f+h]=this[a+h];else if(f>a)for(h=l;h--;)this[f+h]=this[a+h];if(s&&e===c)this.length=c,this.push.apply(this,i);else{this.length=c+s;for(h=0;h<s;++h)this[e+h]=i[h]}}return r};else{var v=Array.prototype.splice;Array.prototype.splice=function(e,t){return arguments.length?v.apply(this,[e===void 0?0:e,t===void 0?this.length-e:t].concat(u.call(arguments,2))):[]}}Array.isArray||(Array.isArray=function(t){return a(t)==\"[object Array]\"});var m=Object(\"a\"),g=m[0]!=\"a\"||!(0 in m);Array.prototype.forEach||(Array.prototype.forEach=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=arguments[1],s=-1,o=r.length>>>0;if(a(t)!=\"[object Function]\")throw new TypeError;while(++s<o)s in r&&t.call(i,r[s],s,n)}),Array.prototype.map||(Array.prototype.map=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0,s=Array(i),o=arguments[1];if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");for(var u=0;u<i;u++)u in r&&(s[u]=t.call(o,r[u],u,n));return s}),Array.prototype.filter||(Array.prototype.filter=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0,s=[],o,u=arguments[1];if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");for(var f=0;f<i;f++)f in r&&(o=r[f],t.call(u,o,f,n)&&s.push(o));return s}),Array.prototype.every||(Array.prototype.every=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0,s=arguments[1];if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");for(var o=0;o<i;o++)if(o in r&&!t.call(s,r[o],o,n))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0,s=arguments[1];if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");for(var o=0;o<i;o++)if(o in r&&t.call(s,r[o],o,n))return!0;return!1}),Array.prototype.reduce||(Array.prototype.reduce=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0;if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");if(!i&&arguments.length==1)throw new TypeError(\"reduce of empty array with no initial value\");var s=0,o;if(arguments.length>=2)o=arguments[1];else do{if(s in r){o=r[s++];break}if(++s>=i)throw new TypeError(\"reduce of empty array with no initial value\")}while(!0);for(;s<i;s++)s in r&&(o=t.call(void 0,o,r[s],s,n));return o}),Array.prototype.reduceRight||(Array.prototype.reduceRight=function(t){var n=F(this),r=g&&a(this)==\"[object String]\"?this.split(\"\"):n,i=r.length>>>0;if(a(t)!=\"[object Function]\")throw new TypeError(t+\" is not a function\");if(!i&&arguments.length==1)throw new TypeError(\"reduceRight of empty array with no initial value\");var s,o=i-1;if(arguments.length>=2)s=arguments[1];else do{if(o in r){s=r[o--];break}if(--o<0)throw new TypeError(\"reduceRight of empty array with no initial value\")}while(!0);do o in this&&(s=t.call(void 0,s,r[o],o,n));while(o--);return s});if(!Array.prototype.indexOf||[0,1].indexOf(1,2)!=-1)Array.prototype.indexOf=function(t){var n=g&&a(this)==\"[object String]\"?this.split(\"\"):F(this),r=n.length>>>0;if(!r)return-1;var i=0;arguments.length>1&&(i=H(arguments[1])),i=i>=0?i:Math.max(0,r+i);for(;i<r;i++)if(i in n&&n[i]===t)return i;return-1};if(!Array.prototype.lastIndexOf||[0,1].lastIndexOf(0,-3)!=-1)Array.prototype.lastIndexOf=function(t){var n=g&&a(this)==\"[object String]\"?this.split(\"\"):F(this),r=n.length>>>0;if(!r)return-1;var i=r-1;arguments.length>1&&(i=Math.min(i,H(arguments[1]))),i=i>=0?i:r-Math.abs(i);for(;i>=0;i--)if(i in n&&t===n[i])return i;return-1};Object.getPrototypeOf||(Object.getPrototypeOf=function(t){return t.__proto__||(t.constructor?t.constructor.prototype:o)});if(!Object.getOwnPropertyDescriptor){var y=\"Object.getOwnPropertyDescriptor called on a non-object: \";Object.getOwnPropertyDescriptor=function(t,n){if(typeof t!=\"object\"&&typeof t!=\"function\"||t===null)throw new TypeError(y+t);if(!f(t,n))return;var r,i,s;r={enumerable:!0,configurable:!0};if(d){var u=t.__proto__;t.__proto__=o;var i=h(t,n),s=p(t,n);t.__proto__=u;if(i||s)return i&&(r.get=i),s&&(r.set=s),r}return r.value=t[n],r}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(t){return Object.keys(t)});if(!Object.create){var b;Object.prototype.__proto__===null?b=function(){return{__proto__:null}}:b=function(){var e={};for(var t in e)e[t]=null;return e.constructor=e.hasOwnProperty=e.propertyIsEnumerable=e.isPrototypeOf=e.toLocaleString=e.toString=e.valueOf=e.__proto__=null,e},Object.create=function(t,n){var r;if(t===null)r=b();else{if(typeof t!=\"object\")throw new TypeError(\"typeof prototype[\"+typeof t+\"] != 'object'\");var i=function(){};i.prototype=t,r=new i,r.__proto__=t}return n!==void 0&&Object.defineProperties(r,n),r}}if(Object.defineProperty){var E=w({}),S=typeof document==\"undefined\"||w(document.createElement(\"div\"));if(!E||!S)var x=Object.defineProperty}if(!Object.defineProperty||x){var T=\"Property description must be an object: \",N=\"Object.defineProperty called on non-object: \",C=\"getters & setters can not be defined on this javascript engine\";Object.defineProperty=function(t,n,r){if(typeof t!=\"object\"&&typeof t!=\"function\"||t===null)throw new TypeError(N+t);if(typeof r!=\"object\"&&typeof r!=\"function\"||r===null)throw new TypeError(T+r);if(x)try{return x.call(Object,t,n,r)}catch(i){}if(f(r,\"value\"))if(d&&(h(t,n)||p(t,n))){var s=t.__proto__;t.__proto__=o,delete t[n],t[n]=r.value,t.__proto__=s}else t[n]=r.value;else{if(!d)throw new TypeError(C);f(r,\"get\")&&l(t,n,r.get),f(r,\"set\")&&c(t,n,r.set)}return t}}Object.defineProperties||(Object.defineProperties=function(t,n){for(var r in n)f(n,r)&&Object.defineProperty(t,r,n[r]);return t}),Object.seal||(Object.seal=function(t){return t}),Object.freeze||(Object.freeze=function(t){return t});try{Object.freeze(function(){})}catch(k){Object.freeze=function(t){return function(n){return typeof n==\"function\"?n:t(n)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(t){return t}),Object.isSealed||(Object.isSealed=function(t){return!1}),Object.isFrozen||(Object.isFrozen=function(t){return!1}),Object.isExtensible||(Object.isExtensible=function(t){if(Object(t)===t)throw new TypeError;var n=\"\";while(f(t,n))n+=\"?\";t[n]=!0;var r=f(t,n);return delete t[n],r});if(!Object.keys){var L=!0,A=[\"toString\",\"toLocaleString\",\"valueOf\",\"hasOwnProperty\",\"isPrototypeOf\",\"propertyIsEnumerable\",\"constructor\"],O=A.length;for(var M in{toString:null})L=!1;Object.keys=function I(e){if(typeof e!=\"object\"&&typeof e!=\"function\"||e===null)throw new TypeError(\"Object.keys called on a non-object\");var I=[];for(var t in e)f(e,t)&&I.push(t);if(L)for(var n=0,r=O;n<r;n++){var i=A[n];f(e,i)&&I.push(i)}return I}}Date.now||(Date.now=function(){return(new Date).getTime()});var _=\"  \\n\u000b\\f\\r \\u00a0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029\\ufeff\";if(!String.prototype.trim||_.trim()){_=\"[\"+_+\"]\";var D=new RegExp(\"^\"+_+_+\"*\"),P=new RegExp(_+_+\"*$\");String.prototype.trim=function(){return String(this).replace(D,\"\").replace(P,\"\")}}var F=function(e){if(e==null)throw new TypeError(\"can't convert \"+e+\" to object\");return Object(e)}}),define(\"ace/lib/fixoldbrowsers\",[\"require\",\"exports\",\"module\",\"ace/lib/regexp\",\"ace/lib/es5-shim\"],function(e,t,n){\"use strict\";e(\"./regexp\"),e(\"./es5-shim\")}),define(\"ace/lib/dom\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";var r=\"http://www.w3.org/1999/xhtml\";t.getDocumentHead=function(e){return e||(e=document),e.head||e.getElementsByTagName(\"head\")[0]||e.documentElement},t.createElement=function(e,t){return document.createElementNS?document.createElementNS(t||r,e):document.createElement(e)},t.hasCssClass=function(e,t){var n=(e.className+\"\").split(/\\s+/g);return n.indexOf(t)!==-1},t.addCssClass=function(e,n){t.hasCssClass(e,n)||(e.className+=\" \"+n)},t.removeCssClass=function(e,t){var n=e.className.split(/\\s+/g);for(;;){var r=n.indexOf(t);if(r==-1)break;n.splice(r,1)}e.className=n.join(\" \")},t.toggleCssClass=function(e,t){var n=e.className.split(/\\s+/g),r=!0;for(;;){var i=n.indexOf(t);if(i==-1)break;r=!1,n.splice(i,1)}return r&&n.push(t),e.className=n.join(\" \"),r},t.setCssClass=function(e,n,r){r?t.addCssClass(e,n):t.removeCssClass(e,n)},t.hasCssString=function(e,t){var n=0,r;t=t||document;if(t.createStyleSheet&&(r=t.styleSheets)){while(n<r.length)if(r[n++].owningElement.id===e)return!0}else if(r=t.getElementsByTagName(\"style\"))while(n<r.length)if(r[n++].id===e)return!0;return!1},t.importCssString=function(n,r,i){i=i||document;if(r&&t.hasCssString(r,i))return null;var s;r&&(n+=\"\\n/*# sourceURL=ace/css/\"+r+\" */\"),i.createStyleSheet?(s=i.createStyleSheet(),s.cssText=n,r&&(s.owningElement.id=r)):(s=t.createElement(\"style\"),s.appendChild(i.createTextNode(n)),r&&(s.id=r),t.getDocumentHead(i).appendChild(s))},t.importCssStylsheet=function(e,n){if(n.createStyleSheet)n.createStyleSheet(e);else{var r=t.createElement(\"link\");r.rel=\"stylesheet\",r.href=e,t.getDocumentHead(n).appendChild(r)}},t.getInnerWidth=function(e){return parseInt(t.computedStyle(e,\"paddingLeft\"),10)+parseInt(t.computedStyle(e,\"paddingRight\"),10)+e.clientWidth},t.getInnerHeight=function(e){return parseInt(t.computedStyle(e,\"paddingTop\"),10)+parseInt(t.computedStyle(e,\"paddingBottom\"),10)+e.clientHeight},t.scrollbarWidth=function(e){var n=t.createElement(\"ace_inner\");n.style.width=\"100%\",n.style.minWidth=\"0px\",n.style.height=\"200px\",n.style.display=\"block\";var r=t.createElement(\"ace_outer\"),i=r.style;i.position=\"absolute\",i.left=\"-10000px\",i.overflow=\"hidden\",i.width=\"200px\",i.minWidth=\"0px\",i.height=\"150px\",i.display=\"block\",r.appendChild(n);var s=e.documentElement;s.appendChild(r);var o=n.offsetWidth;i.overflow=\"scroll\";var u=n.offsetWidth;return o==u&&(u=r.clientWidth),s.removeChild(r),o-u};if(typeof document==\"undefined\"){t.importCssString=function(){};return}window.pageYOffset!==undefined?(t.getPageScrollTop=function(){return window.pageYOffset},t.getPageScrollLeft=function(){return window.pageXOffset}):(t.getPageScrollTop=function(){return document.body.scrollTop},t.getPageScrollLeft=function(){return document.body.scrollLeft}),window.getComputedStyle?t.computedStyle=function(e,t){return t?(window.getComputedStyle(e,\"\")||{})[t]||\"\":window.getComputedStyle(e,\"\")||{}}:t.computedStyle=function(e,t){return t?e.currentStyle[t]:e.currentStyle},t.setInnerHtml=function(e,t){var n=e.cloneNode(!1);return n.innerHTML=t,e.parentNode.replaceChild(n,e),n},\"textContent\"in document.documentElement?(t.setInnerText=function(e,t){e.textContent=t},t.getInnerText=function(e){return e.textContent}):(t.setInnerText=function(e,t){e.innerText=t},t.getInnerText=function(e){return e.innerText}),t.getParentWindow=function(e){return e.defaultView||e.parentWindow}}),define(\"ace/lib/oop\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";t.inherits=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})},t.mixin=function(e,t){for(var n in t)e[n]=t[n];return e},t.implement=function(e,n){t.mixin(e,n)}}),define(\"ace/lib/keys\",[\"require\",\"exports\",\"module\",\"ace/lib/fixoldbrowsers\",\"ace/lib/oop\"],function(e,t,n){\"use strict\";e(\"./fixoldbrowsers\");var r=e(\"./oop\"),i=function(){var e={MODIFIER_KEYS:{16:\"Shift\",17:\"Ctrl\",18:\"Alt\",224:\"Meta\"},KEY_MODS:{ctrl:1,alt:2,option:2,shift:4,\"super\":8,meta:8,command:8,cmd:8},FUNCTION_KEYS:{8:\"Backspace\",9:\"Tab\",13:\"Return\",19:\"Pause\",27:\"Esc\",32:\"Space\",33:\"PageUp\",34:\"PageDown\",35:\"End\",36:\"Home\",37:\"Left\",38:\"Up\",39:\"Right\",40:\"Down\",44:\"Print\",45:\"Insert\",46:\"Delete\",96:\"Numpad0\",97:\"Numpad1\",98:\"Numpad2\",99:\"Numpad3\",100:\"Numpad4\",101:\"Numpad5\",102:\"Numpad6\",103:\"Numpad7\",104:\"Numpad8\",105:\"Numpad9\",\"-13\":\"NumpadEnter\",112:\"F1\",113:\"F2\",114:\"F3\",115:\"F4\",116:\"F5\",117:\"F6\",118:\"F7\",119:\"F8\",120:\"F9\",121:\"F10\",122:\"F11\",123:\"F12\",144:\"Numlock\",145:\"Scrolllock\"},PRINTABLE_KEYS:{32:\" \",48:\"0\",49:\"1\",50:\"2\",51:\"3\",52:\"4\",53:\"5\",54:\"6\",55:\"7\",56:\"8\",57:\"9\",59:\";\",61:\"=\",65:\"a\",66:\"b\",67:\"c\",68:\"d\",69:\"e\",70:\"f\",71:\"g\",72:\"h\",73:\"i\",74:\"j\",75:\"k\",76:\"l\",77:\"m\",78:\"n\",79:\"o\",80:\"p\",81:\"q\",82:\"r\",83:\"s\",84:\"t\",85:\"u\",86:\"v\",87:\"w\",88:\"x\",89:\"y\",90:\"z\",107:\"+\",109:\"-\",110:\".\",186:\";\",187:\"=\",188:\",\",189:\"-\",190:\".\",191:\"/\",192:\"`\",219:\"[\",220:\"\\\\\",221:\"]\",222:\"'\",111:\"/\",106:\"*\"}},t,n;for(n in e.FUNCTION_KEYS)t=e.FUNCTION_KEYS[n].toLowerCase(),e[t]=parseInt(n,10);for(n in e.PRINTABLE_KEYS)t=e.PRINTABLE_KEYS[n].toLowerCase(),e[t]=parseInt(n,10);return r.mixin(e,e.MODIFIER_KEYS),r.mixin(e,e.PRINTABLE_KEYS),r.mixin(e,e.FUNCTION_KEYS),e.enter=e[\"return\"],e.escape=e.esc,e.del=e[\"delete\"],e[173]=\"-\",function(){var t=[\"cmd\",\"ctrl\",\"alt\",\"shift\"];for(var n=Math.pow(2,t.length);n--;)e.KEY_MODS[n]=t.filter(function(t){return n&e.KEY_MODS[t]}).join(\"-\")+\"-\"}(),e.KEY_MODS[0]=\"\",e.KEY_MODS[-1]=\"input-\",e}();r.mixin(t,i),t.keyCodeToString=function(e){var t=i[e];return typeof t!=\"string\"&&(t=String.fromCharCode(e)),t.toLowerCase()}}),define(\"ace/lib/useragent\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";t.OS={LINUX:\"LINUX\",MAC:\"MAC\",WINDOWS:\"WINDOWS\"},t.getOS=function(){return t.isMac?t.OS.MAC:t.isLinux?t.OS.LINUX:t.OS.WINDOWS};if(typeof navigator!=\"object\")return;var r=(navigator.platform.match(/mac|win|linux/i)||[\"other\"])[0].toLowerCase(),i=navigator.userAgent;t.isWin=r==\"win\",t.isMac=r==\"mac\",t.isLinux=r==\"linux\",t.isIE=navigator.appName==\"Microsoft Internet Explorer\"||navigator.appName.indexOf(\"MSAppHost\")>=0?parseFloat((i.match(/(?:MSIE |Trident\\/[0-9]+[\\.0-9]+;.*rv:)([0-9]+[\\.0-9]+)/)||[])[1]):parseFloat((i.match(/(?:Trident\\/[0-9]+[\\.0-9]+;.*rv:)([0-9]+[\\.0-9]+)/)||[])[1]),t.isOldIE=t.isIE&&t.isIE<9,t.isGecko=t.isMozilla=(window.Controllers||window.controllers)&&window.navigator.product===\"Gecko\",t.isOldGecko=t.isGecko&&parseInt((i.match(/rv:(\\d+)/)||[])[1],10)<4,t.isOpera=window.opera&&Object.prototype.toString.call(window.opera)==\"[object Opera]\",t.isWebKit=parseFloat(i.split(\"WebKit/\")[1])||undefined,t.isChrome=parseFloat(i.split(\" Chrome/\")[1])||undefined,t.isAIR=i.indexOf(\"AdobeAIR\")>=0,t.isIPad=i.indexOf(\"iPad\")>=0,t.isChromeOS=i.indexOf(\" CrOS \")>=0,t.isIOS=/iPad|iPhone|iPod/.test(i)&&!window.MSStream,t.isIOS&&(t.isMac=!0)}),define(\"ace/lib/event\",[\"require\",\"exports\",\"module\",\"ace/lib/keys\",\"ace/lib/useragent\"],function(e,t,n){\"use strict\";function a(e,t,n){var a=u(t);if(!i.isMac&&s){t.getModifierState&&(t.getModifierState(\"OS\")||t.getModifierState(\"Win\"))&&(a|=8);if(s.altGr){if((3&a)==3)return;s.altGr=0}if(n===18||n===17){var f=\"location\"in t?t.location:t.keyLocation;if(n===17&&f===1)s[n]==1&&(o=t.timeStamp);else if(n===18&&a===3&&f===2){var l=t.timeStamp-o;l<50&&(s.altGr=!0)}}}n in r.MODIFIER_KEYS&&(n=-1),a&8&&n>=91&&n<=93&&(n=-1);if(!a&&n===13){var f=\"location\"in t?t.location:t.keyLocation;if(f===3){e(t,a,-n);if(t.defaultPrevented)return}}if(i.isChromeOS&&a&8){e(t,a,n);if(t.defaultPrevented)return;a&=-9}return!!a||n in r.FUNCTION_KEYS||n in r.PRINTABLE_KEYS?e(t,a,n):!1}function f(){s=Object.create(null)}var r=e(\"./keys\"),i=e(\"./useragent\"),s=null,o=0;t.addListener=function(e,t,n){if(e.addEventListener)return e.addEventListener(t,n,!1);if(e.attachEvent){var r=function(){n.call(e,window.event)};n._wrapper=r,e.attachEvent(\"on\"+t,r)}},t.removeListener=function(e,t,n){if(e.removeEventListener)return e.removeEventListener(t,n,!1);e.detachEvent&&e.detachEvent(\"on\"+t,n._wrapper||n)},t.stopEvent=function(e){return t.stopPropagation(e),t.preventDefault(e),!1},t.stopPropagation=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},t.preventDefault=function(e){e.preventDefault?e.preventDefault():e.returnValue=!1},t.getButton=function(e){return e.type==\"dblclick\"?0:e.type==\"contextmenu\"||i.isMac&&e.ctrlKey&&!e.altKey&&!e.shiftKey?2:e.preventDefault?e.button:{1:0,2:2,4:1}[e.button]},t.capture=function(e,n,r){function i(e){n&&n(e),r&&r(e),t.removeListener(document,\"mousemove\",n,!0),t.removeListener(document,\"mouseup\",i,!0),t.removeListener(document,\"dragstart\",i,!0)}return t.addListener(document,\"mousemove\",n,!0),t.addListener(document,\"mouseup\",i,!0),t.addListener(document,\"dragstart\",i,!0),i},t.addTouchMoveListener=function(e,n){if(\"ontouchmove\"in e){var r,i;t.addListener(e,\"touchstart\",function(e){var t=e.changedTouches[0];r=t.clientX,i=t.clientY}),t.addListener(e,\"touchmove\",function(e){var t=1,s=e.changedTouches[0];e.wheelX=-(s.clientX-r)/t,e.wheelY=-(s.clientY-i)/t,r=s.clientX,i=s.clientY,n(e)})}},t.addMouseWheelListener=function(e,n){\"onmousewheel\"in e?t.addListener(e,\"mousewheel\",function(e){var t=8;e.wheelDeltaX!==undefined?(e.wheelX=-e.wheelDeltaX/t,e.wheelY=-e.wheelDeltaY/t):(e.wheelX=0,e.wheelY=-e.wheelDelta/t),n(e)}):\"onwheel\"in e?t.addListener(e,\"wheel\",function(e){var t=.35;switch(e.deltaMode){case e.DOM_DELTA_PIXEL:e.wheelX=e.deltaX*t||0,e.wheelY=e.deltaY*t||0;break;case e.DOM_DELTA_LINE:case e.DOM_DELTA_PAGE:e.wheelX=(e.deltaX||0)*5,e.wheelY=(e.deltaY||0)*5}n(e)}):t.addListener(e,\"DOMMouseScroll\",function(e){e.axis&&e.axis==e.HORIZONTAL_AXIS?(e.wheelX=(e.detail||0)*5,e.wheelY=0):(e.wheelX=0,e.wheelY=(e.detail||0)*5),n(e)})},t.addMultiMouseDownListener=function(e,n,r,s){function c(e){t.getButton(e)!==0?o=0:e.detail>1?(o++,o>4&&(o=1)):o=1;if(i.isIE){var c=Math.abs(e.clientX-u)>5||Math.abs(e.clientY-a)>5;if(!f||c)o=1;f&&clearTimeout(f),f=setTimeout(function(){f=null},n[o-1]||600),o==1&&(u=e.clientX,a=e.clientY)}e._clicks=o,r[s](\"mousedown\",e);if(o>4)o=0;else if(o>1)return r[s](l[o],e)}function h(e){o=2,f&&clearTimeout(f),f=setTimeout(function(){f=null},n[o-1]||600),r[s](\"mousedown\",e),r[s](l[o],e)}var o=0,u,a,f,l={2:\"dblclick\",3:\"tripleclick\",4:\"quadclick\"};Array.isArray(e)||(e=[e]),e.forEach(function(e){t.addListener(e,\"mousedown\",c),i.isOldIE&&t.addListener(e,\"dblclick\",h)})};var u=!i.isMac||!i.isOpera||\"KeyboardEvent\"in window?function(e){return 0|(e.ctrlKey?1:0)|(e.altKey?2:0)|(e.shiftKey?4:0)|(e.metaKey?8:0)}:function(e){return 0|(e.metaKey?1:0)|(e.altKey?2:0)|(e.shiftKey?4:0)|(e.ctrlKey?8:0)};t.getModifierString=function(e){return r.KEY_MODS[u(e)]},t.addCommandKeyListener=function(e,n){var r=t.addListener;if(i.isOldGecko||i.isOpera&&!(\"KeyboardEvent\"in window)){var o=null;r(e,\"keydown\",function(e){o=e.keyCode}),r(e,\"keypress\",function(e){return a(n,e,o)})}else{var u=null;r(e,\"keydown\",function(e){s[e.keyCode]=(s[e.keyCode]||0)+1;var t=a(n,e,e.keyCode);return u=e.defaultPrevented,t}),r(e,\"keypress\",function(e){u&&(e.ctrlKey||e.altKey||e.shiftKey||e.metaKey)&&(t.stopEvent(e),u=null)}),r(e,\"keyup\",function(e){s[e.keyCode]=null}),s||(f(),r(window,\"focus\",f))}};if(typeof window==\"object\"&&window.postMessage&&!i.isOldIE){var l=1;t.nextTick=function(e,n){n=n||window;var r=\"zero-timeout-message-\"+l;t.addListener(n,\"message\",function i(s){s.data==r&&(t.stopPropagation(s),t.removeListener(n,\"message\",i),e())}),n.postMessage(r,\"*\")}}t.nextFrame=typeof window==\"object\"&&(window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame),t.nextFrame?t.nextFrame=t.nextFrame.bind(window):t.nextFrame=function(e){setTimeout(e,17)}}),define(\"ace/lib/lang\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";t.last=function(e){return e[e.length-1]},t.stringReverse=function(e){return e.split(\"\").reverse().join(\"\")},t.stringRepeat=function(e,t){var n=\"\";while(t>0){t&1&&(n+=e);if(t>>=1)e+=e}return n};var r=/^\\s\\s*/,i=/\\s\\s*$/;t.stringTrimLeft=function(e){return e.replace(r,\"\")},t.stringTrimRight=function(e){return e.replace(i,\"\")},t.copyObject=function(e){var t={};for(var n in e)t[n]=e[n];return t},t.copyArray=function(e){var t=[];for(var n=0,r=e.length;n<r;n++)e[n]&&typeof e[n]==\"object\"?t[n]=this.copyObject(e[n]):t[n]=e[n];return t},t.deepCopy=function s(e){if(typeof e!=\"object\"||!e)return e;var t;if(Array.isArray(e)){t=[];for(var n=0;n<e.length;n++)t[n]=s(e[n]);return t}if(Object.prototype.toString.call(e)!==\"[object Object]\")return e;t={};for(var n in e)t[n]=s(e[n]);return t},t.arrayToMap=function(e){var t={};for(var n=0;n<e.length;n++)t[e[n]]=1;return t},t.createMap=function(e){var t=Object.create(null);for(var n in e)t[n]=e[n];return t},t.arrayRemove=function(e,t){for(var n=0;n<=e.length;n++)t===e[n]&&e.splice(n,1)},t.escapeRegExp=function(e){return e.replace(/([.*+?^${}()|[\\]\\/\\\\])/g,\"\\\\$1\")},t.escapeHTML=function(e){return e.replace(/&/g,\"&#38;\").replace(/\"/g,\"&#34;\").replace(/'/g,\"&#39;\").replace(/</g,\"&#60;\")},t.getMatchOffsets=function(e,t){var n=[];return e.replace(t,function(e){n.push({offset:arguments[arguments.length-2],length:e.length})}),n},t.deferredCall=function(e){var t=null,n=function(){t=null,e()},r=function(e){return r.cancel(),t=setTimeout(n,e||0),r};return r.schedule=r,r.call=function(){return this.cancel(),e(),r},r.cancel=function(){return clearTimeout(t),t=null,r},r.isPending=function(){return t},r},t.delayedCall=function(e,t){var n=null,r=function(){n=null,e()},i=function(e){n==null&&(n=setTimeout(r,e||t))};return i.delay=function(e){n&&clearTimeout(n),n=setTimeout(r,e||t)},i.schedule=i,i.call=function(){this.cancel(),e()},i.cancel=function(){n&&clearTimeout(n),n=null},i.isPending=function(){return n},i}}),define(\"ace/keyboard/textinput_ios\",[\"require\",\"exports\",\"module\",\"ace/lib/event\",\"ace/lib/useragent\",\"ace/lib/dom\",\"ace/lib/lang\",\"ace/lib/keys\"],function(e,t,n){\"use strict\";var r=e(\"../lib/event\"),i=e(\"../lib/useragent\"),s=e(\"../lib/dom\"),o=e(\"../lib/lang\"),u=e(\"../lib/keys\"),a=u.KEY_MODS,f=i.isChrome<18,l=i.isIE,c=function(e,t){function x(e){if(m)return;m=!0;if(k)t=0,n=e?0:c.value.length-1;else var t=4,n=5;try{c.setSelectionRange(t,n)}catch(r){}m=!1}function T(){if(m)return;c.value=h,i.isWebKit&&S.schedule()}function R(){clearTimeout(q),q=setTimeout(function(){g&&(c.style.cssText=g,g=\"\"),t.renderer.$keepTextAreaAtCursor==null&&(t.renderer.$keepTextAreaAtCursor=!0,t.renderer.$moveTextAreaToCursor())},0)}var n=this,c=s.createElement(\"textarea\");c.className=i.isIOS?\"ace_text-input ace_text-input-ios\":\"ace_text-input\",i.isTouchPad&&c.setAttribute(\"x-palm-disable-auto-cap\",!0),c.setAttribute(\"wrap\",\"off\"),c.setAttribute(\"autocorrect\",\"off\"),c.setAttribute(\"autocapitalize\",\"off\"),c.setAttribute(\"spellcheck\",!1),c.style.opacity=\"0\",e.insertBefore(c,e.firstChild);var h=\"\\n aaaa a\\n\",p=!1,d=!1,v=!1,m=!1,g=\"\",y=!0;try{var b=document.activeElement===c}catch(w){}r.addListener(c,\"blur\",function(e){t.onBlur(e),b=!1}),r.addListener(c,\"focus\",function(e){b=!0,t.onFocus(e),x()}),this.focus=function(){if(g)return c.focus();c.style.position=\"fixed\",c.focus()},this.blur=function(){c.blur()},this.isFocused=function(){return b};var E=o.delayedCall(function(){b&&x(y)}),S=o.delayedCall(function(){m||(c.value=h,b&&x())});i.isWebKit||t.addEventListener(\"changeSelection\",function(){t.selection.isEmpty()!=y&&(y=!y,E.schedule())}),T(),b&&t.onFocus();var N=function(e){return e.selectionStart===0&&e.selectionEnd===e.value.length},C=function(e){N(c)?(t.selectAll(),x()):k&&x(t.selection.isEmpty())},k=null;this.setInputHandler=function(e){k=e},this.getInputHandler=function(){return k};var L=!1,A=function(e){if(c.selectionStart===4&&c.selectionEnd===5)return;k&&(e=k(e),k=null),v?(x(),e&&t.onPaste(e),v=!1):e==h.substr(0)&&c.selectionStart===4?L?t.execCommand(\"del\",{source:\"ace\"}):t.execCommand(\"backspace\",{source:\"ace\"}):p||(e.substring(0,9)==h&&e.length>h.length?e=e.substr(9):e.substr(0,4)==h.substr(0,4)?e=e.substr(4,e.length-h.length+1):e.charAt(e.length-1)==h.charAt(0)&&(e=e.slice(0,-1)),e!=h.charAt(0)&&e.charAt(e.length-1)==h.charAt(0)&&(e=e.slice(0,-1)),e&&t.onTextInput(e)),p&&(p=!1),L&&(L=!1)},O=function(e){if(m)return;var t=c.value;A(t),T()},M=function(e,t,n){var r=e.clipboardData||window.clipboardData;if(!r||f)return;var i=l||n?\"Text\":\"text/plain\";try{return t?r.setData(i,t)!==!1:r.getData(i)}catch(e){if(!n)return M(e,t,!0)}},_=function(e,n){var s=t.getCopyText();if(!s)return r.preventDefault(e);M(e,s)?(i.isIOS&&(d=n,c.value=\"\\n aa\"+s+\"a a\\n\",c.setSelectionRange(4,4+s.length),p={value:s}),n?t.onCut():t.onCopy(),i.isIOS||r.preventDefault(e)):(p=!0,c.value=s,c.select(),setTimeout(function(){p=!1,T(),x(),n?t.onCut():t.onCopy()}))},D=function(e){_(e,!0)},P=function(e){_(e,!1)},H=function(e){var n=M(e);typeof n==\"string\"?(n&&t.onPaste(n,e),i.isIE&&setTimeout(x),r.preventDefault(e)):(c.value=\"\",v=!0)};r.addCommandKeyListener(c,t.onCommandKey.bind(t)),r.addListener(c,\"select\",C),r.addListener(c,\"input\",O),r.addListener(c,\"cut\",D),r.addListener(c,\"copy\",P),r.addListener(c,\"paste\",H);var B=function(e){if(m||!t.onCompositionStart||t.$readOnly)return;m={},m.canUndo=t.session.$undoManager,t.onCompositionStart(),setTimeout(j,0),t.on(\"mousedown\",F),m.canUndo&&!t.selection.isEmpty()&&(t.insert(\"\"),t.session.markUndoGroup(),t.selection.clearSelection()),t.session.markUndoGroup()},j=function(){if(!m||!t.onCompositionUpdate||t.$readOnly)return;var e=c.value.replace(/\\x01/g,\"\");if(m.lastValue===e)return;t.onCompositionUpdate(e),m.lastValue&&t.undo(),m.canUndo&&(m.lastValue=e);if(m.lastValue){var n=t.selection.getRange();t.insert(m.lastValue),t.session.markUndoGroup(),m.range=t.selection.getRange(),t.selection.setRange(n),t.selection.clearSelection()}},F=function(e){if(!t.onCompositionEnd||t.$readOnly)return;var n=m;m=!1;var r=setTimeout(function(){r=null;var e=c.value.replace(/\\x01/g,\"\");if(m)return;e==n.lastValue?T():!n.lastValue&&e&&(T(),A(e))});k=function(i){return r&&clearTimeout(r),i=i.replace(/\\x01/g,\"\"),i==n.lastValue?\"\":(n.lastValue&&r&&t.undo(),i)},t.onCompositionEnd(),t.removeListener(\"mousedown\",F),e.type==\"compositionend\"&&n.range&&t.selection.setRange(n.range);var s=!!i.isChrome&&i.isChrome>=53||!!i.isWebKit&&i.isWebKit>=603;s&&O()},I=o.delayedCall(j,50);r.addListener(c,\"compositionstart\",B),i.isGecko?r.addListener(c,\"text\",function(){I.schedule()}):(r.addListener(c,\"keyup\",function(){I.schedule()}),r.addListener(c,\"keydown\",function(){I.schedule()})),r.addListener(c,\"compositionend\",F),this.getElement=function(){return c},this.setReadOnly=function(e){c.readOnly=e},this.onContextMenu=function(e){L=!0,x(t.selection.isEmpty()),t._emit(\"nativecontextmenu\",{target:t,domEvent:e}),this.moveToMouse(e,!0)},this.moveToMouse=function(e,n){g||(g=c.style.cssText),c.style.cssText=(n?\"z-index:100000;\":\"\")+\"height:\"+c.style.height+\";\"+(i.isIE?\"opacity:0.1;\":\"\");var o=t.container.getBoundingClientRect(),u=s.computedStyle(t.container),a=o.top+(parseInt(u.borderTopWidth)||0),f=o.left+(parseInt(o.borderLeftWidth)||0),l=o.bottom-a-c.clientHeight-2,h=function(e){c.style.left=e.clientX-f-2+\"px\",c.style.top=Math.min(e.clientY-a-2,l)+\"px\"};h(e);if(e.type!=\"mousedown\")return;t.renderer.$keepTextAreaAtCursor&&(t.renderer.$keepTextAreaAtCursor=null),clearTimeout(q),i.isWin&&r.capture(t.container,h,R)},this.onContextMenuClose=R;var q,U=function(e){t.textInput.onContextMenu(e),R()};r.addListener(c,\"mouseup\",U),r.addListener(c,\"mousedown\",function(e){e.preventDefault(),R()}),r.addListener(t.renderer.scroller,\"contextmenu\",U),r.addListener(c,\"contextmenu\",U);if(i.isIOS){var z=null,W=!1;e.addEventListener(\"keydown\",function(e){z&&clearTimeout(z),W=!0}),e.addEventListener(\"keyup\",function(e){z=setTimeout(function(){W=!1},100)});var X=function(e){if(document.activeElement!==c)return;if(W)return;if(d)return setTimeout(function(){d=!1},100);var n=c.selectionStart,r=c.selectionEnd;c.setSelectionRange(4,5);if(n==r)switch(n){case 0:t.onCommandKey(null,0,u.up);break;case 1:t.onCommandKey(null,0,u.home);break;case 2:t.onCommandKey(null,a.option,u.left);break;case 4:t.onCommandKey(null,0,u.left);break;case 5:t.onCommandKey(null,0,u.right);break;case 7:t.onCommandKey(null,a.option,u.right);break;case 8:t.onCommandKey(null,0,u.end);break;case 9:t.onCommandKey(null,0,u.down)}else{switch(r){case 6:t.onCommandKey(null,a.shift,u.right);break;case 7:t.onCommandKey(null,a.shift|a.option,u.right);break;case 8:t.onCommandKey(null,a.shift,u.end);break;case 9:t.onCommandKey(null,a.shift,u.down)}switch(n){case 0:t.onCommandKey(null,a.shift,u.up);break;case 1:t.onCommandKey(null,a.shift,u.home);break;case 2:t.onCommandKey(null,a.shift|a.option,u.left);break;case 3:t.onCommandKey(null,a.shift,u.left)}}};document.addEventListener(\"selectionchange\",X),t.on(\"destroy\",function(){document.removeEventListener(\"selectionchange\",X)})}};t.TextInput=c}),define(\"ace/keyboard/textinput\",[\"require\",\"exports\",\"module\",\"ace/lib/event\",\"ace/lib/useragent\",\"ace/lib/dom\",\"ace/lib/lang\",\"ace/keyboard/textinput_ios\"],function(e,t,n){\"use strict\";var r=e(\"../lib/event\"),i=e(\"../lib/useragent\"),s=e(\"../lib/dom\"),o=e(\"../lib/lang\"),u=i.isChrome<18,a=i.isIE,f=e(\"./textinput_ios\").TextInput,l=function(e,t){function w(e){if(p)return;p=!0;if(T)t=0,r=e?0:n.value.length-1;else var t=e?2:1,r=2;try{n.setSelectionRange(t,r)}catch(i){}p=!1}function E(){if(p)return;n.value=l,i.isWebKit&&b.schedule()}function F(){clearTimeout(j),j=setTimeout(function(){d&&(n.style.cssText=d,d=\"\"),t.renderer.$keepTextAreaAtCursor==null&&(t.renderer.$keepTextAreaAtCursor=!0,t.renderer.$moveTextAreaToCursor())},0)}if(i.isIOS)return f.call(this,e,t);var n=s.createElement(\"textarea\");n.className=\"ace_text-input\",n.setAttribute(\"wrap\",\"off\"),n.setAttribute(\"autocorrect\",\"off\"),n.setAttribute(\"autocapitalize\",\"off\"),n.setAttribute(\"spellcheck\",!1),n.style.opacity=\"0\",e.insertBefore(n,e.firstChild);var l=\"\\u2028\\u2028\",c=!1,h=!1,p=!1,d=\"\",v=!0;try{var m=document.activeElement===n}catch(g){}r.addListener(n,\"blur\",function(e){t.onBlur(e),m=!1}),r.addListener(n,\"focus\",function(e){m=!0,t.onFocus(e),w()}),this.focus=function(){if(d)return n.focus();var e=n.style.top;n.style.position=\"fixed\",n.style.top=\"0px\",n.focus(),setTimeout(function(){n.style.position=\"\",n.style.top==\"0px\"&&(n.style.top=e)},0)},this.blur=function(){n.blur()},this.isFocused=function(){return m};var y=o.delayedCall(function(){m&&w(v)}),b=o.delayedCall(function(){p||(n.value=l,m&&w())});i.isWebKit||t.addEventListener(\"changeSelection\",function(){t.selection.isEmpty()!=v&&(v=!v,y.schedule())}),E(),m&&t.onFocus();var S=function(e){return e.selectionStart===0&&e.selectionEnd===e.value.length},x=function(e){c?c=!1:S(n)?(t.selectAll(),w()):T&&w(t.selection.isEmpty())},T=null;this.setInputHandler=function(e){T=e},this.getInputHandler=function(){return T};var N=!1,C=function(e){T&&(e=T(e),T=null),h?(w(),e&&t.onPaste(e),h=!1):e==l.charAt(0)?N?t.execCommand(\"del\",{source:\"ace\"}):t.execCommand(\"backspace\",{source:\"ace\"}):(e.substring(0,2)==l?e=e.substr(2):e.charAt(0)==l.charAt(0)?e=e.substr(1):e.charAt(e.length-1)==l.charAt(0)&&(e=e.slice(0,-1)),e.charAt(e.length-1)==l.charAt(0)&&(e=e.slice(0,-1)),e&&t.onTextInput(e)),N&&(N=!1)},k=function(e){if(p)return;var t=n.value;C(t),E()},L=function(e,t,n){var r=e.clipboardData||window.clipboardData;if(!r||u)return;var i=a||n?\"Text\":\"text/plain\";try{return t?r.setData(i,t)!==!1:r.getData(i)}catch(e){if(!n)return L(e,t,!0)}},A=function(e,i){var s=t.getCopyText();if(!s)return r.preventDefault(e);L(e,s)?(i?t.onCut():t.onCopy(),r.preventDefault(e)):(c=!0,n.value=s,n.select(),setTimeout(function(){c=!1,E(),w(),i?t.onCut():t.onCopy()}))},O=function(e){A(e,!0)},M=function(e){A(e,!1)},_=function(e){var s=L(e);typeof s==\"string\"?(s&&t.onPaste(s,e),i.isIE&&setTimeout(w),r.preventDefault(e)):(n.value=\"\",h=!0)};r.addCommandKeyListener(n,t.onCommandKey.bind(t)),r.addListener(n,\"select\",x),r.addListener(n,\"input\",k),r.addListener(n,\"cut\",O),r.addListener(n,\"copy\",M),r.addListener(n,\"paste\",_),(!(\"oncut\"in n)||!(\"oncopy\"in n)||!(\"onpaste\"in n))&&r.addListener(e,\"keydown\",function(e){if(i.isMac&&!e.metaKey||!e.ctrlKey)return;switch(e.keyCode){case 67:M(e);break;case 86:_(e);break;case 88:O(e)}});var D=function(e){if(p||!t.onCompositionStart||t.$readOnly)return;p={},p.canUndo=t.session.$undoManager,t.onCompositionStart(),setTimeout(P,0),t.on(\"mousedown\",H),p.canUndo&&!t.selection.isEmpty()&&(t.insert(\"\"),t.session.markUndoGroup(),t.selection.clearSelection()),t.session.markUndoGroup()},P=function(){if(!p||!t.onCompositionUpdate||t.$readOnly)return;var e=n.value.replace(/\\u2028/g,\"\");if(p.lastValue===e)return;t.onCompositionUpdate(e),p.lastValue&&t.undo(),p.canUndo&&(p.lastValue=e);if(p.lastValue){var r=t.selection.getRange();t.insert(p.lastValue),t.session.markUndoGroup(),p.range=t.selection.getRange(),t.selection.setRange(r),t.selection.clearSelection()}},H=function(e){if(!t.onCompositionEnd||t.$readOnly)return;var r=p;p=!1;var s=setTimeout(function(){s=null;var e=n.value.replace(/\\u2028/g,\"\");if(p)return;e==r.lastValue?E():!r.lastValue&&e&&(E(),C(e))});T=function(n){return s&&clearTimeout(s),n=n.replace(/\\u2028/g,\"\"),n==r.lastValue?\"\":(r.lastValue&&s&&t.undo(),n)},t.onCompositionEnd(),t.removeListener(\"mousedown\",H),e.type==\"compositionend\"&&r.range&&t.selection.setRange(r.range);var o=!!i.isChrome&&i.isChrome>=53||!!i.isWebKit&&i.isWebKit>=603;o&&k()},B=o.delayedCall(P,50);r.addListener(n,\"compositionstart\",D),i.isGecko?r.addListener(n,\"text\",function(){B.schedule()}):(r.addListener(n,\"keyup\",function(){B.schedule()}),r.addListener(n,\"keydown\",function(){B.schedule()})),r.addListener(n,\"compositionend\",H),this.getElement=function(){return n},this.setReadOnly=function(e){n.readOnly=e},this.onContextMenu=function(e){N=!0,w(t.selection.isEmpty()),t._emit(\"nativecontextmenu\",{target:t,domEvent:e}),this.moveToMouse(e,!0)},this.moveToMouse=function(e,o){d||(d=n.style.cssText),n.style.cssText=(o?\"z-index:100000;\":\"\")+\"height:\"+n.style.height+\";\"+(i.isIE?\"opacity:0.1;\":\"\");var u=t.container.getBoundingClientRect(),a=s.computedStyle(t.container),f=u.top+(parseInt(a.borderTopWidth)||0),l=u.left+(parseInt(u.borderLeftWidth)||0),c=u.bottom-f-n.clientHeight-2,h=function(e){n.style.left=e.clientX-l-2+\"px\",n.style.top=Math.min(e.clientY-f-2,c)+\"px\"};h(e);if(e.type!=\"mousedown\")return;t.renderer.$keepTextAreaAtCursor&&(t.renderer.$keepTextAreaAtCursor=null),clearTimeout(j),i.isWin&&r.capture(t.container,h,F)},this.onContextMenuClose=F;var j,I=function(e){t.textInput.onContextMenu(e),F()};r.addListener(n,\"mouseup\",I),r.addListener(n,\"mousedown\",function(e){e.preventDefault(),F()}),r.addListener(t.renderer.scroller,\"contextmenu\",I),r.addListener(n,\"contextmenu\",I)};t.TextInput=l}),define(\"ace/mouse/default_handlers\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/lib/event\",\"ace/lib/useragent\"],function(e,t,n){\"use strict\";function u(e){e.$clickSelection=null;var t=e.editor;t.setDefaultHandler(\"mousedown\",this.onMouseDown.bind(e)),t.setDefaultHandler(\"dblclick\",this.onDoubleClick.bind(e)),t.setDefaultHandler(\"tripleclick\",this.onTripleClick.bind(e)),t.setDefaultHandler(\"quadclick\",this.onQuadClick.bind(e)),t.setDefaultHandler(\"mousewheel\",this.onMouseWheel.bind(e)),t.setDefaultHandler(\"touchmove\",this.onTouchMove.bind(e));var n=[\"select\",\"startSelect\",\"selectEnd\",\"selectAllEnd\",\"selectByWordsEnd\",\"selectByLinesEnd\",\"dragWait\",\"dragWaitEnd\",\"focusWait\"];n.forEach(function(t){e[t]=this[t]},this),e.selectByLines=this.extendSelectionBy.bind(e,\"getLineRange\"),e.selectByWords=this.extendSelectionBy.bind(e,\"getWordRange\")}function a(e,t,n,r){return Math.sqrt(Math.pow(n-e,2)+Math.pow(r-t,2))}function f(e,t){if(e.start.row==e.end.row)var n=2*t.column-e.start.column-e.end.column;else if(e.start.row==e.end.row-1&&!e.start.column&&!e.end.column)var n=t.column-4;else var n=2*t.row-e.start.row-e.end.row;return n<0?{cursor:e.start,anchor:e.end}:{cursor:e.end,anchor:e.start}}var r=e(\"../lib/dom\"),i=e(\"../lib/event\"),s=e(\"../lib/useragent\"),o=0;(function(){this.onMouseDown=function(e){var t=e.inSelection(),n=e.getDocumentPosition();this.mousedownEvent=e;var r=this.editor,i=e.getButton();if(i!==0){var o=r.getSelectionRange(),u=o.isEmpty();r.$blockScrolling++,(u||i==1)&&r.selection.moveToPosition(n),r.$blockScrolling--,i==2&&(r.textInput.onContextMenu(e.domEvent),s.isMozilla||e.preventDefault());return}this.mousedownEvent.time=Date.now();if(t&&!r.isFocused()){r.focus();if(this.$focusTimout&&!this.$clickSelection&&!r.inMultiSelectMode){this.setState(\"focusWait\"),this.captureMouse(e);return}}return this.captureMouse(e),this.startSelect(n,e.domEvent._clicks>1),e.preventDefault()},this.startSelect=function(e,t){e=e||this.editor.renderer.screenToTextCoordinates(this.x,this.y);var n=this.editor;n.$blockScrolling++,this.mousedownEvent.getShiftKey()?n.selection.selectToPosition(e):t||n.selection.moveToPosition(e),t||this.select(),n.renderer.scroller.setCapture&&n.renderer.scroller.setCapture(),n.setStyle(\"ace_selecting\"),this.setState(\"select\"),n.$blockScrolling--},this.select=function(){var e,t=this.editor,n=t.renderer.screenToTextCoordinates(this.x,this.y);t.$blockScrolling++;if(this.$clickSelection){var r=this.$clickSelection.comparePoint(n);if(r==-1)e=this.$clickSelection.end;else if(r==1)e=this.$clickSelection.start;else{var i=f(this.$clickSelection,n);n=i.cursor,e=i.anchor}t.selection.setSelectionAnchor(e.row,e.column)}t.selection.selectToPosition(n),t.$blockScrolling--,t.renderer.scrollCursorIntoView()},this.extendSelectionBy=function(e){var t,n=this.editor,r=n.renderer.screenToTextCoordinates(this.x,this.y),i=n.selection[e](r.row,r.column);n.$blockScrolling++;if(this.$clickSelection){var s=this.$clickSelection.comparePoint(i.start),o=this.$clickSelection.comparePoint(i.end);if(s==-1&&o<=0){t=this.$clickSelection.end;if(i.end.row!=r.row||i.end.column!=r.column)r=i.start}else if(o==1&&s>=0){t=this.$clickSelection.start;if(i.start.row!=r.row||i.start.column!=r.column)r=i.end}else if(s==-1&&o==1)r=i.end,t=i.start;else{var u=f(this.$clickSelection,r);r=u.cursor,t=u.anchor}n.selection.setSelectionAnchor(t.row,t.column)}n.selection.selectToPosition(r),n.$blockScrolling--,n.renderer.scrollCursorIntoView()},this.selectEnd=this.selectAllEnd=this.selectByWordsEnd=this.selectByLinesEnd=function(){this.$clickSelection=null,this.editor.unsetStyle(\"ace_selecting\"),this.editor.renderer.scroller.releaseCapture&&this.editor.renderer.scroller.releaseCapture()},this.focusWait=function(){var e=a(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y),t=Date.now();(e>o||t-this.mousedownEvent.time>this.$focusTimout)&&this.startSelect(this.mousedownEvent.getDocumentPosition())},this.onDoubleClick=function(e){var t=e.getDocumentPosition(),n=this.editor,r=n.session,i=r.getBracketRange(t);i?(i.isEmpty()&&(i.start.column--,i.end.column++),this.setState(\"select\")):(i=n.selection.getWordRange(t.row,t.column),this.setState(\"selectByWords\")),this.$clickSelection=i,this.select()},this.onTripleClick=function(e){var t=e.getDocumentPosition(),n=this.editor;this.setState(\"selectByLines\");var r=n.getSelectionRange();r.isMultiLine()&&r.contains(t.row,t.column)?(this.$clickSelection=n.selection.getLineRange(r.start.row),this.$clickSelection.end=n.selection.getLineRange(r.end.row).end):this.$clickSelection=n.selection.getLineRange(t.row),this.select()},this.onQuadClick=function(e){var t=this.editor;t.selectAll(),this.$clickSelection=t.getSelectionRange(),this.setState(\"selectAll\")},this.onMouseWheel=function(e){if(e.getAccelKey())return;e.getShiftKey()&&e.wheelY&&!e.wheelX&&(e.wheelX=e.wheelY,e.wheelY=0);var t=e.domEvent.timeStamp,n=t-(this.$lastScrollTime||0),r=this.editor,i=r.renderer.isScrollableBy(e.wheelX*e.speed,e.wheelY*e.speed);if(i||n<200)return this.$lastScrollTime=t,r.renderer.scrollBy(e.wheelX*e.speed,e.wheelY*e.speed),e.stop()},this.onTouchMove=function(e){var t=e.domEvent.timeStamp,n=t-(this.$lastScrollTime||0),r=this.editor,i=r.renderer.isScrollableBy(e.wheelX*e.speed,e.wheelY*e.speed);if(i||n<200)return this.$lastScrollTime=t,r.renderer.scrollBy(e.wheelX*e.speed,e.wheelY*e.speed),e.stop()}}).call(u.prototype),t.DefaultHandlers=u}),define(\"ace/tooltip\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\"],function(e,t,n){\"use strict\";function s(e){this.isOpen=!1,this.$element=null,this.$parentNode=e}var r=e(\"./lib/oop\"),i=e(\"./lib/dom\");(function(){this.$init=function(){return this.$element=i.createElement(\"div\"),this.$element.className=\"ace_tooltip\",this.$element.style.display=\"none\",this.$parentNode.appendChild(this.$element),this.$element},this.getElement=function(){return this.$element||this.$init()},this.setText=function(e){i.setInnerText(this.getElement(),e)},this.setHtml=function(e){this.getElement().innerHTML=e},this.setPosition=function(e,t){this.getElement().style.left=e+\"px\",this.getElement().style.top=t+\"px\"},this.setClassName=function(e){i.addCssClass(this.getElement(),e)},this.show=function(e,t,n){e!=null&&this.setText(e),t!=null&&n!=null&&this.setPosition(t,n),this.isOpen||(this.getElement().style.display=\"block\",this.isOpen=!0)},this.hide=function(){this.isOpen&&(this.getElement().style.display=\"none\",this.isOpen=!1)},this.getHeight=function(){return this.getElement().offsetHeight},this.getWidth=function(){return this.getElement().offsetWidth},this.destroy=function(){this.isOpen=!1,this.$element&&this.$element.parentNode&&this.$element.parentNode.removeChild(this.$element)}}).call(s.prototype),t.Tooltip=s}),define(\"ace/mouse/default_gutter_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/lib/oop\",\"ace/lib/event\",\"ace/tooltip\"],function(e,t,n){\"use strict\";function u(e){function l(){var r=u.getDocumentPosition().row,s=n.$annotations[r];if(!s)return c();var o=t.session.getLength();if(r==o){var a=t.renderer.pixelToScreenCoordinates(0,u.y).row,l=u.$pos;if(a>t.session.documentToScreenRow(l.row,l.column))return c()}if(f==s)return;f=s.text.join(\"<br/>\"),i.setHtml(f),i.show(),t._signal(\"showGutterTooltip\",i),t.on(\"mousewheel\",c);if(e.$tooltipFollowsMouse)h(u);else{var p=u.domEvent.target,d=p.getBoundingClientRect(),v=i.getElement().style;v.left=d.right+\"px\",v.top=d.bottom+\"px\"}}function c(){o&&(o=clearTimeout(o)),f&&(i.hide(),f=null,t._signal(\"hideGutterTooltip\",i),t.removeEventListener(\"mousewheel\",c))}function h(e){i.setPosition(e.x,e.y)}var t=e.editor,n=t.renderer.$gutterLayer,i=new a(t.container);e.editor.setDefaultHandler(\"guttermousedown\",function(r){if(!t.isFocused()||r.getButton()!=0)return;var i=n.getRegion(r);if(i==\"foldWidgets\")return;var s=r.getDocumentPosition().row,o=t.session.selection;if(r.getShiftKey())o.selectTo(s,0);else{if(r.domEvent.detail==2)return t.selectAll(),r.preventDefault();e.$clickSelection=t.selection.getLineRange(s)}return e.setState(\"selectByLines\"),e.captureMouse(r),r.preventDefault()});var o,u,f;e.editor.setDefaultHandler(\"guttermousemove\",function(t){var n=t.domEvent.target||t.domEvent.srcElement;if(r.hasCssClass(n,\"ace_fold-widget\"))return c();f&&e.$tooltipFollowsMouse&&h(t),u=t;if(o)return;o=setTimeout(function(){o=null,u&&!e.isMousePressed?l():c()},50)}),s.addListener(t.renderer.$gutter,\"mouseout\",function(e){u=null;if(!f||o)return;o=setTimeout(function(){o=null,c()},50)}),t.on(\"changeSession\",c)}function a(e){o.call(this,e)}var r=e(\"../lib/dom\"),i=e(\"../lib/oop\"),s=e(\"../lib/event\"),o=e(\"../tooltip\").Tooltip;i.inherits(a,o),function(){this.setPosition=function(e,t){var n=window.innerWidth||document.documentElement.clientWidth,r=window.innerHeight||document.documentElement.clientHeight,i=this.getWidth(),s=this.getHeight();e+=15,t+=15,e+i>n&&(e-=e+i-n),t+s>r&&(t-=20+s),o.prototype.setPosition.call(this,e,t)}}.call(a.prototype),t.GutterHandler=u}),define(\"ace/mouse/mouse_event\",[\"require\",\"exports\",\"module\",\"ace/lib/event\",\"ace/lib/useragent\"],function(e,t,n){\"use strict\";var r=e(\"../lib/event\"),i=e(\"../lib/useragent\"),s=t.MouseEvent=function(e,t){this.domEvent=e,this.editor=t,this.x=this.clientX=e.clientX,this.y=this.clientY=e.clientY,this.$pos=null,this.$inSelection=null,this.propagationStopped=!1,this.defaultPrevented=!1};(function(){this.stopPropagation=function(){r.stopPropagation(this.domEvent),this.propagationStopped=!0},this.preventDefault=function(){r.preventDefault(this.domEvent),this.defaultPrevented=!0},this.stop=function(){this.stopPropagation(),this.preventDefault()},this.getDocumentPosition=function(){return this.$pos?this.$pos:(this.$pos=this.editor.renderer.screenToTextCoordinates(this.clientX,this.clientY),this.$pos)},this.inSelection=function(){if(this.$inSelection!==null)return this.$inSelection;var e=this.editor,t=e.getSelectionRange();if(t.isEmpty())this.$inSelection=!1;else{var n=this.getDocumentPosition();this.$inSelection=t.contains(n.row,n.column)}return this.$inSelection},this.getButton=function(){return r.getButton(this.domEvent)},this.getShiftKey=function(){return this.domEvent.shiftKey},this.getAccelKey=i.isMac?function(){return this.domEvent.metaKey}:function(){return this.domEvent.ctrlKey}}).call(s.prototype)}),define(\"ace/mouse/dragdrop_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/lib/event\",\"ace/lib/useragent\"],function(e,t,n){\"use strict\";function f(e){function T(e,n){var r=Date.now(),i=!n||e.row!=n.row,s=!n||e.column!=n.column;if(!S||i||s)t.$blockScrolling+=1,t.moveCursorToPosition(e),t.$blockScrolling-=1,S=r,x={x:p,y:d};else{var o=l(x.x,x.y,p,d);o>a?S=null:r-S>=u&&(t.renderer.scrollCursorIntoView(),S=null)}}function N(e,n){var r=Date.now(),i=t.renderer.layerConfig.lineHeight,s=t.renderer.layerConfig.characterWidth,u=t.renderer.scroller.getBoundingClientRect(),a={x:{left:p-u.left,right:u.right-p},y:{top:d-u.top,bottom:u.bottom-d}},f=Math.min(a.x.left,a.x.right),l=Math.min(a.y.top,a.y.bottom),c={row:e.row,column:e.column};f/s<=2&&(c.column+=a.x.left<a.x.right?-3:2),l/i<=1&&(c.row+=a.y.top<a.y.bottom?-1:1);var h=e.row!=c.row,v=e.column!=c.column,m=!n||e.row!=n.row;h||v&&!m?E?r-E>=o&&t.renderer.scrollCursorIntoView(c):E=r:E=null}function C(){var e=g;g=t.renderer.screenToTextCoordinates(p,d),T(g,e),N(g,e)}function k(){m=t.selection.toOrientedRange(),h=t.session.addMarker(m,\"ace_selection\",t.getSelectionStyle()),t.clearSelection(),t.isFocused()&&t.renderer.$cursorLayer.setBlinking(!1),clearInterval(v),C(),v=setInterval(C,20),y=0,i.addListener(document,\"mousemove\",O)}function L(){clearInterval(v),t.session.removeMarker(h),h=null,t.$blockScrolling+=1,t.selection.fromOrientedRange(m),t.$blockScrolling-=1,t.isFocused()&&!w&&t.renderer.$cursorLayer.setBlinking(!t.getReadOnly()),m=null,g=null,y=0,E=null,S=null,i.removeListener(document,\"mousemove\",O)}function O(){A==null&&(A=setTimeout(function(){A!=null&&h&&L()},20))}function M(e){var t=e.types;return!t||Array.prototype.some.call(t,function(e){return e==\"text/plain\"||e==\"Text\"})}function _(e){var t=[\"copy\",\"copymove\",\"all\",\"uninitialized\"],n=[\"move\",\"copymove\",\"linkmove\",\"all\",\"uninitialized\"],r=s.isMac?e.altKey:e.ctrlKey,i=\"uninitialized\";try{i=e.dataTransfer.effectAllowed.toLowerCase()}catch(e){}var o=\"none\";return r&&t.indexOf(i)>=0?o=\"copy\":n.indexOf(i)>=0?o=\"move\":t.indexOf(i)>=0&&(o=\"copy\"),o}var t=e.editor,n=r.createElement(\"img\");n.src=\"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\",s.isOpera&&(n.style.cssText=\"width:1px;height:1px;position:fixed;top:0;left:0;z-index:2147483647;opacity:0;\");var f=[\"dragWait\",\"dragWaitEnd\",\"startDrag\",\"dragReadyEnd\",\"onMouseDrag\"];f.forEach(function(t){e[t]=this[t]},this),t.addEventListener(\"mousedown\",this.onMouseDown.bind(e));var c=t.container,h,p,d,v,m,g,y=0,b,w,E,S,x;this.onDragStart=function(e){if(this.cancelDrag||!c.draggable){var r=this;return setTimeout(function(){r.startSelect(),r.captureMouse(e)},0),e.preventDefault()}m=t.getSelectionRange();var i=e.dataTransfer;i.effectAllowed=t.getReadOnly()?\"copy\":\"copyMove\",s.isOpera&&(t.container.appendChild(n),n.scrollTop=0),i.setDragImage&&i.setDragImage(n,0,0),s.isOpera&&t.container.removeChild(n),i.clearData(),i.setData(\"Text\",t.session.getTextRange()),w=!0,this.setState(\"drag\")},this.onDragEnd=function(e){c.draggable=!1,w=!1,this.setState(null);if(!t.getReadOnly()){var n=e.dataTransfer.dropEffect;!b&&n==\"move\"&&t.session.remove(t.getSelectionRange()),t.renderer.$cursorLayer.setBlinking(!0)}this.editor.unsetStyle(\"ace_dragging\"),this.editor.renderer.setCursorStyle(\"\")},this.onDragEnter=function(e){if(t.getReadOnly()||!M(e.dataTransfer))return;return p=e.clientX,d=e.clientY,h||k(),y++,e.dataTransfer.dropEffect=b=_(e),i.preventDefault(e)},this.onDragOver=function(e){if(t.getReadOnly()||!M(e.dataTransfer))return;return p=e.clientX,d=e.clientY,h||(k(),y++),A!==null&&(A=null),e.dataTransfer.dropEffect=b=_(e),i.preventDefault(e)},this.onDragLeave=function(e){y--;if(y<=0&&h)return L(),b=null,i.preventDefault(e)},this.onDrop=function(e){if(!g)return;var n=e.dataTransfer;if(w)switch(b){case\"move\":m.contains(g.row,g.column)?m={start:g,end:g}:m=t.moveText(m,g);break;case\"copy\":m=t.moveText(m,g,!0)}else{var r=n.getData(\"Text\");m={start:g,end:t.session.insert(g,r)},t.focus(),b=null}return L(),i.preventDefault(e)},i.addListener(c,\"dragstart\",this.onDragStart.bind(e)),i.addListener(c,\"dragend\",this.onDragEnd.bind(e)),i.addListener(c,\"dragenter\",this.onDragEnter.bind(e)),i.addListener(c,\"dragover\",this.onDragOver.bind(e)),i.addListener(c,\"dragleave\",this.onDragLeave.bind(e)),i.addListener(c,\"drop\",this.onDrop.bind(e));var A=null}function l(e,t,n,r){return Math.sqrt(Math.pow(n-e,2)+Math.pow(r-t,2))}var r=e(\"../lib/dom\"),i=e(\"../lib/event\"),s=e(\"../lib/useragent\"),o=200,u=200,a=5;(function(){this.dragWait=function(){var e=Date.now()-this.mousedownEvent.time;e>this.editor.getDragDelay()&&this.startDrag()},this.dragWaitEnd=function(){var e=this.editor.container;e.draggable=!1,this.startSelect(this.mousedownEvent.getDocumentPosition()),this.selectEnd()},this.dragReadyEnd=function(e){this.editor.renderer.$cursorLayer.setBlinking(!this.editor.getReadOnly()),this.editor.unsetStyle(\"ace_dragging\"),this.editor.renderer.setCursorStyle(\"\"),this.dragWaitEnd()},this.startDrag=function(){this.cancelDrag=!1;var e=this.editor,t=e.container;t.draggable=!0,e.renderer.$cursorLayer.setBlinking(!1),e.setStyle(\"ace_dragging\");var n=s.isWin?\"default\":\"move\";e.renderer.setCursorStyle(n),this.setState(\"dragReady\")},this.onMouseDrag=function(e){var t=this.editor.container;if(s.isIE&&this.state==\"dragReady\"){var n=l(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y);n>3&&t.dragDrop()}if(this.state===\"dragWait\"){var n=l(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y);n>0&&(t.draggable=!1,this.startSelect(this.mousedownEvent.getDocumentPosition()))}},this.onMouseDown=function(e){if(!this.$dragEnabled)return;this.mousedownEvent=e;var t=this.editor,n=e.inSelection(),r=e.getButton(),i=e.domEvent.detail||1;if(i===1&&r===0&&n){if(e.editor.inMultiSelectMode&&(e.getAccelKey()||e.getShiftKey()))return;this.mousedownEvent.time=Date.now();var o=e.domEvent.target||e.domEvent.srcElement;\"unselectable\"in o&&(o.unselectable=\"on\");if(t.getDragDelay()){if(s.isWebKit){this.cancelDrag=!0;var u=t.container;u.draggable=!0}this.setState(\"dragWait\")}else this.startDrag();this.captureMouse(e,this.onMouseDrag.bind(this)),e.defaultPrevented=!0}}}).call(f.prototype),t.DragdropHandler=f}),define(\"ace/lib/net\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\"],function(e,t,n){\"use strict\";var r=e(\"./dom\");t.get=function(e,t){var n=new XMLHttpRequest;n.open(\"GET\",e,!0),n.onreadystatechange=function(){n.readyState===4&&t(n.responseText)},n.send(null)},t.loadScript=function(e,t){var n=r.getDocumentHead(),i=document.createElement(\"script\");i.src=e,n.appendChild(i),i.onload=i.onreadystatechange=function(e,n){if(n||!i.readyState||i.readyState==\"loaded\"||i.readyState==\"complete\")i=i.onload=i.onreadystatechange=null,n||t()}},t.qualifyURL=function(e){var t=document.createElement(\"a\");return t.href=e,t.href}}),define(\"ace/lib/event_emitter\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";var r={},i=function(){this.propagationStopped=!0},s=function(){this.defaultPrevented=!0};r._emit=r._dispatchEvent=function(e,t){this._eventRegistry||(this._eventRegistry={}),this._defaultHandlers||(this._defaultHandlers={});var n=this._eventRegistry[e]||[],r=this._defaultHandlers[e];if(!n.length&&!r)return;if(typeof t!=\"object\"||!t)t={};t.type||(t.type=e),t.stopPropagation||(t.stopPropagation=i),t.preventDefault||(t.preventDefault=s),n=n.slice();for(var o=0;o<n.length;o++){n[o](t,this);if(t.propagationStopped)break}if(r&&!t.defaultPrevented)return r(t,this)},r._signal=function(e,t){var n=(this._eventRegistry||{})[e];if(!n)return;n=n.slice();for(var r=0;r<n.length;r++)n[r](t,this)},r.once=function(e,t){var n=this;t&&this.addEventListener(e,function r(){n.removeEventListener(e,r),t.apply(null,arguments)})},r.setDefaultHandler=function(e,t){var n=this._defaultHandlers;n||(n=this._defaultHandlers={_disabled_:{}});if(n[e]){var r=n[e],i=n._disabled_[e];i||(n._disabled_[e]=i=[]),i.push(r);var s=i.indexOf(t);s!=-1&&i.splice(s,1)}n[e]=t},r.removeDefaultHandler=function(e,t){var n=this._defaultHandlers;if(!n)return;var r=n._disabled_[e];if(n[e]==t){var i=n[e];r&&this.setDefaultHandler(e,r.pop())}else if(r){var s=r.indexOf(t);s!=-1&&r.splice(s,1)}},r.on=r.addEventListener=function(e,t,n){this._eventRegistry=this._eventRegistry||{};var r=this._eventRegistry[e];return r||(r=this._eventRegistry[e]=[]),r.indexOf(t)==-1&&r[n?\"unshift\":\"push\"](t),t},r.off=r.removeListener=r.removeEventListener=function(e,t){this._eventRegistry=this._eventRegistry||{};var n=this._eventRegistry[e];if(!n)return;var r=n.indexOf(t);r!==-1&&n.splice(r,1)},r.removeAllListeners=function(e){this._eventRegistry&&(this._eventRegistry[e]=[])},t.EventEmitter=r}),define(\"ace/lib/app_config\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\"],function(e,t,n){\"no use strict\";function o(e){typeof console!=\"undefined\"&&console.warn&&console.warn.apply(console,arguments)}function u(e,t){var n=new Error(e);n.data=t,typeof console==\"object\"&&console.error&&console.error(n),setTimeout(function(){throw n})}var r=e(\"./oop\"),i=e(\"./event_emitter\").EventEmitter,s={setOptions:function(e){Object.keys(e).forEach(function(t){this.setOption(t,e[t])},this)},getOptions:function(e){var t={};return e?Array.isArray(e)||(t=e,e=Object.keys(t)):e=Object.keys(this.$options),e.forEach(function(e){t[e]=this.getOption(e)},this),t},setOption:function(e,t){if(this[\"$\"+e]===t)return;var n=this.$options[e];if(!n)return o('misspelled option \"'+e+'\"');if(n.forwardTo)return this[n.forwardTo]&&this[n.forwardTo].setOption(e,t);n.handlesSet||(this[\"$\"+e]=t),n&&n.set&&n.set.call(this,t)},getOption:function(e){var t=this.$options[e];return t?t.forwardTo?this[t.forwardTo]&&this[t.forwardTo].getOption(e):t&&t.get?t.get.call(this):this[\"$\"+e]:o('misspelled option \"'+e+'\"')}},a=function(){this.$defaultOptions={}};(function(){r.implement(this,i),this.defineOptions=function(e,t,n){return e.$options||(this.$defaultOptions[t]=e.$options={}),Object.keys(n).forEach(function(t){var r=n[t];typeof r==\"string\"&&(r={forwardTo:r}),r.name||(r.name=t),e.$options[r.name]=r,\"initialValue\"in r&&(e[\"$\"+r.name]=r.initialValue)}),r.implement(e,s),this},this.resetOptions=function(e){Object.keys(e.$options).forEach(function(t){var n=e.$options[t];\"value\"in n&&e.setOption(t,n.value)})},this.setDefaultValue=function(e,t,n){var r=this.$defaultOptions[e]||(this.$defaultOptions[e]={});r[t]&&(r.forwardTo?this.setDefaultValue(r.forwardTo,t,n):r[t].value=n)},this.setDefaultValues=function(e,t){Object.keys(t).forEach(function(n){this.setDefaultValue(e,n,t[n])},this)},this.warn=o,this.reportError=u}).call(a.prototype),t.AppConfig=a}),define(\"ace/config\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\",\"ace/lib/oop\",\"ace/lib/net\",\"ace/lib/app_config\"],function(e,t,n){\"no use strict\";function f(r){if(!u||!u.document)return;a.packaged=r||e.packaged||n.packaged||u.define&&define.packaged;var i={},s=\"\",o=document.currentScript||document._currentScript,f=o&&o.ownerDocument||document,c=f.getElementsByTagName(\"script\");for(var h=0;h<c.length;h++){var p=c[h],d=p.src||p.getAttribute(\"src\");if(!d)continue;var v=p.attributes;for(var m=0,g=v.length;m<g;m++){var y=v[m];y.name.indexOf(\"data-ace-\")===0&&(i[l(y.name.replace(/^data-ace-/,\"\"))]=y.value)}var b=d.match(/^(.*)\\/ace(\\-\\w+)?\\.js(\\?|$)/);b&&(s=b[1])}s&&(i.base=i.base||s,i.packaged=!0),i.basePath=i.base,i.workerPath=i.workerPath||i.base,i.modePath=i.modePath||i.base,i.themePath=i.themePath||i.base,delete i.base;for(var w in i)typeof i[w]!=\"undefined\"&&t.set(w,i[w])}function l(e){return e.replace(/-(.)/g,function(e,t){return t.toUpperCase()})}var r=e(\"./lib/lang\"),i=e(\"./lib/oop\"),s=e(\"./lib/net\"),o=e(\"./lib/app_config\").AppConfig;n.exports=t=new o;var u=function(){return this||typeof window!=\"undefined\"&&window}(),a={packaged:!1,workerPath:null,modePath:null,themePath:null,basePath:\"\",suffix:\".js\",$moduleUrls:{}};t.get=function(e){if(!a.hasOwnProperty(e))throw new Error(\"Unknown config key: \"+e);return a[e]},t.set=function(e,t){if(!a.hasOwnProperty(e))throw new Error(\"Unknown config key: \"+e);a[e]=t},t.all=function(){return r.copyObject(a)},t.moduleUrl=function(e,t){if(a.$moduleUrls[e])return a.$moduleUrls[e];var n=e.split(\"/\");t=t||n[n.length-2]||\"\";var r=t==\"snippets\"?\"/\":\"-\",i=n[n.length-1];if(t==\"worker\"&&r==\"-\"){var s=new RegExp(\"^\"+t+\"[\\\\-_]|[\\\\-_]\"+t+\"$\",\"g\");i=i.replace(s,\"\")}(!i||i==t)&&n.length>1&&(i=n[n.length-2]);var o=a[t+\"Path\"];return o==null?o=a.basePath:r==\"/\"&&(t=r=\"\"),o&&o.slice(-1)!=\"/\"&&(o+=\"/\"),o+t+r+i+this.get(\"suffix\")},t.setModuleUrl=function(e,t){return a.$moduleUrls[e]=t},t.$loading={},t.loadModule=function(n,r){var i,o;Array.isArray(n)&&(o=n[0],n=n[1]);try{i=e(n)}catch(u){}if(i&&!t.$loading[n])return r&&r(i);t.$loading[n]||(t.$loading[n]=[]),t.$loading[n].push(r);if(t.$loading[n].length>1)return;var a=function(){e([n],function(e){t._emit(\"load.module\",{name:n,module:e});var r=t.$loading[n];t.$loading[n]=null,r.forEach(function(t){t&&t(e)})})};if(!t.get(\"packaged\"))return a();s.loadScript(t.moduleUrl(n,o),a)},t.init=f}),define(\"ace/mouse/mouse_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/event\",\"ace/lib/useragent\",\"ace/mouse/default_handlers\",\"ace/mouse/default_gutter_handler\",\"ace/mouse/mouse_event\",\"ace/mouse/dragdrop_handler\",\"ace/config\"],function(e,t,n){\"use strict\";var r=e(\"../lib/event\"),i=e(\"../lib/useragent\"),s=e(\"./default_handlers\").DefaultHandlers,o=e(\"./default_gutter_handler\").GutterHandler,u=e(\"./mouse_event\").MouseEvent,a=e(\"./dragdrop_handler\").DragdropHandler,f=e(\"../config\"),l=function(e){var t=this;this.editor=e,new s(this),new o(this),new a(this);var n=function(t){var n=!document.hasFocus||!document.hasFocus()||!e.isFocused()&&document.activeElement==(e.textInput&&e.textInput.getElement());n&&window.focus(),e.focus()},u=e.renderer.getMouseEventTarget();r.addListener(u,\"click\",this.onMouseEvent.bind(this,\"click\")),r.addListener(u,\"mousemove\",this.onMouseMove.bind(this,\"mousemove\")),r.addMultiMouseDownListener([u,e.renderer.scrollBarV&&e.renderer.scrollBarV.inner,e.renderer.scrollBarH&&e.renderer.scrollBarH.inner,e.textInput&&e.textInput.getElement()].filter(Boolean),[400,300,250],this,\"onMouseEvent\"),r.addMouseWheelListener(e.container,this.onMouseWheel.bind(this,\"mousewheel\")),r.addTouchMoveListener(e.container,this.onTouchMove.bind(this,\"touchmove\"));var f=e.renderer.$gutter;r.addListener(f,\"mousedown\",this.onMouseEvent.bind(this,\"guttermousedown\")),r.addListener(f,\"click\",this.onMouseEvent.bind(this,\"gutterclick\")),r.addListener(f,\"dblclick\",this.onMouseEvent.bind(this,\"gutterdblclick\")),r.addListener(f,\"mousemove\",this.onMouseEvent.bind(this,\"guttermousemove\")),r.addListener(u,\"mousedown\",n),r.addListener(f,\"mousedown\",n),i.isIE&&e.renderer.scrollBarV&&(r.addListener(e.renderer.scrollBarV.element,\"mousedown\",n),r.addListener(e.renderer.scrollBarH.element,\"mousedown\",n)),e.on(\"mousemove\",function(n){if(t.state||t.$dragDelay||!t.$dragEnabled)return;var r=e.renderer.screenToTextCoordinates(n.x,n.y),i=e.session.selection.getRange(),s=e.renderer;!i.isEmpty()&&i.insideStart(r.row,r.column)?s.setCursorStyle(\"default\"):s.setCursorStyle(\"\")})};(function(){this.onMouseEvent=function(e,t){this.editor._emit(e,new u(t,this.editor))},this.onMouseMove=function(e,t){var n=this.editor._eventRegistry&&this.editor._eventRegistry.mousemove;if(!n||!n.length)return;this.editor._emit(e,new u(t,this.editor))},this.onMouseWheel=function(e,t){var n=new u(t,this.editor);n.speed=this.$scrollSpeed*2,n.wheelX=t.wheelX,n.wheelY=t.wheelY,this.editor._emit(e,n)},this.onTouchMove=function(e,t){var n=new u(t,this.editor);n.speed=1,n.wheelX=t.wheelX,n.wheelY=t.wheelY,this.editor._emit(e,n)},this.setState=function(e){this.state=e},this.captureMouse=function(e,t){this.x=e.x,this.y=e.y,this.isMousePressed=!0;var n=this.editor.renderer;n.$keepTextAreaAtCursor&&(n.$keepTextAreaAtCursor=null);var s=this,o=function(e){if(!e)return;if(i.isWebKit&&!e.which&&s.releaseMouse)return s.releaseMouse();s.x=e.clientX,s.y=e.clientY,t&&t(e),s.mouseEvent=new u(e,s.editor),s.$mouseMoved=!0},a=function(e){clearInterval(l),f(),s[s.state+\"End\"]&&s[s.state+\"End\"](e),s.state=\"\",n.$keepTextAreaAtCursor==null&&(n.$keepTextAreaAtCursor=!0,n.$moveTextAreaToCursor()),s.isMousePressed=!1,s.$onCaptureMouseMove=s.releaseMouse=null,e&&s.onMouseEvent(\"mouseup\",e)},f=function(){s[s.state]&&s[s.state](),s.$mouseMoved=!1};if(i.isOldIE&&e.domEvent.type==\"dblclick\")return setTimeout(function(){a(e)});s.$onCaptureMouseMove=o,s.releaseMouse=r.capture(this.editor.container,o,a);var l=setInterval(f,20)},this.releaseMouse=null,this.cancelContextMenu=function(){var e=function(t){if(t&&t.domEvent&&t.domEvent.type!=\"contextmenu\")return;this.editor.off(\"nativecontextmenu\",e),t&&t.domEvent&&r.stopEvent(t.domEvent)}.bind(this);setTimeout(e,10),this.editor.on(\"nativecontextmenu\",e)}}).call(l.prototype),f.defineOptions(l.prototype,\"mouseHandler\",{scrollSpeed:{initialValue:2},dragDelay:{initialValue:i.isMac?150:0},dragEnabled:{initialValue:!0},focusTimout:{initialValue:0},tooltipFollowsMouse:{initialValue:!0}}),t.MouseHandler=l}),define(\"ace/mouse/fold_handler\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";function r(e){e.on(\"click\",function(t){var n=t.getDocumentPosition(),r=e.session,i=r.getFoldAt(n.row,n.column,1);i&&(t.getAccelKey()?r.removeFold(i):r.expandFold(i),t.stop())}),e.on(\"gutterclick\",function(t){var n=e.renderer.$gutterLayer.getRegion(t);if(n==\"foldWidgets\"){var r=t.getDocumentPosition().row,i=e.session;i.foldWidgets&&i.foldWidgets[r]&&e.session.onFoldWidgetClick(r,t),e.isFocused()||e.focus(),t.stop()}}),e.on(\"gutterdblclick\",function(t){var n=e.renderer.$gutterLayer.getRegion(t);if(n==\"foldWidgets\"){var r=t.getDocumentPosition().row,i=e.session,s=i.getParentFoldRangeData(r,!0),o=s.range||s.firstRange;if(o){r=o.start.row;var u=i.getFoldAt(r,i.getLine(r).length,1);u?i.removeFold(u):(i.addFold(\"...\",o),e.renderer.scrollCursorIntoView({row:o.start.row,column:0}))}t.stop()}})}t.FoldHandler=r}),define(\"ace/keyboard/keybinding\",[\"require\",\"exports\",\"module\",\"ace/lib/keys\",\"ace/lib/event\"],function(e,t,n){\"use strict\";var r=e(\"../lib/keys\"),i=e(\"../lib/event\"),s=function(e){this.$editor=e,this.$data={editor:e},this.$handlers=[],this.setDefaultHandler(e.commands)};(function(){this.setDefaultHandler=function(e){this.removeKeyboardHandler(this.$defaultHandler),this.$defaultHandler=e,this.addKeyboardHandler(e,0)},this.setKeyboardHandler=function(e){var t=this.$handlers;if(t[t.length-1]==e)return;while(t[t.length-1]&&t[t.length-1]!=this.$defaultHandler)this.removeKeyboardHandler(t[t.length-1]);this.addKeyboardHandler(e,1)},this.addKeyboardHandler=function(e,t){if(!e)return;typeof e==\"function\"&&!e.handleKeyboard&&(e.handleKeyboard=e);var n=this.$handlers.indexOf(e);n!=-1&&this.$handlers.splice(n,1),t==undefined?this.$handlers.push(e):this.$handlers.splice(t,0,e),n==-1&&e.attach&&e.attach(this.$editor)},this.removeKeyboardHandler=function(e){var t=this.$handlers.indexOf(e);return t==-1?!1:(this.$handlers.splice(t,1),e.detach&&e.detach(this.$editor),!0)},this.getKeyboardHandler=function(){return this.$handlers[this.$handlers.length-1]},this.getStatusText=function(){var e=this.$data,t=e.editor;return this.$handlers.map(function(n){return n.getStatusText&&n.getStatusText(t,e)||\"\"}).filter(Boolean).join(\" \")},this.$callKeyboardHandlers=function(e,t,n,r){var s,o=!1,u=this.$editor.commands;for(var a=this.$handlers.length;a--;){s=this.$handlers[a].handleKeyboard(this.$data,e,t,n,r);if(!s||!s.command)continue;s.command==\"null\"?o=!0:o=u.exec(s.command,this.$editor,s.args,r),o&&r&&e!=-1&&s.passEvent!=1&&s.command.passEvent!=1&&i.stopEvent(r);if(o)break}return!o&&e==-1&&(s={command:\"insertstring\"},o=u.exec(\"insertstring\",this.$editor,t)),o&&this.$editor._signal&&this.$editor._signal(\"keyboardActivity\",s),o},this.onCommandKey=function(e,t,n){var i=r.keyCodeToString(n);this.$callKeyboardHandlers(t,i,n,e)},this.onTextInput=function(e){this.$callKeyboardHandlers(-1,e)}}).call(s.prototype),t.KeyBinding=s}),define(\"ace/range\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";var r=function(e,t){return e.row-t.row||e.column-t.column},i=function(e,t,n,r){this.start={row:e,column:t},this.end={row:n,column:r}};(function(){this.isEqual=function(e){return this.start.row===e.start.row&&this.end.row===e.end.row&&this.start.column===e.start.column&&this.end.column===e.end.column},this.toString=function(){return\"Range: [\"+this.start.row+\"/\"+this.start.column+\"] -> [\"+this.end.row+\"/\"+this.end.column+\"]\"},this.contains=function(e,t){return this.compare(e,t)==0},this.compareRange=function(e){var t,n=e.end,r=e.start;return t=this.compare(n.row,n.column),t==1?(t=this.compare(r.row,r.column),t==1?2:t==0?1:0):t==-1?-2:(t=this.compare(r.row,r.column),t==-1?-1:t==1?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return this.comparePoint(e.start)==0&&this.comparePoint(e.end)==0},this.intersects=function(e){var t=this.compareRange(e);return t==-1||t==0||t==1},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){typeof e==\"object\"?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){typeof e==\"object\"?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},this.insideStart=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)?!1:!0:!1},this.insideEnd=function(e,t){return this.compare(e,t)==0?this.isStart(e,t)?!1:!0:!1},this.compare=function(e,t){return!this.isMultiLine()&&e===this.start.row?t<this.start.column?-1:t>this.end.column?1:0:e<this.start.row?-1:e>this.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var n={row:t+1,column:0};else if(this.end.row<e)var n={row:e,column:0};if(this.start.row>t)var r={row:t+1,column:0};else if(this.start.row<e)var r={row:e,column:0};return i.fromPoints(r||this.start,n||this.end)},this.extend=function(e,t){var n=this.compare(e,t);if(n==0)return this;if(n==-1)var r={row:e,column:t};else var s={row:e,column:t};return i.fromPoints(r||this.start,s||this.end)},this.isEmpty=function(){return this.start.row===this.end.row&&this.start.column===this.end.column},this.isMultiLine=function(){return this.start.row!==this.end.row},this.clone=function(){return i.fromPoints(this.start,this.end)},this.collapseRows=function(){return this.end.column==0?new i(this.start.row,0,Math.max(this.start.row,this.end.row-1),0):new i(this.start.row,0,this.end.row,0)},this.toScreenRange=function(e){var t=e.documentToScreenPosition(this.start),n=e.documentToScreenPosition(this.end);return new i(t.row,t.column,n.row,n.column)},this.moveBy=function(e,t){this.start.row+=e,this.start.column+=t,this.end.row+=e,this.end.column+=t}}).call(i.prototype),i.fromPoints=function(e,t){return new i(e.row,e.column,t.row,t.column)},i.comparePoints=r,i.comparePoints=function(e,t){return e.row-t.row||e.column-t.column},t.Range=i}),define(\"ace/selection\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/lang\",\"ace/lib/event_emitter\",\"ace/range\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./lib/lang\"),s=e(\"./lib/event_emitter\").EventEmitter,o=e(\"./range\").Range,u=function(e){this.session=e,this.doc=e.getDocument(),this.clearSelection(),this.lead=this.selectionLead=this.doc.createAnchor(0,0),this.anchor=this.selectionAnchor=this.doc.createAnchor(0,0);var t=this;this.lead.on(\"change\",function(e){t._emit(\"changeCursor\"),t.$isEmpty||t._emit(\"changeSelection\"),!t.$keepDesiredColumnOnChange&&e.old.column!=e.value.column&&(t.$desiredColumn=null)}),this.selectionAnchor.on(\"change\",function(){t.$isEmpty||t._emit(\"changeSelection\")})};(function(){r.implement(this,s),this.isEmpty=function(){return this.$isEmpty||this.anchor.row==this.lead.row&&this.anchor.column==this.lead.column},this.isMultiLine=function(){return this.isEmpty()?!1:this.getRange().isMultiLine()},this.getCursor=function(){return this.lead.getPosition()},this.setSelectionAnchor=function(e,t){this.anchor.setPosition(e,t),this.$isEmpty&&(this.$isEmpty=!1,this._emit(\"changeSelection\"))},this.getSelectionAnchor=function(){return this.$isEmpty?this.getSelectionLead():this.anchor.getPosition()},this.getSelectionLead=function(){return this.lead.getPosition()},this.shiftSelection=function(e){if(this.$isEmpty){this.moveCursorTo(this.lead.row,this.lead.column+e);return}var t=this.getSelectionAnchor(),n=this.getSelectionLead(),r=this.isBackwards();(!r||t.column!==0)&&this.setSelectionAnchor(t.row,t.column+e),(r||n.column!==0)&&this.$moveSelection(function(){this.moveCursorTo(n.row,n.column+e)})},this.isBackwards=function(){var e=this.anchor,t=this.lead;return e.row>t.row||e.row==t.row&&e.column>t.column},this.getRange=function(){var e=this.anchor,t=this.lead;return this.isEmpty()?o.fromPoints(t,t):this.isBackwards()?o.fromPoints(t,e):o.fromPoints(e,t)},this.clearSelection=function(){this.$isEmpty||(this.$isEmpty=!0,this._emit(\"changeSelection\"))},this.selectAll=function(){var e=this.doc.getLength()-1;this.setSelectionAnchor(0,0),this.moveCursorTo(e,this.doc.getLine(e).length)},this.setRange=this.setSelectionRange=function(e,t){t?(this.setSelectionAnchor(e.end.row,e.end.column),this.selectTo(e.start.row,e.start.column)):(this.setSelectionAnchor(e.start.row,e.start.column),this.selectTo(e.end.row,e.end.column)),this.getRange().isEmpty()&&(this.$isEmpty=!0),this.$desiredColumn=null},this.$moveSelection=function(e){var t=this.lead;this.$isEmpty&&this.setSelectionAnchor(t.row,t.column),e.call(this)},this.selectTo=function(e,t){this.$moveSelection(function(){this.moveCursorTo(e,t)})},this.selectToPosition=function(e){this.$moveSelection(function(){this.moveCursorToPosition(e)})},this.moveTo=function(e,t){this.clearSelection(),this.moveCursorTo(e,t)},this.moveToPosition=function(e){this.clearSelection(),this.moveCursorToPosition(e)},this.selectUp=function(){this.$moveSelection(this.moveCursorUp)},this.selectDown=function(){this.$moveSelection(this.moveCursorDown)},this.selectRight=function(){this.$moveSelection(this.moveCursorRight)},this.selectLeft=function(){this.$moveSelection(this.moveCursorLeft)},this.selectLineStart=function(){this.$moveSelection(this.moveCursorLineStart)},this.selectLineEnd=function(){this.$moveSelection(this.moveCursorLineEnd)},this.selectFileEnd=function(){this.$moveSelection(this.moveCursorFileEnd)},this.selectFileStart=function(){this.$moveSelection(this.moveCursorFileStart)},this.selectWordRight=function(){this.$moveSelection(this.moveCursorWordRight)},this.selectWordLeft=function(){this.$moveSelection(this.moveCursorWordLeft)},this.getWordRange=function(e,t){if(typeof t==\"undefined\"){var n=e||this.lead;e=n.row,t=n.column}return this.session.getWordRange(e,t)},this.selectWord=function(){this.setSelectionRange(this.getWordRange())},this.selectAWord=function(){var e=this.getCursor(),t=this.session.getAWordRange(e.row,e.column);this.setSelectionRange(t)},this.getLineRange=function(e,t){var n=typeof e==\"number\"?e:this.lead.row,r,i=this.session.getFoldLine(n);return i?(n=i.start.row,r=i.end.row):r=n,t===!0?new o(n,0,r,this.session.getLine(r).length):new o(n,0,r+1,0)},this.selectLine=function(){this.setSelectionRange(this.getLineRange())},this.moveCursorUp=function(){this.moveCursorBy(-1,0)},this.moveCursorDown=function(){this.moveCursorBy(1,0)},this.wouldMoveIntoSoftTab=function(e,t,n){var r=e.column,i=e.column+t;return n<0&&(r=e.column-t,i=e.column),this.session.isTabStop(e)&&this.doc.getLine(e.row).slice(r,i).split(\" \").length-1==t},this.moveCursorLeft=function(){var e=this.lead.getPosition(),t;if(t=this.session.getFoldAt(e.row,e.column,-1))this.moveCursorTo(t.start.row,t.start.column);else if(e.column===0)e.row>0&&this.moveCursorTo(e.row-1,this.doc.getLine(e.row-1).length);else{var n=this.session.getTabSize();this.wouldMoveIntoSoftTab(e,n,-1)&&!this.session.getNavigateWithinSoftTabs()?this.moveCursorBy(0,-n):this.moveCursorBy(0,-1)}},this.moveCursorRight=function(){var e=this.lead.getPosition(),t;if(t=this.session.getFoldAt(e.row,e.column,1))this.moveCursorTo(t.end.row,t.end.column);else if(this.lead.column==this.doc.getLine(this.lead.row).length)this.lead.row<this.doc.getLength()-1&&this.moveCursorTo(this.lead.row+1,0);else{var n=this.session.getTabSize(),e=this.lead;this.wouldMoveIntoSoftTab(e,n,1)&&!this.session.getNavigateWithinSoftTabs()?this.moveCursorBy(0,n):this.moveCursorBy(0,1)}},this.moveCursorLineStart=function(){var e=this.lead.row,t=this.lead.column,n=this.session.documentToScreenRow(e,t),r=this.session.screenToDocumentPosition(n,0),i=this.session.getDisplayLine(e,null,r.row,r.column),s=i.match(/^\\s*/);s[0].length!=t&&!this.session.$useEmacsStyleLineStart&&(r.column+=s[0].length),this.moveCursorToPosition(r)},this.moveCursorLineEnd=function(){var e=this.lead,t=this.session.getDocumentLastRowColumnPosition(e.row,e.column);if(this.lead.column==t.column){var n=this.session.getLine(t.row);if(t.column==n.length){var r=n.search(/\\s+$/);r>0&&(t.column=r)}}this.moveCursorTo(t.row,t.column)},this.moveCursorFileEnd=function(){var e=this.doc.getLength()-1,t=this.doc.getLine(e).length;this.moveCursorTo(e,t)},this.moveCursorFileStart=function(){this.moveCursorTo(0,0)},this.moveCursorLongWordRight=function(){var e=this.lead.row,t=this.lead.column,n=this.doc.getLine(e),r=n.substring(t),i;this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0;var s=this.session.getFoldAt(e,t,1);if(s){this.moveCursorTo(s.end.row,s.end.column);return}if(i=this.session.nonTokenRe.exec(r))t+=this.session.nonTokenRe.lastIndex,this.session.nonTokenRe.lastIndex=0,r=n.substring(t);if(t>=n.length){this.moveCursorTo(e,n.length),this.moveCursorRight(),e<this.doc.getLength()-1&&this.moveCursorWordRight();return}if(i=this.session.tokenRe.exec(r))t+=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0;this.moveCursorTo(e,t)},this.moveCursorLongWordLeft=function(){var e=this.lead.row,t=this.lead.column,n;if(n=this.session.getFoldAt(e,t,-1)){this.moveCursorTo(n.start.row,n.start.column);return}var r=this.session.getFoldStringAt(e,t,-1);r==null&&(r=this.doc.getLine(e).substring(0,t));var s=i.stringReverse(r),o;this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0;if(o=this.session.nonTokenRe.exec(s))t-=this.session.nonTokenRe.lastIndex,s=s.slice(this.session.nonTokenRe.lastIndex),this.session.nonTokenRe.lastIndex=0;if(t<=0){this.moveCursorTo(e,0),this.moveCursorLeft(),e>0&&this.moveCursorWordLeft();return}if(o=this.session.tokenRe.exec(s))t-=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0;this.moveCursorTo(e,t)},this.$shortWordEndIndex=function(e){var t,n=0,r,i=/\\s/,s=this.session.tokenRe;s.lastIndex=0;if(t=this.session.tokenRe.exec(e))n=this.session.tokenRe.lastIndex;else{while((r=e[n])&&i.test(r))n++;if(n<1){s.lastIndex=0;while((r=e[n])&&!s.test(r)){s.lastIndex=0,n++;if(i.test(r)){if(n>2){n--;break}while((r=e[n])&&i.test(r))n++;if(n>2)break}}}}return s.lastIndex=0,n},this.moveCursorShortWordRight=function(){var e=this.lead.row,t=this.lead.column,n=this.doc.getLine(e),r=n.substring(t),i=this.session.getFoldAt(e,t,1);if(i)return this.moveCursorTo(i.end.row,i.end.column);if(t==n.length){var s=this.doc.getLength();do e++,r=this.doc.getLine(e);while(e<s&&/^\\s*$/.test(r));/^\\s+/.test(r)||(r=\"\"),t=0}var o=this.$shortWordEndIndex(r);this.moveCursorTo(e,t+o)},this.moveCursorShortWordLeft=function(){var e=this.lead.row,t=this.lead.column,n;if(n=this.session.getFoldAt(e,t,-1))return this.moveCursorTo(n.start.row,n.start.column);var r=this.session.getLine(e).substring(0,t);if(t===0){do e--,r=this.doc.getLine(e);while(e>0&&/^\\s*$/.test(r));t=r.length,/\\s+$/.test(r)||(r=\"\")}var s=i.stringReverse(r),o=this.$shortWordEndIndex(s);return this.moveCursorTo(e,t-o)},this.moveCursorWordRight=function(){this.session.$selectLongWords?this.moveCursorLongWordRight():this.moveCursorShortWordRight()},this.moveCursorWordLeft=function(){this.session.$selectLongWords?this.moveCursorLongWordLeft():this.moveCursorShortWordLeft()},this.moveCursorBy=function(e,t){var n=this.session.documentToScreenPosition(this.lead.row,this.lead.column);t===0&&(this.$desiredColumn?n.column=this.$desiredColumn:this.$desiredColumn=n.column);var r=this.session.screenToDocumentPosition(n.row+e,n.column);e!==0&&t===0&&r.row===this.lead.row&&r.column===this.lead.column&&this.session.lineWidgets&&this.session.lineWidgets[r.row]&&(r.row>0||e>0)&&r.row++,this.moveCursorTo(r.row,r.column+t,t===0)},this.moveCursorToPosition=function(e){this.moveCursorTo(e.row,e.column)},this.moveCursorTo=function(e,t,n){var r=this.session.getFoldAt(e,t,1);r&&(e=r.start.row,t=r.start.column),this.$keepDesiredColumnOnChange=!0,this.lead.setPosition(e,t),this.$keepDesiredColumnOnChange=!1,n||(this.$desiredColumn=null)},this.moveCursorToScreen=function(e,t,n){var r=this.session.screenToDocumentPosition(e,t);this.moveCursorTo(r.row,r.column,n)},this.detach=function(){this.lead.detach(),this.anchor.detach(),this.session=this.doc=null},this.fromOrientedRange=function(e){this.setSelectionRange(e,e.cursor==e.start),this.$desiredColumn=e.desiredColumn||this.$desiredColumn},this.toOrientedRange=function(e){var t=this.getRange();return e?(e.start.column=t.start.column,e.start.row=t.start.row,e.end.column=t.end.column,e.end.row=t.end.row):e=t,e.cursor=this.isBackwards()?e.start:e.end,e.desiredColumn=this.$desiredColumn,e},this.getRangeOfMovements=function(e){var t=this.getCursor();try{e(this);var n=this.getCursor();return o.fromPoints(t,n)}catch(r){return o.fromPoints(t,t)}finally{this.moveCursorToPosition(t)}},this.toJSON=function(){if(this.rangeCount)var e=this.ranges.map(function(e){var t=e.clone();return t.isBackwards=e.cursor==e.start,t});else{var e=this.getRange();e.isBackwards=this.isBackwards()}return e},this.fromJSON=function(e){if(e.start==undefined){if(this.rangeList){this.toSingleRange(e[0]);for(var t=e.length;t--;){var n=o.fromPoints(e[t].start,e[t].end);e[t].isBackwards&&(n.cursor=n.start),this.addRange(n,!0)}return}e=e[0]}this.rangeList&&this.toSingleRange(e),this.setSelectionRange(e,e.isBackwards)},this.isEqual=function(e){if((e.length||this.rangeCount)&&e.length!=this.rangeCount)return!1;if(!e.length||!this.ranges)return this.getRange().isEqual(e);for(var t=this.ranges.length;t--;)if(!this.ranges[t].isEqual(e[t]))return!1;return!0}}).call(u.prototype),t.Selection=u}),define(\"ace/tokenizer\",[\"require\",\"exports\",\"module\",\"ace/config\"],function(e,t,n){\"use strict\";var r=e(\"./config\"),i=2e3,s=function(e){this.states=e,this.regExps={},this.matchMappings={};for(var t in this.states){var n=this.states[t],r=[],i=0,s=this.matchMappings[t]={defaultToken:\"text\"},o=\"g\",u=[];for(var a=0;a<n.length;a++){var f=n[a];f.defaultToken&&(s.defaultToken=f.defaultToken),f.caseInsensitive&&(o=\"gi\");if(f.regex==null)continue;f.regex instanceof RegExp&&(f.regex=f.regex.toString().slice(1,-1));var l=f.regex,c=(new RegExp(\"(?:(\"+l+\")|(.))\")).exec(\"a\").length-2;Array.isArray(f.token)?f.token.length==1||c==1?f.token=f.token[0]:c-1!=f.token.length?(this.reportError(\"number of classes and regexp groups doesn't match\",{rule:f,groupCount:c-1}),f.token=f.token[0]):(f.tokenArray=f.token,f.token=null,f.onMatch=this.$arrayTokens):typeof f.token==\"function\"&&!f.onMatch&&(c>1?f.onMatch=this.$applyToken:f.onMatch=f.token),c>1&&(/\\\\\\d/.test(f.regex)?l=f.regex.replace(/\\\\([0-9]+)/g,function(e,t){return\"\\\\\"+(parseInt(t,10)+i+1)}):(c=1,l=this.removeCapturingGroups(f.regex)),!f.splitRegex&&typeof f.token!=\"string\"&&u.push(f)),s[i]=a,i+=c,r.push(l),f.onMatch||(f.onMatch=null)}r.length||(s[0]=0,r.push(\"$\")),u.forEach(function(e){e.splitRegex=this.createSplitterRegexp(e.regex,o)},this),this.regExps[t]=new RegExp(\"(\"+r.join(\")|(\")+\")|($)\",o)}};(function(){this.$setMaxTokenCount=function(e){i=e|0},this.$applyToken=function(e){var t=this.splitRegex.exec(e).slice(1),n=this.token.apply(this,t);if(typeof n==\"string\")return[{type:n,value:e}];var r=[];for(var i=0,s=n.length;i<s;i++)t[i]&&(r[r.length]={type:n[i],value:t[i]});return r},this.$arrayTokens=function(e){if(!e)return[];var t=this.splitRegex.exec(e);if(!t)return\"text\";var n=[],r=this.tokenArray;for(var i=0,s=r.length;i<s;i++)t[i+1]&&(n[n.length]={type:r[i],value:t[i+1]});return n},this.removeCapturingGroups=function(e){var t=e.replace(/\\[(?:\\\\.|[^\\]])*?\\]|\\\\.|\\(\\?[:=!]|(\\()/g,function(e,t){return t?\"(?:\":e});return t},this.createSplitterRegexp=function(e,t){if(e.indexOf(\"(?=\")!=-1){var n=0,r=!1,i={};e.replace(/(\\\\.)|(\\((?:\\?[=!])?)|(\\))|([\\[\\]])/g,function(e,t,s,o,u,a){return r?r=u!=\"]\":u?r=!0:o?(n==i.stack&&(i.end=a+1,i.stack=-1),n--):s&&(n++,s.length!=1&&(i.stack=n,i.start=a)),e}),i.end!=null&&/^\\)*$/.test(e.substr(i.end))&&(e=e.substring(0,i.start)+e.substr(i.end))}return e.charAt(0)!=\"^\"&&(e=\"^\"+e),e.charAt(e.length-1)!=\"$\"&&(e+=\"$\"),new RegExp(e,(t||\"\").replace(\"g\",\"\"))},this.getLineTokens=function(e,t){if(t&&typeof t!=\"string\"){var n=t.slice(0);t=n[0],t===\"#tmp\"&&(n.shift(),t=n.shift())}else var n=[];var r=t||\"start\",s=this.states[r];s||(r=\"start\",s=this.states[r]);var o=this.matchMappings[r],u=this.regExps[r];u.lastIndex=0;var a,f=[],l=0,c=0,h={type:null,value:\"\"};while(a=u.exec(e)){var p=o.defaultToken,d=null,v=a[0],m=u.lastIndex;if(m-v.length>l){var g=e.substring(l,m-v.length);h.type==p?h.value+=g:(h.type&&f.push(h),h={type:p,value:g})}for(var y=0;y<a.length-2;y++){if(a[y+1]===undefined)continue;d=s[o[y]],d.onMatch?p=d.onMatch(v,r,n,e):p=d.token,d.next&&(typeof d.next==\"string\"?r=d.next:r=d.next(r,n),s=this.states[r],s||(this.reportError(\"state doesn't exist\",r),r=\"start\",s=this.states[r]),o=this.matchMappings[r],l=m,u=this.regExps[r],u.lastIndex=m),d.consumeLineEnd&&(l=m);break}if(v)if(typeof p==\"string\")!!d&&d.merge===!1||h.type!==p?(h.type&&f.push(h),h={type:p,value:v}):h.value+=v;else if(p){h.type&&f.push(h),h={type:null,value:\"\"};for(var y=0;y<p.length;y++)f.push(p[y])}if(l==e.length)break;l=m;if(c++>i){c>2*e.length&&this.reportError(\"infinite loop with in ace tokenizer\",{startState:t,line:e});while(l<e.length)h.type&&f.push(h),h={value:e.substring(l,l+=2e3),type:\"overflow\"};r=\"start\",n=[];break}}return h.type&&f.push(h),n.length>1&&n[0]!==r&&n.unshift(\"#tmp\",r),{tokens:f,state:n.length?n:r}},this.reportError=r.reportError}).call(s.prototype),t.Tokenizer=s}),define(\"ace/mode/text_highlight_rules\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\"],function(e,t,n){\"use strict\";var r=e(\"../lib/lang\"),i=function(){this.$rules={start:[{token:\"empty_line\",regex:\"^$\"},{defaultToken:\"text\"}]}};(function(){this.addRules=function(e,t){if(!t){for(var n in e)this.$rules[n]=e[n];return}for(var n in e){var r=e[n];for(var i=0;i<r.length;i++){var s=r[i];if(s.next||s.onMatch)typeof s.next==\"string\"&&s.next.indexOf(t)!==0&&(s.next=t+s.next),s.nextState&&s.nextState.indexOf(t)!==0&&(s.nextState=t+s.nextState)}this.$rules[t+n]=r}},this.getRules=function(){return this.$rules},this.embedRules=function(e,t,n,i,s){var o=typeof e==\"function\"?(new e).getRules():e;if(i)for(var u=0;u<i.length;u++)i[u]=t+i[u];else{i=[];for(var a in o)i.push(t+a)}this.addRules(o,t);if(n){var f=Array.prototype[s?\"push\":\"unshift\"];for(var u=0;u<i.length;u++)f.apply(this.$rules[i[u]],r.deepCopy(n))}this.$embeds||(this.$embeds=[]),this.$embeds.push(t)},this.getEmbeds=function(){return this.$embeds};var e=function(e,t){return(e!=\"start\"||t.length)&&t.unshift(this.nextState,e),this.nextState},t=function(e,t){return t.shift(),t.shift()||\"start\"};this.normalizeRules=function(){function i(s){var o=r[s];o.processed=!0;for(var u=0;u<o.length;u++){var a=o[u],f=null;Array.isArray(a)&&(f=a,a={}),!a.regex&&a.start&&(a.regex=a.start,a.next||(a.next=[]),a.next.push({defaultToken:a.token},{token:a.token+\".end\",regex:a.end||a.start,next:\"pop\"}),a.token=a.token+\".start\",a.push=!0);var l=a.next||a.push;if(l&&Array.isArray(l)){var c=a.stateName;c||(c=a.token,typeof c!=\"string\"&&(c=c[0]||\"\"),r[c]&&(c+=n++)),r[c]=l,a.next=c,i(c)}else l==\"pop\"&&(a.next=t);a.push&&(a.nextState=a.next||a.push,a.next=e,delete a.push);if(a.rules)for(var h in a.rules)r[h]?r[h].push&&r[h].push.apply(r[h],a.rules[h]):r[h]=a.rules[h];var p=typeof a==\"string\"?a:a.include;p&&(Array.isArray(p)?f=p.map(function(e){return r[e]}):f=r[p]);if(f){var d=[u,1].concat(f);a.noEscape&&(d=d.filter(function(e){return!e.next})),o.splice.apply(o,d),u--}a.keywordMap&&(a.token=this.createKeywordMapper(a.keywordMap,a.defaultToken||\"text\",a.caseInsensitive),delete a.defaultToken)}}var n=0,r=this.$rules;Object.keys(r).forEach(i,this)},this.createKeywordMapper=function(e,t,n,r){var i=Object.create(null);return Object.keys(e).forEach(function(t){var s=e[t];n&&(s=s.toLowerCase());var o=s.split(r||\"|\");for(var u=o.length;u--;)i[o[u]]=t}),Object.getPrototypeOf(i)&&(i.__proto__=null),this.$keywordList=Object.keys(i),e=null,n?function(e){return i[e.toLowerCase()]||t}:function(e){return i[e]||t}},this.getKeywords=function(){return this.$keywords}}).call(i.prototype),t.TextHighlightRules=i}),define(\"ace/mode/behaviour\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";var r=function(){this.$behaviours={}};(function(){this.add=function(e,t,n){switch(undefined){case this.$behaviours:this.$behaviours={};case this.$behaviours[e]:this.$behaviours[e]={}}this.$behaviours[e][t]=n},this.addBehaviours=function(e){for(var t in e)for(var n in e[t])this.add(t,n,e[t][n])},this.remove=function(e){this.$behaviours&&this.$behaviours[e]&&delete this.$behaviours[e]},this.inherit=function(e,t){if(typeof e==\"function\")var n=(new e).getBehaviours(t);else var n=e.getBehaviours(t);this.addBehaviours(n)},this.getBehaviours=function(e){if(!e)return this.$behaviours;var t={};for(var n=0;n<e.length;n++)this.$behaviours[e[n]]&&(t[e[n]]=this.$behaviours[e[n]]);return t}}).call(r.prototype),t.Behaviour=r}),define(\"ace/token_iterator\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";var r=function(e,t,n){this.$session=e,this.$row=t,this.$rowTokens=e.getTokens(t);var r=e.getTokenAt(t,n);this.$tokenIndex=r?r.index:-1};(function(){this.stepBackward=function(){this.$tokenIndex-=1;while(this.$tokenIndex<0){this.$row-=1;if(this.$row<0)return this.$row=0,null;this.$rowTokens=this.$session.getTokens(this.$row),this.$tokenIndex=this.$rowTokens.length-1}return this.$rowTokens[this.$tokenIndex]},this.stepForward=function(){this.$tokenIndex+=1;var e;while(this.$tokenIndex>=this.$rowTokens.length){this.$row+=1,e||(e=this.$session.getLength());if(this.$row>=e)return this.$row=e-1,null;this.$rowTokens=this.$session.getTokens(this.$row),this.$tokenIndex=0}return this.$rowTokens[this.$tokenIndex]},this.getCurrentToken=function(){return this.$rowTokens[this.$tokenIndex]},this.getCurrentTokenRow=function(){return this.$row},this.getCurrentTokenColumn=function(){var e=this.$rowTokens,t=this.$tokenIndex,n=e[t].start;if(n!==undefined)return n;n=0;while(t>0)t-=1,n+=e[t].value.length;return n},this.getCurrentTokenPosition=function(){return{row:this.$row,column:this.getCurrentTokenColumn()}}}).call(r.prototype),t.TokenIterator=r}),define(\"ace/mode/behaviour/cstyle\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/mode/behaviour\",\"ace/token_iterator\",\"ace/lib/lang\"],function(e,t,n){\"use strict\";var r=e(\"../../lib/oop\"),i=e(\"../behaviour\").Behaviour,s=e(\"../../token_iterator\").TokenIterator,o=e(\"../../lib/lang\"),u=[\"text\",\"paren.rparen\",\"punctuation.operator\"],a=[\"text\",\"paren.rparen\",\"punctuation.operator\",\"comment\"],f,l={},c={'\"':'\"',\"'\":\"'\"},h=function(e){var t=-1;e.multiSelect&&(t=e.selection.index,l.rangeCount!=e.multiSelect.rangeCount&&(l={rangeCount:e.multiSelect.rangeCount}));if(l[t])return f=l[t];f=l[t]={autoInsertedBrackets:0,autoInsertedRow:-1,autoInsertedLineEnd:\"\",maybeInsertedBrackets:0,maybeInsertedRow:-1,maybeInsertedLineStart:\"\",maybeInsertedLineEnd:\"\"}},p=function(e,t,n,r){var i=e.end.row-e.start.row;return{text:n+t+r,selection:[0,e.start.column+1,i,e.end.column+(i?0:1)]}},d=function(e){this.add(\"braces\",\"insertion\",function(t,n,r,i,s){var u=r.getCursorPosition(),a=i.doc.getLine(u.row);if(s==\"{\"){h(r);var l=r.getSelectionRange(),c=i.doc.getTextRange(l);if(c!==\"\"&&c!==\"{\"&&r.getWrapBehavioursEnabled())return p(l,c,\"{\",\"}\");if(d.isSaneInsertion(r,i))return/[\\]\\}\\)]/.test(a[u.column])||r.inMultiSelectMode||e&&e.braces?(d.recordAutoInsert(r,i,\"}\"),{text:\"{}\",selection:[1,1]}):(d.recordMaybeInsert(r,i,\"{\"),{text:\"{\",selection:[1,1]})}else if(s==\"}\"){h(r);var v=a.substring(u.column,u.column+1);if(v==\"}\"){var m=i.$findOpeningBracket(\"}\",{column:u.column+1,row:u.row});if(m!==null&&d.isAutoInsertedClosing(u,a,s))return d.popAutoInsertedClosing(),{text:\"\",selection:[1,1]}}}else{if(s==\"\\n\"||s==\"\\r\\n\"){h(r);var g=\"\";d.isMaybeInsertedClosing(u,a)&&(g=o.stringRepeat(\"}\",f.maybeInsertedBrackets),d.clearMaybeInsertedClosing());var v=a.substring(u.column,u.column+1);if(v===\"}\"){var y=i.findMatchingBracket({row:u.row,column:u.column+1},\"}\");if(!y)return null;var b=this.$getIndent(i.getLine(y.row))}else{if(!g){d.clearMaybeInsertedClosing();return}var b=this.$getIndent(a)}var w=b+i.getTabString();return{text:\"\\n\"+w+\"\\n\"+b+g,selection:[1,w.length,1,w.length]}}d.clearMaybeInsertedClosing()}}),this.add(\"braces\",\"deletion\",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s==\"{\"){h(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u==\"}\")return i.end.column++,i;f.maybeInsertedBrackets--}}),this.add(\"parens\",\"insertion\",function(e,t,n,r,i){if(i==\"(\"){h(n);var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==\"\"&&n.getWrapBehavioursEnabled())return p(s,o,\"(\",\")\");if(d.isSaneInsertion(n,r))return d.recordAutoInsert(n,r,\")\"),{text:\"()\",selection:[1,1]}}else if(i==\")\"){h(n);var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==\")\"){var l=r.$findOpeningBracket(\")\",{column:u.column+1,row:u.row});if(l!==null&&d.isAutoInsertedClosing(u,a,i))return d.popAutoInsertedClosing(),{text:\"\",selection:[1,1]}}}}),this.add(\"parens\",\"deletion\",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s==\"(\"){h(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==\")\")return i.end.column++,i}}),this.add(\"brackets\",\"insertion\",function(e,t,n,r,i){if(i==\"[\"){h(n);var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==\"\"&&n.getWrapBehavioursEnabled())return p(s,o,\"[\",\"]\");if(d.isSaneInsertion(n,r))return d.recordAutoInsert(n,r,\"]\"),{text:\"[]\",selection:[1,1]}}else if(i==\"]\"){h(n);var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==\"]\"){var l=r.$findOpeningBracket(\"]\",{column:u.column+1,row:u.row});if(l!==null&&d.isAutoInsertedClosing(u,a,i))return d.popAutoInsertedClosing(),{text:\"\",selection:[1,1]}}}}),this.add(\"brackets\",\"deletion\",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s==\"[\"){h(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==\"]\")return i.end.column++,i}}),this.add(\"string_dquotes\",\"insertion\",function(e,t,n,r,i){var s=r.$mode.$quotes||c;if(i.length==1&&s[i]){if(this.lineCommentStart&&this.lineCommentStart.indexOf(i)!=-1)return;h(n);var o=i,u=n.getSelectionRange(),a=r.doc.getTextRange(u);if(a!==\"\"&&(a.length!=1||!s[a])&&n.getWrapBehavioursEnabled())return p(u,a,o,o);if(!a){var f=n.getCursorPosition(),l=r.doc.getLine(f.row),d=l.substring(f.column-1,f.column),v=l.substring(f.column,f.column+1),m=r.getTokenAt(f.row,f.column),g=r.getTokenAt(f.row,f.column+1);if(d==\"\\\\\"&&m&&/escape/.test(m.type))return null;var y=m&&/string|escape/.test(m.type),b=!g||/string|escape/.test(g.type),w;if(v==o)w=y!==b,w&&/string\\.end/.test(g.type)&&(w=!1);else{if(y&&!b)return null;if(y&&b)return null;var E=r.$mode.tokenRe;E.lastIndex=0;var S=E.test(d);E.lastIndex=0;var x=E.test(d);if(S||x)return null;if(v&&!/[\\s;,.})\\]\\\\]/.test(v))return null;w=!0}return{text:w?o+o:\"\",selection:[1,1]}}}}),this.add(\"string_dquotes\",\"deletion\",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='\"'||s==\"'\")){h(n);var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};d.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||\"text\",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||\"text\",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||\"text\",a)},d.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},d.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,f.autoInsertedLineEnd[0])||(f.autoInsertedBrackets=0),f.autoInsertedRow=r.row,f.autoInsertedLineEnd=n+i.substr(r.column),f.autoInsertedBrackets++},d.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(f.maybeInsertedBrackets=0),f.maybeInsertedRow=r.row,f.maybeInsertedLineStart=i.substr(0,r.column)+n,f.maybeInsertedLineEnd=i.substr(r.column),f.maybeInsertedBrackets++},d.isAutoInsertedClosing=function(e,t,n){return f.autoInsertedBrackets>0&&e.row===f.autoInsertedRow&&n===f.autoInsertedLineEnd[0]&&t.substr(e.column)===f.autoInsertedLineEnd},d.isMaybeInsertedClosing=function(e,t){return f.maybeInsertedBrackets>0&&e.row===f.maybeInsertedRow&&t.substr(e.column)===f.maybeInsertedLineEnd&&t.substr(0,e.column)==f.maybeInsertedLineStart},d.popAutoInsertedClosing=function(){f.autoInsertedLineEnd=f.autoInsertedLineEnd.substr(1),f.autoInsertedBrackets--},d.clearMaybeInsertedClosing=function(){f&&(f.maybeInsertedBrackets=0,f.maybeInsertedRow=-1)},r.inherits(d,i),t.CstyleBehaviour=d}),define(\"ace/unicode\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";function r(e){var n=/\\w{4}/g;for(var r in e)t.packages[r]=e[r].replace(n,\"\\\\u$&\")}t.packages={},r({L:\"0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05250531-055605590561-058705D0-05EA05F0-05F20621-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0800-0815081A082408280904-0939093D09500958-0961097109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510D0-10FA10FC1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317D717DC1820-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541AA71B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF11D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209421022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2D00-2D252D30-2D652D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A65FA662-A66EA67F-A697A6A0-A6E5A717-A71FA722-A788A78BA78CA7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2A9CFAA00-AA28AA40-AA42AA44-AA4BAA60-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADB-AADDABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC\",Ll:\"0061-007A00AA00B500BA00DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F0521052305250561-05871D00-1D2B1D62-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7C2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2D00-2D25A641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CFB00-FB06FB13-FB17FF41-FF5A\",Lu:\"0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E0520052205240531-055610A0-10C51E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CEDA640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BFF21-FF3A\",Lt:\"01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC\",Lm:\"02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D611D781D9B-1DBF2071207F2090-20942C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A9CFAA70AADDFF70FF9EFF9F\",Lo:\"01BB01C0-01C3029405D0-05EA05F0-05F20621-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150904-0939093D09500958-096109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317DC1820-18421844-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF12135-21382D30-2D652D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC\",M:\"0300-036F0483-04890591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DE-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0903093C093E-094E0951-0955096209630981-098309BC09BE-09C409C709C809CB-09CD09D709E209E30A01-0A030A3C0A3E-0A420A470A480A4B-0A4D0A510A700A710A750A81-0A830ABC0ABE-0AC50AC7-0AC90ACB-0ACD0AE20AE30B01-0B030B3C0B3E-0B440B470B480B4B-0B4D0B560B570B620B630B820BBE-0BC20BC6-0BC80BCA-0BCD0BD70C01-0C030C3E-0C440C46-0C480C4A-0C4D0C550C560C620C630C820C830CBC0CBE-0CC40CC6-0CC80CCA-0CCD0CD50CD60CE20CE30D020D030D3E-0D440D46-0D480D4A-0D4D0D570D620D630D820D830DCA0DCF-0DD40DD60DD8-0DDF0DF20DF30E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F3E0F3F0F71-0F840F860F870F90-0F970F99-0FBC0FC6102B-103E1056-1059105E-10601062-10641067-106D1071-10741082-108D108F109A-109D135F1712-17141732-1734175217531772177317B6-17D317DD180B-180D18A91920-192B1930-193B19B0-19C019C819C91A17-1A1B1A55-1A5E1A60-1A7C1A7F1B00-1B041B34-1B441B6B-1B731B80-1B821BA1-1BAA1C24-1C371CD0-1CD21CD4-1CE81CED1CF21DC0-1DE61DFD-1DFF20D0-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66F-A672A67CA67DA6F0A6F1A802A806A80BA823-A827A880A881A8B4-A8C4A8E0-A8F1A926-A92DA947-A953A980-A983A9B3-A9C0AA29-AA36AA43AA4CAA4DAA7BAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE3-ABEAABECABEDFB1EFE00-FE0FFE20-FE26\",Mn:\"0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0902093C0941-0948094D0951-095509620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F90-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135F1712-17141732-1734175217531772177317B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1DC0-1DE61DFD-1DFF20D0-20DC20E120E5-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66FA67CA67DA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26\",Mc:\"0903093E-09400949-094C094E0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1C24-1C2B1C341C351CE11CF2A823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BABE3ABE4ABE6ABE7ABE9ABEAABEC\",Me:\"0488048906DE20DD-20E020E2-20E4A670-A672\",N:\"0030-003900B200B300B900BC-00BE0660-066906F0-06F907C0-07C90966-096F09E6-09EF09F4-09F90A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BF20C66-0C6F0C78-0C7E0CE6-0CEF0D66-0D750E50-0E590ED0-0ED90F20-0F331040-10491090-10991369-137C16EE-16F017E0-17E917F0-17F91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C5920702074-20792080-20892150-21822185-21892460-249B24EA-24FF2776-27932CFD30073021-30293038-303A3192-31953220-32293251-325F3280-328932B1-32BFA620-A629A6E6-A6EFA830-A835A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19\",Nd:\"0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19\",Nl:\"16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF\",No:\"00B200B300B900BC-00BE09F4-09F90BF0-0BF20C78-0C7E0D70-0D750F2A-0F331369-137C17F0-17F920702074-20792080-20892150-215F21892460-249B24EA-24FF2776-27932CFD3192-31953220-32293251-325F3280-328932B1-32BFA830-A835\",P:\"0021-00230025-002A002C-002F003A003B003F0040005B-005D005F007B007D00A100AB00B700BB00BF037E0387055A-055F0589058A05BE05C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F3A-0F3D0F850FD0-0FD4104A-104F10FB1361-13681400166D166E169B169C16EB-16ED1735173617D4-17D617D8-17DA1800-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD32010-20272030-20432045-20512053-205E207D207E208D208E2329232A2768-277527C527C627E6-27EF2983-299829D8-29DB29FC29FD2CF9-2CFC2CFE2CFF2E00-2E2E2E302E313001-30033008-30113014-301F3030303D30A030FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFD3EFD3FFE10-FE19FE30-FE52FE54-FE61FE63FE68FE6AFE6BFF01-FF03FF05-FF0AFF0C-FF0FFF1AFF1BFF1FFF20FF3B-FF3DFF3FFF5BFF5DFF5F-FF65\",Pd:\"002D058A05BE140018062010-20152E172E1A301C303030A0FE31FE32FE58FE63FF0D\",Ps:\"0028005B007B0F3A0F3C169B201A201E2045207D208D23292768276A276C276E27702772277427C527E627E827EA27EC27EE2983298529872989298B298D298F299129932995299729D829DA29FC2E222E242E262E283008300A300C300E3010301430163018301A301DFD3EFE17FE35FE37FE39FE3BFE3DFE3FFE41FE43FE47FE59FE5BFE5DFF08FF3BFF5BFF5FFF62\",Pe:\"0029005D007D0F3B0F3D169C2046207E208E232A2769276B276D276F27712773277527C627E727E927EB27ED27EF298429862988298A298C298E2990299229942996299829D929DB29FD2E232E252E272E293009300B300D300F3011301530173019301B301E301FFD3FFE18FE36FE38FE3AFE3CFE3EFE40FE42FE44FE48FE5AFE5CFE5EFF09FF3DFF5DFF60FF63\",Pi:\"00AB2018201B201C201F20392E022E042E092E0C2E1C2E20\",Pf:\"00BB2019201D203A2E032E052E0A2E0D2E1D2E21\",Pc:\"005F203F20402054FE33FE34FE4D-FE4FFF3F\",Po:\"0021-00230025-0027002A002C002E002F003A003B003F0040005C00A100B700BF037E0387055A-055F058905C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F850FD0-0FD4104A-104F10FB1361-1368166D166E16EB-16ED1735173617D4-17D617D8-17DA1800-18051807-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD3201620172020-20272030-2038203B-203E2041-20432047-205120532055-205E2CF9-2CFC2CFE2CFF2E002E012E06-2E082E0B2E0E-2E162E182E192E1B2E1E2E1F2E2A-2E2E2E302E313001-3003303D30FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFE10-FE16FE19FE30FE45FE46FE49-FE4CFE50-FE52FE54-FE57FE5F-FE61FE68FE6AFE6BFF01-FF03FF05-FF07FF0AFF0CFF0EFF0FFF1AFF1BFF1FFF20FF3CFF61FF64FF65\",S:\"0024002B003C-003E005E0060007C007E00A2-00A900AC00AE-00B100B400B600B800D700F702C2-02C502D2-02DF02E5-02EB02ED02EF-02FF03750384038503F604820606-0608060B060E060F06E906FD06FE07F609F209F309FA09FB0AF10B700BF3-0BFA0C7F0CF10CF20D790E3F0F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-139917DB194019E0-19FF1B61-1B6A1B74-1B7C1FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE20442052207A-207C208A-208C20A0-20B8210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B2140-2144214A-214D214F2190-2328232B-23E82400-24262440-244A249C-24E92500-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE27C0-27C427C7-27CA27CC27D0-27E527F0-29822999-29D729DC-29FB29FE-2B4C2B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F309B309C319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A700-A716A720A721A789A78AA828-A82BA836-A839AA77-AA79FB29FDFCFDFDFE62FE64-FE66FE69FF04FF0BFF1C-FF1EFF3EFF40FF5CFF5EFFE0-FFE6FFE8-FFEEFFFCFFFD\",Sm:\"002B003C-003E007C007E00AC00B100D700F703F60606-060820442052207A-207C208A-208C2140-2144214B2190-2194219A219B21A021A321A621AE21CE21CF21D221D421F4-22FF2308-230B23202321237C239B-23B323DC-23E125B725C125F8-25FF266F27C0-27C427C7-27CA27CC27D0-27E527F0-27FF2900-29822999-29D729DC-29FB29FE-2AFF2B30-2B442B47-2B4CFB29FE62FE64-FE66FF0BFF1C-FF1EFF5CFF5EFFE2FFE9-FFEC\",Sc:\"002400A2-00A5060B09F209F309FB0AF10BF90E3F17DB20A0-20B8A838FDFCFE69FF04FFE0FFE1FFE5FFE6\",Sk:\"005E006000A800AF00B400B802C2-02C502D2-02DF02E5-02EB02ED02EF-02FF0375038403851FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE309B309CA700-A716A720A721A789A78AFF3EFF40FFE3\",So:\"00A600A700A900AE00B000B60482060E060F06E906FD06FE07F609FA0B700BF3-0BF80BFA0C7F0CF10CF20D790F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-1399194019E0-19FF1B61-1B6A1B74-1B7C210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B214A214C214D214F2195-2199219C-219F21A121A221A421A521A7-21AD21AF-21CD21D021D121D321D5-21F32300-2307230C-231F2322-2328232B-237B237D-239A23B4-23DB23E2-23E82400-24262440-244A249C-24E92500-25B625B8-25C025C2-25F72600-266E2670-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE2800-28FF2B00-2B2F2B452B462B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A828-A82BA836A837A839AA77-AA79FDFDFFE4FFE8FFEDFFEEFFFCFFFD\",Z:\"002000A01680180E2000-200A20282029202F205F3000\",Zs:\"002000A01680180E2000-200A202F205F3000\",Zl:\"2028\",Zp:\"2029\",C:\"0000-001F007F-009F00AD03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-0605061C061D0620065F06DD070E070F074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17B417B517DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF200B-200F202A-202E2060-206F20722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-F8FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFD-FF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFFBFFFEFFFF\",Cc:\"0000-001F007F-009F\",Cf:\"00AD0600-060306DD070F17B417B5200B-200F202A-202E2060-2064206A-206FFEFFFFF9-FFFB\",Co:\"E000-F8FF\",Cs:\"D800-DFFF\",Cn:\"03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-05FF06040605061C061D0620065F070E074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF2065-206920722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-D7FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFDFEFEFF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFF8FFFEFFFF\"})}),define(\"ace/mode/text\",[\"require\",\"exports\",\"module\",\"ace/tokenizer\",\"ace/mode/text_highlight_rules\",\"ace/mode/behaviour/cstyle\",\"ace/unicode\",\"ace/lib/lang\",\"ace/token_iterator\",\"ace/range\"],function(e,t,n){\"use strict\";var r=e(\"../tokenizer\").Tokenizer,i=e(\"./text_highlight_rules\").TextHighlightRules,s=e(\"./behaviour/cstyle\").CstyleBehaviour,o=e(\"../unicode\"),u=e(\"../lib/lang\"),a=e(\"../token_iterator\").TokenIterator,f=e(\"../range\").Range,l=function(){this.HighlightRules=i};(function(){this.$defaultBehaviour=new s,this.tokenRe=new RegExp(\"^[\"+o.packages.L+o.packages.Mn+o.packages.Mc+o.packages.Nd+o.packages.Pc+\"\\\\$_]+\",\"g\"),this.nonTokenRe=new RegExp(\"^(?:[^\"+o.packages.L+o.packages.Mn+o.packages.Mc+o.packages.Nd+o.packages.Pc+\"\\\\$_]|\\\\s])+\",\"g\"),this.getTokenizer=function(){return this.$tokenizer||(this.$highlightRules=this.$highlightRules||new this.HighlightRules(this.$highlightRuleConfig),this.$tokenizer=new r(this.$highlightRules.getRules())),this.$tokenizer},this.lineCommentStart=\"\",this.blockComment=\"\",this.toggleCommentLines=function(e,t,n,r){function w(e){for(var t=n;t<=r;t++)e(i.getLine(t),t)}var i=t.doc,s=!0,o=!0,a=Infinity,f=t.getTabSize(),l=!1;if(!this.lineCommentStart){if(!this.blockComment)return!1;var c=this.blockComment.start,h=this.blockComment.end,p=new RegExp(\"^(\\\\s*)(?:\"+u.escapeRegExp(c)+\")\"),d=new RegExp(\"(?:\"+u.escapeRegExp(h)+\")\\\\s*$\"),v=function(e,t){if(g(e,t))return;if(!s||/\\S/.test(e))i.insertInLine({row:t,column:e.length},h),i.insertInLine({row:t,column:a},c)},m=function(e,t){var n;(n=e.match(d))&&i.removeInLine(t,e.length-n[0].length,e.length),(n=e.match(p))&&i.removeInLine(t,n[1].length,n[0].length)},g=function(e,n){if(p.test(e))return!0;var r=t.getTokens(n);for(var i=0;i<r.length;i++)if(r[i].type===\"comment\")return!0}}else{if(Array.isArray(this.lineCommentStart))var p=this.lineCommentStart.map(u.escapeRegExp).join(\"|\"),c=this.lineCommentStart[0];else var p=u.escapeRegExp(this.lineCommentStart),c=this.lineCommentStart;p=new RegExp(\"^(\\\\s*)(?:\"+p+\") ?\"),l=t.getUseSoftTabs();var m=function(e,t){var n=e.match(p);if(!n)return;var r=n[1].length,s=n[0].length;!b(e,r,s)&&n[0][s-1]==\" \"&&s--,i.removeInLine(t,r,s)},y=c+\" \",v=function(e,t){if(!s||/\\S/.test(e))b(e,a,a)?i.insertInLine({row:t,column:a},y):i.insertInLine({row:t,column:a},c)},g=function(e,t){return p.test(e)},b=function(e,t,n){var r=0;while(t--&&e.charAt(t)==\" \")r++;if(r%f!=0)return!1;var r=0;while(e.charAt(n++)==\" \")r++;return f>2?r%f!=f-1:r%f==0}}var E=Infinity;w(function(e,t){var n=e.search(/\\S/);n!==-1?(n<a&&(a=n),o&&!g(e,t)&&(o=!1)):E>e.length&&(E=e.length)}),a==Infinity&&(a=E,s=!1,o=!1),l&&a%f!=0&&(a=Math.floor(a/f)*f),w(o?m:v)},this.toggleBlockComment=function(e,t,n,r){var i=this.blockComment;if(!i)return;!i.start&&i[0]&&(i=i[0]);var s=new a(t,r.row,r.column),o=s.getCurrentToken(),u=t.selection,l=t.selection.toOrientedRange(),c,h;if(o&&/comment/.test(o.type)){var p,d;while(o&&/comment/.test(o.type)){var v=o.value.indexOf(i.start);if(v!=-1){var m=s.getCurrentTokenRow(),g=s.getCurrentTokenColumn()+v;p=new f(m,g,m,g+i.start.length);break}o=s.stepBackward()}var s=new a(t,r.row,r.column),o=s.getCurrentToken();while(o&&/comment/.test(o.type)){var v=o.value.indexOf(i.end);if(v!=-1){var m=s.getCurrentTokenRow(),g=s.getCurrentTokenColumn()+v;d=new f(m,g,m,g+i.end.length);break}o=s.stepForward()}d&&t.remove(d),p&&(t.remove(p),c=p.start.row,h=-i.start.length)}else h=i.start.length,c=n.start.row,t.insert(n.end,i.end),t.insert(n.start,i.start);l.start.row==c&&(l.start.column+=h),l.end.row==c&&(l.end.column+=h),t.selection.fromOrientedRange(l)},this.getNextLineIndent=function(e,t,n){return this.$getIndent(t)},this.checkOutdent=function(e,t,n){return!1},this.autoOutdent=function(e,t,n){},this.$getIndent=function(e){return e.match(/^\\s*/)[0]},this.createWorker=function(e){return null},this.createModeDelegates=function(e){this.$embeds=[],this.$modes={};for(var t in e)e[t]&&(this.$embeds.push(t),this.$modes[t]=new e[t]);var n=[\"toggleBlockComment\",\"toggleCommentLines\",\"getNextLineIndent\",\"checkOutdent\",\"autoOutdent\",\"transformAction\",\"getCompletions\"];for(var t=0;t<n.length;t++)(function(e){var r=n[t],i=e[r];e[n[t]]=function(){return this.$delegator(r,arguments,i)}})(this)},this.$delegator=function(e,t,n){var r=t[0];typeof r!=\"string\"&&(r=r[0]);for(var i=0;i<this.$embeds.length;i++){if(!this.$modes[this.$embeds[i]])continue;var s=r.split(this.$embeds[i]);if(!s[0]&&s[1]){t[0]=s[1];var o=this.$modes[this.$embeds[i]];return o[e].apply(o,t)}}var u=n.apply(this,t);return n?u:undefined},this.transformAction=function(e,t,n,r,i){if(this.$behaviour){var s=this.$behaviour.getBehaviours();for(var o in s)if(s[o][t]){var u=s[o][t].apply(this,arguments);if(u)return u}}},this.getKeywords=function(e){if(!this.completionKeywords){var t=this.$tokenizer.rules,n=[];for(var r in t){var i=t[r];for(var s=0,o=i.length;s<o;s++)if(typeof i[s].token==\"string\")/keyword|support|storage/.test(i[s].token)&&n.push(i[s].regex);else if(typeof i[s].token==\"object\")for(var u=0,a=i[s].token.length;u<a;u++)if(/keyword|support|storage/.test(i[s].token[u])){var r=i[s].regex.match(/\\(.+?\\)/g)[u];n.push(r.substr(1,r.length-2))}}this.completionKeywords=n}return e?n.concat(this.$keywordList||[]):this.$keywordList},this.$createKeywordList=function(){return this.$highlightRules||this.getTokenizer(),this.$keywordList=this.$highlightRules.$keywordList||[]},this.getCompletions=function(e,t,n,r){var i=this.$keywordList||this.$createKeywordList();return i.map(function(e){return{name:e,value:e,score:0,meta:\"keyword\"}})},this.$id=\"ace/mode/text\"}).call(l.prototype),t.Mode=l}),define(\"ace/apply_delta\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";function r(e,t){throw console.log(\"Invalid Delta:\",e),\"Invalid Delta: \"+t}function i(e,t){return t.row>=0&&t.row<e.length&&t.column>=0&&t.column<=e[t.row].length}function s(e,t){t.action!=\"insert\"&&t.action!=\"remove\"&&r(t,\"delta.action must be 'insert' or 'remove'\"),t.lines instanceof Array||r(t,\"delta.lines must be an Array\"),(!t.start||!t.end)&&r(t,\"delta.start/end must be an present\");var n=t.start;i(e,t.start)||r(t,\"delta.start must be contained in document\");var s=t.end;t.action==\"remove\"&&!i(e,s)&&r(t,\"delta.end must contained in document for 'remove' actions\");var o=s.row-n.row,u=s.column-(o==0?n.column:0);(o!=t.lines.length-1||t.lines[o].length!=u)&&r(t,\"delta.range must match delta lines\")}t.applyDelta=function(e,t,n){var r=t.start.row,i=t.start.column,s=e[r]||\"\";switch(t.action){case\"insert\":var o=t.lines;if(o.length===1)e[r]=s.substring(0,i)+t.lines[0]+s.substring(i);else{var u=[r,1].concat(t.lines);e.splice.apply(e,u),e[r]=s.substring(0,i)+e[r],e[r+t.lines.length-1]+=s.substring(i)}break;case\"remove\":var a=t.end.column,f=t.end.row;r===f?e[r]=s.substring(0,i)+s.substring(a):e.splice(r,f-r+1,s.substring(0,i)+e[f].substring(a))}}}),define(\"ace/anchor\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./lib/event_emitter\").EventEmitter,s=t.Anchor=function(e,t,n){this.$onChange=this.onChange.bind(this),this.attach(e),typeof n==\"undefined\"?this.setPosition(t.row,t.column):this.setPosition(t,n)};(function(){function e(e,t,n){var r=n?e.column<=t.column:e.column<t.column;return e.row<t.row||e.row==t.row&&r}function t(t,n,r){var i=t.action==\"insert\",s=(i?1:-1)*(t.end.row-t.start.row),o=(i?1:-1)*(t.end.column-t.start.column),u=t.start,a=i?u:t.end;return e(n,u,r)?{row:n.row,column:n.column}:e(a,n,!r)?{row:n.row+s,column:n.column+(n.row==a.row?o:0)}:{row:u.row,column:u.column}}r.implement(this,i),this.getPosition=function(){return this.$clipPositionToDocument(this.row,this.column)},this.getDocument=function(){return this.document},this.$insertRight=!1,this.onChange=function(e){if(e.start.row==e.end.row&&e.start.row!=this.row)return;if(e.start.row>this.row)return;var n=t(e,{row:this.row,column:this.column},this.$insertRight);this.setPosition(n.row,n.column,!0)},this.setPosition=function(e,t,n){var r;n?r={row:e,column:t}:r=this.$clipPositionToDocument(e,t);if(this.row==r.row&&this.column==r.column)return;var i={row:this.row,column:this.column};this.row=r.row,this.column=r.column,this._signal(\"change\",{old:i,value:r})},this.detach=function(){this.document.removeEventListener(\"change\",this.$onChange)},this.attach=function(e){this.document=e||this.document,this.document.on(\"change\",this.$onChange)},this.$clipPositionToDocument=function(e,t){var n={};return e>=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n}}).call(s.prototype)}),define(\"ace/document\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/apply_delta\",\"ace/lib/event_emitter\",\"ace/range\",\"ace/anchor\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./apply_delta\").applyDelta,s=e(\"./lib/event_emitter\").EventEmitter,o=e(\"./range\").Range,u=e(\"./anchor\").Anchor,a=function(e){this.$lines=[\"\"],e.length===0?this.$lines=[\"\"]:Array.isArray(e)?this.insertMergedLines({row:0,column:0},e):this.insert({row:0,column:0},e)};(function(){r.implement(this,s),this.setValue=function(e){var t=this.getLength()-1;this.remove(new o(0,0,t,this.getLine(t).length)),this.insert({row:0,column:0},e)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(e,t){return new u(this,e,t)},\"aaa\".split(/a/).length===0?this.$split=function(e){return e.replace(/\\r\\n|\\r/g,\"\\n\").split(\"\\n\")}:this.$split=function(e){return e.split(/\\r\\n|\\r|\\n/)},this.$detectNewLine=function(e){var t=e.match(/^.*?(\\r\\n|\\r|\\n)/m);this.$autoNewLine=t?t[1]:\"\\n\",this._signal(\"changeNewLineMode\")},this.getNewLineCharacter=function(){switch(this.$newLineMode){case\"windows\":return\"\\r\\n\";case\"unix\":return\"\\n\";default:return this.$autoNewLine||\"\\n\"}},this.$autoNewLine=\"\",this.$newLineMode=\"auto\",this.setNewLineMode=function(e){if(this.$newLineMode===e)return;this.$newLineMode=e,this._signal(\"changeNewLineMode\")},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(e){return e==\"\\r\\n\"||e==\"\\r\"||e==\"\\n\"},this.getLine=function(e){return this.$lines[e]||\"\"},this.getLines=function(e,t){return this.$lines.slice(e,t+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(e){return this.getLinesForRange(e).join(this.getNewLineCharacter())},this.getLinesForRange=function(e){var t;if(e.start.row===e.end.row)t=[this.getLine(e.start.row).substring(e.start.column,e.end.column)];else{t=this.getLines(e.start.row,e.end.row),t[0]=(t[0]||\"\").substring(e.start.column);var n=t.length-1;e.end.row-e.start.row==n&&(t[n]=t[n].substring(0,e.end.column))}return t},this.insertLines=function(e,t){return console.warn(\"Use of document.insertLines is deprecated. Use the insertFullLines method instead.\"),this.insertFullLines(e,t)},this.removeLines=function(e,t){return console.warn(\"Use of document.removeLines is deprecated. Use the removeFullLines method instead.\"),this.removeFullLines(e,t)},this.insertNewLine=function(e){return console.warn(\"Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead.\"),this.insertMergedLines(e,[\"\",\"\"])},this.insert=function(e,t){return this.getLength()<=1&&this.$detectNewLine(t),this.insertMergedLines(e,this.$split(t))},this.insertInLine=function(e,t){var n=this.clippedPos(e.row,e.column),r=this.pos(e.row,e.column+t.length);return this.applyDelta({start:n,end:r,action:\"insert\",lines:[t]},!0),this.clonePos(r)},this.clippedPos=function(e,t){var n=this.getLength();e===undefined?e=n:e<0?e=0:e>=n&&(e=n-1,t=undefined);var r=this.getLine(e);return t==undefined&&(t=r.length),t=Math.min(Math.max(t,0),r.length),{row:e,column:t}},this.clonePos=function(e){return{row:e.row,column:e.column}},this.pos=function(e,t){return{row:e,column:t}},this.$clipPosition=function(e){var t=this.getLength();return e.row>=t?(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length):(e.row=Math.max(0,e.row),e.column=Math.min(Math.max(e.column,0),this.getLine(e.row).length)),e},this.insertFullLines=function(e,t){e=Math.min(Math.max(e,0),this.getLength());var n=0;e<this.getLength()?(t=t.concat([\"\"]),n=0):(t=[\"\"].concat(t),e--,n=this.$lines[e].length),this.insertMergedLines({row:e,column:n},t)},this.insertMergedLines=function(e,t){var n=this.clippedPos(e.row,e.column),r={row:n.row+t.length-1,column:(t.length==1?n.column:0)+t[t.length-1].length};return this.applyDelta({start:n,end:r,action:\"insert\",lines:t}),this.clonePos(r)},this.remove=function(e){var t=this.clippedPos(e.start.row,e.start.column),n=this.clippedPos(e.end.row,e.end.column);return this.applyDelta({start:t,end:n,action:\"remove\",lines:this.getLinesForRange({start:t,end:n})}),this.clonePos(t)},this.removeInLine=function(e,t,n){var r=this.clippedPos(e,t),i=this.clippedPos(e,n);return this.applyDelta({start:r,end:i,action:\"remove\",lines:this.getLinesForRange({start:r,end:i})},!0),this.clonePos(r)},this.removeFullLines=function(e,t){e=Math.min(Math.max(0,e),this.getLength()-1),t=Math.min(Math.max(0,t),this.getLength()-1);var n=t==this.getLength()-1&&e>0,r=t<this.getLength()-1,i=n?e-1:e,s=n?this.getLine(i).length:0,u=r?t+1:t,a=r?0:this.getLine(u).length,f=new o(i,s,u,a),l=this.$lines.slice(e,t+1);return this.applyDelta({start:f.start,end:f.end,action:\"remove\",lines:this.getLinesForRange(f)}),l},this.removeNewLine=function(e){e<this.getLength()-1&&e>=0&&this.applyDelta({start:this.pos(e,this.getLine(e).length),end:this.pos(e+1,0),action:\"remove\",lines:[\"\",\"\"]})},this.replace=function(e,t){e instanceof o||(e=o.fromPoints(e.start,e.end));if(t.length===0&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);var n;return t?n=this.insert(e.start,t):n=e.start,n},this.applyDeltas=function(e){for(var t=0;t<e.length;t++)this.applyDelta(e[t])},this.revertDeltas=function(e){for(var t=e.length-1;t>=0;t--)this.revertDelta(e[t])},this.applyDelta=function(e,t){var n=e.action==\"insert\";if(n?e.lines.length<=1&&!e.lines[0]:!o.comparePoints(e.start,e.end))return;n&&e.lines.length>2e4&&this.$splitAndapplyLargeDelta(e,2e4),i(this.$lines,e,t),this._signal(\"change\",e)},this.$splitAndapplyLargeDelta=function(e,t){var n=e.lines,r=n.length,i=e.start.row,s=e.start.column,o=0,u=0;do{o=u,u+=t-1;var a=n.slice(o,u);if(u>r){e.lines=a,e.start.row=i+o,e.start.column=s;break}a.push(\"\"),this.applyDelta({start:this.pos(i+o,s),end:this.pos(i+u,s=0),action:e.action,lines:a},!0)}while(!0)},this.revertDelta=function(e){this.applyDelta({start:this.clonePos(e.start),end:this.clonePos(e.end),action:e.action==\"insert\"?\"remove\":\"insert\",lines:e.lines.slice()})},this.indexToPosition=function(e,t){var n=this.$lines||this.getAllLines(),r=this.getNewLineCharacter().length;for(var i=t||0,s=n.length;i<s;i++){e-=n[i].length+r;if(e<0)return{row:i,column:e+n[i].length+r}}return{row:s-1,column:n[s-1].length}},this.positionToIndex=function(e,t){var n=this.$lines||this.getAllLines(),r=this.getNewLineCharacter().length,i=0,s=Math.min(e.row,n.length);for(var o=t||0;o<s;++o)i+=n[o].length+r;return i+e.column}}).call(a.prototype),t.Document=a}),define(\"ace/background_tokenizer\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./lib/event_emitter\").EventEmitter,s=function(e,t){this.running=!1,this.lines=[],this.states=[],this.currentLine=0,this.tokenizer=e;var n=this;this.$worker=function(){if(!n.running)return;var e=new Date,t=n.currentLine,r=-1,i=n.doc,s=t;while(n.lines[t])t++;var o=i.getLength(),u=0;n.running=!1;while(t<o){n.$tokenizeRow(t),r=t;do t++;while(n.lines[t]);u++;if(u%5===0&&new Date-e>20){n.running=setTimeout(n.$worker,20);break}}n.currentLine=t,r==-1&&(r=t),s<=r&&n.fireUpdateEvent(s,r)}};(function(){r.implement(this,i),this.setTokenizer=function(e){this.tokenizer=e,this.lines=[],this.states=[],this.start(0)},this.setDocument=function(e){this.doc=e,this.lines=[],this.states=[],this.stop()},this.fireUpdateEvent=function(e,t){var n={first:e,last:t};this._signal(\"update\",{data:n})},this.start=function(e){this.currentLine=Math.min(e||0,this.currentLine,this.doc.getLength()),this.lines.splice(this.currentLine,this.lines.length),this.states.splice(this.currentLine,this.states.length),this.stop(),this.running=setTimeout(this.$worker,700)},this.scheduleStart=function(){this.running||(this.running=setTimeout(this.$worker,700))},this.$updateOnChange=function(e){var t=e.start.row,n=e.end.row-t;if(n===0)this.lines[t]=null;else if(e.action==\"remove\")this.lines.splice(t,n+1,null),this.states.splice(t,n+1,null);else{var r=Array(n+1);r.unshift(t,1),this.lines.splice.apply(this.lines,r),this.states.splice.apply(this.states,r)}this.currentLine=Math.min(t,this.currentLine,this.doc.getLength()),this.stop()},this.stop=function(){this.running&&clearTimeout(this.running),this.running=!1},this.getTokens=function(e){return this.lines[e]||this.$tokenizeRow(e)},this.getState=function(e){return this.currentLine==e&&this.$tokenizeRow(e),this.states[e]||\"start\"},this.$tokenizeRow=function(e){var t=this.doc.getLine(e),n=this.states[e-1],r=this.tokenizer.getLineTokens(t,n,e);return this.states[e]+\"\"!=r.state+\"\"?(this.states[e]=r.state,this.lines[e+1]=null,this.currentLine>e+1&&(this.currentLine=e+1)):this.currentLine==e&&(this.currentLine=e+1),this.lines[e]=r.tokens}}).call(s.prototype),t.BackgroundTokenizer=s}),define(\"ace/search_highlight\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\",\"ace/lib/oop\",\"ace/range\"],function(e,t,n){\"use strict\";var r=e(\"./lib/lang\"),i=e(\"./lib/oop\"),s=e(\"./range\").Range,o=function(e,t,n){this.setRegexp(e),this.clazz=t,this.type=n||\"text\"};(function(){this.MAX_RANGES=500,this.setRegexp=function(e){if(this.regExp+\"\"==e+\"\")return;this.regExp=e,this.cache=[]},this.update=function(e,t,n,i){if(!this.regExp)return;var o=i.firstRow,u=i.lastRow;for(var a=o;a<=u;a++){var f=this.cache[a];f==null&&(f=r.getMatchOffsets(n.getLine(a),this.regExp),f.length>this.MAX_RANGES&&(f=f.slice(0,this.MAX_RANGES)),f=f.map(function(e){return new s(a,e.offset,a,e.offset+e.length)}),this.cache[a]=f.length?f:\"\");for(var l=f.length;l--;)t.drawSingleLineMarker(e,f[l].toScreenRange(n),this.clazz,i)}}}).call(o.prototype),t.SearchHighlight=o}),define(\"ace/edit_session/fold_line\",[\"require\",\"exports\",\"module\",\"ace/range\"],function(e,t,n){\"use strict\";function i(e,t){this.foldData=e,Array.isArray(t)?this.folds=t:t=this.folds=[t];var n=t[t.length-1];this.range=new r(t[0].start.row,t[0].start.column,n.end.row,n.end.column),this.start=this.range.start,this.end=this.range.end,this.folds.forEach(function(e){e.setFoldLine(this)},this)}var r=e(\"../range\").Range;(function(){this.shiftRow=function(e){this.start.row+=e,this.end.row+=e,this.folds.forEach(function(t){t.start.row+=e,t.end.row+=e})},this.addFold=function(e){if(e.sameRow){if(e.start.row<this.startRow||e.endRow>this.endRow)throw new Error(\"Can't add a fold to this FoldLine as it has no connection\");this.folds.push(e),this.folds.sort(function(e,t){return-e.range.compareEnd(t.start.row,t.start.column)}),this.range.compareEnd(e.start.row,e.start.column)>0?(this.end.row=e.end.row,this.end.column=e.end.column):this.range.compareStart(e.end.row,e.end.column)<0&&(this.start.row=e.start.row,this.start.column=e.start.column)}else if(e.start.row==this.end.row)this.folds.push(e),this.end.row=e.end.row,this.end.column=e.end.column;else{if(e.end.row!=this.start.row)throw new Error(\"Trying to add fold to FoldRow that doesn't have a matching row\");this.folds.unshift(e),this.start.row=e.start.row,this.start.column=e.start.column}e.foldLine=this},this.containsRow=function(e){return e>=this.start.row&&e<=this.end.row},this.walk=function(e,t,n){var r=0,i=this.folds,s,o,u,a=!0;t==null&&(t=this.end.row,n=this.end.column);for(var f=0;f<i.length;f++){s=i[f],o=s.range.compareStart(t,n);if(o==-1){e(null,t,n,r,a);return}u=e(null,s.start.row,s.start.column,r,a),u=!u&&e(s.placeholder,s.start.row,s.start.column,r);if(u||o===0)return;a=!s.sameRow,r=s.end.column}e(null,t,n,r,a)},this.getNextFoldTo=function(e,t){var n,r;for(var i=0;i<this.folds.length;i++){n=this.folds[i],r=n.range.compareEnd(e,t);if(r==-1)return{fold:n,kind:\"after\"};if(r===0)return{fold:n,kind:\"inside\"}}return null},this.addRemoveChars=function(e,t,n){var r=this.getNextFoldTo(e,t),i,s;if(r){i=r.fold;if(r.kind==\"inside\"&&i.start.column!=t&&i.start.row!=e)window.console&&window.console.log(e,t,i);else if(i.start.row==e){s=this.folds;var o=s.indexOf(i);o===0&&(this.start.column+=n);for(o;o<s.length;o++){i=s[o],i.start.column+=n;if(!i.sameRow)return;i.end.column+=n}this.end.column+=n}}},this.split=function(e,t){var n=this.getNextFoldTo(e,t);if(!n||n.kind==\"inside\")return null;var r=n.fold,s=this.folds,o=this.foldData,u=s.indexOf(r),a=s[u-1];this.end.row=a.end.row,this.end.column=a.end.column,s=s.splice(u,s.length-u);var f=new i(o,s);return o.splice(o.indexOf(this)+1,0,f),f},this.merge=function(e){var t=e.folds;for(var n=0;n<t.length;n++)this.addFold(t[n]);var r=this.foldData;r.splice(r.indexOf(e),1)},this.toString=function(){var e=[this.range.toString()+\": [\"];return this.folds.forEach(function(t){e.push(\"  \"+t.toString())}),e.push(\"]\"),e.join(\"\\n\")},this.idxToPosition=function(e){var t=0;for(var n=0;n<this.folds.length;n++){var r=this.folds[n];e-=r.start.column-t;if(e<0)return{row:r.start.row,column:r.start.column+e};e-=r.placeholder.length;if(e<0)return r.start;t=r.end.column}return{row:this.end.row,column:this.end.column+e}}}).call(i.prototype),t.FoldLine=i}),define(\"ace/range_list\",[\"require\",\"exports\",\"module\",\"ace/range\"],function(e,t,n){\"use strict\";var r=e(\"./range\").Range,i=r.comparePoints,s=function(){this.ranges=[]};(function(){this.comparePoints=i,this.pointIndex=function(e,t,n){var r=this.ranges;for(var s=n||0;s<r.length;s++){var o=r[s],u=i(e,o.end);if(u>0)continue;var a=i(e,o.start);return u===0?t&&a!==0?-s-2:s:a>0||a===0&&!t?s:-s-1}return-s-1},this.add=function(e){var t=!e.isEmpty(),n=this.pointIndex(e.start,t);n<0&&(n=-n-1);var r=this.pointIndex(e.end,t,n);return r<0?r=-r-1:r++,this.ranges.splice(n,r-n,e)},this.addList=function(e){var t=[];for(var n=e.length;n--;)t.push.apply(t,this.add(e[n]));return t},this.substractPoint=function(e){var t=this.pointIndex(e);if(t>=0)return this.ranges.splice(t,1)},this.merge=function(){var e=[],t=this.ranges;t=t.sort(function(e,t){return i(e.start,t.start)});var n=t[0],r;for(var s=1;s<t.length;s++){r=n,n=t[s];var o=i(r.end,n.start);if(o<0)continue;if(o==0&&!r.isEmpty()&&!n.isEmpty())continue;i(r.end,n.end)<0&&(r.end.row=n.end.row,r.end.column=n.end.column),t.splice(s,1),e.push(n),n=r,s--}return this.ranges=t,e},this.contains=function(e,t){return this.pointIndex({row:e,column:t})>=0},this.containsPoint=function(e){return this.pointIndex(e)>=0},this.rangeAtPoint=function(e){var t=this.pointIndex(e);if(t>=0)return this.ranges[t]},this.clipRows=function(e,t){var n=this.ranges;if(n[0].start.row>t||n[n.length-1].start.row<e)return[];var r=this.pointIndex({row:e,column:0});r<0&&(r=-r-1);var i=this.pointIndex({row:t,column:0},r);i<0&&(i=-i-1);var s=[];for(var o=r;o<i;o++)s.push(n[o]);return s},this.removeAll=function(){return this.ranges.splice(0,this.ranges.length)},this.attach=function(e){this.session&&this.detach(),this.session=e,this.onChange=this.$onChange.bind(this),this.session.on(\"change\",this.onChange)},this.detach=function(){if(!this.session)return;this.session.removeListener(\"change\",this.onChange),this.session=null},this.$onChange=function(e){if(e.action==\"insert\")var t=e.start,n=e.end;else var n=e.start,t=e.end;var r=t.row,i=n.row,s=i-r,o=-t.column+n.column,u=this.ranges;for(var a=0,f=u.length;a<f;a++){var l=u[a];if(l.end.row<r)continue;if(l.start.row>r)break;l.start.row==r&&l.start.column>=t.column&&(l.start.column!=t.column||!this.$insertRight)&&(l.start.column+=o,l.start.row+=s);if(l.end.row==r&&l.end.column>=t.column){if(l.end.column==t.column&&this.$insertRight)continue;l.end.column==t.column&&o>0&&a<f-1&&l.end.column>l.start.column&&l.end.column==u[a+1].start.column&&(l.end.column-=o),l.end.column+=o,l.end.row+=s}}if(s!=0&&a<f)for(;a<f;a++){var l=u[a];l.start.row+=s,l.end.row+=s}}}).call(s.prototype),t.RangeList=s}),define(\"ace/edit_session/fold\",[\"require\",\"exports\",\"module\",\"ace/range\",\"ace/range_list\",\"ace/lib/oop\"],function(e,t,n){\"use strict\";function u(e,t){e.row-=t.row,e.row==0&&(e.column-=t.column)}function a(e,t){u(e.start,t),u(e.end,t)}function f(e,t){e.row==0&&(e.column+=t.column),e.row+=t.row}function l(e,t){f(e.start,t),f(e.end,t)}var r=e(\"../range\").Range,i=e(\"../range_list\").RangeList,s=e(\"../lib/oop\"),o=t.Fold=function(e,t){this.foldLine=null,this.placeholder=t,this.range=e,this.start=e.start,this.end=e.end,this.sameRow=e.start.row==e.end.row,this.subFolds=this.ranges=[]};s.inherits(o,i),function(){this.toString=function(){return'\"'+this.placeholder+'\" '+this.range.toString()},this.setFoldLine=function(e){this.foldLine=e,this.subFolds.forEach(function(t){t.setFoldLine(e)})},this.clone=function(){var e=this.range.clone(),t=new o(e,this.placeholder);return this.subFolds.forEach(function(e){t.subFolds.push(e.clone())}),t.collapseChildren=this.collapseChildren,t},this.addSubFold=function(e){if(this.range.isEqual(e))return;if(!this.range.containsRange(e))throw new Error(\"A fold can't intersect already existing fold\"+e.range+this.range);a(e,this.start);var t=e.start.row,n=e.start.column;for(var r=0,i=-1;r<this.subFolds.length;r++){i=this.subFolds[r].range.compare(t,n);if(i!=1)break}var s=this.subFolds[r];if(i==0)return s.addSubFold(e);var t=e.range.end.row,n=e.range.end.column;for(var o=r,i=-1;o<this.subFolds.length;o++){i=this.subFolds[o].range.compare(t,n);if(i!=1)break}var u=this.subFolds[o];if(i==0)throw new Error(\"A fold can't intersect already existing fold\"+e.range+this.range);var f=this.subFolds.splice(r,o-r,e);return e.setFoldLine(this.foldLine),e},this.restoreRange=function(e){return l(e,this.start)}}.call(o.prototype)}),define(\"ace/edit_session/folding\",[\"require\",\"exports\",\"module\",\"ace/range\",\"ace/edit_session/fold_line\",\"ace/edit_session/fold\",\"ace/token_iterator\"],function(e,t,n){\"use strict\";function u(){this.getFoldAt=function(e,t,n){var r=this.getFoldLine(e);if(!r)return null;var i=r.folds;for(var s=0;s<i.length;s++){var o=i[s];if(o.range.contains(e,t)){if(n==1&&o.range.isEnd(e,t))continue;if(n==-1&&o.range.isStart(e,t))continue;return o}}},this.getFoldsInRange=function(e){var t=e.start,n=e.end,r=this.$foldData,i=[];t.column+=1,n.column-=1;for(var s=0;s<r.length;s++){var o=r[s].range.compareRange(e);if(o==2)continue;if(o==-2)break;var u=r[s].folds;for(var a=0;a<u.length;a++){var f=u[a];o=f.range.compareRange(e);if(o==-2)break;if(o==2)continue;if(o==42)break;i.push(f)}}return t.column-=1,n.column+=1,i},this.getFoldsInRangeList=function(e){if(Array.isArray(e)){var t=[];e.forEach(function(e){t=t.concat(this.getFoldsInRange(e))},this)}else var t=this.getFoldsInRange(e);return t},this.getAllFolds=function(){var e=[],t=this.$foldData;for(var n=0;n<t.length;n++)for(var r=0;r<t[n].folds.length;r++)e.push(t[n].folds[r]);return e},this.getFoldStringAt=function(e,t,n,r){r=r||this.getFoldLine(e);if(!r)return null;var i={end:{column:0}},s,o;for(var u=0;u<r.folds.length;u++){o=r.folds[u];var a=o.range.compareEnd(e,t);if(a==-1){s=this.getLine(o.start.row).substring(i.end.column,o.start.column);break}if(a===0)return null;i=o}return s||(s=this.getLine(o.start.row).substring(i.end.column)),n==-1?s.substring(0,t-i.end.column):n==1?s.substring(t-i.end.column):s},this.getFoldLine=function(e,t){var n=this.$foldData,r=0;t&&(r=n.indexOf(t)),r==-1&&(r=0);for(r;r<n.length;r++){var i=n[r];if(i.start.row<=e&&i.end.row>=e)return i;if(i.end.row>e)return null}return null},this.getNextFoldLine=function(e,t){var n=this.$foldData,r=0;t&&(r=n.indexOf(t)),r==-1&&(r=0);for(r;r<n.length;r++){var i=n[r];if(i.end.row>=e)return i}return null},this.getFoldedRowCount=function(e,t){var n=this.$foldData,r=t-e+1;for(var i=0;i<n.length;i++){var s=n[i],o=s.end.row,u=s.start.row;if(o>=t){u<t&&(u>=e?r-=t-u:r=0);break}o>=e&&(u>=e?r-=o-u:r-=o-e+1)}return r},this.$addFoldLine=function(e){return this.$foldData.push(e),this.$foldData.sort(function(e,t){return e.start.row-t.start.row}),e},this.addFold=function(e,t){var n=this.$foldData,r=!1,o;e instanceof s?o=e:(o=new s(t,e),o.collapseChildren=t.collapseChildren),this.$clipRangeToDocument(o.range);var u=o.start.row,a=o.start.column,f=o.end.row,l=o.end.column;if(u<f||u==f&&a<=l-2){var c=this.getFoldAt(u,a,1),h=this.getFoldAt(f,l,-1);if(c&&h==c)return c.addSubFold(o);c&&!c.range.isStart(u,a)&&this.removeFold(c),h&&!h.range.isEnd(f,l)&&this.removeFold(h);var p=this.getFoldsInRange(o.range);p.length>0&&(this.removeFolds(p),p.forEach(function(e){o.addSubFold(e)}));for(var d=0;d<n.length;d++){var v=n[d];if(f==v.start.row){v.addFold(o),r=!0;break}if(u==v.end.row){v.addFold(o),r=!0;if(!o.sameRow){var m=n[d+1];if(m&&m.start.row==f){v.merge(m);break}}break}if(f<=v.start.row)break}return r||(v=this.$addFoldLine(new i(this.$foldData,o))),this.$useWrapMode?this.$updateWrapData(v.start.row,v.start.row):this.$updateRowLengthCache(v.start.row,v.start.row),this.$modified=!0,this._signal(\"changeFold\",{data:o,action:\"add\"}),o}throw new Error(\"The range has to be at least 2 characters width\")},this.addFolds=function(e){e.forEach(function(e){this.addFold(e)},this)},this.removeFold=function(e){var t=e.foldLine,n=t.start.row,r=t.end.row,i=this.$foldData,s=t.folds;if(s.length==1)i.splice(i.indexOf(t),1);else if(t.range.isEnd(e.end.row,e.end.column))s.pop(),t.end.row=s[s.length-1].end.row,t.end.column=s[s.length-1].end.column;else if(t.range.isStart(e.start.row,e.start.column))s.shift(),t.start.row=s[0].start.row,t.start.column=s[0].start.column;else if(e.sameRow)s.splice(s.indexOf(e),1);else{var o=t.split(e.start.row,e.start.column);s=o.folds,s.shift(),o.start.row=s[0].start.row,o.start.column=s[0].start.column}this.$updating||(this.$useWrapMode?this.$updateWrapData(n,r):this.$updateRowLengthCache(n,r)),this.$modified=!0,this._signal(\"changeFold\",{data:e,action:\"remove\"})},this.removeFolds=function(e){var t=[];for(var n=0;n<e.length;n++)t.push(e[n]);t.forEach(function(e){this.removeFold(e)},this),this.$modified=!0},this.expandFold=function(e){this.removeFold(e),e.subFolds.forEach(function(t){e.restoreRange(t),this.addFold(t)},this),e.collapseChildren>0&&this.foldAll(e.start.row+1,e.end.row,e.collapseChildren-1),e.subFolds=[]},this.expandFolds=function(e){e.forEach(function(e){this.expandFold(e)},this)},this.unfold=function(e,t){var n,i;e==null?(n=new r(0,0,this.getLength(),0),t=!0):typeof e==\"number\"?n=new r(e,0,e,this.getLine(e).length):\"row\"in e?n=r.fromPoints(e,e):n=e,i=this.getFoldsInRangeList(n);if(t)this.removeFolds(i);else{var s=i;while(s.length)this.expandFolds(s),s=this.getFoldsInRangeList(n)}if(i.length)return i},this.isRowFolded=function(e,t){return!!this.getFoldLine(e,t)},this.getRowFoldEnd=function(e,t){var n=this.getFoldLine(e,t);return n?n.end.row:e},this.getRowFoldStart=function(e,t){var n=this.getFoldLine(e,t);return n?n.start.row:e},this.getFoldDisplayLine=function(e,t,n,r,i){r==null&&(r=e.start.row),i==null&&(i=0),t==null&&(t=e.end.row),n==null&&(n=this.getLine(t).length);var s=this.doc,o=\"\";return e.walk(function(e,t,n,u){if(t<r)return;if(t==r){if(n<i)return;u=Math.max(i,u)}e!=null?o+=e:o+=s.getLine(t).substring(u,n)},t,n),o},this.getDisplayLine=function(e,t,n,r){var i=this.getFoldLine(e);if(!i){var s;return s=this.doc.getLine(e),s.substring(r||0,t||s.length)}return this.getFoldDisplayLine(i,e,t,n,r)},this.$cloneFoldData=function(){var e=[];return e=this.$foldData.map(function(t){var n=t.folds.map(function(e){return e.clone()});return new i(e,n)}),e},this.toggleFold=function(e){var t=this.selection,n=t.getRange(),r,i;if(n.isEmpty()){var s=n.start;r=this.getFoldAt(s.row,s.column);if(r){this.expandFold(r);return}(i=this.findMatchingBracket(s))?n.comparePoint(i)==1?n.end=i:(n.start=i,n.start.column++,n.end.column--):(i=this.findMatchingBracket({row:s.row,column:s.column+1}))?(n.comparePoint(i)==1?n.end=i:n.start=i,n.start.column++):n=this.getCommentFoldRange(s.row,s.column)||n}else{var o=this.getFoldsInRange(n);if(e&&o.length){this.expandFolds(o);return}o.length==1&&(r=o[0])}r||(r=this.getFoldAt(n.start.row,n.start.column));if(r&&r.range.toString()==n.toString()){this.expandFold(r);return}var u=\"...\";if(!n.isMultiLine()){u=this.getTextRange(n);if(u.length<4)return;u=u.trim().substring(0,2)+\"..\"}this.addFold(u,n)},this.getCommentFoldRange=function(e,t,n){var i=new o(this,e,t),s=i.getCurrentToken(),u=s.type;if(s&&/^comment|string/.test(u)){u=u.match(/comment|string/)[0],u==\"comment\"&&(u+=\"|doc-start\");var a=new RegExp(u),f=new r;if(n!=1){do s=i.stepBackward();while(s&&a.test(s.type));i.stepForward()}f.start.row=i.getCurrentTokenRow(),f.start.column=i.getCurrentTokenColumn()+2,i=new o(this,e,t);if(n!=-1){var l=-1;do{s=i.stepForward();if(l==-1){var c=this.getState(i.$row);a.test(c)||(l=i.$row)}else if(i.$row>l)break}while(s&&a.test(s.type));s=i.stepBackward()}else s=i.getCurrentToken();return f.end.row=i.getCurrentTokenRow(),f.end.column=i.getCurrentTokenColumn()+s.value.length-2,f}},this.foldAll=function(e,t,n){n==undefined&&(n=1e5);var r=this.foldWidgets;if(!r)return;t=t||this.getLength(),e=e||0;for(var i=e;i<t;i++){r[i]==null&&(r[i]=this.getFoldWidget(i));if(r[i]!=\"start\")continue;var s=this.getFoldWidgetRange(i);if(s&&s.isMultiLine()&&s.end.row<=t&&s.start.row>=e){i=s.end.row;try{var o=this.addFold(\"...\",s);o&&(o.collapseChildren=n)}catch(u){}}}},this.$foldStyles={manual:1,markbegin:1,markbeginend:1},this.$foldStyle=\"markbegin\",this.setFoldStyle=function(e){if(!this.$foldStyles[e])throw new Error(\"invalid fold style: \"+e+\"[\"+Object.keys(this.$foldStyles).join(\", \")+\"]\");if(this.$foldStyle==e)return;this.$foldStyle=e,e==\"manual\"&&this.unfold();var t=this.$foldMode;this.$setFolding(null),this.$setFolding(t)},this.$setFolding=function(e){if(this.$foldMode==e)return;this.$foldMode=e,this.off(\"change\",this.$updateFoldWidgets),this.off(\"tokenizerUpdate\",this.$tokenizerUpdateFoldWidgets),this._signal(\"changeAnnotation\");if(!e||this.$foldStyle==\"manual\"){this.foldWidgets=null;return}this.foldWidgets=[],this.getFoldWidget=e.getFoldWidget.bind(e,this,this.$foldStyle),this.getFoldWidgetRange=e.getFoldWidgetRange.bind(e,this,this.$foldStyle),this.$updateFoldWidgets=this.updateFoldWidgets.bind(this),this.$tokenizerUpdateFoldWidgets=this.tokenizerUpdateFoldWidgets.bind(this),this.on(\"change\",this.$updateFoldWidgets),this.on(\"tokenizerUpdate\",this.$tokenizerUpdateFoldWidgets)},this.getParentFoldRangeData=function(e,t){var n=this.foldWidgets;if(!n||t&&n[e])return{};var r=e-1,i;while(r>=0){var s=n[r];s==null&&(s=n[r]=this.getFoldWidget(r));if(s==\"start\"){var o=this.getFoldWidgetRange(r);i||(i=o);if(o&&o.end.row>=e)break}r--}return{range:r!==-1&&o,firstRange:i}},this.onFoldWidgetClick=function(e,t){t=t.domEvent;var n={children:t.shiftKey,all:t.ctrlKey||t.metaKey,siblings:t.altKey},r=this.$toggleFoldWidget(e,n);if(!r){var i=t.target||t.srcElement;i&&/ace_fold-widget/.test(i.className)&&(i.className+=\" ace_invalid\")}},this.$toggleFoldWidget=function(e,t){if(!this.getFoldWidget)return;var n=this.getFoldWidget(e),r=this.getLine(e),i=n===\"end\"?-1:1,s=this.getFoldAt(e,i===-1?0:r.length,i);if(s)return t.children||t.all?this.removeFold(s):this.expandFold(s),s;var o=this.getFoldWidgetRange(e,!0);if(o&&!o.isMultiLine()){s=this.getFoldAt(o.start.row,o.start.column,1);if(s&&o.isEqual(s.range))return this.removeFold(s),s}if(t.siblings){var u=this.getParentFoldRangeData(e);if(u.range)var a=u.range.start.row+1,f=u.range.end.row;this.foldAll(a,f,t.all?1e4:0)}else t.children?(f=o?o.end.row:this.getLength(),this.foldAll(e+1,f,t.all?1e4:0)):o&&(t.all&&(o.collapseChildren=1e4),this.addFold(\"...\",o));return o},this.toggleFoldWidget=function(e){var t=this.selection.getCursor().row;t=this.getRowFoldStart(t);var n=this.$toggleFoldWidget(t,{});if(n)return;var r=this.getParentFoldRangeData(t,!0);n=r.range||r.firstRange;if(n){t=n.start.row;var i=this.getFoldAt(t,this.getLine(t).length,1);i?this.removeFold(i):this.addFold(\"...\",n)}},this.updateFoldWidgets=function(e){var t=e.start.row,n=e.end.row-t;if(n===0)this.foldWidgets[t]=null;else if(e.action==\"remove\")this.foldWidgets.splice(t,n+1,null);else{var r=Array(n+1);r.unshift(t,1),this.foldWidgets.splice.apply(this.foldWidgets,r)}},this.tokenizerUpdateFoldWidgets=function(e){var t=e.data;t.first!=t.last&&this.foldWidgets.length>t.first&&this.foldWidgets.splice(t.first,this.foldWidgets.length)}}var r=e(\"../range\").Range,i=e(\"./fold_line\").FoldLine,s=e(\"./fold\").Fold,o=e(\"../token_iterator\").TokenIterator;t.Folding=u}),define(\"ace/edit_session/bracket_match\",[\"require\",\"exports\",\"module\",\"ace/token_iterator\",\"ace/range\"],function(e,t,n){\"use strict\";function s(){this.findMatchingBracket=function(e,t){if(e.column==0)return null;var n=t||this.getLine(e.row).charAt(e.column-1);if(n==\"\")return null;var r=n.match(/([\\(\\[\\{])|([\\)\\]\\}])/);return r?r[1]?this.$findClosingBracket(r[1],e):this.$findOpeningBracket(r[2],e):null},this.getBracketRange=function(e){var t=this.getLine(e.row),n=!0,r,s=t.charAt(e.column-1),o=s&&s.match(/([\\(\\[\\{])|([\\)\\]\\}])/);o||(s=t.charAt(e.column),e={row:e.row,column:e.column+1},o=s&&s.match(/([\\(\\[\\{])|([\\)\\]\\}])/),n=!1);if(!o)return null;if(o[1]){var u=this.$findClosingBracket(o[1],e);if(!u)return null;r=i.fromPoints(e,u),n||(r.end.column++,r.start.column--),r.cursor=r.end}else{var u=this.$findOpeningBracket(o[2],e);if(!u)return null;r=i.fromPoints(u,e),n||(r.start.column++,r.end.column--),r.cursor=r.start}return r},this.$brackets={\")\":\"(\",\"(\":\")\",\"]\":\"[\",\"[\":\"]\",\"{\":\"}\",\"}\":\"{\"},this.$findOpeningBracket=function(e,t,n){var i=this.$brackets[e],s=1,o=new r(this,t.row,t.column),u=o.getCurrentToken();u||(u=o.stepForward());if(!u)return;n||(n=new RegExp(\"(\\\\.?\"+u.type.replace(\".\",\"\\\\.\").replace(\"rparen\",\".paren\").replace(/\\b(?:end)\\b/,\"(?:start|begin|end)\")+\")+\"));var a=t.column-o.getCurrentTokenColumn()-2,f=u.value;for(;;){while(a>=0){var l=f.charAt(a);if(l==i){s-=1;if(s==0)return{row:o.getCurrentTokenRow(),column:a+o.getCurrentTokenColumn()}}else l==e&&(s+=1);a-=1}do u=o.stepBackward();while(u&&!n.test(u.type));if(u==null)break;f=u.value,a=f.length-1}return null},this.$findClosingBracket=function(e,t,n){var i=this.$brackets[e],s=1,o=new r(this,t.row,t.column),u=o.getCurrentToken();u||(u=o.stepForward());if(!u)return;n||(n=new RegExp(\"(\\\\.?\"+u.type.replace(\".\",\"\\\\.\").replace(\"lparen\",\".paren\").replace(/\\b(?:start|begin)\\b/,\"(?:start|begin|end)\")+\")+\"));var a=t.column-o.getCurrentTokenColumn();for(;;){var f=u.value,l=f.length;while(a<l){var c=f.charAt(a);if(c==i){s-=1;if(s==0)return{row:o.getCurrentTokenRow(),column:a+o.getCurrentTokenColumn()}}else c==e&&(s+=1);a+=1}do u=o.stepForward();while(u&&!n.test(u.type));if(u==null)break;a=0}return null}}var r=e(\"../token_iterator\").TokenIterator,i=e(\"../range\").Range;t.BracketMatch=s}),define(\"ace/edit_session\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/lang\",\"ace/config\",\"ace/lib/event_emitter\",\"ace/selection\",\"ace/mode/text\",\"ace/range\",\"ace/document\",\"ace/background_tokenizer\",\"ace/search_highlight\",\"ace/edit_session/folding\",\"ace/edit_session/bracket_match\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./lib/lang\"),s=e(\"./config\"),o=e(\"./lib/event_emitter\").EventEmitter,u=e(\"./selection\").Selection,a=e(\"./mode/text\").Mode,f=e(\"./range\").Range,l=e(\"./document\").Document,c=e(\"./background_tokenizer\").BackgroundTokenizer,h=e(\"./search_highlight\").SearchHighlight,p=function(e,t){this.$breakpoints=[],this.$decorations=[],this.$frontMarkers={},this.$backMarkers={},this.$markerId=1,this.$undoSelect=!0,this.$foldData=[],this.id=\"session\"+ ++p.$uid,this.$foldData.toString=function(){return this.join(\"\\n\")},this.on(\"changeFold\",this.onChangeFold.bind(this)),this.$onChange=this.onChange.bind(this);if(typeof e!=\"object\"||!e.getLine)e=new l(e);this.setDocument(e),this.selection=new u(this),s.resetOptions(this),this.setMode(t),s._signal(\"session\",this)};p.$uid=0,function(){function m(e){return e<4352?!1:e>=4352&&e<=4447||e>=4515&&e<=4519||e>=4602&&e<=4607||e>=9001&&e<=9002||e>=11904&&e<=11929||e>=11931&&e<=12019||e>=12032&&e<=12245||e>=12272&&e<=12283||e>=12288&&e<=12350||e>=12353&&e<=12438||e>=12441&&e<=12543||e>=12549&&e<=12589||e>=12593&&e<=12686||e>=12688&&e<=12730||e>=12736&&e<=12771||e>=12784&&e<=12830||e>=12832&&e<=12871||e>=12880&&e<=13054||e>=13056&&e<=19903||e>=19968&&e<=42124||e>=42128&&e<=42182||e>=43360&&e<=43388||e>=44032&&e<=55203||e>=55216&&e<=55238||e>=55243&&e<=55291||e>=63744&&e<=64255||e>=65040&&e<=65049||e>=65072&&e<=65106||e>=65108&&e<=65126||e>=65128&&e<=65131||e>=65281&&e<=65376||e>=65504&&e<=65510}r.implement(this,o),this.setDocument=function(e){this.doc&&this.doc.removeListener(\"change\",this.$onChange),this.doc=e,e.on(\"change\",this.$onChange),this.bgTokenizer&&this.bgTokenizer.setDocument(this.getDocument()),this.resetCaches()},this.getDocument=function(){return this.doc},this.$resetRowCache=function(e){if(!e){this.$docRowCache=[],this.$screenRowCache=[];return}var t=this.$docRowCache.length,n=this.$getRowCacheIndex(this.$docRowCache,e)+1;t>n&&(this.$docRowCache.splice(n,t),this.$screenRowCache.splice(n,t))},this.$getRowCacheIndex=function(e,t){var n=0,r=e.length-1;while(n<=r){var i=n+r>>1,s=e[i];if(t>s)n=i+1;else{if(!(t<s))return i;r=i-1}}return n-1},this.resetCaches=function(){this.$modified=!0,this.$wrapData=[],this.$rowLengthCache=[],this.$resetRowCache(0),this.bgTokenizer&&this.bgTokenizer.start(0)},this.onChangeFold=function(e){var t=e.data;this.$resetRowCache(t.start.row)},this.onChange=function(e){this.$modified=!0,this.$resetRowCache(e.start.row);var t=this.$updateInternalDataOnChange(e);!this.$fromUndo&&this.$undoManager&&!e.ignore&&(this.$deltasDoc.push(e),t&&t.length!=0&&this.$deltasFold.push({action:\"removeFolds\",folds:t}),this.$informUndoManager.schedule()),this.bgTokenizer&&this.bgTokenizer.$updateOnChange(e),this._signal(\"change\",e)},this.setValue=function(e){this.doc.setValue(e),this.selection.moveTo(0,0),this.$resetRowCache(0),this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.setUndoManager(this.$undoManager),this.getUndoManager().reset()},this.getValue=this.toString=function(){return this.doc.getValue()},this.getSelection=function(){return this.selection},this.getState=function(e){return this.bgTokenizer.getState(e)},this.getTokens=function(e){return this.bgTokenizer.getTokens(e)},this.getTokenAt=function(e,t){var n=this.bgTokenizer.getTokens(e),r,i=0;if(t==null)s=n.length-1,i=this.getLine(e).length;else for(var s=0;s<n.length;s++){i+=n[s].value.length;if(i>=t)break}return r=n[s],r?(r.index=s,r.start=i-r.value.length,r):null},this.setUndoManager=function(e){this.$undoManager=e,this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.$informUndoManager&&this.$informUndoManager.cancel();if(e){var t=this;this.$syncInformUndoManager=function(){t.$informUndoManager.cancel(),t.$deltasFold.length&&(t.$deltas.push({group:\"fold\",deltas:t.$deltasFold}),t.$deltasFold=[]),t.$deltasDoc.length&&(t.$deltas.push({group:\"doc\",deltas:t.$deltasDoc}),t.$deltasDoc=[]),t.$deltas.length>0&&e.execute({action:\"aceupdate\",args:[t.$deltas,t],merge:t.mergeUndoDeltas}),t.mergeUndoDeltas=!1,t.$deltas=[]},this.$informUndoManager=i.delayedCall(this.$syncInformUndoManager)}},this.markUndoGroup=function(){this.$syncInformUndoManager&&this.$syncInformUndoManager()},this.$defaultUndoManager={undo:function(){},redo:function(){},reset:function(){}},this.getUndoManager=function(){return this.$undoManager||this.$defaultUndoManager},this.getTabString=function(){return this.getUseSoftTabs()?i.stringRepeat(\" \",this.getTabSize()):\"    \"},this.setUseSoftTabs=function(e){this.setOption(\"useSoftTabs\",e)},this.getUseSoftTabs=function(){return this.$useSoftTabs&&!this.$mode.$indentWithTabs},this.setTabSize=function(e){this.setOption(\"tabSize\",e)},this.getTabSize=function(){return this.$tabSize},this.isTabStop=function(e){return this.$useSoftTabs&&e.column%this.$tabSize===0},this.setNavigateWithinSoftTabs=function(e){this.setOption(\"navigateWithinSoftTabs\",e)},this.getNavigateWithinSoftTabs=function(){return this.$navigateWithinSoftTabs},this.$overwrite=!1,this.setOverwrite=function(e){this.setOption(\"overwrite\",e)},this.getOverwrite=function(){return this.$overwrite},this.toggleOverwrite=function(){this.setOverwrite(!this.$overwrite)},this.addGutterDecoration=function(e,t){this.$decorations[e]||(this.$decorations[e]=\"\"),this.$decorations[e]+=\" \"+t,this._signal(\"changeBreakpoint\",{})},this.removeGutterDecoration=function(e,t){this.$decorations[e]=(this.$decorations[e]||\"\").replace(\" \"+t,\"\"),this._signal(\"changeBreakpoint\",{})},this.getBreakpoints=function(){return this.$breakpoints},this.setBreakpoints=function(e){this.$breakpoints=[];for(var t=0;t<e.length;t++)this.$breakpoints[e[t]]=\"ace_breakpoint\";this._signal(\"changeBreakpoint\",{})},this.clearBreakpoints=function(){this.$breakpoints=[],this._signal(\"changeBreakpoint\",{})},this.setBreakpoint=function(e,t){t===undefined&&(t=\"ace_breakpoint\"),t?this.$breakpoints[e]=t:delete this.$breakpoints[e],this._signal(\"changeBreakpoint\",{})},this.clearBreakpoint=function(e){delete this.$breakpoints[e],this._signal(\"changeBreakpoint\",{})},this.addMarker=function(e,t,n,r){var i=this.$markerId++,s={range:e,type:n||\"line\",renderer:typeof n==\"function\"?n:null,clazz:t,inFront:!!r,id:i};return r?(this.$frontMarkers[i]=s,this._signal(\"changeFrontMarker\")):(this.$backMarkers[i]=s,this._signal(\"changeBackMarker\")),i},this.addDynamicMarker=function(e,t){if(!e.update)return;var n=this.$markerId++;return e.id=n,e.inFront=!!t,t?(this.$frontMarkers[n]=e,this._signal(\"changeFrontMarker\")):(this.$backMarkers[n]=e,this._signal(\"changeBackMarker\")),e},this.removeMarker=function(e){var t=this.$frontMarkers[e]||this.$backMarkers[e];if(!t)return;var n=t.inFront?this.$frontMarkers:this.$backMarkers;t&&(delete n[e],this._signal(t.inFront?\"changeFrontMarker\":\"changeBackMarker\"))},this.getMarkers=function(e){return e?this.$frontMarkers:this.$backMarkers},this.highlight=function(e){if(!this.$searchHighlight){var t=new h(null,\"ace_selected-word\",\"text\");this.$searchHighlight=this.addDynamicMarker(t)}this.$searchHighlight.setRegexp(e)},this.highlightLines=function(e,t,n,r){typeof t!=\"number\"&&(n=t,t=e),n||(n=\"ace_step\");var i=new f(e,0,t,Infinity);return i.id=this.addMarker(i,n,\"fullLine\",r),i},this.setAnnotations=function(e){this.$annotations=e,this._signal(\"changeAnnotation\",{})},this.getAnnotations=function(){return this.$annotations||[]},this.clearAnnotations=function(){this.setAnnotations([])},this.$detectNewLine=function(e){var t=e.match(/^.*?(\\r?\\n)/m);t?this.$autoNewLine=t[1]:this.$autoNewLine=\"\\n\"},this.getWordRange=function(e,t){var n=this.getLine(e),r=!1;t>0&&(r=!!n.charAt(t-1).match(this.tokenRe)),r||(r=!!n.charAt(t).match(this.tokenRe));if(r)var i=this.tokenRe;else if(/^\\s+$/.test(n.slice(t-1,t+1)))var i=/\\s/;else var i=this.nonTokenRe;var s=t;if(s>0){do s--;while(s>=0&&n.charAt(s).match(i));s++}var o=t;while(o<n.length&&n.charAt(o).match(i))o++;return new f(e,s,e,o)},this.getAWordRange=function(e,t){var n=this.getWordRange(e,t),r=this.getLine(n.end.row);while(r.charAt(n.end.column).match(/[ \\t]/))n.end.column+=1;return n},this.setNewLineMode=function(e){this.doc.setNewLineMode(e)},this.getNewLineMode=function(){return this.doc.getNewLineMode()},this.setUseWorker=function(e){this.setOption(\"useWorker\",e)},this.getUseWorker=function(){return this.$useWorker},this.onReloadTokenizer=function(e){var t=e.data;this.bgTokenizer.start(t.first),this._signal(\"tokenizerUpdate\",e)},this.$modes={},this.$mode=null,this.$modeId=null,this.setMode=function(e,t){if(e&&typeof e==\"object\"){if(e.getTokenizer)return this.$onChangeMode(e);var n=e,r=n.path}else r=e||\"ace/mode/text\";this.$modes[\"ace/mode/text\"]||(this.$modes[\"ace/mode/text\"]=new a);if(this.$modes[r]&&!n){this.$onChangeMode(this.$modes[r]),t&&t();return}this.$modeId=r,s.loadModule([\"mode\",r],function(e){if(this.$modeId!==r)return t&&t();this.$modes[r]&&!n?this.$onChangeMode(this.$modes[r]):e&&e.Mode&&(e=new e.Mode(n),n||(this.$modes[r]=e,e.$id=r),this.$onChangeMode(e)),t&&t()}.bind(this)),this.$mode||this.$onChangeMode(this.$modes[\"ace/mode/text\"],!0)},this.$onChangeMode=function(e,t){t||(this.$modeId=e.$id);if(this.$mode===e)return;this.$mode=e,this.$stopWorker(),this.$useWorker&&this.$startWorker();var n=e.getTokenizer();if(n.addEventListener!==undefined){var r=this.onReloadTokenizer.bind(this);n.addEventListener(\"update\",r)}if(!this.bgTokenizer){this.bgTokenizer=new c(n);var i=this;this.bgTokenizer.addEventListener(\"update\",function(e){i._signal(\"tokenizerUpdate\",e)})}else this.bgTokenizer.setTokenizer(n);this.bgTokenizer.setDocument(this.getDocument()),this.tokenRe=e.tokenRe,this.nonTokenRe=e.nonTokenRe,t||(e.attachToSession&&e.attachToSession(this),this.$options.wrapMethod.set.call(this,this.$wrapMethod),this.$setFolding(e.foldingRules),this.bgTokenizer.start(0),this._emit(\"changeMode\"))},this.$stopWorker=function(){this.$worker&&(this.$worker.terminate(),this.$worker=null)},this.$startWorker=function(){try{this.$worker=this.$mode.createWorker(this)}catch(e){s.warn(\"Could not load worker\",e),this.$worker=null}},this.getMode=function(){return this.$mode},this.$scrollTop=0,this.setScrollTop=function(e){if(this.$scrollTop===e||isNaN(e))return;this.$scrollTop=e,this._signal(\"changeScrollTop\",e)},this.getScrollTop=function(){return this.$scrollTop},this.$scrollLeft=0,this.setScrollLeft=function(e){if(this.$scrollLeft===e||isNaN(e))return;this.$scrollLeft=e,this._signal(\"changeScrollLeft\",e)},this.getScrollLeft=function(){return this.$scrollLeft},this.getScreenWidth=function(){return this.$computeWidth(),this.lineWidgets?Math.max(this.getLineWidgetMaxWidth(),this.screenWidth):this.screenWidth},this.getLineWidgetMaxWidth=function(){if(this.lineWidgetsWidth!=null)return this.lineWidgetsWidth;var e=0;return this.lineWidgets.forEach(function(t){t&&t.screenWidth>e&&(e=t.screenWidth)}),this.lineWidgetWidth=e},this.$computeWidth=function(e){if(this.$modified||e){this.$modified=!1;if(this.$useWrapMode)return this.screenWidth=this.$wrapLimit;var t=this.doc.getAllLines(),n=this.$rowLengthCache,r=0,i=0,s=this.$foldData[i],o=s?s.start.row:Infinity,u=t.length;for(var a=0;a<u;a++){if(a>o){a=s.end.row+1;if(a>=u)break;s=this.$foldData[i++],o=s?s.start.row:Infinity}n[a]==null&&(n[a]=this.$getStringScreenWidth(t[a])[0]),n[a]>r&&(r=n[a])}this.screenWidth=r}},this.getLine=function(e){return this.doc.getLine(e)},this.getLines=function(e,t){return this.doc.getLines(e,t)},this.getLength=function(){return this.doc.getLength()},this.getTextRange=function(e){return this.doc.getTextRange(e||this.selection.getRange())},this.insert=function(e,t){return this.doc.insert(e,t)},this.remove=function(e){return this.doc.remove(e)},this.removeFullLines=function(e,t){return this.doc.removeFullLines(e,t)},this.undoChanges=function(e,t){if(!e.length)return;this.$fromUndo=!0;var n=null;for(var r=e.length-1;r!=-1;r--){var i=e[r];i.group==\"doc\"?(this.doc.revertDeltas(i.deltas),n=this.$getUndoSelection(i.deltas,!0,n)):i.deltas.forEach(function(e){this.addFolds(e.folds)},this)}return this.$fromUndo=!1,n&&this.$undoSelect&&!t&&this.selection.setSelectionRange(n),n},this.redoChanges=function(e,t){if(!e.length)return;this.$fromUndo=!0;var n=null;for(var r=0;r<e.length;r++){var i=e[r];i.group==\"doc\"&&(this.doc.applyDeltas(i.deltas),n=this.$getUndoSelection(i.deltas,!1,n))}return this.$fromUndo=!1,n&&this.$undoSelect&&!t&&this.selection.setSelectionRange(n),n},this.setUndoSelect=function(e){this.$undoSelect=e},this.$getUndoSelection=function(e,t,n){function r(e){return t?e.action!==\"insert\":e.action===\"insert\"}var i=e[0],s,o,u=!1;r(i)?(s=f.fromPoints(i.start,i.end),u=!0):(s=f.fromPoints(i.start,i.start),u=!1);for(var a=1;a<e.length;a++)i=e[a],r(i)?(o=i.start,s.compare(o.row,o.column)==-1&&s.setStart(o),o=i.end,s.compare(o.row,o.column)==1&&s.setEnd(o),u=!0):(o=i.start,s.compare(o.row,o.column)==-1&&(s=f.fromPoints(i.start,i.start)),u=!1);if(n!=null){f.comparePoints(n.start,s.start)===0&&(n.start.column+=s.end.column-s.start.column,n.end.column+=s.end.column-s.start.column);var l=n.compareRange(s);l==1?s.setStart(n.start):l==-1&&s.setEnd(n.end)}return s},this.replace=function(e,t){return this.doc.replace(e,t)},this.moveText=function(e,t,n){var r=this.getTextRange(e),i=this.getFoldsInRange(e),s=f.fromPoints(t,t);if(!n){this.remove(e);var o=e.start.row-e.end.row,u=o?-e.end.column:e.start.column-e.end.column;u&&(s.start.row==e.end.row&&s.start.column>e.end.column&&(s.start.column+=u),s.end.row==e.end.row&&s.end.column>e.end.column&&(s.end.column+=u)),o&&s.start.row>=e.end.row&&(s.start.row+=o,s.end.row+=o)}s.end=this.insert(s.start,r);if(i.length){var a=e.start,l=s.start,o=l.row-a.row,u=l.column-a.column;this.addFolds(i.map(function(e){return e=e.clone(),e.start.row==a.row&&(e.start.column+=u),e.end.row==a.row&&(e.end.column+=u),e.start.row+=o,e.end.row+=o,e}))}return s},this.indentRows=function(e,t,n){n=n.replace(/\\t/g,this.getTabString());for(var r=e;r<=t;r++)this.doc.insertInLine({row:r,column:0},n)},this.outdentRows=function(e){var t=e.collapseRows(),n=new f(0,0,0,0),r=this.getTabSize();for(var i=t.start.row;i<=t.end.row;++i){var s=this.getLine(i);n.start.row=i,n.end.row=i;for(var o=0;o<r;++o)if(s.charAt(o)!=\" \")break;o<r&&s.charAt(o)==\" \"?(n.start.column=o,n.end.column=o+1):(n.start.column=0,n.end.column=o),this.remove(n)}},this.$moveLines=function(e,t,n){e=this.getRowFoldStart(e),t=this.getRowFoldEnd(t);if(n<0){var r=this.getRowFoldStart(e+n);if(r<0)return 0;var i=r-e}else if(n>0){var r=this.getRowFoldEnd(t+n);if(r>this.doc.getLength()-1)return 0;var i=r-t}else{e=this.$clipRowToDocument(e),t=this.$clipRowToDocument(t);var i=t-e+1}var s=new f(e,0,t,Number.MAX_VALUE),o=this.getFoldsInRange(s).map(function(e){return e=e.clone(),e.start.row+=i,e.end.row+=i,e}),u=n==0?this.doc.getLines(e,t):this.doc.removeFullLines(e,t);return this.doc.insertFullLines(e+i,u),o.length&&this.addFolds(o),i},this.moveLinesUp=function(e,t){return this.$moveLines(e,t,-1)},this.moveLinesDown=function(e,t){return this.$moveLines(e,t,1)},this.duplicateLines=function(e,t){return this.$moveLines(e,t,0)},this.$clipRowToDocument=function(e){return Math.max(0,Math.min(e,this.doc.getLength()-1))},this.$clipColumnToRow=function(e,t){return t<0?0:Math.min(this.doc.getLine(e).length,t)},this.$clipPositionToDocument=function(e,t){t=Math.max(0,t);if(e<0)e=0,t=0;else{var n=this.doc.getLength();e>=n?(e=n-1,t=this.doc.getLine(n-1).length):t=Math.min(this.doc.getLine(e).length,t)}return{row:e,column:t}},this.$clipRangeToDocument=function(e){e.start.row<0?(e.start.row=0,e.start.column=0):e.start.column=this.$clipColumnToRow(e.start.row,e.start.column);var t=this.doc.getLength()-1;return e.end.row>t?(e.end.row=t,e.end.column=this.doc.getLine(t).length):e.end.column=this.$clipColumnToRow(e.end.row,e.end.column),e},this.$wrapLimit=80,this.$useWrapMode=!1,this.$wrapLimitRange={min:null,max:null},this.setUseWrapMode=function(e){if(e!=this.$useWrapMode){this.$useWrapMode=e,this.$modified=!0,this.$resetRowCache(0);if(e){var t=this.getLength();this.$wrapData=Array(t),this.$updateWrapData(0,t-1)}this._signal(\"changeWrapMode\")}},this.getUseWrapMode=function(){return this.$useWrapMode},this.setWrapLimitRange=function(e,t){if(this.$wrapLimitRange.min!==e||this.$wrapLimitRange.max!==t)this.$wrapLimitRange={min:e,max:t},this.$modified=!0,this.$useWrapMode&&this._signal(\"changeWrapMode\")},this.adjustWrapLimit=function(e,t){var n=this.$wrapLimitRange;n.max<0&&(n={min:t,max:t});var r=this.$constrainWrapLimit(e,n.min,n.max);return r!=this.$wrapLimit&&r>1?(this.$wrapLimit=r,this.$modified=!0,this.$useWrapMode&&(this.$updateWrapData(0,this.getLength()-1),this.$resetRowCache(0),this._signal(\"changeWrapLimit\")),!0):!1},this.$constrainWrapLimit=function(e,t,n){return t&&(e=Math.max(t,e)),n&&(e=Math.min(n,e)),e},this.getWrapLimit=function(){return this.$wrapLimit},this.setWrapLimit=function(e){this.setWrapLimitRange(e,e)},this.getWrapLimitRange=function(){return{min:this.$wrapLimitRange.min,max:this.$wrapLimitRange.max}},this.$updateInternalDataOnChange=function(e){var t=this.$useWrapMode,n=e.action,r=e.start,i=e.end,s=r.row,o=i.row,u=o-s,a=null;this.$updating=!0;if(u!=0)if(n===\"remove\"){this[t?\"$wrapData\":\"$rowLengthCache\"].splice(s,u);var f=this.$foldData;a=this.getFoldsInRange(e),this.removeFolds(a);var l=this.getFoldLine(i.row),c=0;if(l){l.addRemoveChars(i.row,i.column,r.column-i.column),l.shiftRow(-u);var h=this.getFoldLine(s);h&&h!==l&&(h.merge(l),l=h),c=f.indexOf(l)+1}for(c;c<f.length;c++){var l=f[c];l.start.row>=i.row&&l.shiftRow(-u)}o=s}else{var p=Array(u);p.unshift(s,0);var d=t?this.$wrapData:this.$rowLengthCache;d.splice.apply(d,p);var f=this.$foldData,l=this.getFoldLine(s),c=0;if(l){var v=l.range.compareInside(r.row,r.column);v==0?(l=l.split(r.row,r.column),l&&(l.shiftRow(u),l.addRemoveChars(o,0,i.column-r.column))):v==-1&&(l.addRemoveChars(s,0,i.column-r.column),l.shiftRow(u)),c=f.indexOf(l)+1}for(c;c<f.length;c++){var l=f[c];l.start.row>=s&&l.shiftRow(u)}}else{u=Math.abs(e.start.column-e.end.column),n===\"remove\"&&(a=this.getFoldsInRange(e),this.removeFolds(a),u=-u);var l=this.getFoldLine(s);l&&l.addRemoveChars(s,r.column,u)}return t&&this.$wrapData.length!=this.doc.getLength()&&console.error(\"doc.getLength() and $wrapData.length have to be the same!\"),this.$updating=!1,t?this.$updateWrapData(s,o):this.$updateRowLengthCache(s,o),a},this.$updateRowLengthCache=function(e,t,n){this.$rowLengthCache[e]=null,this.$rowLengthCache[t]=null},this.$updateWrapData=function(e,t){var r=this.doc.getAllLines(),i=this.getTabSize(),s=this.$wrapData,o=this.$wrapLimit,a,f,l=e;t=Math.min(t,r.length-1);while(l<=t)f=this.getFoldLine(l,f),f?(a=[],f.walk(function(e,t,i,s){var o;if(e!=null){o=this.$getDisplayTokens(e,a.length),o[0]=n;for(var f=1;f<o.length;f++)o[f]=u}else o=this.$getDisplayTokens(r[t].substring(s,i),a.length);a=a.concat(o)}.bind(this),f.end.row,r[f.end.row].length+1),s[f.start.row]=this.$computeWrapSplits(a,o,i),l=f.end.row+1):(a=this.$getDisplayTokens(r[l]),s[l]=this.$computeWrapSplits(a,o,i),l++)};var e=1,t=2,n=3,u=4,l=9,p=10,d=11,v=12;this.$computeWrapSplits=function(e,r,i){function g(){var t=0;if(m===0)return t;if(h)for(var n=0;n<e.length;n++){var r=e[n];if(r==p)t+=1;else{if(r!=d){if(r==v)continue;break}t+=i}}return c&&h!==!1&&(t+=i),Math.min(t,m)}function y(t){var n=e.slice(a,t),r=n.length;n.join(\"\").replace(/12/g,function(){r-=1}).replace(/2/g,function(){r-=1}),s.length||(b=g(),s.indent=b),f+=r,s.push(f),a=t}if(e.length==0)return[];var s=[],o=e.length,a=0,f=0,c=this.$wrapAsCode,h=this.$indentedSoftWrap,m=r<=Math.max(2*i,8)||h===!1?0:Math.floor(r/2),b=0;while(o-a>r-b){var w=a+r-b;if(e[w-1]>=p&&e[w]>=p){y(w);continue}if(e[w]==n||e[w]==u){for(w;w!=a-1;w--)if(e[w]==n)break;if(w>a){y(w);continue}w=a+r;for(w;w<e.length;w++)if(e[w]!=u)break;if(w==e.length)break;y(w);continue}var E=Math.max(w-(r-(r>>2)),a-1);while(w>E&&e[w]<n)w--;if(c){while(w>E&&e[w]<n)w--;while(w>E&&e[w]==l)w--}else while(w>E&&e[w]<p)w--;if(w>E){y(++w);continue}w=a+r,e[w]==t&&w--,y(w-b)}return s},this.$getDisplayTokens=function(n,r){var i=[],s;r=r||0;for(var o=0;o<n.length;o++){var u=n.charCodeAt(o);if(u==9){s=this.getScreenTabSize(i.length+r),i.push(d);for(var a=1;a<s;a++)i.push(v)}else u==32?i.push(p):u>39&&u<48||u>57&&u<64?i.push(l):u>=4352&&m(u)?i.push(e,t):i.push(e)}return i},this.$getStringScreenWidth=function(e,t,n){if(t==0)return[0,0];t==null&&(t=Infinity),n=n||0;var r,i;for(i=0;i<e.length;i++){r=e.charCodeAt(i),r==9?n+=this.getScreenTabSize(n):r>=4352&&m(r)?n+=2:n+=1;if(n>t)break}return[n,i]},this.lineWidgets=null,this.getRowLength=function(e){if(this.lineWidgets)var t=this.lineWidgets[e]&&this.lineWidgets[e].rowCount||0;else t=0;return!this.$useWrapMode||!this.$wrapData[e]?1+t:this.$wrapData[e].length+1+t},this.getRowLineCount=function(e){return!this.$useWrapMode||!this.$wrapData[e]?1:this.$wrapData[e].length+1},this.getRowWrapIndent=function(e){if(this.$useWrapMode){var t=this.screenToDocumentPosition(e,Number.MAX_VALUE),n=this.$wrapData[t.row];return n.length&&n[0]<t.column?n.indent:0}return 0},this.getScreenLastRowColumn=function(e){var t=this.screenToDocumentPosition(e,Number.MAX_VALUE);return this.documentToScreenColumn(t.row,t.column)},this.getDocumentLastRowColumn=function(e,t){var n=this.documentToScreenRow(e,t);return this.getScreenLastRowColumn(n)},this.getDocumentLastRowColumnPosition=function(e,t){var n=this.documentToScreenRow(e,t);return this.screenToDocumentPosition(n,Number.MAX_VALUE/10)},this.getRowSplitData=function(e){return this.$useWrapMode?this.$wrapData[e]:undefined},this.getScreenTabSize=function(e){return this.$tabSize-e%this.$tabSize},this.screenToDocumentRow=function(e,t){return this.screenToDocumentPosition(e,t).row},this.screenToDocumentColumn=function(e,t){return this.screenToDocumentPosition(e,t).column},this.screenToDocumentPosition=function(e,t){if(e<0)return{row:0,column:0};var n,r=0,i=0,s,o=0,u=0,a=this.$screenRowCache,f=this.$getRowCacheIndex(a,e),l=a.length;if(l&&f>=0)var o=a[f],r=this.$docRowCache[f],c=e>a[l-1];else var c=!l;var h=this.getLength()-1,p=this.getNextFoldLine(r),d=p?p.start.row:Infinity;while(o<=e){u=this.getRowLength(r);if(o+u>e||r>=h)break;o+=u,r++,r>d&&(r=p.end.row+1,p=this.getNextFoldLine(r,p),d=p?p.start.row:Infinity),c&&(this.$docRowCache.push(r),this.$screenRowCache.push(o))}if(p&&p.start.row<=r)n=this.getFoldDisplayLine(p),r=p.start.row;else{if(o+u<=e||r>h)return{row:h,column:this.getLine(h).length};n=this.getLine(r),p=null}var v=0;if(this.$useWrapMode){var m=this.$wrapData[r];if(m){var g=Math.floor(e-o);s=m[g],g>0&&m.length&&(v=m.indent,i=m[g-1]||m[m.length-1],n=n.substring(i))}}return i+=this.$getStringScreenWidth(n,t-v)[1],this.$useWrapMode&&i>=s&&(i=s-1),p?p.idxToPosition(i):{row:r,column:i}},this.documentToScreenPosition=function(e,t){if(typeof t==\"undefined\")var n=this.$clipPositionToDocument(e.row,e.column);else n=this.$clipPositionToDocument(e,t);e=n.row,t=n.column;var r=0,i=null,s=null;s=this.getFoldAt(e,t,1),s&&(e=s.start.row,t=s.start.column);var o,u=0,a=this.$docRowCache,f=this.$getRowCacheIndex(a,e),l=a.length;if(l&&f>=0)var u=a[f],r=this.$screenRowCache[f],c=e>a[l-1];else var c=!l;var h=this.getNextFoldLine(u),p=h?h.start.row:Infinity;while(u<e){if(u>=p){o=h.end.row+1;if(o>e)break;h=this.getNextFoldLine(o,h),p=h?h.start.row:Infinity}else o=u+1;r+=this.getRowLength(u),u=o,c&&(this.$docRowCache.push(u),this.$screenRowCache.push(r))}var d=\"\";h&&u>=p?(d=this.getFoldDisplayLine(h,e,t),i=h.start.row):(d=this.getLine(e).substring(0,t),i=e);var v=0;if(this.$useWrapMode){var m=this.$wrapData[i];if(m){var g=0;while(d.length>=m[g])r++,g++;d=d.substring(m[g-1]||0,d.length),v=g>0?m.indent:0}}return{row:r,column:v+this.$getStringScreenWidth(d)[0]}},this.documentToScreenColumn=function(e,t){return this.documentToScreenPosition(e,t).column},this.documentToScreenRow=function(e,t){return this.documentToScreenPosition(e,t).row},this.getScreenLength=function(){var e=0,t=null;if(!this.$useWrapMode){e=this.getLength();var n=this.$foldData;for(var r=0;r<n.length;r++)t=n[r],e-=t.end.row-t.start.row}else{var i=this.$wrapData.length,s=0,r=0,t=this.$foldData[r++],o=t?t.start.row:Infinity;while(s<i){var u=this.$wrapData[s];e+=u?u.length+1:1,s++,s>o&&(s=t.end.row+1,t=this.$foldData[r++],o=t?t.start.row:Infinity)}}return this.lineWidgets&&(e+=this.$getWidgetScreenLength()),e},this.$setFontMetrics=function(e){if(!this.$enableVarChar)return;this.$getStringScreenWidth=function(t,n,r){if(n===0)return[0,0];n||(n=Infinity),r=r||0;var i,s;for(s=0;s<t.length;s++){i=t.charAt(s),i===\"   \"?r+=this.getScreenTabSize(r):r+=e.getCharacterWidth(i);if(r>n)break}return[r,s]}},this.destroy=function(){this.bgTokenizer&&(this.bgTokenizer.setDocument(null),this.bgTokenizer=null),this.$stopWorker()}}.call(p.prototype),e(\"./edit_session/folding\").Folding.call(p.prototype),e(\"./edit_session/bracket_match\").BracketMatch.call(p.prototype),s.defineOptions(p.prototype,\"session\",{wrap:{set:function(e){!e||e==\"off\"?e=!1:e==\"free\"?e=!0:e==\"printMargin\"?e=-1:typeof e==\"string\"&&(e=parseInt(e,10)||!1);if(this.$wrap==e)return;this.$wrap=e;if(!e)this.setUseWrapMode(!1);else{var t=typeof e==\"number\"?e:null;this.setWrapLimitRange(t,t),this.setUseWrapMode(!0)}},get:function(){return this.getUseWrapMode()?this.$wrap==-1?\"printMargin\":this.getWrapLimitRange().min?this.$wrap:\"free\":\"off\"},handlesSet:!0},wrapMethod:{set:function(e){e=e==\"auto\"?this.$mode.type!=\"text\":e!=\"text\",e!=this.$wrapAsCode&&(this.$wrapAsCode=e,this.$useWrapMode&&(this.$modified=!0,this.$resetRowCache(0),this.$updateWrapData(0,this.getLength()-1)))},initialValue:\"auto\"},indentedSoftWrap:{initialValue:!0},firstLineNumber:{set:function(){this._signal(\"changeBreakpoint\")},initialValue:1},useWorker:{set:function(e){this.$useWorker=e,this.$stopWorker(),e&&this.$startWorker()},initialValue:!0},useSoftTabs:{initialValue:!0},tabSize:{set:function(e){if(isNaN(e)||this.$tabSize===e)return;this.$modified=!0,this.$rowLengthCache=[],this.$tabSize=e,this._signal(\"changeTabSize\")},initialValue:4,handlesSet:!0},navigateWithinSoftTabs:{initialValue:!1},overwrite:{set:function(e){this._signal(\"changeOverwrite\")},initialValue:!1},newLineMode:{set:function(e){this.doc.setNewLineMode(e)},get:function(){return this.doc.getNewLineMode()},handlesSet:!0},mode:{set:function(e){this.setMode(e)},get:function(){return this.$modeId}}}),t.EditSession=p}),define(\"ace/search\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\",\"ace/lib/oop\",\"ace/range\"],function(e,t,n){\"use strict\";function u(e,t){function n(e){return/\\w/.test(e)||t.regExp?\"\\\\b\":\"\"}return n(e[0])+e+n(e[e.length-1])}var r=e(\"./lib/lang\"),i=e(\"./lib/oop\"),s=e(\"./range\").Range,o=function(){this.$options={}};(function(){this.set=function(e){return i.mixin(this.$options,e),this},this.getOptions=function(){return r.copyObject(this.$options)},this.setOptions=function(e){this.$options=e},this.find=function(e){var t=this.$options,n=this.$matchIterator(e,t);if(!n)return!1;var r=null;return n.forEach(function(e,n,i,o){return r=new s(e,n,i,o),n==o&&t.start&&t.start.start&&t.skipCurrent!=0&&r.isEqual(t.start)?(r=null,!1):!0}),r},this.findAll=function(e){var t=this.$options;if(!t.needle)return[];this.$assembleRegExp(t);var n=t.range,i=n?e.getLines(n.start.row,n.end.row):e.doc.getAllLines(),o=[],u=t.re;if(t.$isMultiLine){var a=u.length,f=i.length-a,l;e:for(var c=u.offset||0;c<=f;c++){for(var h=0;h<a;h++)if(i[c+h].search(u[h])==-1)continue e;var p=i[c],d=i[c+a-1],v=p.length-p.match(u[0])[0].length,m=d.match(u[a-1])[0].length;if(l&&l.end.row===c&&l.end.column>v)continue;o.push(l=new s(c,v,c+a-1,m)),a>2&&(c=c+a-2)}}else for(var g=0;g<i.length;g++){var y=r.getMatchOffsets(i[g],u);for(var h=0;h<y.length;h++){var b=y[h];o.push(new s(g,b.offset,g,b.offset+b.length))}}if(n){var w=n.start.column,E=n.start.column,g=0,h=o.length-1;while(g<h&&o[g].start.column<w&&o[g].start.row==n.start.row)g++;while(g<h&&o[h].end.column>E&&o[h].end.row==n.end.row)h--;o=o.slice(g,h+1);for(g=0,h=o.length;g<h;g++)o[g].start.row+=n.start.row,o[g].end.row+=n.start.row}return o},this.replace=function(e,t){var n=this.$options,r=this.$assembleRegExp(n);if(n.$isMultiLine)return t;if(!r)return;var i=r.exec(e);if(!i||i[0].length!=e.length)return null;t=e.replace(r,t);if(n.preserveCase){t=t.split(\"\");for(var s=Math.min(e.length,e.length);s--;){var o=e[s];o&&o.toLowerCase()!=o?t[s]=t[s].toUpperCase():t[s]=t[s].toLowerCase()}t=t.join(\"\")}return t},this.$assembleRegExp=function(e,t){if(e.needle instanceof RegExp)return e.re=e.needle;var n=e.needle;if(!e.needle)return e.re=!1;e.regExp||(n=r.escapeRegExp(n)),e.wholeWord&&(n=u(n,e));var i=e.caseSensitive?\"gm\":\"gmi\";e.$isMultiLine=!t&&/[\\n\\r]/.test(n);if(e.$isMultiLine)return e.re=this.$assembleMultilineRegExp(n,i);try{var s=new RegExp(n,i)}catch(o){s=!1}return e.re=s},this.$assembleMultilineRegExp=function(e,t){var n=e.replace(/\\r\\n|\\r|\\n/g,\"$\\n^\").split(\"\\n\"),r=[];for(var i=0;i<n.length;i++)try{r.push(new RegExp(n[i],t))}catch(s){return!1}return r},this.$matchIterator=function(e,t){var n=this.$assembleRegExp(t);if(!n)return!1;var r=t.backwards==1,i=t.skipCurrent!=0,s=t.range,o=t.start;o||(o=s?s[r?\"end\":\"start\"]:e.selection.getRange()),o.start&&(o=o[i!=r?\"end\":\"start\"]);var u=s?s.start.row:0,a=s?s.end.row:e.getLength()-1;if(r)var f=function(e){var n=o.row;if(c(n,o.column,e))return;for(n--;n>=u;n--)if(c(n,Number.MAX_VALUE,e))return;if(t.wrap==0)return;for(n=a,u=o.row;n>=u;n--)if(c(n,Number.MAX_VALUE,e))return};else var f=function(e){var n=o.row;if(c(n,o.column,e))return;for(n+=1;n<=a;n++)if(c(n,0,e))return;if(t.wrap==0)return;for(n=u,a=o.row;n<=a;n++)if(c(n,0,e))return};if(t.$isMultiLine)var l=n.length,c=function(t,i,s){var o=r?t-l+1:t;if(o<0)return;var u=e.getLine(o),a=u.search(n[0]);if(!r&&a<i||a===-1)return;for(var f=1;f<l;f++){u=e.getLine(o+f);if(u.search(n[f])==-1)return}var c=u.match(n[l-1])[0].length;if(r&&c>i)return;if(s(o,a,o+l-1,c))return!0};else if(r)var c=function(t,r,i){var s=e.getLine(t),o=[],u,a=0;n.lastIndex=0;while(u=n.exec(s)){var f=u[0].length;a=u.index;if(!f){if(a>=s.length)break;n.lastIndex=a+=1}if(u.index+f>r)break;o.push(u.index,f)}for(var l=o.length-1;l>=0;l-=2){var c=o[l-1],f=o[l];if(i(t,c,t,c+f))return!0}};else var c=function(t,r,i){var s=e.getLine(t),o,u=r;n.lastIndex=r;while(o=n.exec(s)){var a=o[0].length;u=o.index;if(i(t,u,t,u+a))return!0;if(!a){n.lastIndex=u+=1;if(u>=s.length)return!1}}};return{forEach:f}}}).call(o.prototype),t.Search=o}),define(\"ace/keyboard/hash_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/keys\",\"ace/lib/useragent\"],function(e,t,n){\"use strict\";function o(e,t){this.platform=t||(i.isMac?\"mac\":\"win\"),this.commands={},this.commandKeyBinding={},this.addCommands(e),this.$singleCommand=!0}function u(e,t){o.call(this,e,t),this.$singleCommand=!1}var r=e(\"../lib/keys\"),i=e(\"../lib/useragent\"),s=r.KEY_MODS;u.prototype=o.prototype,function(){function e(e){return typeof e==\"object\"&&e.bindKey&&e.bindKey.position||(e.isDefault?-100:0)}this.addCommand=function(e){this.commands[e.name]&&this.removeCommand(e),this.commands[e.name]=e,e.bindKey&&this._buildKeyHash(e)},this.removeCommand=function(e,t){var n=e&&(typeof e==\"string\"?e:e.name);e=this.commands[n],t||delete this.commands[n];var r=this.commandKeyBinding;for(var i in r){var s=r[i];if(s==e)delete r[i];else if(Array.isArray(s)){var o=s.indexOf(e);o!=-1&&(s.splice(o,1),s.length==1&&(r[i]=s[0]))}}},this.bindKey=function(e,t,n){typeof e==\"object\"&&e&&(n==undefined&&(n=e.position),e=e[this.platform]);if(!e)return;if(typeof t==\"function\")return this.addCommand({exec:t,bindKey:e,name:t.name||e});e.split(\"|\").forEach(function(e){var r=\"\";if(e.indexOf(\" \")!=-1){var i=e.split(/\\s+/);e=i.pop(),i.forEach(function(e){var t=this.parseKeys(e),n=s[t.hashId]+t.key;r+=(r?\" \":\"\")+n,this._addCommandToBinding(r,\"chainKeys\")},this),r+=\" \"}var o=this.parseKeys(e),u=s[o.hashId]+o.key;this._addCommandToBinding(r+u,t,n)},this)},this._addCommandToBinding=function(t,n,r){var i=this.commandKeyBinding,s;if(!n)delete i[t];else if(!i[t]||this.$singleCommand)i[t]=n;else{Array.isArray(i[t])?(s=i[t].indexOf(n))!=-1&&i[t].splice(s,1):i[t]=[i[t]],typeof r!=\"number\"&&(r=e(n));var o=i[t];for(s=0;s<o.length;s++){var u=o[s],a=e(u);if(a>r)break}o.splice(s,0,n)}},this.addCommands=function(e){e&&Object.keys(e).forEach(function(t){var n=e[t];if(!n)return;if(typeof n==\"string\")return this.bindKey(n,t);typeof n==\"function\"&&(n={exec:n});if(typeof n!=\"object\")return;n.name||(n.name=t),this.addCommand(n)},this)},this.removeCommands=function(e){Object.keys(e).forEach(function(t){this.removeCommand(e[t])},this)},this.bindKeys=function(e){Object.keys(e).forEach(function(t){this.bindKey(t,e[t])},this)},this._buildKeyHash=function(e){this.bindKey(e.bindKey,e)},this.parseKeys=function(e){var t=e.toLowerCase().split(/[\\-\\+]([\\-\\+])?/).filter(function(e){return e}),n=t.pop(),i=r[n];if(r.FUNCTION_KEYS[i])n=r.FUNCTION_KEYS[i].toLowerCase();else{if(!t.length)return{key:n,hashId:-1};if(t.length==1&&t[0]==\"shift\")return{key:n.toUpperCase(),hashId:-1}}var s=0;for(var o=t.length;o--;){var u=r.KEY_MODS[t[o]];if(u==null)return typeof console!=\"undefined\"&&console.error(\"invalid modifier \"+t[o]+\" in \"+e),!1;s|=u}return{key:n,hashId:s}},this.findKeyCommand=function(t,n){var r=s[t]+n;return this.commandKeyBinding[r]},this.handleKeyboard=function(e,t,n,r){if(r<0)return;var i=s[t]+n,o=this.commandKeyBinding[i];e.$keyChain&&(e.$keyChain+=\" \"+i,o=this.commandKeyBinding[e.$keyChain]||o);if(o)if(o==\"chainKeys\"||o[o.length-1]==\"chainKeys\")return e.$keyChain=e.$keyChain||i,{command:\"null\"};if(e.$keyChain)if(!!t&&t!=4||n.length!=1){if(t==-1||r>0)e.$keyChain=\"\"}else e.$keyChain=e.$keyChain.slice(0,-i.length-1);return{command:o}},this.getStatusText=function(e,t){return t.$keyChain||\"\"}}.call(o.prototype),t.HashHandler=o,t.MultiHashHandler=u}),define(\"ace/commands/command_manager\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/keyboard/hash_handler\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";var r=e(\"../lib/oop\"),i=e(\"../keyboard/hash_handler\").MultiHashHandler,s=e(\"../lib/event_emitter\").EventEmitter,o=function(e,t){i.call(this,t,e),this.byName=this.commands,this.setDefaultHandler(\"exec\",function(e){return e.command.exec(e.editor,e.args||{})})};r.inherits(o,i),function(){r.implement(this,s),this.exec=function(e,t,n){if(Array.isArray(e)){for(var r=e.length;r--;)if(this.exec(e[r],t,n))return!0;return!1}typeof e==\"string\"&&(e=this.commands[e]);if(!e)return!1;if(t&&t.$readOnly&&!e.readOnly)return!1;if(e.isAvailable&&!e.isAvailable(t))return!1;var i={editor:t,command:e,args:n};return i.returnValue=this._emit(\"exec\",i),this._signal(\"afterExec\",i),i.returnValue===!1?!1:!0},this.toggleRecording=function(e){if(this.$inReplay)return;return e&&e._emit(\"changeStatus\"),this.recording?(this.macro.pop(),this.removeEventListener(\"exec\",this.$addCommandToMacro),this.macro.length||(this.macro=this.oldMacro),this.recording=!1):(this.$addCommandToMacro||(this.$addCommandToMacro=function(e){this.macro.push([e.command,e.args])}.bind(this)),this.oldMacro=this.macro,this.macro=[],this.on(\"exec\",this.$addCommandToMacro),this.recording=!0)},this.replay=function(e){if(this.$inReplay||!this.macro)return;if(this.recording)return this.toggleRecording(e);try{this.$inReplay=!0,this.macro.forEach(function(t){typeof t==\"string\"?this.exec(t,e):this.exec(t[0],e,t[1])},this)}finally{this.$inReplay=!1}},this.trimMacro=function(e){return e.map(function(e){return typeof e[0]!=\"string\"&&(e[0]=e[0].name),e[1]||(e=e[0]),e})}}.call(o.prototype),t.CommandManager=o}),define(\"ace/commands/default_commands\",[\"require\",\"exports\",\"module\",\"ace/lib/lang\",\"ace/config\",\"ace/range\"],function(e,t,n){\"use strict\";function o(e,t){return{win:e,mac:t}}var r=e(\"../lib/lang\"),i=e(\"../config\"),s=e(\"../range\").Range;t.commands=[{name:\"showSettingsMenu\",bindKey:o(\"Ctrl-,\",\"Command-,\"),exec:function(e){i.loadModule(\"ace/ext/settings_menu\",function(t){t.init(e),e.showSettingsMenu()})},readOnly:!0},{name:\"goToNextError\",bindKey:o(\"Alt-E\",\"F4\"),exec:function(e){i.loadModule(\"ace/ext/error_marker\",function(t){t.showErrorMarker(e,1)})},scrollIntoView:\"animate\",readOnly:!0},{name:\"goToPreviousError\",bindKey:o(\"Alt-Shift-E\",\"Shift-F4\"),exec:function(e){i.loadModule(\"ace/ext/error_marker\",function(t){t.showErrorMarker(e,-1)})},scrollIntoView:\"animate\",readOnly:!0},{name:\"selectall\",bindKey:o(\"Ctrl-A\",\"Command-A\"),exec:function(e){e.selectAll()},readOnly:!0},{name:\"centerselection\",bindKey:o(null,\"Ctrl-L\"),exec:function(e){e.centerSelection()},readOnly:!0},{name:\"gotoline\",bindKey:o(\"Ctrl-L\",\"Command-L\"),exec:function(e){var t=parseInt(prompt(\"Enter line number:\"),10);isNaN(t)||e.gotoLine(t)},readOnly:!0},{name:\"fold\",bindKey:o(\"Alt-L|Ctrl-F1\",\"Command-Alt-L|Command-F1\"),exec:function(e){e.session.toggleFold(!1)},multiSelectAction:\"forEach\",scrollIntoView:\"center\",readOnly:!0},{name:\"unfold\",bindKey:o(\"Alt-Shift-L|Ctrl-Shift-F1\",\"Command-Alt-Shift-L|Command-Shift-F1\"),exec:function(e){e.session.toggleFold(!0)},multiSelectAction:\"forEach\",scrollIntoView:\"center\",readOnly:!0},{name:\"toggleFoldWidget\",bindKey:o(\"F2\",\"F2\"),exec:function(e){e.session.toggleFoldWidget()},multiSelectAction:\"forEach\",scrollIntoView:\"center\",readOnly:!0},{name:\"toggleParentFoldWidget\",bindKey:o(\"Alt-F2\",\"Alt-F2\"),exec:function(e){e.session.toggleFoldWidget(!0)},multiSelectAction:\"forEach\",scrollIntoView:\"center\",readOnly:!0},{name:\"foldall\",bindKey:o(null,\"Ctrl-Command-Option-0\"),exec:function(e){e.session.foldAll()},scrollIntoView:\"center\",readOnly:!0},{name:\"foldOther\",bindKey:o(\"Alt-0\",\"Command-Option-0\"),exec:function(e){e.session.foldAll(),e.session.unfold(e.selection.getAllRanges())},scrollIntoView:\"center\",readOnly:!0},{name:\"unfoldall\",bindKey:o(\"Alt-Shift-0\",\"Command-Option-Shift-0\"),exec:function(e){e.session.unfold()},scrollIntoView:\"center\",readOnly:!0},{name:\"findnext\",bindKey:o(\"Ctrl-K\",\"Command-G\"),exec:function(e){e.findNext()},multiSelectAction:\"forEach\",scrollIntoView:\"center\",readOnly:!0},{name:\"findprevious\",bindKey:o(\"Ctrl-Shift-K\",\"Command-Shift-G\"),exec:function(e){e.findPrevious()},multiSelectAction:\"forEach\",scrollIntoView:\"center\",readOnly:!0},{name:\"selectOrFindNext\",bindKey:o(\"Alt-K\",\"Ctrl-G\"),exec:function(e){e.selection.isEmpty()?e.selection.selectWord():e.findNext()},readOnly:!0},{name:\"selectOrFindPrevious\",bindKey:o(\"Alt-Shift-K\",\"Ctrl-Shift-G\"),exec:function(e){e.selection.isEmpty()?e.selection.selectWord():e.findPrevious()},readOnly:!0},{name:\"find\",bindKey:o(\"Ctrl-F\",\"Command-F\"),exec:function(e){i.loadModule(\"ace/ext/searchbox\",function(t){t.Search(e)})},readOnly:!0},{name:\"overwrite\",bindKey:\"Insert\",exec:function(e){e.toggleOverwrite()},readOnly:!0},{name:\"selecttostart\",bindKey:o(\"Ctrl-Shift-Home\",\"Command-Shift-Home|Command-Shift-Up\"),exec:function(e){e.getSelection().selectFileStart()},multiSelectAction:\"forEach\",readOnly:!0,scrollIntoView:\"animate\",aceCommandGroup:\"fileJump\"},{name:\"gotostart\",bindKey:o(\"Ctrl-Home\",\"Command-Home|Command-Up\"),exec:function(e){e.navigateFileStart()},multiSelectAction:\"forEach\",readOnly:!0,scrollIntoView:\"animate\",aceCommandGroup:\"fileJump\"},{name:\"selectup\",bindKey:o(\"Shift-Up\",\"Shift-Up|Ctrl-Shift-P\"),exec:function(e){e.getSelection().selectUp()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"golineup\",bindKey:o(\"Up\",\"Up|Ctrl-P\"),exec:function(e,t){e.navigateUp(t.times)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selecttoend\",bindKey:o(\"Ctrl-Shift-End\",\"Command-Shift-End|Command-Shift-Down\"),exec:function(e){e.getSelection().selectFileEnd()},multiSelectAction:\"forEach\",readOnly:!0,scrollIntoView:\"animate\",aceCommandGroup:\"fileJump\"},{name:\"gotoend\",bindKey:o(\"Ctrl-End\",\"Command-End|Command-Down\"),exec:function(e){e.navigateFileEnd()},multiSelectAction:\"forEach\",readOnly:!0,scrollIntoView:\"animate\",aceCommandGroup:\"fileJump\"},{name:\"selectdown\",bindKey:o(\"Shift-Down\",\"Shift-Down|Ctrl-Shift-N\"),exec:function(e){e.getSelection().selectDown()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"golinedown\",bindKey:o(\"Down\",\"Down|Ctrl-N\"),exec:function(e,t){e.navigateDown(t.times)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectwordleft\",bindKey:o(\"Ctrl-Shift-Left\",\"Option-Shift-Left\"),exec:function(e){e.getSelection().selectWordLeft()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"gotowordleft\",bindKey:o(\"Ctrl-Left\",\"Option-Left\"),exec:function(e){e.navigateWordLeft()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selecttolinestart\",bindKey:o(\"Alt-Shift-Left\",\"Command-Shift-Left|Ctrl-Shift-A\"),exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"gotolinestart\",bindKey:o(\"Alt-Left|Home\",\"Command-Left|Home|Ctrl-A\"),exec:function(e){e.navigateLineStart()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectleft\",bindKey:o(\"Shift-Left\",\"Shift-Left|Ctrl-Shift-B\"),exec:function(e){e.getSelection().selectLeft()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"gotoleft\",bindKey:o(\"Left\",\"Left|Ctrl-B\"),exec:function(e,t){e.navigateLeft(t.times)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectwordright\",bindKey:o(\"Ctrl-Shift-Right\",\"Option-Shift-Right\"),exec:function(e){e.getSelection().selectWordRight()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"gotowordright\",bindKey:o(\"Ctrl-Right\",\"Option-Right\"),exec:function(e){e.navigateWordRight()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selecttolineend\",bindKey:o(\"Alt-Shift-Right\",\"Command-Shift-Right|Shift-End|Ctrl-Shift-E\"),exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"gotolineend\",bindKey:o(\"Alt-Right|End\",\"Command-Right|End|Ctrl-E\"),exec:function(e){e.navigateLineEnd()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectright\",bindKey:o(\"Shift-Right\",\"Shift-Right\"),exec:function(e){e.getSelection().selectRight()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"gotoright\",bindKey:o(\"Right\",\"Right|Ctrl-F\"),exec:function(e,t){e.navigateRight(t.times)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectpagedown\",bindKey:\"Shift-PageDown\",exec:function(e){e.selectPageDown()},readOnly:!0},{name:\"pagedown\",bindKey:o(null,\"Option-PageDown\"),exec:function(e){e.scrollPageDown()},readOnly:!0},{name:\"gotopagedown\",bindKey:o(\"PageDown\",\"PageDown|Ctrl-V\"),exec:function(e){e.gotoPageDown()},readOnly:!0},{name:\"selectpageup\",bindKey:\"Shift-PageUp\",exec:function(e){e.selectPageUp()},readOnly:!0},{name:\"pageup\",bindKey:o(null,\"Option-PageUp\"),exec:function(e){e.scrollPageUp()},readOnly:!0},{name:\"gotopageup\",bindKey:\"PageUp\",exec:function(e){e.gotoPageUp()},readOnly:!0},{name:\"scrollup\",bindKey:o(\"Ctrl-Up\",null),exec:function(e){e.renderer.scrollBy(0,-2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:\"scrolldown\",bindKey:o(\"Ctrl-Down\",null),exec:function(e){e.renderer.scrollBy(0,2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:\"selectlinestart\",bindKey:\"Shift-Home\",exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectlineend\",bindKey:\"Shift-End\",exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"togglerecording\",bindKey:o(\"Ctrl-Alt-E\",\"Command-Option-E\"),exec:function(e){e.commands.toggleRecording(e)},readOnly:!0},{name:\"replaymacro\",bindKey:o(\"Ctrl-Shift-E\",\"Command-Shift-E\"),exec:function(e){e.commands.replay(e)},readOnly:!0},{name:\"jumptomatching\",bindKey:o(\"Ctrl-P\",\"Ctrl-P\"),exec:function(e){e.jumpToMatching()},multiSelectAction:\"forEach\",scrollIntoView:\"animate\",readOnly:!0},{name:\"selecttomatching\",bindKey:o(\"Ctrl-Shift-P\",\"Ctrl-Shift-P\"),exec:function(e){e.jumpToMatching(!0)},multiSelectAction:\"forEach\",scrollIntoView:\"animate\",readOnly:!0},{name:\"expandToMatching\",bindKey:o(\"Ctrl-Shift-M\",\"Ctrl-Shift-M\"),exec:function(e){e.jumpToMatching(!0,!0)},multiSelectAction:\"forEach\",scrollIntoView:\"animate\",readOnly:!0},{name:\"passKeysToBrowser\",bindKey:o(null,null),exec:function(){},passEvent:!0,readOnly:!0},{name:\"copy\",exec:function(e){},readOnly:!0},{name:\"cut\",exec:function(e){var t=e.getSelectionRange();e._emit(\"cut\",t),e.selection.isEmpty()||(e.session.remove(t),e.clearSelection())},scrollIntoView:\"cursor\",multiSelectAction:\"forEach\"},{name:\"paste\",exec:function(e,t){e.$handlePaste(t)},scrollIntoView:\"cursor\"},{name:\"removeline\",bindKey:o(\"Ctrl-D\",\"Command-D\"),exec:function(e){e.removeLines()},scrollIntoView:\"cursor\",multiSelectAction:\"forEachLine\"},{name:\"duplicateSelection\",bindKey:o(\"Ctrl-Shift-D\",\"Command-Shift-D\"),exec:function(e){e.duplicateSelection()},scrollIntoView:\"cursor\",multiSelectAction:\"forEach\"},{name:\"sortlines\",bindKey:o(\"Ctrl-Alt-S\",\"Command-Alt-S\"),exec:function(e){e.sortLines()},scrollIntoView:\"selection\",multiSelectAction:\"forEachLine\"},{name:\"togglecomment\",bindKey:o(\"Ctrl-/\",\"Command-/\"),exec:function(e){e.toggleCommentLines()},multiSelectAction:\"forEachLine\",scrollIntoView:\"selectionPart\"},{name:\"toggleBlockComment\",bindKey:o(\"Ctrl-Shift-/\",\"Command-Shift-/\"),exec:function(e){e.toggleBlockComment()},multiSelectAction:\"forEach\",scrollIntoView:\"selectionPart\"},{name:\"modifyNumberUp\",bindKey:o(\"Ctrl-Shift-Up\",\"Alt-Shift-Up\"),exec:function(e){e.modifyNumber(1)},scrollIntoView:\"cursor\",multiSelectAction:\"forEach\"},{name:\"modifyNumberDown\",bindKey:o(\"Ctrl-Shift-Down\",\"Alt-Shift-Down\"),exec:function(e){e.modifyNumber(-1)},scrollIntoView:\"cursor\",multiSelectAction:\"forEach\"},{name:\"replace\",bindKey:o(\"Ctrl-H\",\"Command-Option-F\"),exec:function(e){i.loadModule(\"ace/ext/searchbox\",function(t){t.Search(e,!0)})}},{name:\"undo\",bindKey:o(\"Ctrl-Z\",\"Command-Z\"),exec:function(e){e.undo()}},{name:\"redo\",bindKey:o(\"Ctrl-Shift-Z|Ctrl-Y\",\"Command-Shift-Z|Command-Y\"),exec:function(e){e.redo()}},{name:\"copylinesup\",bindKey:o(\"Alt-Shift-Up\",\"Command-Option-Up\"),exec:function(e){e.copyLinesUp()},scrollIntoView:\"cursor\"},{name:\"movelinesup\",bindKey:o(\"Alt-Up\",\"Option-Up\"),exec:function(e){e.moveLinesUp()},scrollIntoView:\"cursor\"},{name:\"copylinesdown\",bindKey:o(\"Alt-Shift-Down\",\"Command-Option-Down\"),exec:function(e){e.copyLinesDown()},scrollIntoView:\"cursor\"},{name:\"movelinesdown\",bindKey:o(\"Alt-Down\",\"Option-Down\"),exec:function(e){e.moveLinesDown()},scrollIntoView:\"cursor\"},{name:\"del\",bindKey:o(\"Delete\",\"Delete|Ctrl-D|Shift-Delete\"),exec:function(e){e.remove(\"right\")},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"backspace\",bindKey:o(\"Shift-Backspace|Backspace\",\"Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H\"),exec:function(e){e.remove(\"left\")},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"cut_or_delete\",bindKey:o(\"Shift-Delete\",null),exec:function(e){if(!e.selection.isEmpty())return!1;e.remove(\"left\")},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"removetolinestart\",bindKey:o(\"Alt-Backspace\",\"Command-Backspace\"),exec:function(e){e.removeToLineStart()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"removetolineend\",bindKey:o(\"Alt-Delete\",\"Ctrl-K\"),exec:function(e){e.removeToLineEnd()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"removewordleft\",bindKey:o(\"Ctrl-Backspace\",\"Alt-Backspace|Ctrl-Alt-Backspace\"),exec:function(e){e.removeWordLeft()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"removewordright\",bindKey:o(\"Ctrl-Delete\",\"Alt-Delete\"),exec:function(e){e.removeWordRight()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"outdent\",bindKey:o(\"Shift-Tab\",\"Shift-Tab\"),exec:function(e){e.blockOutdent()},multiSelectAction:\"forEach\",scrollIntoView:\"selectionPart\"},{name:\"indent\",bindKey:o(\"Tab\",\"Tab\"),exec:function(e){e.indent()},multiSelectAction:\"forEach\",scrollIntoView:\"selectionPart\"},{name:\"blockoutdent\",bindKey:o(\"Ctrl-[\",\"Ctrl-[\"),exec:function(e){e.blockOutdent()},multiSelectAction:\"forEachLine\",scrollIntoView:\"selectionPart\"},{name:\"blockindent\",bindKey:o(\"Ctrl-]\",\"Ctrl-]\"),exec:function(e){e.blockIndent()},multiSelectAction:\"forEachLine\",scrollIntoView:\"selectionPart\"},{name:\"insertstring\",exec:function(e,t){e.insert(t)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"inserttext\",exec:function(e,t){e.insert(r.stringRepeat(t.text||\"\",t.times||1))},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"splitline\",bindKey:o(null,\"Ctrl-O\"),exec:function(e){e.splitLine()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"transposeletters\",bindKey:o(\"Alt-Shift-X\",\"Ctrl-T\"),exec:function(e){e.transposeLetters()},multiSelectAction:function(e){e.transposeSelections(1)},scrollIntoView:\"cursor\"},{name:\"touppercase\",bindKey:o(\"Ctrl-U\",\"Ctrl-U\"),exec:function(e){e.toUpperCase()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"tolowercase\",bindKey:o(\"Ctrl-Shift-U\",\"Ctrl-Shift-U\"),exec:function(e){e.toLowerCase()},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\"},{name:\"expandtoline\",bindKey:o(\"Ctrl-Shift-L\",\"Command-Shift-L\"),exec:function(e){var t=e.selection.getRange();t.start.column=t.end.column=0,t.end.row++,e.selection.setRange(t,!1)},multiSelectAction:\"forEach\",scrollIntoView:\"cursor\",readOnly:!0},{name:\"joinlines\",bindKey:o(null,null),exec:function(e){var t=e.selection.isBackwards(),n=t?e.selection.getSelectionLead():e.selection.getSelectionAnchor(),i=t?e.selection.getSelectionAnchor():e.selection.getSelectionLead(),o=e.session.doc.getLine(n.row).length,u=e.session.doc.getTextRange(e.selection.getRange()),a=u.replace(/\\n\\s*/,\" \").length,f=e.session.doc.getLine(n.row);for(var l=n.row+1;l<=i.row+1;l++){var c=r.stringTrimLeft(r.stringTrimRight(e.session.doc.getLine(l)));c.length!==0&&(c=\" \"+c),f+=c}i.row+1<e.session.doc.getLength()-1&&(f+=e.session.doc.getNewLineCharacter()),e.clearSelection(),e.session.doc.replace(new s(n.row,0,i.row+2,0),f),a>0?(e.selection.moveCursorTo(n.row,n.column),e.selection.selectTo(n.row,n.column+a)):(o=e.session.doc.getLine(n.row).length>o?o+1:o,e.selection.moveCursorTo(n.row,o))},multiSelectAction:\"forEach\",readOnly:!0},{name:\"invertSelection\",bindKey:o(null,null),exec:function(e){var t=e.session.doc.getLength()-1,n=e.session.doc.getLine(t).length,r=e.selection.rangeList.ranges,i=[];r.length<1&&(r=[e.selection.getRange()]);for(var o=0;o<r.length;o++)o==r.length-1&&(r[o].end.row!==t||r[o].end.column!==n)&&i.push(new s(r[o].end.row,r[o].end.column,t,n)),o===0?(r[o].start.row!==0||r[o].start.column!==0)&&i.push(new s(0,0,r[o].start.row,r[o].start.column)):i.push(new s(r[o-1].end.row,r[o-1].end.column,r[o].start.row,r[o].start.column));e.exitMultiSelectMode(),e.clearSelection();for(var o=0;o<i.length;o++)e.selection.addRange(i[o],!1)},readOnly:!0,scrollIntoView:\"none\"}]}),define(\"ace/editor\",[\"require\",\"exports\",\"module\",\"ace/lib/fixoldbrowsers\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/lib/lang\",\"ace/lib/useragent\",\"ace/keyboard/textinput\",\"ace/mouse/mouse_handler\",\"ace/mouse/fold_handler\",\"ace/keyboard/keybinding\",\"ace/edit_session\",\"ace/search\",\"ace/range\",\"ace/lib/event_emitter\",\"ace/commands/command_manager\",\"ace/commands/default_commands\",\"ace/config\",\"ace/token_iterator\"],function(e,t,n){\"use strict\";e(\"./lib/fixoldbrowsers\");var r=e(\"./lib/oop\"),i=e(\"./lib/dom\"),s=e(\"./lib/lang\"),o=e(\"./lib/useragent\"),u=e(\"./keyboard/textinput\").TextInput,a=e(\"./mouse/mouse_handler\").MouseHandler,f=e(\"./mouse/fold_handler\").FoldHandler,l=e(\"./keyboard/keybinding\").KeyBinding,c=e(\"./edit_session\").EditSession,h=e(\"./search\").Search,p=e(\"./range\").Range,d=e(\"./lib/event_emitter\").EventEmitter,v=e(\"./commands/command_manager\").CommandManager,m=e(\"./commands/default_commands\").commands,g=e(\"./config\"),y=e(\"./token_iterator\").TokenIterator,b=function(e,t){var n=e.getContainerElement();this.container=n,this.renderer=e,this.id=\"editor\"+ ++b.$uid,this.commands=new v(o.isMac?\"mac\":\"win\",m),typeof document==\"object\"&&(this.textInput=new u(e.getTextAreaContainer(),this),this.renderer.textarea=this.textInput.getElement(),this.$mouseHandler=new a(this),new f(this)),this.keyBinding=new l(this),this.$blockScrolling=0,this.$search=(new h).set({wrap:!0}),this.$historyTracker=this.$historyTracker.bind(this),this.commands.on(\"exec\",this.$historyTracker),this.$initOperationListeners(),this._$emitInputEvent=s.delayedCall(function(){this._signal(\"input\",{}),this.session&&this.session.bgTokenizer&&this.session.bgTokenizer.scheduleStart()}.bind(this)),this.on(\"change\",function(e,t){t._$emitInputEvent.schedule(31)}),this.setSession(t||new c(\"\")),g.resetOptions(this),g._signal(\"editor\",this)};b.$uid=0,function(){r.implement(this,d),this.$initOperationListeners=function(){function e(e){return e[e.length-1]}this.selections=[],this.commands.on(\"exec\",this.startOperation.bind(this),!0),this.commands.on(\"afterExec\",this.endOperation.bind(this),!0),this.$opResetTimer=s.delayedCall(this.endOperation.bind(this)),this.on(\"change\",function(){this.curOp||this.startOperation(),this.curOp.docChanged=!0}.bind(this),!0),this.on(\"changeSelection\",function(){this.curOp||this.startOperation(),this.curOp.selectionChanged=!0}.bind(this),!0)},this.curOp=null,this.prevOp={},this.startOperation=function(e){if(this.curOp){if(!e||this.curOp.command)return;this.prevOp=this.curOp}e||(this.previousCommand=null,e={}),this.$opResetTimer.schedule(),this.curOp={command:e.command||{},args:e.args,scrollTop:this.renderer.scrollTop},this.curOp.command.name&&this.curOp.command.scrollIntoView!==undefined&&this.$blockScrolling++},this.endOperation=function(e){if(this.curOp){if(e&&e.returnValue===!1)return this.curOp=null;this._signal(\"beforeEndOperation\");var t=this.curOp.command;t.name&&this.$blockScrolling>0&&this.$blockScrolling--;var n=t&&t.scrollIntoView;if(n){switch(n){case\"center-animate\":n=\"animate\";case\"center\":this.renderer.scrollCursorIntoView(null,.5);break;case\"animate\":case\"cursor\":this.renderer.scrollCursorIntoView();break;case\"selectionPart\":var r=this.selection.getRange(),i=this.renderer.layerConfig;(r.start.row>=i.lastRow||r.end.row<=i.firstRow)&&this.renderer.scrollSelectionIntoView(this.selection.anchor,this.selection.lead);break;default:}n==\"animate\"&&this.renderer.animateScrolling(this.curOp.scrollTop)}this.prevOp=this.curOp,this.curOp=null}},this.$mergeableCommands=[\"backspace\",\"del\",\"insertstring\"],this.$historyTracker=function(e){if(!this.$mergeUndoDeltas)return;var t=this.prevOp,n=this.$mergeableCommands,r=t.command&&e.command.name==t.command.name;if(e.command.name==\"insertstring\"){var i=e.args;this.mergeNextCommand===undefined&&(this.mergeNextCommand=!0),r=r&&this.mergeNextCommand&&(!/\\s/.test(i)||/\\s/.test(t.args)),this.mergeNextCommand=!0}else r=r&&n.indexOf(e.command.name)!==-1;this.$mergeUndoDeltas!=\"always\"&&Date.now()-this.sequenceStartTime>2e3&&(r=!1),r?this.session.mergeUndoDeltas=!0:n.indexOf(e.command.name)!==-1&&(this.sequenceStartTime=Date.now())},this.setKeyboardHandler=function(e,t){if(e&&typeof e==\"string\"){this.$keybindingId=e;var n=this;g.loadModule([\"keybinding\",e],function(r){n.$keybindingId==e&&n.keyBinding.setKeyboardHandler(r&&r.handler),t&&t()})}else this.$keybindingId=null,this.keyBinding.setKeyboardHandler(e),t&&t()},this.getKeyboardHandler=function(){return this.keyBinding.getKeyboardHandler()},this.setSession=function(e){if(this.session==e)return;this.curOp&&this.endOperation(),this.curOp={};var t=this.session;if(t){this.session.off(\"change\",this.$onDocumentChange),this.session.off(\"changeMode\",this.$onChangeMode),this.session.off(\"tokenizerUpdate\",this.$onTokenizerUpdate),this.session.off(\"changeTabSize\",this.$onChangeTabSize),this.session.off(\"changeWrapLimit\",this.$onChangeWrapLimit),this.session.off(\"changeWrapMode\",this.$onChangeWrapMode),this.session.off(\"changeFold\",this.$onChangeFold),this.session.off(\"changeFrontMarker\",this.$onChangeFrontMarker),this.session.off(\"changeBackMarker\",this.$onChangeBackMarker),this.session.off(\"changeBreakpoint\",this.$onChangeBreakpoint),this.session.off(\"changeAnnotation\",this.$onChangeAnnotation),this.session.off(\"changeOverwrite\",this.$onCursorChange),this.session.off(\"changeScrollTop\",this.$onScrollTopChange),this.session.off(\"changeScrollLeft\",this.$onScrollLeftChange);var n=this.session.getSelection();n.off(\"changeCursor\",this.$onCursorChange),n.off(\"changeSelection\",this.$onSelectionChange)}this.session=e,e?(this.$onDocumentChange=this.onDocumentChange.bind(this),e.on(\"change\",this.$onDocumentChange),this.renderer.setSession(e),this.$onChangeMode=this.onChangeMode.bind(this),e.on(\"changeMode\",this.$onChangeMode),this.$onTokenizerUpdate=this.onTokenizerUpdate.bind(this),e.on(\"tokenizerUpdate\",this.$onTokenizerUpdate),this.$onChangeTabSize=this.renderer.onChangeTabSize.bind(this.renderer),e.on(\"changeTabSize\",this.$onChangeTabSize),this.$onChangeWrapLimit=this.onChangeWrapLimit.bind(this),e.on(\"changeWrapLimit\",this.$onChangeWrapLimit),this.$onChangeWrapMode=this.onChangeWrapMode.bind(this),e.on(\"changeWrapMode\",this.$onChangeWrapMode),this.$onChangeFold=this.onChangeFold.bind(this),e.on(\"changeFold\",this.$onChangeFold),this.$onChangeFrontMarker=this.onChangeFrontMarker.bind(this),this.session.on(\"changeFrontMarker\",this.$onChangeFrontMarker),this.$onChangeBackMarker=this.onChangeBackMarker.bind(this),this.session.on(\"changeBackMarker\",this.$onChangeBackMarker),this.$onChangeBreakpoint=this.onChangeBreakpoint.bind(this),this.session.on(\"changeBreakpoint\",this.$onChangeBreakpoint),this.$onChangeAnnotation=this.onChangeAnnotation.bind(this),this.session.on(\"changeAnnotation\",this.$onChangeAnnotation),this.$onCursorChange=this.onCursorChange.bind(this),this.session.on(\"changeOverwrite\",this.$onCursorChange),this.$onScrollTopChange=this.onScrollTopChange.bind(this),this.session.on(\"changeScrollTop\",this.$onScrollTopChange),this.$onScrollLeftChange=this.onScrollLeftChange.bind(this),this.session.on(\"changeScrollLeft\",this.$onScrollLeftChange),this.selection=e.getSelection(),this.selection.on(\"changeCursor\",this.$onCursorChange),this.$onSelectionChange=this.onSelectionChange.bind(this),this.selection.on(\"changeSelection\",this.$onSelectionChange),this.onChangeMode(),this.$blockScrolling+=1,this.onCursorChange(),this.$blockScrolling-=1,this.onScrollTopChange(),this.onScrollLeftChange(),this.onSelectionChange(),this.onChangeFrontMarker(),this.onChangeBackMarker(),this.onChangeBreakpoint(),this.onChangeAnnotation(),this.session.getUseWrapMode()&&this.renderer.adjustWrapLimit(),this.renderer.updateFull()):(this.selection=null,this.renderer.setSession(e)),this._signal(\"changeSession\",{session:e,oldSession:t}),this.curOp=null,t&&t._signal(\"changeEditor\",{oldEditor:this}),e&&e._signal(\"changeEditor\",{editor:this}),e&&e.bgTokenizer&&e.bgTokenizer.scheduleStart()},this.getSession=function(){return this.session},this.setValue=function(e,t){return this.session.doc.setValue(e),t?t==1?this.navigateFileEnd():t==-1&&this.navigateFileStart():this.selectAll(),e},this.getValue=function(){return this.session.getValue()},this.getSelection=function(){return this.selection},this.resize=function(e){this.renderer.onResize(e)},this.setTheme=function(e,t){this.renderer.setTheme(e,t)},this.getTheme=function(){return this.renderer.getTheme()},this.setStyle=function(e){this.renderer.setStyle(e)},this.unsetStyle=function(e){this.renderer.unsetStyle(e)},this.getFontSize=function(){return this.getOption(\"fontSize\")||i.computedStyle(this.container,\"fontSize\")},this.setFontSize=function(e){this.setOption(\"fontSize\",e)},this.$highlightBrackets=function(){this.session.$bracketHighlight&&(this.session.removeMarker(this.session.$bracketHighlight),this.session.$bracketHighlight=null);if(this.$highlightPending)return;var e=this;this.$highlightPending=!0,setTimeout(function(){e.$highlightPending=!1;var t=e.session;if(!t||!t.bgTokenizer)return;var n=t.findMatchingBracket(e.getCursorPosition());if(n)var r=new p(n.row,n.column,n.row,n.column+1);else if(t.$mode.getMatching)var r=t.$mode.getMatching(e.session);r&&(t.$bracketHighlight=t.addMarker(r,\"ace_bracket\",\"text\"))},50)},this.$highlightTags=function(){if(this.$highlightTagPending)return;var e=this;this.$highlightTagPending=!0,setTimeout(function(){e.$highlightTagPending=!1;var t=e.session;if(!t||!t.bgTokenizer)return;var n=e.getCursorPosition(),r=new y(e.session,n.row,n.column),i=r.getCurrentToken();if(!i||!/\\b(?:tag-open|tag-name)/.test(i.type)){t.removeMarker(t.$tagHighlight),t.$tagHighlight=null;return}if(i.type.indexOf(\"tag-open\")!=-1){i=r.stepForward();if(!i)return}var s=i.value,o=0,u=r.stepBackward();if(u.value==\"<\"){do u=i,i=r.stepForward(),i&&i.value===s&&i.type.indexOf(\"tag-name\")!==-1&&(u.value===\"<\"?o++:u.value===\"</\"&&o--);while(i&&o>=0)}else{do i=u,u=r.stepBackward(),i&&i.value===s&&i.type.indexOf(\"tag-name\")!==-1&&(u.value===\"<\"?o++:u.value===\"</\"&&o--);while(u&&o<=0);r.stepForward()}if(!i){t.removeMarker(t.$tagHighlight),t.$tagHighlight=null;return}var a=r.getCurrentTokenRow(),f=r.getCurrentTokenColumn(),l=new p(a,f,a,f+i.value.length),c=t.$backMarkers[t.$tagHighlight];t.$tagHighlight&&c!=undefined&&l.compareRange(c.range)!==0&&(t.removeMarker(t.$tagHighlight),t.$tagHighlight=null),l&&!t.$tagHighlight&&(t.$tagHighlight=t.addMarker(l,\"ace_bracket\",\"text\"))},50)},this.focus=function(){var e=this;setTimeout(function(){e.textInput.focus()}),this.textInput.focus()},this.isFocused=function(){return this.textInput.isFocused()},this.blur=function(){this.textInput.blur()},this.onFocus=function(e){if(this.$isFocused)return;this.$isFocused=!0,this.renderer.showCursor(),this.renderer.visualizeFocus(),this._emit(\"focus\",e)},this.onBlur=function(e){if(!this.$isFocused)return;this.$isFocused=!1,this.renderer.hideCursor(),this.renderer.visualizeBlur(),this._emit(\"blur\",e)},this.$cursorChange=function(){this.renderer.updateCursor()},this.onDocumentChange=function(e){var t=this.session.$useWrapMode,n=e.start.row==e.end.row?e.end.row:Infinity;this.renderer.updateLines(e.start.row,n,t),this._signal(\"change\",e),this.$cursorChange(),this.$updateHighlightActiveLine()},this.onTokenizerUpdate=function(e){var t=e.data;this.renderer.updateLines(t.first,t.last)},this.onScrollTopChange=function(){this.renderer.scrollToY(this.session.getScrollTop())},this.onScrollLeftChange=function(){this.renderer.scrollToX(this.session.getScrollLeft())},this.onCursorChange=function(){this.$cursorChange(),this.$blockScrolling||(g.warn(\"Automatically scrolling cursor into view after selection change\",\"this will be disabled in the next version\",\"set editor.$blockScrolling = Infinity to disable this message\"),this.renderer.scrollCursorIntoView()),this.$highlightBrackets(),this.$highlightTags(),this.$updateHighlightActiveLine(),this._signal(\"changeSelection\")},this.$updateHighlightActiveLine=function(){var e=this.getSession(),t;if(this.$highlightActiveLine){if(this.$selectionStyle!=\"line\"||!this.selection.isMultiLine())t=this.getCursorPosition();this.renderer.$maxLines&&this.session.getLength()===1&&!(this.renderer.$minLines>1)&&(t=!1)}if(e.$highlightLineMarker&&!t)e.removeMarker(e.$highlightLineMarker.id),e.$highlightLineMarker=null;else if(!e.$highlightLineMarker&&t){var n=new p(t.row,t.column,t.row,Infinity);n.id=e.addMarker(n,\"ace_active-line\",\"screenLine\"),e.$highlightLineMarker=n}else t&&(e.$highlightLineMarker.start.row=t.row,e.$highlightLineMarker.end.row=t.row,e.$highlightLineMarker.start.column=t.column,e._signal(\"changeBackMarker\"))},this.onSelectionChange=function(e){var t=this.session;t.$selectionMarker&&t.removeMarker(t.$selectionMarker),t.$selectionMarker=null;if(!this.selection.isEmpty()){var n=this.selection.getRange(),r=this.getSelectionStyle();t.$selectionMarker=t.addMarker(n,\"ace_selection\",r)}else this.$updateHighlightActiveLine();var i=this.$highlightSelectedWord&&this.$getSelectionHighLightRegexp();this.session.highlight(i),this._signal(\"changeSelection\")},this.$getSelectionHighLightRegexp=function(){var e=this.session,t=this.getSelectionRange();if(t.isEmpty()||t.isMultiLine())return;var n=t.start.column-1,r=t.end.column+1,i=e.getLine(t.start.row),s=i.length,o=i.substring(Math.max(n,0),Math.min(r,s));if(n>=0&&/^[\\w\\d]/.test(o)||r<=s&&/[\\w\\d]$/.test(o))return;o=i.substring(t.start.column,t.end.column);if(!/^[\\w\\d]+$/.test(o))return;var u=this.$search.$assembleRegExp({wholeWord:!0,caseSensitive:!0,needle:o});return u},this.onChangeFrontMarker=function(){this.renderer.updateFrontMarkers()},this.onChangeBackMarker=function(){this.renderer.updateBackMarkers()},this.onChangeBreakpoint=function(){this.renderer.updateBreakpoints()},this.onChangeAnnotation=function(){this.renderer.setAnnotations(this.session.getAnnotations())},this.onChangeMode=function(e){this.renderer.updateText(),this._emit(\"changeMode\",e)},this.onChangeWrapLimit=function(){this.renderer.updateFull()},this.onChangeWrapMode=function(){this.renderer.onResize(!0)},this.onChangeFold=function(){this.$updateHighlightActiveLine(),this.renderer.updateFull()},this.getSelectedText=function(){return this.session.getTextRange(this.getSelectionRange())},this.getCopyText=function(){var e=this.getSelectedText();return this._signal(\"copy\",e),e},this.onCopy=function(){this.commands.exec(\"copy\",this)},this.onCut=function(){this.commands.exec(\"cut\",this)},this.onPaste=function(e,t){var n={text:e,event:t};this.commands.exec(\"paste\",this,n)},this.$handlePaste=function(e){typeof e==\"string\"&&(e={text:e}),this._signal(\"paste\",e);var t=e.text;if(!this.inMultiSelectMode||this.inVirtualSelectionMode)this.insert(t);else{var n=t.split(/\\r\\n|\\r|\\n/),r=this.selection.rangeList.ranges;if(n.length>r.length||n.length<2||!n[1])return this.commands.exec(\"insertstring\",this,t);for(var i=r.length;i--;){var s=r[i];s.isEmpty()||this.session.remove(s),this.session.insert(s.start,n[i])}}},this.execCommand=function(e,t){return this.commands.exec(e,this,t)},this.insert=function(e,t){var n=this.session,r=n.getMode(),i=this.getCursorPosition();if(this.getBehavioursEnabled()&&!t){var s=r.transformAction(n.getState(i.row),\"insertion\",this,n,e);s&&(e!==s.text&&(this.session.mergeUndoDeltas=!1,this.$mergeNextCommand=!1),e=s.text)}e==\"  \"&&(e=this.session.getTabString());if(!this.selection.isEmpty()){var o=this.getSelectionRange();i=this.session.remove(o),this.clearSelection()}else if(this.session.getOverwrite()&&e.indexOf(\"\\n\")==-1){var o=new p.fromPoints(i,i);o.end.column+=e.length,this.session.remove(o)}if(e==\"\\n\"||e==\"\\r\\n\"){var u=n.getLine(i.row);if(i.column>u.search(/\\S|$/)){var a=u.substr(i.column).search(/\\S|$/);n.doc.removeInLine(i.row,i.column,i.column+a)}}this.clearSelection();var f=i.column,l=n.getState(i.row),u=n.getLine(i.row),c=r.checkOutdent(l,u,e),h=n.insert(i,e);s&&s.selection&&(s.selection.length==2?this.selection.setSelectionRange(new p(i.row,f+s.selection[0],i.row,f+s.selection[1])):this.selection.setSelectionRange(new p(i.row+s.selection[0],s.selection[1],i.row+s.selection[2],s.selection[3])));if(n.getDocument().isNewLine(e)){var d=r.getNextLineIndent(l,u.slice(0,i.column),n.getTabString());n.insert({row:i.row+1,column:0},d)}c&&r.autoOutdent(l,n,i.row)},this.onTextInput=function(e){this.keyBinding.onTextInput(e)},this.onCommandKey=function(e,t,n){this.keyBinding.onCommandKey(e,t,n)},this.setOverwrite=function(e){this.session.setOverwrite(e)},this.getOverwrite=function(){return this.session.getOverwrite()},this.toggleOverwrite=function(){this.session.toggleOverwrite()},this.setScrollSpeed=function(e){this.setOption(\"scrollSpeed\",e)},this.getScrollSpeed=function(){return this.getOption(\"scrollSpeed\")},this.setDragDelay=function(e){this.setOption(\"dragDelay\",e)},this.getDragDelay=function(){return this.getOption(\"dragDelay\")},this.setSelectionStyle=function(e){this.setOption(\"selectionStyle\",e)},this.getSelectionStyle=function(){return this.getOption(\"selectionStyle\")},this.setHighlightActiveLine=function(e){this.setOption(\"highlightActiveLine\",e)},this.getHighlightActiveLine=function(){return this.getOption(\"highlightActiveLine\")},this.setHighlightGutterLine=function(e){this.setOption(\"highlightGutterLine\",e)},this.getHighlightGutterLine=function(){return this.getOption(\"highlightGutterLine\")},this.setHighlightSelectedWord=function(e){this.setOption(\"highlightSelectedWord\",e)},this.getHighlightSelectedWord=function(){return this.$highlightSelectedWord},this.setAnimatedScroll=function(e){this.renderer.setAnimatedScroll(e)},this.getAnimatedScroll=function(){return this.renderer.getAnimatedScroll()},this.setShowInvisibles=function(e){this.renderer.setShowInvisibles(e)},this.getShowInvisibles=function(){return this.renderer.getShowInvisibles()},this.setDisplayIndentGuides=function(e){this.renderer.setDisplayIndentGuides(e)},this.getDisplayIndentGuides=function(){return this.renderer.getDisplayIndentGuides()},this.setShowPrintMargin=function(e){this.renderer.setShowPrintMargin(e)},this.getShowPrintMargin=function(){return this.renderer.getShowPrintMargin()},this.setPrintMarginColumn=function(e){this.renderer.setPrintMarginColumn(e)},this.getPrintMarginColumn=function(){return this.renderer.getPrintMarginColumn()},this.setReadOnly=function(e){this.setOption(\"readOnly\",e)},this.getReadOnly=function(){return this.getOption(\"readOnly\")},this.setBehavioursEnabled=function(e){this.setOption(\"behavioursEnabled\",e)},this.getBehavioursEnabled=function(){return this.getOption(\"behavioursEnabled\")},this.setWrapBehavioursEnabled=function(e){this.setOption(\"wrapBehavioursEnabled\",e)},this.getWrapBehavioursEnabled=function(){return this.getOption(\"wrapBehavioursEnabled\")},this.setShowFoldWidgets=function(e){this.setOption(\"showFoldWidgets\",e)},this.getShowFoldWidgets=function(){return this.getOption(\"showFoldWidgets\")},this.setFadeFoldWidgets=function(e){this.setOption(\"fadeFoldWidgets\",e)},this.getFadeFoldWidgets=function(){return this.getOption(\"fadeFoldWidgets\")},this.remove=function(e){this.selection.isEmpty()&&(e==\"left\"?this.selection.selectLeft():this.selection.selectRight());var t=this.getSelectionRange();if(this.getBehavioursEnabled()){var n=this.session,r=n.getState(t.start.row),i=n.getMode().transformAction(r,\"deletion\",this,n,t);if(t.end.column===0){var s=n.getTextRange(t);if(s[s.length-1]==\"\\n\"){var o=n.getLine(t.end.row);/^\\s+$/.test(o)&&(t.end.column=o.length)}}i&&(t=i)}this.session.remove(t),this.clearSelection()},this.removeWordRight=function(){this.selection.isEmpty()&&this.selection.selectWordRight(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeWordLeft=function(){this.selection.isEmpty()&&this.selection.selectWordLeft(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineStart=function(){this.selection.isEmpty()&&this.selection.selectLineStart(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineEnd=function(){this.selection.isEmpty()&&this.selection.selectLineEnd();var e=this.getSelectionRange();e.start.column==e.end.column&&e.start.row==e.end.row&&(e.end.column=0,e.end.row++),this.session.remove(e),this.clearSelection()},this.splitLine=function(){this.selection.isEmpty()||(this.session.remove(this.getSelectionRange()),this.clearSelection());var e=this.getCursorPosition();this.insert(\"\\n\"),this.moveCursorToPosition(e)},this.transposeLetters=function(){if(!this.selection.isEmpty())return;var e=this.getCursorPosition(),t=e.column;if(t===0)return;var n=this.session.getLine(e.row),r,i;t<n.length?(r=n.charAt(t)+n.charAt(t-1),i=new p(e.row,t-1,e.row,t+1)):(r=n.charAt(t-1)+n.charAt(t-2),i=new p(e.row,t-2,e.row,t)),this.session.replace(i,r),this.session.selection.moveToPosition(i.end)},this.toLowerCase=function(){var e=this.getSelectionRange();this.selection.isEmpty()&&this.selection.selectWord();var t=this.getSelectionRange(),n=this.session.getTextRange(t);this.session.replace(t,n.toLowerCase()),this.selection.setSelectionRange(e)},this.toUpperCase=function(){var e=this.getSelectionRange();this.selection.isEmpty()&&this.selection.selectWord();var t=this.getSelectionRange(),n=this.session.getTextRange(t);this.session.replace(t,n.toUpperCase()),this.selection.setSelectionRange(e)},this.indent=function(){var e=this.session,t=this.getSelectionRange();if(t.start.row<t.end.row){var n=this.$getSelectedRows();e.indentRows(n.first,n.last,\"  \");return}if(t.start.column<t.end.column){var r=e.getTextRange(t);if(!/^\\s+$/.test(r)){var n=this.$getSelectedRows();e.indentRows(n.first,n.last,\"  \");return}}var i=e.getLine(t.start.row),o=t.start,u=e.getTabSize(),a=e.documentToScreenColumn(o.row,o.column);if(this.session.getUseSoftTabs())var f=u-a%u,l=s.stringRepeat(\" \",f);else{var f=a%u;while(i[t.start.column-1]==\" \"&&f)t.start.column--,f--;this.selection.setSelectionRange(t),l=\"    \"}return this.insert(l)},this.blockIndent=function(){var e=this.$getSelectedRows();this.session.indentRows(e.first,e.last,\" \")},this.blockOutdent=function(){var e=this.session.getSelection();this.session.outdentRows(e.getRange())},this.sortLines=function(){var e=this.$getSelectedRows(),t=this.session,n=[];for(i=e.first;i<=e.last;i++)n.push(t.getLine(i));n.sort(function(e,t){return e.toLowerCase()<t.toLowerCase()?-1:e.toLowerCase()>t.toLowerCase()?1:0});var r=new p(0,0,0,0);for(var i=e.first;i<=e.last;i++){var s=t.getLine(i);r.start.row=i,r.end.row=i,r.end.column=s.length,t.replace(r,n[i-e.first])}},this.toggleCommentLines=function(){var e=this.session.getState(this.getCursorPosition().row),t=this.$getSelectedRows();this.session.getMode().toggleCommentLines(e,this.session,t.first,t.last)},this.toggleBlockComment=function(){var e=this.getCursorPosition(),t=this.session.getState(e.row),n=this.getSelectionRange();this.session.getMode().toggleBlockComment(t,this.session,n,e)},this.getNumberAt=function(e,t){var n=/[\\-]?[0-9]+(?:\\.[0-9]+)?/g;n.lastIndex=0;var r=this.session.getLine(e);while(n.lastIndex<t){var i=n.exec(r);if(i.index<=t&&i.index+i[0].length>=t){var s={value:i[0],start:i.index,end:i.index+i[0].length};return s}}return null},this.modifyNumber=function(e){var t=this.selection.getCursor().row,n=this.selection.getCursor().column,r=new p(t,n-1,t,n),i=this.session.getTextRange(r);if(!isNaN(parseFloat(i))&&isFinite(i)){var s=this.getNumberAt(t,n);if(s){var o=s.value.indexOf(\".\")>=0?s.start+s.value.indexOf(\".\")+1:s.end,u=s.start+s.value.length-o,a=parseFloat(s.value);a*=Math.pow(10,u),o!==s.end&&n<o?e*=Math.pow(10,s.end-n-1):e*=Math.pow(10,s.end-n),a+=e,a/=Math.pow(10,u);var f=a.toFixed(u),l=new p(t,s.start,t,s.end);this.session.replace(l,f),this.moveCursorTo(t,Math.max(s.start+1,n+f.length-s.value.length))}}},this.removeLines=function(){var e=this.$getSelectedRows();this.session.removeFullLines(e.first,e.last),this.clearSelection()},this.duplicateSelection=function(){var e=this.selection,t=this.session,n=e.getRange(),r=e.isBackwards();if(n.isEmpty()){var i=n.start.row;t.duplicateLines(i,i)}else{var s=r?n.start:n.end,o=t.insert(s,t.getTextRange(n),!1);n.start=s,n.end=o,e.setSelectionRange(n,r)}},this.moveLinesDown=function(){this.$moveLines(1,!1)},this.moveLinesUp=function(){this.$moveLines(-1,!1)},this.moveText=function(e,t,n){return this.session.moveText(e,t,n)},this.copyLinesUp=function(){this.$moveLines(-1,!0)},this.copyLinesDown=function(){this.$moveLines(1,!0)},this.$moveLines=function(e,t){var n,r,i=this.selection;if(!i.inMultiSelectMode||this.inVirtualSelectionMode){var s=i.toOrientedRange();n=this.$getSelectedRows(s),r=this.session.$moveLines(n.first,n.last,t?0:e),t&&e==-1&&(r=0),s.moveBy(r,0),i.fromOrientedRange(s)}else{var o=i.rangeList.ranges;i.rangeList.detach(this.session),this.inVirtualSelectionMode=!0;var u=0,a=0,f=o.length;for(var l=0;l<f;l++){var c=l;o[l].moveBy(u,0),n=this.$getSelectedRows(o[l]);var h=n.first,p=n.last;while(++l<f){a&&o[l].moveBy(a,0);var d=this.$getSelectedRows(o[l]);if(t&&d.first!=p)break;if(!t&&d.first>p+1)break;p=d.last}l--,u=this.session.$moveLines(h,p,t?0:e),t&&e==-1&&(c=l+1);while(c<=l)o[c].moveBy(u,0),c++;t||(u=0),a+=u}i.fromOrientedRange(i.ranges[0]),i.rangeList.attach(this.session),this.inVirtualSelectionMode=!1}},this.$getSelectedRows=function(e){return e=(e||this.getSelectionRange()).collapseRows(),{first:this.session.getRowFoldStart(e.start.row),last:this.session.getRowFoldEnd(e.end.row)}},this.onCompositionStart=function(e){this.renderer.showComposition(this.getCursorPosition())},this.onCompositionUpdate=function(e){this.renderer.setCompositionText(e)},this.onCompositionEnd=function(){this.renderer.hideComposition()},this.getFirstVisibleRow=function(){return this.renderer.getFirstVisibleRow()},this.getLastVisibleRow=function(){return this.renderer.getLastVisibleRow()},this.isRowVisible=function(e){return e>=this.getFirstVisibleRow()&&e<=this.getLastVisibleRow()},this.isRowFullyVisible=function(e){return e>=this.renderer.getFirstFullyVisibleRow()&&e<=this.renderer.getLastFullyVisibleRow()},this.$getVisibleRowCount=function(){return this.renderer.getScrollBottomRow()-this.renderer.getScrollTopRow()+1},this.$moveByPage=function(e,t){var n=this.renderer,r=this.renderer.layerConfig,i=e*Math.floor(r.height/r.lineHeight);this.$blockScrolling++,t===!0?this.selection.$moveSelection(function(){this.moveCursorBy(i,0)}):t===!1&&(this.selection.moveCursorBy(i,0),this.selection.clearSelection()),this.$blockScrolling--;var s=n.scrollTop;n.scrollBy(0,i*r.lineHeight),t!=null&&n.scrollCursorIntoView(null,.5),n.animateScrolling(s)},this.selectPageDown=function(){this.$moveByPage(1,!0)},this.selectPageUp=function(){this.$moveByPage(-1,!0)},this.gotoPageDown=function(){this.$moveByPage(1,!1)},this.gotoPageUp=function(){this.$moveByPage(-1,!1)},this.scrollPageDown=function(){this.$moveByPage(1)},this.scrollPageUp=function(){this.$moveByPage(-1)},this.scrollToRow=function(e){this.renderer.scrollToRow(e)},this.scrollToLine=function(e,t,n,r){this.renderer.scrollToLine(e,t,n,r)},this.centerSelection=function(){var e=this.getSelectionRange(),t={row:Math.floor(e.start.row+(e.end.row-e.start.row)/2),column:Math.floor(e.start.column+(e.end.column-e.start.column)/2)};this.renderer.alignCursor(t,.5)},this.getCursorPosition=function(){return this.selection.getCursor()},this.getCursorPositionScreen=function(){return this.session.documentToScreenPosition(this.getCursorPosition())},this.getSelectionRange=function(){return this.selection.getRange()},this.selectAll=function(){this.$blockScrolling+=1,this.selection.selectAll(),this.$blockScrolling-=1},this.clearSelection=function(){this.selection.clearSelection()},this.moveCursorTo=function(e,t){this.selection.moveCursorTo(e,t)},this.moveCursorToPosition=function(e){this.selection.moveCursorToPosition(e)},this.jumpToMatching=function(e,t){var n=this.getCursorPosition(),r=new y(this.session,n.row,n.column),i=r.getCurrentToken(),s=i||r.stepForward();if(!s)return;var o,u=!1,a={},f=n.column-s.start,l,c={\")\":\"(\",\"(\":\"(\",\"]\":\"[\",\"[\":\"[\",\"{\":\"{\",\"}\":\"{\"};do{if(s.value.match(/[{}()\\[\\]]/g))for(;f<s.value.length&&!u;f++){if(!c[s.value[f]])continue;l=c[s.value[f]]+\".\"+s.type.replace(\"rparen\",\"lparen\"),isNaN(a[l])&&(a[l]=0);switch(s.value[f]){case\"(\":case\"[\":case\"{\":a[l]++;break;case\")\":case\"]\":case\"}\":a[l]--,a[l]===-1&&(o=\"bracket\",u=!0)}}else s&&s.type.indexOf(\"tag-name\")!==-1&&(isNaN(a[s.value])&&(a[s.value]=0),i.value===\"<\"?a[s.value]++:i.value===\"</\"&&a[s.value]--,a[s.value]===-1&&(o=\"tag\",u=!0));u||(i=s,s=r.stepForward(),f=0)}while(s&&!u);if(!o)return;var h,d;if(o===\"bracket\"){h=this.session.getBracketRange(n);if(!h){h=new p(r.getCurrentTokenRow(),r.getCurrentTokenColumn()+f-1,r.getCurrentTokenRow(),r.getCurrentTokenColumn()+f-1),d=h.start;if(t||d.row===n.row&&Math.abs(d.column-n.column)<2)h=this.session.getBracketRange(d)}}else if(o===\"tag\"){if(!s||s.type.indexOf(\"tag-name\")===-1)return;var v=s.value;h=new p(r.getCurrentTokenRow(),r.getCurrentTokenColumn()-2,r.getCurrentTokenRow(),r.getCurrentTokenColumn()-2);if(h.compare(n.row,n.column)===0){u=!1;do s=i,i=r.stepBackward(),i&&(i.type.indexOf(\"tag-close\")!==-1&&h.setEnd(r.getCurrentTokenRow(),r.getCurrentTokenColumn()+1),s.value===v&&s.type.indexOf(\"tag-name\")!==-1&&(i.value===\"<\"?a[v]++:i.value===\"</\"&&a[v]--,a[v]===0&&(u=!0)));while(i&&!u)}s&&s.type.indexOf(\"tag-name\")&&(d=h.start,d.row==n.row&&Math.abs(d.column-n.column)<2&&(d=h.end))}d=h&&h.cursor||d,d&&(e?h&&t?this.selection.setRange(h):h&&h.isEqual(this.getSelectionRange())?this.clearSelection():this.selection.selectTo(d.row,d.column):this.selection.moveTo(d.row,d.column))},this.gotoLine=function(e,t,n){this.selection.clearSelection(),this.session.unfold({row:e-1,column:t||0}),this.$blockScrolling+=1,this.exitMultiSelectMode&&this.exitMultiSelectMode(),this.moveCursorTo(e-1,t||0),this.$blockScrolling-=1,this.isRowFullyVisible(e-1)||this.scrollToLine(e-1,!0,n)},this.navigateTo=function(e,t){this.selection.moveTo(e,t)},this.navigateUp=function(e){if(this.selection.isMultiLine()&&!this.selection.isBackwards()){var t=this.selection.anchor.getPosition();return this.moveCursorToPosition(t)}this.selection.clearSelection(),this.selection.moveCursorBy(-e||-1,0)},this.navigateDown=function(e){if(this.selection.isMultiLine()&&this.selection.isBackwards()){var t=this.selection.anchor.getPosition();return this.moveCursorToPosition(t)}this.selection.clearSelection(),this.selection.moveCursorBy(e||1,0)},this.navigateLeft=function(e){if(!this.selection.isEmpty()){var t=this.getSelectionRange().start;this.moveCursorToPosition(t)}else{e=e||1;while(e--)this.selection.moveCursorLeft()}this.clearSelection()},this.navigateRight=function(e){if(!this.selection.isEmpty()){var t=this.getSelectionRange().end;this.moveCursorToPosition(t)}else{e=e||1;while(e--)this.selection.moveCursorRight()}this.clearSelection()},this.navigateLineStart=function(){this.selection.moveCursorLineStart(),this.clearSelection()},this.navigateLineEnd=function(){this.selection.moveCursorLineEnd(),this.clearSelection()},this.navigateFileEnd=function(){this.selection.moveCursorFileEnd(),this.clearSelection()},this.navigateFileStart=function(){this.selection.moveCursorFileStart(),this.clearSelection()},this.navigateWordRight=function(){this.selection.moveCursorWordRight(),this.clearSelection()},this.navigateWordLeft=function(){this.selection.moveCursorWordLeft(),this.clearSelection()},this.replace=function(e,t){t&&this.$search.set(t);var n=this.$search.find(this.session),r=0;return n?(this.$tryReplace(n,e)&&(r=1),n!==null&&(this.selection.setSelectionRange(n),this.renderer.scrollSelectionIntoView(n.start,n.end)),r):r},this.replaceAll=function(e,t){t&&this.$search.set(t);var n=this.$search.findAll(this.session),r=0;if(!n.length)return r;this.$blockScrolling+=1;var i=this.getSelectionRange();this.selection.moveTo(0,0);for(var s=n.length-1;s>=0;--s)this.$tryReplace(n[s],e)&&r++;return this.selection.setSelectionRange(i),this.$blockScrolling-=1,r},this.$tryReplace=function(e,t){var n=this.session.getTextRange(e);return t=this.$search.replace(n,t),t!==null?(e.end=this.session.replace(e,t),e):null},this.getLastSearchOptions=function(){return this.$search.getOptions()},this.find=function(e,t,n){t||(t={}),typeof e==\"string\"||e instanceof RegExp?t.needle=e:typeof e==\"object\"&&r.mixin(t,e);var i=this.selection.getRange();t.needle==null&&(e=this.session.getTextRange(i)||this.$search.$options.needle,e||(i=this.session.getWordRange(i.start.row,i.start.column),e=this.session.getTextRange(i)),this.$search.set({needle:e})),this.$search.set(t),t.start||this.$search.set({start:i});var s=this.$search.find(this.session);if(t.preventScroll)return s;if(s)return this.revealRange(s,n),s;t.backwards?i.start=i.end:i.end=i.start,this.selection.setRange(i)},this.findNext=function(e,t){this.find({skipCurrent:!0,backwards:!1},e,t)},this.findPrevious=function(e,t){this.find(e,{skipCurrent:!0,backwards:!0},t)},this.revealRange=function(e,t){this.$blockScrolling+=1,this.session.unfold(e),this.selection.setSelectionRange(e),this.$blockScrolling-=1;var n=this.renderer.scrollTop;this.renderer.scrollSelectionIntoView(e.start,e.end,.5),t!==!1&&this.renderer.animateScrolling(n)},this.undo=function(){this.$blockScrolling++,this.session.getUndoManager().undo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.redo=function(){this.$blockScrolling++,this.session.getUndoManager().redo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.destroy=function(){this.renderer.destroy(),this._signal(\"destroy\",this),this.session&&this.session.destroy()},this.setAutoScrollEditorIntoView=function(e){if(!e)return;var t,n=this,r=!1;this.$scrollAnchor||(this.$scrollAnchor=document.createElement(\"div\"));var i=this.$scrollAnchor;i.style.cssText=\"position:absolute\",this.container.insertBefore(i,this.container.firstChild);var s=this.on(\"changeSelection\",function(){r=!0}),o=this.renderer.on(\"beforeRender\",function(){r&&(t=n.renderer.container.getBoundingClientRect())}),u=this.renderer.on(\"afterRender\",function(){if(r&&t&&(n.isFocused()||n.searchBox&&n.searchBox.isFocused())){var e=n.renderer,s=e.$cursorLayer.$pixelPos,o=e.layerConfig,u=s.top-o.offset;s.top>=0&&u+t.top<0?r=!0:s.top<o.height&&s.top+t.top+o.lineHeight>window.innerHeight?r=!1:r=null,r!=null&&(i.style.top=u+\"px\",i.style.left=s.left+\"px\",i.style.height=o.lineHeight+\"px\",i.scrollIntoView(r)),r=t=null}});this.setAutoScrollEditorIntoView=function(e){if(e)return;delete this.setAutoScrollEditorIntoView,this.off(\"changeSelection\",s),this.renderer.off(\"afterRender\",u),this.renderer.off(\"beforeRender\",o)}},this.$resetCursorStyle=function(){var e=this.$cursorStyle||\"ace\",t=this.renderer.$cursorLayer;if(!t)return;t.setSmoothBlinking(/smooth/.test(e)),t.isBlinking=!this.$readOnly&&e!=\"wide\",i.setCssClass(t.element,\"ace_slim-cursors\",/slim/.test(e))}}.call(b.prototype),g.defineOptions(b.prototype,\"editor\",{selectionStyle:{set:function(e){this.onSelectionChange(),this._signal(\"changeSelectionStyle\",{data:e})},initialValue:\"line\"},highlightActiveLine:{set:function(){this.$updateHighlightActiveLine()},initialValue:!0},highlightSelectedWord:{set:function(e){this.$onSelectionChange()},initialValue:!0},readOnly:{set:function(e){this.$resetCursorStyle()},initialValue:!1},cursorStyle:{set:function(e){this.$resetCursorStyle()},values:[\"ace\",\"slim\",\"smooth\",\"wide\"],initialValue:\"ace\"},mergeUndoDeltas:{values:[!1,!0,\"always\"],initialValue:!0},behavioursEnabled:{initialValue:!0},wrapBehavioursEnabled:{initialValue:!0},autoScrollEditorIntoView:{set:function(e){this.setAutoScrollEditorIntoView(e)}},keyboardHandler:{set:function(e){this.setKeyboardHandler(e)},get:function(){return this.keybindingId},handlesSet:!0},hScrollBarAlwaysVisible:\"renderer\",vScrollBarAlwaysVisible:\"renderer\",highlightGutterLine:\"renderer\",animatedScroll:\"renderer\",showInvisibles:\"renderer\",showPrintMargin:\"renderer\",printMarginColumn:\"renderer\",printMargin:\"renderer\",fadeFoldWidgets:\"renderer\",showFoldWidgets:\"renderer\",showLineNumbers:\"renderer\",showGutter:\"renderer\",displayIndentGuides:\"renderer\",fontSize:\"renderer\",fontFamily:\"renderer\",maxLines:\"renderer\",minLines:\"renderer\",scrollPastEnd:\"renderer\",fixedWidthGutter:\"renderer\",theme:\"renderer\",scrollSpeed:\"$mouseHandler\",dragDelay:\"$mouseHandler\",dragEnabled:\"$mouseHandler\",focusTimout:\"$mouseHandler\",tooltipFollowsMouse:\"$mouseHandler\",firstLineNumber:\"session\",overwrite:\"session\",newLineMode:\"session\",useWorker:\"session\",useSoftTabs:\"session\",tabSize:\"session\",wrap:\"session\",indentedSoftWrap:\"session\",foldStyle:\"session\",mode:\"session\"}),t.Editor=b}),define(\"ace/undomanager\",[\"require\",\"exports\",\"module\"],function(e,t,n){\"use strict\";var r=function(){this.reset()};(function(){function e(e){return{action:e.action,start:e.start,end:e.end,lines:e.lines.length==1?null:e.lines,text:e.lines.length==1?e.lines[0]:null}}function t(e){return{action:e.action,start:e.start,end:e.end,lines:e.lines||[e.text]}}function n(e,t){var n=new Array(e.length);for(var r=0;r<e.length;r++){var i=e[r],s={group:i.group,deltas:new Array(i.length)};for(var o=0;o<i.deltas.length;o++){var u=i.deltas[o];s.deltas[o]=t(u)}n[r]=s}return n}this.execute=function(e){var t=e.args[0];this.$doc=e.args[1],e.merge&&this.hasUndo()&&(this.dirtyCounter--,t=this.$undoStack.pop().concat(t)),this.$undoStack.push(t),this.$redoStack=[],this.dirtyCounter<0&&(this.dirtyCounter=NaN),this.dirtyCounter++},this.undo=function(e){var t=this.$undoStack.pop(),n=null;return t&&(n=this.$doc.undoChanges(t,e),this.$redoStack.push(t),this.dirtyCounter--),n},this.redo=function(e){var t=this.$redoStack.pop(),n=null;return t&&(n=this.$doc.redoChanges(this.$deserializeDeltas(t),e),this.$undoStack.push(t),this.dirtyCounter++),n},this.reset=function(){this.$undoStack=[],this.$redoStack=[],this.dirtyCounter=0},this.hasUndo=function(){return this.$undoStack.length>0},this.hasRedo=function(){return this.$redoStack.length>0},this.markClean=function(){this.dirtyCounter=0},this.isClean=function(){return this.dirtyCounter===0},this.$serializeDeltas=function(t){return n(t,e)},this.$deserializeDeltas=function(e){return n(e,t)}}).call(r.prototype),t.UndoManager=r}),define(\"ace/layer/gutter\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\",\"ace/lib/oop\",\"ace/lib/lang\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";var r=e(\"../lib/dom\"),i=e(\"../lib/oop\"),s=e(\"../lib/lang\"),o=e(\"../lib/event_emitter\").EventEmitter,u=function(e){this.element=r.createElement(\"div\"),this.element.className=\"ace_layer ace_gutter-layer\",e.appendChild(this.element),this.setShowFoldWidgets(this.$showFoldWidgets),this.gutterWidth=0,this.$annotations=[],this.$updateAnnotations=this.$updateAnnotations.bind(this),this.$cells=[]};(function(){i.implement(this,o),this.setSession=function(e){this.session&&this.session.removeEventListener(\"change\",this.$updateAnnotations),this.session=e,e&&e.on(\"change\",this.$updateAnnotations)},this.addGutterDecoration=function(e,t){window.console&&console.warn&&console.warn(\"deprecated use session.addGutterDecoration\"),this.session.addGutterDecoration(e,t)},this.removeGutterDecoration=function(e,t){window.console&&console.warn&&console.warn(\"deprecated use session.removeGutterDecoration\"),this.session.removeGutterDecoration(e,t)},this.setAnnotations=function(e){this.$annotations=[];for(var t=0;t<e.length;t++){var n=e[t],r=n.row,i=this.$annotations[r];i||(i=this.$annotations[r]={text:[]});var o=n.text;o=o?s.escapeHTML(o):n.html||\"\",i.text.indexOf(o)===-1&&i.text.push(o);var u=n.type;u==\"error\"?i.className=\" ace_error\":u==\"warning\"&&i.className!=\" ace_error\"?i.className=\" ace_warning\":u==\"info\"&&!i.className&&(i.className=\" ace_info\")}},this.$updateAnnotations=function(e){if(!this.$annotations.length)return;var t=e.start.row,n=e.end.row-t;if(n!==0)if(e.action==\"remove\")this.$annotations.splice(t,n+1,null);else{var r=new Array(n+1);r.unshift(t,1),this.$annotations.splice.apply(this.$annotations,r)}},this.update=function(e){var t=this.session,n=e.firstRow,i=Math.min(e.lastRow+e.gutterOffset,t.getLength()-1),s=t.getNextFoldLine(n),o=s?s.start.row:Infinity,u=this.$showFoldWidgets&&t.foldWidgets,a=t.$breakpoints,f=t.$decorations,l=t.$firstLineNumber,c=0,h=t.gutterRenderer||this.$renderer,p=null,d=-1,v=n;for(;;){v>o&&(v=s.end.row+1,s=t.getNextFoldLine(v,s),o=s?s.start.row:Infinity);if(v>i){while(this.$cells.length>d+1)p=this.$cells.pop(),this.element.removeChild(p.element);break}p=this.$cells[++d],p||(p={element:null,textNode:null,foldWidget:null},p.element=r.createElement(\"div\"),p.textNode=document.createTextNode(\"\"),p.element.appendChild(p.textNode),this.element.appendChild(p.element),this.$cells[d]=p);var m=\"ace_gutter-cell \";a[v]&&(m+=a[v]),f[v]&&(m+=f[v]),this.$annotations[v]&&(m+=this.$annotations[v].className),p.element.className!=m&&(p.element.className=m);var g=t.getRowLength(v)*e.lineHeight+\"px\";g!=p.element.style.height&&(p.element.style.height=g);if(u){var y=u[v];y==null&&(y=u[v]=t.getFoldWidget(v))}if(y){p.foldWidget||(p.foldWidget=r.createElement(\"span\"),p.element.appendChild(p.foldWidget));var m=\"ace_fold-widget ace_\"+y;y==\"start\"&&v==o&&v<s.end.row?m+=\" ace_closed\":m+=\" ace_open\",p.foldWidget.className!=m&&(p.foldWidget.className=m);var g=e.lineHeight+\"px\";p.foldWidget.style.height!=g&&(p.foldWidget.style.height=g)}else p.foldWidget&&(p.element.removeChild(p.foldWidget),p.foldWidget=null);var b=c=h?h.getText(t,v):v+l;b!==p.textNode.data&&(p.textNode.data=b),v++}this.element.style.height=e.minHeight+\"px\";if(this.$fixedWidth||t.$useWrapMode)c=t.getLength()+l;var w=h?h.getWidth(t,c,e):c.toString().length*e.characterWidth,E=this.$padding||this.$computePadding();w+=E.left+E.right,w!==this.gutterWidth&&!isNaN(w)&&(this.gutterWidth=w,this.element.style.width=Math.ceil(this.gutterWidth)+\"px\",this._emit(\"changeGutterWidth\",w))},this.$fixedWidth=!1,this.$showLineNumbers=!0,this.$renderer=\"\",this.setShowLineNumbers=function(e){this.$renderer=!e&&{getWidth:function(){return\"\"},getText:function(){return\"\"}}},this.getShowLineNumbers=function(){return this.$showLineNumbers},this.$showFoldWidgets=!0,this.setShowFoldWidgets=function(e){e?r.addCssClass(this.element,\"ace_folding-enabled\"):r.removeCssClass(this.element,\"ace_folding-enabled\"),this.$showFoldWidgets=e,this.$padding=null},this.getShowFoldWidgets=function(){return this.$showFoldWidgets},this.$computePadding=function(){if(!this.element.firstChild)return{left:0,right:0};var e=r.computedStyle(this.element.firstChild);return this.$padding={},this.$padding.left=parseInt(e.paddingLeft)+1||0,this.$padding.right=parseInt(e.paddingRight)||0,this.$padding},this.getRegion=function(e){var t=this.$padding||this.$computePadding(),n=this.element.getBoundingClientRect();if(e.x<t.left+n.left)return\"markers\";if(this.$showFoldWidgets&&e.x>n.right-t.right)return\"foldWidgets\"}}).call(u.prototype),t.Gutter=u}),define(\"ace/layer/marker\",[\"require\",\"exports\",\"module\",\"ace/range\",\"ace/lib/dom\"],function(e,t,n){\"use strict\";var r=e(\"../range\").Range,i=e(\"../lib/dom\"),s=function(e){this.element=i.createElement(\"div\"),this.element.className=\"ace_layer ace_marker-layer\",e.appendChild(this.element)};(function(){function e(e,t,n,r){return(e?1:0)|(t?2:0)|(n?4:0)|(r?8:0)}this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setMarkers=function(e){this.markers=e},this.update=function(e){if(!e)return;this.config=e;var t=[];for(var n in this.markers){var r=this.markers[n];if(!r.range){r.update(t,this,this.session,e);continue}var i=r.range.clipRows(e.firstRow,e.lastRow);if(i.isEmpty())continue;i=i.toScreenRange(this.session);if(r.renderer){var s=this.$getTop(i.start.row,e),o=this.$padding+i.start.column*e.characterWidth;r.renderer(t,i,o,s,e)}else r.type==\"fullLine\"?this.drawFullLineMarker(t,i,r.clazz,e):r.type==\"screenLine\"?this.drawScreenLineMarker(t,i,r.clazz,e):i.isMultiLine()?r.type==\"text\"?this.drawTextMarker(t,i,r.clazz,e):this.drawMultiLineMarker(t,i,r.clazz,e):this.drawSingleLineMarker(t,i,r.clazz+\" ace_start\"+\" ace_br15\",e)}this.element.innerHTML=t.join(\"\")},this.$getTop=function(e,t){return(e-t.firstRowScreen)*t.lineHeight},this.drawTextMarker=function(t,n,i,s,o){var u=this.session,a=n.start.row,f=n.end.row,l=a,c=0,h=0,p=u.getScreenLastRowColumn(l),d=new r(l,n.start.column,l,h);for(;l<=f;l++)d.start.row=d.end.row=l,d.start.column=l==a?n.start.column:u.getRowWrapIndent(l),d.end.column=p,c=h,h=p,p=l+1<f?u.getScreenLastRowColumn(l+1):l==f?0:n.end.column,this.drawSingleLineMarker(t,d,i+(l==a?\" ace_start\":\"\")+\" ace_br\"+e(l==a||l==a+1&&n.start.column,c<h,h>p,l==f),s,l==f?0:1,o)},this.drawMultiLineMarker=function(e,t,n,r,i){var s=this.$padding,o=r.lineHeight,u=this.$getTop(t.start.row,r),a=s+t.start.column*r.characterWidth;i=i||\"\",e.push(\"<div class='\",n,\" ace_br1 ace_start' style='\",\"height:\",o,\"px;\",\"right:0;\",\"top:\",u,\"px;\",\"left:\",a,\"px;\",i,\"'></div>\"),u=this.$getTop(t.end.row,r);var f=t.end.column*r.characterWidth;e.push(\"<div class='\",n,\" ace_br12' style='\",\"height:\",o,\"px;\",\"width:\",f,\"px;\",\"top:\",u,\"px;\",\"left:\",s,\"px;\",i,\"'></div>\"),o=(t.end.row-t.start.row-1)*r.lineHeight;if(o<=0)return;u=this.$getTop(t.start.row+1,r);var l=(t.start.column?1:0)|(t.end.column?0:8);e.push(\"<div class='\",n,l?\" ace_br\"+l:\"\",\"' style='\",\"height:\",o,\"px;\",\"right:0;\",\"top:\",u,\"px;\",\"left:\",s,\"px;\",i,\"'></div>\")},this.drawSingleLineMarker=function(e,t,n,r,i,s){var o=r.lineHeight,u=(t.end.column+(i||0)-t.start.column)*r.characterWidth,a=this.$getTop(t.start.row,r),f=this.$padding+t.start.column*r.characterWidth;e.push(\"<div class='\",n,\"' style='\",\"height:\",o,\"px;\",\"width:\",u,\"px;\",\"top:\",a,\"px;\",\"left:\",f,\"px;\",s||\"\",\"'></div>\")},this.drawFullLineMarker=function(e,t,n,r,i){var s=this.$getTop(t.start.row,r),o=r.lineHeight;t.start.row!=t.end.row&&(o+=this.$getTop(t.end.row,r)-s),e.push(\"<div class='\",n,\"' style='\",\"height:\",o,\"px;\",\"top:\",s,\"px;\",\"left:0;right:0;\",i||\"\",\"'></div>\")},this.drawScreenLineMarker=function(e,t,n,r,i){var s=this.$getTop(t.start.row,r),o=r.lineHeight;e.push(\"<div class='\",n,\"' style='\",\"height:\",o,\"px;\",\"top:\",s,\"px;\",\"left:0;right:0;\",i||\"\",\"'></div>\")}}).call(s.prototype),t.Marker=s}),define(\"ace/layer/text\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/lib/lang\",\"ace/lib/useragent\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";var r=e(\"../lib/oop\"),i=e(\"../lib/dom\"),s=e(\"../lib/lang\"),o=e(\"../lib/useragent\"),u=e(\"../lib/event_emitter\").EventEmitter,a=function(e){this.element=i.createElement(\"div\"),this.element.className=\"ace_layer ace_text-layer\",e.appendChild(this.element),this.$updateEolChar=this.$updateEolChar.bind(this)};(function(){r.implement(this,u),this.EOF_CHAR=\"\\u00b6\",this.EOL_CHAR_LF=\"\\u00ac\",this.EOL_CHAR_CRLF=\"\\u00a4\",this.EOL_CHAR=this.EOL_CHAR_LF,this.TAB_CHAR=\"\\u2014\",this.SPACE_CHAR=\"\\u00b7\",this.$padding=0,this.$updateEolChar=function(){var e=this.session.doc.getNewLineCharacter()==\"\\n\"?this.EOL_CHAR_LF:this.EOL_CHAR_CRLF;if(this.EOL_CHAR!=e)return this.EOL_CHAR=e,!0},this.setPadding=function(e){this.$padding=e,this.element.style.padding=\"0 \"+e+\"px\"},this.getLineHeight=function(){return this.$fontMetrics.$characterSize.height||0},this.getCharacterWidth=function(){return this.$fontMetrics.$characterSize.width||0},this.$setFontMetrics=function(e){this.$fontMetrics=e,this.$fontMetrics.on(\"changeCharacterSize\",function(e){this._signal(\"changeCharacterSize\",e)}.bind(this)),this.$pollSizeChanges()},this.checkForSizeChanges=function(){this.$fontMetrics.checkForSizeChanges()},this.$pollSizeChanges=function(){return this.$pollSizeChangesTimer=this.$fontMetrics.$pollSizeChanges()},this.setSession=function(e){this.session=e,e&&this.$computeTabString()},this.showInvisibles=!1,this.setShowInvisibles=function(e){return this.showInvisibles==e?!1:(this.showInvisibles=e,this.$computeTabString(),!0)},this.displayIndentGuides=!0,this.setDisplayIndentGuides=function(e){return this.displayIndentGuides==e?!1:(this.displayIndentGuides=e,this.$computeTabString(),!0)},this.$tabStrings=[],this.onChangeTabSize=this.$computeTabString=function(){var e=this.session.getTabSize();this.tabSize=e;var t=this.$tabStrings=[0];for(var n=1;n<e+1;n++)this.showInvisibles?t.push(\"<span class='ace_invisible ace_invisible_tab'>\"+s.stringRepeat(this.TAB_CHAR,n)+\"</span>\"):t.push(s.stringRepeat(\" \",n));if(this.displayIndentGuides){this.$indentGuideRe=/\\s\\S| \\t|\\t |\\s$/;var r=\"ace_indent-guide\",i=\"\",o=\"\";if(this.showInvisibles){r+=\" ace_invisible\",i=\" ace_invisible_space\",o=\" ace_invisible_tab\";var u=s.stringRepeat(this.SPACE_CHAR,this.tabSize),a=s.stringRepeat(this.TAB_CHAR,this.tabSize)}else var u=s.stringRepeat(\" \",this.tabSize),a=u;this.$tabStrings[\" \"]=\"<span class='\"+r+i+\"'>\"+u+\"</span>\",this.$tabStrings[\" \"]=\"<span class='\"+r+o+\"'>\"+a+\"</span>\"}},this.updateLines=function(e,t,n){(this.config.lastRow!=e.lastRow||this.config.firstRow!=e.firstRow)&&this.scrollLines(e),this.config=e;var r=Math.max(t,e.firstRow),i=Math.min(n,e.lastRow),s=this.element.childNodes,o=0;for(var u=e.firstRow;u<r;u++){var a=this.session.getFoldLine(u);if(a){if(a.containsRow(r)){r=a.start.row;break}u=a.end.row}o++}var u=r,a=this.session.getNextFoldLine(u),f=a?a.start.row:Infinity;for(;;){u>f&&(u=a.end.row+1,a=this.session.getNextFoldLine(u,a),f=a?a.start.row:Infinity);if(u>i)break;var l=s[o++];if(l){var c=[];this.$renderLine(c,u,!this.$useLineGroups(),u==f?a:!1),l.style.height=e.lineHeight*this.session.getRowLength(u)+\"px\",l.innerHTML=c.join(\"\")}u++}},this.scrollLines=function(e){var t=this.config;this.config=e;if(!t||t.lastRow<e.firstRow)return this.update(e);if(e.lastRow<t.firstRow)return this.update(e);var n=this.element;if(t.firstRow<e.firstRow)for(var r=this.session.getFoldedRowCount(t.firstRow,e.firstRow-1);r>0;r--)n.removeChild(n.firstChild);if(t.lastRow>e.lastRow)for(var r=this.session.getFoldedRowCount(e.lastRow+1,t.lastRow);r>0;r--)n.removeChild(n.lastChild);if(e.firstRow<t.firstRow){var i=this.$renderLinesFragment(e,e.firstRow,t.firstRow-1);n.firstChild?n.insertBefore(i,n.firstChild):n.appendChild(i)}if(e.lastRow>t.lastRow){var i=this.$renderLinesFragment(e,t.lastRow+1,e.lastRow);n.appendChild(i)}},this.$renderLinesFragment=function(e,t,n){var r=this.element.ownerDocument.createDocumentFragment(),s=t,o=this.session.getNextFoldLine(s),u=o?o.start.row:Infinity;for(;;){s>u&&(s=o.end.row+1,o=this.session.getNextFoldLine(s,o),u=o?o.start.row:Infinity);if(s>n)break;var a=i.createElement(\"div\"),f=[];this.$renderLine(f,s,!1,s==u?o:!1),a.innerHTML=f.join(\"\");if(this.$useLineGroups())a.className=\"ace_line_group\",r.appendChild(a),a.style.height=e.lineHeight*this.session.getRowLength(s)+\"px\";else while(a.firstChild)r.appendChild(a.firstChild);s++}return r},this.update=function(e){this.config=e;var t=[],n=e.firstRow,r=e.lastRow,i=n,s=this.session.getNextFoldLine(i),o=s?s.start.row:Infinity;for(;;){i>o&&(i=s.end.row+1,s=this.session.getNextFoldLine(i,s),o=s?s.start.row:Infinity);if(i>r)break;this.$useLineGroups()&&t.push(\"<div class='ace_line_group' style='height:\",e.lineHeight*this.session.getRowLength(i),\"px'>\"),this.$renderLine(t,i,!1,i==o?s:!1),this.$useLineGroups()&&t.push(\"</div>\"),i++}this.element.innerHTML=t.join(\"\")},this.$textToken={text:!0,rparen:!0,lparen:!0},this.$renderToken=function(e,t,n,r){var i=this,o=/\\t|&|<|>|( +)|([\\x00-\\x1f\\x80-\\xa0\\xad\\u1680\\u180E\\u2000-\\u200f\\u2028\\u2029\\u202F\\u205F\\u3000\\uFEFF\\uFFF9-\\uFFFC])|[\\u1100-\\u115F\\u11A3-\\u11A7\\u11FA-\\u11FF\\u2329-\\u232A\\u2E80-\\u2E99\\u2E9B-\\u2EF3\\u2F00-\\u2FD5\\u2FF0-\\u2FFB\\u3000-\\u303E\\u3041-\\u3096\\u3099-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u3190-\\u31BA\\u31C0-\\u31E3\\u31F0-\\u321E\\u3220-\\u3247\\u3250-\\u32FE\\u3300-\\u4DBF\\u4E00-\\uA48C\\uA490-\\uA4C6\\uA960-\\uA97C\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFAFF\\uFE10-\\uFE19\\uFE30-\\uFE52\\uFE54-\\uFE66\\uFE68-\\uFE6B\\uFF01-\\uFF60\\uFFE0-\\uFFE6]/g,u=function(e,n,r,o,u){if(n)return i.showInvisibles?\"<span class='ace_invisible ace_invisible_space'>\"+s.stringRepeat(i.SPACE_CHAR,e.length)+\"</span>\":e;if(e==\"&\")return\"&#38;\";if(e==\"<\")return\"&#60;\";if(e==\">\")return\"&#62;\";if(e==\" \"){var a=i.session.getScreenTabSize(t+o);return t+=a-1,i.$tabStrings[a]}if(e==\"\\u3000\"){var f=i.showInvisibles?\"ace_cjk ace_invisible ace_invisible_space\":\"ace_cjk\",l=i.showInvisibles?i.SPACE_CHAR:\"\";return t+=1,\"<span class='\"+f+\"' style='width:\"+i.config.characterWidth*2+\"px'>\"+l+\"</span>\"}return r?\"<span class='ace_invisible ace_invisible_space ace_invalid'>\"+i.SPACE_CHAR+\"</span>\":(t+=1,\"<span class='ace_cjk' style='width:\"+i.config.characterWidth*2+\"px'>\"+e+\"</span>\")},a=r.replace(o,u);if(!this.$textToken[n.type]){var f=\"ace_\"+n.type.replace(/\\./g,\" ace_\"),l=\"\";n.type==\"fold\"&&(l=\" style='width:\"+n.value.length*this.config.characterWidth+\"px;' \"),e.push(\"<span class='\",f,\"'\",l,\">\",a,\"</span>\")}else e.push(a);return t+r.length},this.renderIndentGuide=function(e,t,n){var r=t.search(this.$indentGuideRe);return r<=0||r>=n?t:t[0]==\" \"?(r-=r%this.tabSize,e.push(s.stringRepeat(this.$tabStrings[\" \"],r/this.tabSize)),t.substr(r)):t[0]==\" \"?(e.push(s.stringRepeat(this.$tabStrings[\" \"],r)),t.substr(r)):t},this.$renderWrappedLine=function(e,t,n,r){var i=0,o=0,u=n[0],a=0;for(var f=0;f<t.length;f++){var l=t[f],c=l.value;if(f==0&&this.displayIndentGuides){i=c.length,c=this.renderIndentGuide(e,c,u);if(!c)continue;i-=c.length}if(i+c.length<u)a=this.$renderToken(e,a,l,c),i+=c.length;else{while(i+c.length>=u)a=this.$renderToken(e,a,l,c.substring(0,u-i)),c=c.substring(u-i),i=u,r||e.push(\"</div>\",\"<div class='ace_line' style='height:\",this.config.lineHeight,\"px'>\"),e.push(s.stringRepeat(\"\\u00a0\",n.indent)),o++,a=0,u=n[o]||Number.MAX_VALUE;c.length!=0&&(i+=c.length,a=this.$renderToken(e,a,l,c))}}},this.$renderSimpleLine=function(e,t){var n=0,r=t[0],i=r.value;this.displayIndentGuides&&(i=this.renderIndentGuide(e,i)),i&&(n=this.$renderToken(e,n,r,i));for(var s=1;s<t.length;s++)r=t[s],i=r.value,n=this.$renderToken(e,n,r,i)},this.$renderLine=function(e,t,n,r){!r&&r!=0&&(r=this.session.getFoldLine(t));if(r)var i=this.$getFoldLineTokens(t,r);else var i=this.session.getTokens(t);n||e.push(\"<div class='ace_line' style='height:\",this.config.lineHeight*(this.$useLineGroups()?1:this.session.getRowLength(t)),\"px'>\");if(i.length){var s=this.session.getRowSplitData(t);s&&s.length?this.$renderWrappedLine(e,i,s,n):this.$renderSimpleLine(e,i)}this.showInvisibles&&(r&&(t=r.end.row),e.push(\"<span class='ace_invisible ace_invisible_eol'>\",t==this.session.getLength()-1?this.EOF_CHAR:this.EOL_CHAR,\"</span>\")),n||e.push(\"</div>\")},this.$getFoldLineTokens=function(e,t){function i(e,t,n){var i=0,s=0;while(s+e[i].value.length<t){s+=e[i].value.length,i++;if(i==e.length)return}if(s!=t){var o=e[i].value.substring(t-s);o.length>n-t&&(o=o.substring(0,n-t)),r.push({type:e[i].type,value:o}),s=t+o.length,i+=1}while(s<n&&i<e.length){var o=e[i].value;o.length+s>n?r.push({type:e[i].type,value:o.substring(0,n-s)}):r.push(e[i]),s+=o.length,i+=1}}var n=this.session,r=[],s=n.getTokens(e);return t.walk(function(e,t,o,u,a){e!=null?r.push({type:\"fold\",value:e}):(a&&(s=n.getTokens(t)),s.length&&i(s,u,o))},t.end.row,this.session.getLine(t.end.row).length),r},this.$useLineGroups=function(){return this.session.getUseWrapMode()},this.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.$measureNode&&this.$measureNode.parentNode.removeChild(this.$measureNode),delete this.$measureNode}}).call(a.prototype),t.Text=a}),define(\"ace/layer/cursor\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\"],function(e,t,n){\"use strict\";var r=e(\"../lib/dom\"),i,s=function(e){this.element=r.createElement(\"div\"),this.element.className=\"ace_layer ace_cursor-layer\",e.appendChild(this.element),i===undefined&&(i=!(\"opacity\"in this.element.style)),this.isVisible=!1,this.isBlinking=!0,this.blinkInterval=1e3,this.smoothBlinking=!1,this.cursors=[],this.cursor=this.addCursor(),r.addCssClass(this.element,\"ace_hidden-cursors\"),this.$updateCursors=(i?this.$updateVisibility:this.$updateOpacity).bind(this)};(function(){this.$updateVisibility=function(e){var t=this.cursors;for(var n=t.length;n--;)t[n].style.visibility=e?\"\":\"hidden\"},this.$updateOpacity=function(e){var t=this.cursors;for(var n=t.length;n--;)t[n].style.opacity=e?\"\":\"0\"},this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setBlinking=function(e){e!=this.isBlinking&&(this.isBlinking=e,this.restartTimer())},this.setBlinkInterval=function(e){e!=this.blinkInterval&&(this.blinkInterval=e,this.restartTimer())},this.setSmoothBlinking=function(e){e!=this.smoothBlinking&&!i&&(this.smoothBlinking=e,r.setCssClass(this.element,\"ace_smooth-blinking\",e),this.$updateCursors(!0),this.$updateCursors=this.$updateOpacity.bind(this),this.restartTimer())},this.addCursor=function(){var e=r.createElement(\"div\");return e.className=\"ace_cursor\",this.element.appendChild(e),this.cursors.push(e),e},this.removeCursor=function(){if(this.cursors.length>1){var e=this.cursors.pop();return e.parentNode.removeChild(e),e}},this.hideCursor=function(){this.isVisible=!1,r.addCssClass(this.element,\"ace_hidden-cursors\"),this.restartTimer()},this.showCursor=function(){this.isVisible=!0,r.removeCssClass(this.element,\"ace_hidden-cursors\"),this.restartTimer()},this.restartTimer=function(){var e=this.$updateCursors;clearInterval(this.intervalId),clearTimeout(this.timeoutId),this.smoothBlinking&&r.removeCssClass(this.element,\"ace_smooth-blinking\"),e(!0);if(!this.isBlinking||!this.blinkInterval||!this.isVisible)return;this.smoothBlinking&&setTimeout(function(){r.addCssClass(this.element,\"ace_smooth-blinking\")}.bind(this));var t=function(){this.timeoutId=setTimeout(function(){e(!1)},.6*this.blinkInterval)}.bind(this);this.intervalId=setInterval(function(){e(!0),t()},this.blinkInterval),t()},this.getPixelPosition=function(e,t){if(!this.config||!this.session)return{left:0,top:0};e||(e=this.session.selection.getCursor());var n=this.session.documentToScreenPosition(e),r=this.$padding+n.column*this.config.characterWidth,i=(n.row-(t?this.config.firstRowScreen:0))*this.config.lineHeight;return{left:r,top:i}},this.update=function(e){this.config=e;var t=this.session.$selectionMarkers,n=0,r=0;if(t===undefined||t.length===0)t=[{cursor:null}];for(var n=0,i=t.length;n<i;n++){var s=this.getPixelPosition(t[n].cursor,!0);if((s.top>e.height+e.offset||s.top<0)&&n>1)continue;var o=(this.cursors[r++]||this.addCursor()).style;this.drawCursor?this.drawCursor(o,s,e,t[n],this.session):(o.left=s.left+\"px\",o.top=s.top+\"px\",o.width=e.characterWidth+\"px\",o.height=e.lineHeight+\"px\")}while(this.cursors.length>r)this.removeCursor();var u=this.session.getOverwrite();this.$setOverwrite(u),this.$pixelPos=s,this.restartTimer()},this.drawCursor=null,this.$setOverwrite=function(e){e!=this.overwrite&&(this.overwrite=e,e?r.addCssClass(this.element,\"ace_overwrite-cursors\"):r.removeCssClass(this.element,\"ace_overwrite-cursors\"))},this.destroy=function(){clearInterval(this.intervalId),clearTimeout(this.timeoutId)}}).call(s.prototype),t.Cursor=s}),define(\"ace/scrollbar\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/lib/event\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./lib/dom\"),s=e(\"./lib/event\"),o=e(\"./lib/event_emitter\").EventEmitter,u=32768,a=function(e){this.element=i.createElement(\"div\"),this.element.className=\"ace_scrollbar ace_scrollbar\"+this.classSuffix,this.inner=i.createElement(\"div\"),this.inner.className=\"ace_scrollbar-inner\",this.element.appendChild(this.inner),e.appendChild(this.element),this.setVisible(!1),this.skipEvent=!1,s.addListener(this.element,\"scroll\",this.onScroll.bind(this)),s.addListener(this.element,\"mousedown\",s.preventDefault)};(function(){r.implement(this,o),this.setVisible=function(e){this.element.style.display=e?\"\":\"none\",this.isVisible=e,this.coeff=1}}).call(a.prototype);var f=function(e,t){a.call(this,e),this.scrollTop=0,this.scrollHeight=0,t.$scrollbarWidth=this.width=i.scrollbarWidth(e.ownerDocument),this.inner.style.width=this.element.style.width=(this.width||15)+5+\"px\",this.$minWidth=0};r.inherits(f,a),function(){this.classSuffix=\"-v\",this.onScroll=function(){if(!this.skipEvent){this.scrollTop=this.element.scrollTop;if(this.coeff!=1){var e=this.element.clientHeight/this.scrollHeight;this.scrollTop=this.scrollTop*(1-e)/(this.coeff-e)}this._emit(\"scroll\",{data:this.scrollTop})}this.skipEvent=!1},this.getWidth=function(){return Math.max(this.isVisible?this.width:0,this.$minWidth||0)},this.setHeight=function(e){this.element.style.height=e+\"px\"},this.setInnerHeight=this.setScrollHeight=function(e){this.scrollHeight=e,e>u?(this.coeff=u/e,e=u):this.coeff!=1&&(this.coeff=1),this.inner.style.height=e+\"px\"},this.setScrollTop=function(e){this.scrollTop!=e&&(this.skipEvent=!0,this.scrollTop=e,this.element.scrollTop=e*this.coeff)}}.call(f.prototype);var l=function(e,t){a.call(this,e),this.scrollLeft=0,this.height=t.$scrollbarWidth,this.inner.style.height=this.element.style.height=(this.height||15)+5+\"px\"};r.inherits(l,a),function(){this.classSuffix=\"-h\",this.onScroll=function(){this.skipEvent||(this.scrollLeft=this.element.scrollLeft,this._emit(\"scroll\",{data:this.scrollLeft})),this.skipEvent=!1},this.getHeight=function(){return this.isVisible?this.height:0},this.setWidth=function(e){this.element.style.width=e+\"px\"},this.setInnerWidth=function(e){this.inner.style.width=e+\"px\"},this.setScrollWidth=function(e){this.inner.style.width=e+\"px\"},this.setScrollLeft=function(e){this.scrollLeft!=e&&(this.skipEvent=!0,this.scrollLeft=this.element.scrollLeft=e)}}.call(l.prototype),t.ScrollBar=f,t.ScrollBarV=f,t.ScrollBarH=l,t.VScrollBar=f,t.HScrollBar=l}),define(\"ace/renderloop\",[\"require\",\"exports\",\"module\",\"ace/lib/event\"],function(e,t,n){\"use strict\";var r=e(\"./lib/event\"),i=function(e,t){this.onRender=e,this.pending=!1,this.changes=0,this.window=t||window};(function(){this.schedule=function(e){this.changes=this.changes|e;if(!this.pending&&this.changes){this.pending=!0;var t=this;r.nextFrame(function(){t.pending=!1;var e;while(e=t.changes)t.changes=0,t.onRender(e)},this.window)}}}).call(i.prototype),t.RenderLoop=i}),define(\"ace/layer/font_metrics\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/lib/lang\",\"ace/lib/useragent\",\"ace/lib/event_emitter\"],function(e,t,n){var r=e(\"../lib/oop\"),i=e(\"../lib/dom\"),s=e(\"../lib/lang\"),o=e(\"../lib/useragent\"),u=e(\"../lib/event_emitter\").EventEmitter,a=0,f=t.FontMetrics=function(e){this.el=i.createElement(\"div\"),this.$setMeasureNodeStyles(this.el.style,!0),this.$main=i.createElement(\"div\"),this.$setMeasureNodeStyles(this.$main.style),this.$measureNode=i.createElement(\"div\"),this.$setMeasureNodeStyles(this.$measureNode.style),this.el.appendChild(this.$main),this.el.appendChild(this.$measureNode),e.appendChild(this.el),a||this.$testFractionalRect(),this.$measureNode.innerHTML=s.stringRepeat(\"X\",a),this.$characterSize={width:0,height:0},this.checkForSizeChanges()};(function(){r.implement(this,u),this.$characterSize={width:0,height:0},this.$testFractionalRect=function(){var e=i.createElement(\"div\");this.$setMeasureNodeStyles(e.style),e.style.width=\"0.2px\",document.documentElement.appendChild(e);var t=e.getBoundingClientRect().width;t>0&&t<1?a=50:a=100,e.parentNode.removeChild(e)},this.$setMeasureNodeStyles=function(e,t){e.width=e.height=\"auto\",e.left=e.top=\"0px\",e.visibility=\"hidden\",e.position=\"absolute\",e.whiteSpace=\"pre\",o.isIE<8?e[\"font-family\"]=\"inherit\":e.font=\"inherit\",e.overflow=t?\"hidden\":\"visible\"},this.checkForSizeChanges=function(){var e=this.$measureSizes();if(e&&(this.$characterSize.width!==e.width||this.$characterSize.height!==e.height)){this.$measureNode.style.fontWeight=\"bold\";var t=this.$measureSizes();this.$measureNode.style.fontWeight=\"\",this.$characterSize=e,this.charSizes=Object.create(null),this.allowBoldFonts=t&&t.width===e.width&&t.height===e.height,this._emit(\"changeCharacterSize\",{data:e})}},this.$pollSizeChanges=function(){if(this.$pollSizeChangesTimer)return this.$pollSizeChangesTimer;var e=this;return this.$pollSizeChangesTimer=setInterval(function(){e.checkForSizeChanges()},500)},this.setPolling=function(e){e?this.$pollSizeChanges():this.$pollSizeChangesTimer&&(clearInterval(this.$pollSizeChangesTimer),this.$pollSizeChangesTimer=0)},this.$measureSizes=function(){if(a===50){var e=null;try{e=this.$measureNode.getBoundingClientRect()}catch(t){e={width:0,height:0}}var n={height:e.height,width:e.width/a}}else var n={height:this.$measureNode.clientHeight,width:this.$measureNode.clientWidth/a};return n.width===0||n.height===0?null:n},this.$measureCharWidth=function(e){this.$main.innerHTML=s.stringRepeat(e,a);var t=this.$main.getBoundingClientRect();return t.width/a},this.getCharacterWidth=function(e){var t=this.charSizes[e];return t===undefined&&(t=this.charSizes[e]=this.$measureCharWidth(e)/this.$characterSize.width),t},this.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.el&&this.el.parentNode&&this.el.parentNode.removeChild(this.el)}}).call(f.prototype)}),define(\"ace/virtual_renderer\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/config\",\"ace/lib/useragent\",\"ace/layer/gutter\",\"ace/layer/marker\",\"ace/layer/text\",\"ace/layer/cursor\",\"ace/scrollbar\",\"ace/scrollbar\",\"ace/renderloop\",\"ace/layer/font_metrics\",\"ace/lib/event_emitter\"],function(e,t,n){\"use strict\";var r=e(\"./lib/oop\"),i=e(\"./lib/dom\"),s=e(\"./config\"),o=e(\"./lib/useragent\"),u=e(\"./layer/gutter\").Gutter,a=e(\"./layer/marker\").Marker,f=e(\"./layer/text\").Text,l=e(\"./layer/cursor\").Cursor,c=e(\"./scrollbar\").HScrollBar,h=e(\"./scrollbar\").VScrollBar,p=e(\"./renderloop\").RenderLoop,d=e(\"./layer/font_metrics\").FontMetrics,v=e(\"./lib/event_emitter\").EventEmitter,m='.ace_editor {position: relative;overflow: hidden;font: 12px/normal \\'Monaco\\', \\'Menlo\\', \\'Ubuntu Mono\\', \\'Consolas\\', \\'source-code-pro\\', monospace;direction: ltr;text-align: left;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}.ace_scroller {position: absolute;overflow: hidden;top: 0;bottom: 0;background-color: inherit;-ms-user-select: none;-moz-user-select: none;-webkit-user-select: none;user-select: none;cursor: text;}.ace_content {position: absolute;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;min-width: 100%;}.ace_dragging .ace_scroller:before{position: absolute;top: 0;left: 0;right: 0;bottom: 0;content: \\'\\';background: rgba(250, 250, 250, 0.01);z-index: 1000;}.ace_dragging.ace_dark .ace_scroller:before{background: rgba(0, 0, 0, 0.01);}.ace_selecting, .ace_selecting * {cursor: text !important;}.ace_gutter {position: absolute;overflow : hidden;width: auto;top: 0;bottom: 0;left: 0;cursor: default;z-index: 4;-ms-user-select: none;-moz-user-select: none;-webkit-user-select: none;user-select: none;}.ace_gutter-active-line {position: absolute;left: 0;right: 0;}.ace_scroller.ace_scroll-left {box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset;}.ace_gutter-cell {padding-left: 19px;padding-right: 6px;background-repeat: no-repeat;}.ace_gutter-cell.ace_error {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitmk2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg==\");background-repeat: no-repeat;background-position: 2px center;}.ace_gutter-cell.ace_warning {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg==\");background-position: 2px center;}.ace_gutter-cell.ace_info {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAJ0Uk5TAAB2k804AAAAPklEQVQY02NgIB68QuO3tiLznjAwpKTgNyDbMegwisCHZUETUZV0ZqOquBpXj2rtnpSJT1AEnnRmL2OgGgAAIKkRQap2htgAAAAASUVORK5CYII=\");background-position: 2px center;}.ace_dark .ace_gutter-cell.ace_info {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAChoaGAgIAqKiq+vr6tra1ZWVmUlJSbm5s8PDxubm56enrdgzg3AAAAAXRSTlMAQObYZgAAAClJREFUeNpjYMAPdsMYHegyJZFQBlsUlMFVCWUYKkAZMxZAGdxlDMQBAG+TBP4B6RyJAAAAAElFTkSuQmCC\");}.ace_scrollbar {position: absolute;right: 0;bottom: 0;z-index: 6;}.ace_scrollbar-inner {position: absolute;cursor: text;left: 0;top: 0;}.ace_scrollbar-v{overflow-x: hidden;overflow-y: scroll;top: 0;}.ace_scrollbar-h {overflow-x: scroll;overflow-y: hidden;left: 0;}.ace_print-margin {position: absolute;height: 100%;}.ace_text-input {position: absolute;z-index: 0;width: 0.5em;height: 1em;opacity: 0;background: transparent;-moz-appearance: none;appearance: none;border: none;resize: none;outline: none;overflow: hidden;font: inherit;padding: 0 1px;margin: 0 -1px;text-indent: -1em;-ms-user-select: text;-moz-user-select: text;-webkit-user-select: text;user-select: text;white-space: pre!important;}.ace_text-input.ace_composition {background: inherit;color: inherit;z-index: 1000;opacity: 1;text-indent: 0;}.ace_layer {z-index: 1;position: absolute;overflow: hidden;word-wrap: normal;white-space: pre;height: 100%;width: 100%;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;pointer-events: none;}.ace_gutter-layer {position: relative;width: auto;text-align: right;pointer-events: auto;}.ace_text-layer {font: inherit !important;}.ace_cjk {display: inline-block;text-align: center;}.ace_cursor-layer {z-index: 4;}.ace_cursor {z-index: 4;position: absolute;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;border-left: 2px solid;transform: translatez(0);}.ace_multiselect .ace_cursor {border-left-width: 1px;}.ace_slim-cursors .ace_cursor {border-left-width: 1px;}.ace_overwrite-cursors .ace_cursor {border-left-width: 0;border-bottom: 1px solid;}.ace_hidden-cursors .ace_cursor {opacity: 0.2;}.ace_smooth-blinking .ace_cursor {-webkit-transition: opacity 0.18s;transition: opacity 0.18s;}.ace_marker-layer .ace_step, .ace_marker-layer .ace_stack {position: absolute;z-index: 3;}.ace_marker-layer .ace_selection {position: absolute;z-index: 5;}.ace_marker-layer .ace_bracket {position: absolute;z-index: 6;}.ace_marker-layer .ace_active-line {position: absolute;z-index: 2;}.ace_marker-layer .ace_selected-word {position: absolute;z-index: 4;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;}.ace_line .ace_fold {-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;display: inline-block;height: 11px;margin-top: -2px;vertical-align: middle;background-image:url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII=\"),url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi+P//fxgTAwPDBxDxD078RSX+YeEyDFMCIMAAI3INmXiwf2YAAAAASUVORK5CYII=\");background-repeat: no-repeat, repeat-x;background-position: center center, top left;color: transparent;border: 1px solid black;border-radius: 2px;cursor: pointer;pointer-events: auto;}.ace_dark .ace_fold {}.ace_fold:hover{background-image:url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII=\"),url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi+P//fz4TAwPDZxDxD5X4i5fLMEwJgAADAEPVDbjNw87ZAAAAAElFTkSuQmCC\");}.ace_tooltip {background-color: #FFF;background-image: -webkit-linear-gradient(top, transparent, rgba(0, 0, 0, 0.1));background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1));border: 1px solid gray;border-radius: 1px;box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);color: black;max-width: 100%;padding: 3px 4px;position: fixed;z-index: 999999;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;cursor: default;white-space: pre;word-wrap: break-word;line-height: normal;font-style: normal;font-weight: normal;letter-spacing: normal;pointer-events: none;}.ace_folding-enabled > .ace_gutter-cell {padding-right: 13px;}.ace_fold-widget {-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;margin: 0 -12px 0 1px;display: none;width: 11px;vertical-align: top;background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg==\");background-repeat: no-repeat;background-position: center;border-radius: 3px;border: 1px solid transparent;cursor: pointer;}.ace_folding-enabled .ace_fold-widget {display: inline-block;   }.ace_fold-widget.ace_end {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg==\");}.ace_fold-widget.ace_closed {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA==\");}.ace_fold-widget:hover {border: 1px solid rgba(0, 0, 0, 0.3);background-color: rgba(255, 255, 255, 0.2);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);}.ace_fold-widget:active {border: 1px solid rgba(0, 0, 0, 0.4);background-color: rgba(0, 0, 0, 0.05);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);}.ace_dark .ace_fold-widget {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC\");}.ace_dark .ace_fold-widget.ace_end {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg==\");}.ace_dark .ace_fold-widget.ace_closed {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg==\");}.ace_dark .ace_fold-widget:hover {box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);background-color: rgba(255, 255, 255, 0.1);}.ace_dark .ace_fold-widget:active {box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);}.ace_fold-widget.ace_invalid {background-color: #FFB4B4;border-color: #DE5555;}.ace_fade-fold-widgets .ace_fold-widget {-webkit-transition: opacity 0.4s ease 0.05s;transition: opacity 0.4s ease 0.05s;opacity: 0;}.ace_fade-fold-widgets:hover .ace_fold-widget {-webkit-transition: opacity 0.05s ease 0.05s;transition: opacity 0.05s ease 0.05s;opacity:1;}.ace_underline {text-decoration: underline;}.ace_bold {font-weight: bold;}.ace_nobold .ace_bold {font-weight: normal;}.ace_italic {font-style: italic;}.ace_error-marker {background-color: rgba(255, 0, 0,0.2);position: absolute;z-index: 9;}.ace_highlight-marker {background-color: rgba(255, 255, 0,0.2);position: absolute;z-index: 8;}.ace_br1 {border-top-left-radius    : 3px;}.ace_br2 {border-top-right-radius   : 3px;}.ace_br3 {border-top-left-radius    : 3px; border-top-right-radius:    3px;}.ace_br4 {border-bottom-right-radius: 3px;}.ace_br5 {border-top-left-radius    : 3px; border-bottom-right-radius: 3px;}.ace_br6 {border-top-right-radius   : 3px; border-bottom-right-radius: 3px;}.ace_br7 {border-top-left-radius    : 3px; border-top-right-radius:    3px; border-bottom-right-radius: 3px;}.ace_br8 {border-bottom-left-radius : 3px;}.ace_br9 {border-top-left-radius    : 3px; border-bottom-left-radius:  3px;}.ace_br10{border-top-right-radius   : 3px; border-bottom-left-radius:  3px;}.ace_br11{border-top-left-radius    : 3px; border-top-right-radius:    3px; border-bottom-left-radius:  3px;}.ace_br12{border-bottom-right-radius: 3px; border-bottom-left-radius:  3px;}.ace_br13{border-top-left-radius    : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius:  3px;}.ace_br14{border-top-right-radius   : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius:  3px;}.ace_br15{border-top-left-radius    : 3px; border-top-right-radius:    3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}.ace_text-input-ios {position: absolute !important;top: -100000px !important;left: -100000px !important;}';i.importCssString(m,\"ace_editor.css\");var g=function(e,t){var n=this;this.container=e||i.createElement(\"div\"),this.$keepTextAreaAtCursor=!o.isOldIE,i.addCssClass(this.container,\"ace_editor\"),this.setTheme(t),this.$gutter=i.createElement(\"div\"),this.$gutter.className=\"ace_gutter\",this.container.appendChild(this.$gutter),this.scroller=i.createElement(\"div\"),this.scroller.className=\"ace_scroller\",this.container.appendChild(this.scroller),this.content=i.createElement(\"div\"),this.content.className=\"ace_content\",this.scroller.appendChild(this.content),this.$gutterLayer=new u(this.$gutter),this.$gutterLayer.on(\"changeGutterWidth\",this.onGutterResize.bind(this)),this.$markerBack=new a(this.content);var r=this.$textLayer=new f(this.content);this.canvas=r.element,this.$markerFront=new a(this.content),this.$cursorLayer=new l(this.content),this.$horizScroll=!1,this.$vScroll=!1,this.scrollBar=this.scrollBarV=new h(this.container,this),this.scrollBarH=new c(this.container,this),this.scrollBarV.addEventListener(\"scroll\",function(e){n.$scrollAnimation||n.session.setScrollTop(e.data-n.scrollMargin.top)}),this.scrollBarH.addEventListener(\"scroll\",function(e){n.$scrollAnimation||n.session.setScrollLeft(e.data-n.scrollMargin.left)}),this.scrollTop=0,this.scrollLeft=0,this.cursorPos={row:0,column:0},this.$fontMetrics=new d(this.container),this.$textLayer.$setFontMetrics(this.$fontMetrics),this.$textLayer.addEventListener(\"changeCharacterSize\",function(e){n.updateCharacterSize(),n.onResize(!0,n.gutterWidth,n.$size.width,n.$size.height),n._signal(\"changeCharacterSize\",e)}),this.$size={width:0,height:0,scrollerHeight:0,scrollerWidth:0,$dirty:!0},this.layerConfig={width:1,padding:0,firstRow:0,firstRowScreen:0,lastRow:0,lineHeight:0,characterWidth:0,minHeight:1,maxHeight:1,offset:0,height:1,gutterOffset:1},this.scrollMargin={left:0,right:0,top:0,bottom:0,v:0,h:0},this.$loop=new p(this.$renderChanges.bind(this),this.container.ownerDocument.defaultView),this.$loop.schedule(this.CHANGE_FULL),this.updateCharacterSize(),this.setPadding(4),s.resetOptions(this),s._emit(\"renderer\",this)};(function(){this.CHANGE_CURSOR=1,this.CHANGE_MARKER=2,this.CHANGE_GUTTER=4,this.CHANGE_SCROLL=8,this.CHANGE_LINES=16,this.CHANGE_TEXT=32,this.CHANGE_SIZE=64,this.CHANGE_MARKER_BACK=128,this.CHANGE_MARKER_FRONT=256,this.CHANGE_FULL=512,this.CHANGE_H_SCROLL=1024,r.implement(this,v),this.updateCharacterSize=function(){this.$textLayer.allowBoldFonts!=this.$allowBoldFonts&&(this.$allowBoldFonts=this.$textLayer.allowBoldFonts,this.setStyle(\"ace_nobold\",!this.$allowBoldFonts)),this.layerConfig.characterWidth=this.characterWidth=this.$textLayer.getCharacterWidth(),this.layerConfig.lineHeight=this.lineHeight=this.$textLayer.getLineHeight(),this.$updatePrintMargin()},this.setSession=function(e){this.session&&this.session.doc.off(\"changeNewLineMode\",this.onChangeNewLineMode),this.session=e,e&&this.scrollMargin.top&&e.getScrollTop()<=0&&e.setScrollTop(-this.scrollMargin.top),this.$cursorLayer.setSession(e),this.$markerBack.setSession(e),this.$markerFront.setSession(e),this.$gutterLayer.setSession(e),this.$textLayer.setSession(e);if(!e)return;this.$loop.schedule(this.CHANGE_FULL),this.session.$setFontMetrics(this.$fontMetrics),this.scrollBarH.scrollLeft=this.scrollBarV.scrollTop=null,this.onChangeNewLineMode=this.onChangeNewLineMode.bind(this),this.onChangeNewLineMode(),this.session.doc.on(\"changeNewLineMode\",this.onChangeNewLineMode)},this.updateLines=function(e,t,n){t===undefined&&(t=Infinity),this.$changedLines?(this.$changedLines.firstRow>e&&(this.$changedLines.firstRow=e),this.$changedLines.lastRow<t&&(this.$changedLines.lastRow=t)):this.$changedLines={firstRow:e,lastRow:t};if(this.$changedLines.lastRow<this.layerConfig.firstRow){if(!n)return;this.$changedLines.lastRow=this.layerConfig.lastRow}if(this.$changedLines.firstRow>this.layerConfig.lastRow)return;this.$loop.schedule(this.CHANGE_LINES)},this.onChangeNewLineMode=function(){this.$loop.schedule(this.CHANGE_TEXT),this.$textLayer.$updateEolChar()},this.onChangeTabSize=function(){this.$loop.schedule(this.CHANGE_TEXT|this.CHANGE_MARKER),this.$textLayer.onChangeTabSize()},this.updateText=function(){this.$loop.schedule(this.CHANGE_TEXT)},this.updateFull=function(e){e?this.$renderChanges(this.CHANGE_FULL,!0):this.$loop.schedule(this.CHANGE_FULL)},this.updateFontSize=function(){this.$textLayer.checkForSizeChanges()},this.$changes=0,this.$updateSizeAsync=function(){this.$loop.pending?this.$size.$dirty=!0:this.onResize()},this.onResize=function(e,t,n,r){if(this.resizing>2)return;this.resizing>0?this.resizing++:this.resizing=e?1:0;var i=this.container;r||(r=i.clientHeight||i.scrollHeight),n||(n=i.clientWidth||i.scrollWidth);var s=this.$updateCachedSize(e,t,n,r);if(!this.$size.scrollerHeight||!n&&!r)return this.resizing=0;e&&(this.$gutterLayer.$padding=null),e?this.$renderChanges(s|this.$changes,!0):this.$loop.schedule(s|this.$changes),this.resizing&&(this.resizing=0),this.scrollBarV.scrollLeft=this.scrollBarV.scrollTop=null},this.$updateCachedSize=function(e,t,n,r){r-=this.$extraHeight||0;var i=0,s=this.$size,o={width:s.width,height:s.height,scrollerHeight:s.scrollerHeight,scrollerWidth:s.scrollerWidth};r&&(e||s.height!=r)&&(s.height=r,i|=this.CHANGE_SIZE,s.scrollerHeight=s.height,this.$horizScroll&&(s.scrollerHeight-=this.scrollBarH.getHeight()),this.scrollBarV.element.style.bottom=this.scrollBarH.getHeight()+\"px\",i|=this.CHANGE_SCROLL);if(n&&(e||s.width!=n)){i|=this.CHANGE_SIZE,s.width=n,t==null&&(t=this.$showGutter?this.$gutter.offsetWidth:0),this.gutterWidth=t,this.scrollBarH.element.style.left=this.scroller.style.left=t+\"px\",s.scrollerWidth=Math.max(0,n-t-this.scrollBarV.getWidth()),this.scrollBarH.element.style.right=this.scroller.style.right=this.scrollBarV.getWidth()+\"px\",this.scroller.style.bottom=this.scrollBarH.getHeight()+\"px\";if(this.session&&this.session.getUseWrapMode()&&this.adjustWrapLimit()||e)i|=this.CHANGE_FULL}return s.$dirty=!n||!r,i&&this._signal(\"resize\",o),i},this.onGutterResize=function(){var e=this.$showGutter?this.$gutter.offsetWidth:0;e!=this.gutterWidth&&(this.$changes|=this.$updateCachedSize(!0,e,this.$size.width,this.$size.height)),this.session.getUseWrapMode()&&this.adjustWrapLimit()?this.$loop.schedule(this.CHANGE_FULL):this.$size.$dirty?this.$loop.schedule(this.CHANGE_FULL):(this.$computeLayerConfig(),this.$loop.schedule(this.CHANGE_MARKER))},this.adjustWrapLimit=function(){var e=this.$size.scrollerWidth-this.$padding*2,t=Math.floor(e/this.characterWidth);return this.session.adjustWrapLimit(t,this.$showPrintMargin&&this.$printMarginColumn)},this.setAnimatedScroll=function(e){this.setOption(\"animatedScroll\",e)},this.getAnimatedScroll=function(){return this.$animatedScroll},this.setShowInvisibles=function(e){this.setOption(\"showInvisibles\",e)},this.getShowInvisibles=function(){return this.getOption(\"showInvisibles\")},this.getDisplayIndentGuides=function(){return this.getOption(\"displayIndentGuides\")},this.setDisplayIndentGuides=function(e){this.setOption(\"displayIndentGuides\",e)},this.setShowPrintMargin=function(e){this.setOption(\"showPrintMargin\",e)},this.getShowPrintMargin=function(){return this.getOption(\"showPrintMargin\")},this.setPrintMarginColumn=function(e){this.setOption(\"printMarginColumn\",e)},this.getPrintMarginColumn=function(){return this.getOption(\"printMarginColumn\")},this.getShowGutter=function(){return this.getOption(\"showGutter\")},this.setShowGutter=function(e){return this.setOption(\"showGutter\",e)},this.getFadeFoldWidgets=function(){return this.getOption(\"fadeFoldWidgets\")},this.setFadeFoldWidgets=function(e){this.setOption(\"fadeFoldWidgets\",e)},this.setHighlightGutterLine=function(e){this.setOption(\"highlightGutterLine\",e)},this.getHighlightGutterLine=function(){return this.getOption(\"highlightGutterLine\")},this.$updateGutterLineHighlight=function(){var e=this.$cursorLayer.$pixelPos,t=this.layerConfig.lineHeight;if(this.session.getUseWrapMode()){var n=this.session.selection.getCursor();n.column=0,e=this.$cursorLayer.getPixelPosition(n,!0),t*=this.session.getRowLength(n.row)}this.$gutterLineHighlight.style.top=e.top-this.layerConfig.offset+\"px\",this.$gutterLineHighlight.style.height=t+\"px\"},this.$updatePrintMargin=function(){if(!this.$showPrintMargin&&!this.$printMarginEl)return;if(!this.$printMarginEl){var e=i.createElement(\"div\");e.className=\"ace_layer ace_print-margin-layer\",this.$printMarginEl=i.createElement(\"div\"),this.$printMarginEl.className=\"ace_print-margin\",e.appendChild(this.$printMarginEl),this.content.insertBefore(e,this.content.firstChild)}var t=this.$printMarginEl.style;t.left=this.characterWidth*this.$printMarginColumn+this.$padding+\"px\",t.visibility=this.$showPrintMargin?\"visible\":\"hidden\",this.session&&this.session.$wrap==-1&&this.adjustWrapLimit()},this.getContainerElement=function(){return this.container},this.getMouseEventTarget=function(){return this.scroller},this.getTextAreaContainer=function(){return this.container},this.$moveTextAreaToCursor=function(){if(!this.$keepTextAreaAtCursor)return;var e=this.layerConfig,t=this.$cursorLayer.$pixelPos.top,n=this.$cursorLayer.$pixelPos.left;t-=e.offset;var r=this.textarea.style,i=this.lineHeight;if(t<0||t>e.height-i){r.top=r.left=\"0\";return}var s=this.characterWidth;if(this.$composition){var o=this.textarea.value.replace(/^\\x01+/,\"\");s*=this.session.$getStringScreenWidth(o)[0]+2,i+=2}n-=this.scrollLeft,n>this.$size.scrollerWidth-s&&(n=this.$size.scrollerWidth-s),n+=this.gutterWidth,r.height=i+\"px\",r.width=s+\"px\",r.left=Math.min(n,this.$size.scrollerWidth-s)+\"px\",r.top=Math.min(t,this.$size.height-i)+\"px\"},this.getFirstVisibleRow=function(){return this.layerConfig.firstRow},this.getFirstFullyVisibleRow=function(){return this.layerConfig.firstRow+(this.layerConfig.offset===0?0:1)},this.getLastFullyVisibleRow=function(){var e=this.layerConfig,t=e.lastRow,n=this.session.documentToScreenRow(t,0)*e.lineHeight;return n-this.session.getScrollTop()>e.height-e.lineHeight?t-1:t},this.getLastVisibleRow=function(){return this.layerConfig.lastRow},this.$padding=null,this.setPadding=function(e){this.$padding=e,this.$textLayer.setPadding(e),this.$cursorLayer.setPadding(e),this.$markerFront.setPadding(e),this.$markerBack.setPadding(e),this.$loop.schedule(this.CHANGE_FULL),this.$updatePrintMargin()},this.setScrollMargin=function(e,t,n,r){var i=this.scrollMargin;i.top=e|0,i.bottom=t|0,i.right=r|0,i.left=n|0,i.v=i.top+i.bottom,i.h=i.left+i.right,i.top&&this.scrollTop<=0&&this.session&&this.session.setScrollTop(-i.top),this.updateFull()},this.getHScrollBarAlwaysVisible=function(){return this.$hScrollBarAlwaysVisible},this.setHScrollBarAlwaysVisible=function(e){this.setOption(\"hScrollBarAlwaysVisible\",e)},this.getVScrollBarAlwaysVisible=function(){return this.$vScrollBarAlwaysVisible},this.setVScrollBarAlwaysVisible=function(e){this.setOption(\"vScrollBarAlwaysVisible\",e)},this.$updateScrollBarV=function(){var e=this.layerConfig.maxHeight,t=this.$size.scrollerHeight;!this.$maxLines&&this.$scrollPastEnd&&(e-=(t-this.lineHeight)*this.$scrollPastEnd,this.scrollTop>e-t&&(e=this.scrollTop+t,this.scrollBarV.scrollTop=null)),this.scrollBarV.setScrollHeight(e+this.scrollMargin.v),this.scrollBarV.setScrollTop(this.scrollTop+this.scrollMargin.top)},this.$updateScrollBarH=function(){this.scrollBarH.setScrollWidth(this.layerConfig.width+2*this.$padding+this.scrollMargin.h),this.scrollBarH.setScrollLeft(this.scrollLeft+this.scrollMargin.left)},this.$frozen=!1,this.freeze=function(){this.$frozen=!0},this.unfreeze=function(){this.$frozen=!1},this.$renderChanges=function(e,t){this.$changes&&(e|=this.$changes,this.$changes=0);if(!this.session||!this.container.offsetWidth||this.$frozen||!e&&!t){this.$changes|=e;return}if(this.$size.$dirty)return this.$changes|=e,this.onResize(!0);this.lineHeight||this.$textLayer.checkForSizeChanges(),this._signal(\"beforeRender\");var n=this.layerConfig;if(e&this.CHANGE_FULL||e&this.CHANGE_SIZE||e&this.CHANGE_TEXT||e&this.CHANGE_LINES||e&this.CHANGE_SCROLL||e&this.CHANGE_H_SCROLL){e|=this.$computeLayerConfig();if(n.firstRow!=this.layerConfig.firstRow&&n.firstRowScreen==this.layerConfig.firstRowScreen){var r=this.scrollTop+(n.firstRow-this.layerConfig.firstRow)*this.lineHeight;r>0&&(this.scrollTop=r,e|=this.CHANGE_SCROLL,e|=this.$computeLayerConfig())}n=this.layerConfig,this.$updateScrollBarV(),e&this.CHANGE_H_SCROLL&&this.$updateScrollBarH(),this.$gutterLayer.element.style.marginTop=-n.offset+\"px\",this.content.style.marginTop=-n.offset+\"px\",this.content.style.width=n.width+2*this.$padding+\"px\",this.content.style.height=n.minHeight+\"px\"}e&this.CHANGE_H_SCROLL&&(this.content.style.marginLeft=-this.scrollLeft+\"px\",this.scroller.className=this.scrollLeft<=0?\"ace_scroller\":\"ace_scroller ace_scroll-left\");if(e&this.CHANGE_FULL){this.$textLayer.update(n),this.$showGutter&&this.$gutterLayer.update(n),this.$markerBack.update(n),this.$markerFront.update(n),this.$cursorLayer.update(n),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight(),this._signal(\"afterRender\");return}if(e&this.CHANGE_SCROLL){e&this.CHANGE_TEXT||e&this.CHANGE_LINES?this.$textLayer.update(n):this.$textLayer.scrollLines(n),this.$showGutter&&this.$gutterLayer.update(n),this.$markerBack.update(n),this.$markerFront.update(n),this.$cursorLayer.update(n),this.$highlightGutterLine&&this.$updateGutterLineHighlight(),this.$moveTextAreaToCursor(),this._signal(\"afterRender\");return}e&this.CHANGE_TEXT?(this.$textLayer.update(n),this.$showGutter&&this.$gutterLayer.update(n)):e&this.CHANGE_LINES?(this.$updateLines()||e&this.CHANGE_GUTTER&&this.$showGutter)&&this.$gutterLayer.update(n):(e&this.CHANGE_TEXT||e&this.CHANGE_GUTTER)&&this.$showGutter&&this.$gutterLayer.update(n),e&this.CHANGE_CURSOR&&(this.$cursorLayer.update(n),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight()),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_FRONT)&&this.$markerFront.update(n),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_BACK)&&this.$markerBack.update(n),this._signal(\"afterRender\")},this.$autosize=function(){var e=this.session.getScreenLength()*this.lineHeight,t=this.$maxLines*this.lineHeight,n=Math.min(t,Math.max((this.$minLines||1)*this.lineHeight,e))+this.scrollMargin.v+(this.$extraHeight||0);this.$horizScroll&&(n+=this.scrollBarH.getHeight()),this.$maxPixelHeight&&n>this.$maxPixelHeight&&(n=this.$maxPixelHeight);var r=e>t;if(n!=this.desiredHeight||this.$size.height!=this.desiredHeight||r!=this.$vScroll){r!=this.$vScroll&&(this.$vScroll=r,this.scrollBarV.setVisible(r));var i=this.container.clientWidth;this.container.style.height=n+\"px\",this.$updateCachedSize(!0,this.$gutterWidth,i,n),this.desiredHeight=n,this._signal(\"autosize\")}},this.$computeLayerConfig=function(){var e=this.session,t=this.$size,n=t.height<=2*this.lineHeight,r=this.session.getScreenLength(),i=r*this.lineHeight,s=this.$getLongestLine(),o=!n&&(this.$hScrollBarAlwaysVisible||t.scrollerWidth-s-2*this.$padding<0),u=this.$horizScroll!==o;u&&(this.$horizScroll=o,this.scrollBarH.setVisible(o));var a=this.$vScroll;this.$maxLines&&this.lineHeight>1&&this.$autosize();var f=this.scrollTop%this.lineHeight,l=t.scrollerHeight+this.lineHeight,c=!this.$maxLines&&this.$scrollPastEnd?(t.scrollerHeight-this.lineHeight)*this.$scrollPastEnd:0;i+=c;var h=this.scrollMargin;this.session.setScrollTop(Math.max(-h.top,Math.min(this.scrollTop,i-t.scrollerHeight+h.bottom))),this.session.setScrollLeft(Math.max(-h.left,Math.min(this.scrollLeft,s+2*this.$padding-t.scrollerWidth+h.right)));var p=!n&&(this.$vScrollBarAlwaysVisible||t.scrollerHeight-i+c<0||this.scrollTop>h.top),d=a!==p;d&&(this.$vScroll=p,this.scrollBarV.setVisible(p));var v=Math.ceil(l/this.lineHeight)-1,m=Math.max(0,Math.round((this.scrollTop-f)/this.lineHeight)),g=m+v,y,b,w=this.lineHeight;m=e.screenToDocumentRow(m,0);var E=e.getFoldLine(m);E&&(m=E.start.row),y=e.documentToScreenRow(m,0),b=e.getRowLength(m)*w,g=Math.min(e.screenToDocumentRow(g,0),e.getLength()-1),l=t.scrollerHeight+e.getRowLength(g)*w+b,f=this.scrollTop-y*w;var S=0;this.layerConfig.width!=s&&(S=this.CHANGE_H_SCROLL);if(u||d)S=this.$updateCachedSize(!0,this.gutterWidth,t.width,t.height),this._signal(\"scrollbarVisibilityChanged\"),d&&(s=this.$getLongestLine());return this.layerConfig={width:s,padding:this.$padding,firstRow:m,firstRowScreen:y,lastRow:g,lineHeight:w,characterWidth:this.characterWidth,minHeight:l,maxHeight:i,offset:f,gutterOffset:w?Math.max(0,Math.ceil((f+t.height-t.scrollerHeight)/w)):0,height:this.$size.scrollerHeight},S},this.$updateLines=function(){if(!this.$changedLines)return;var e=this.$changedLines.firstRow,t=this.$changedLines.lastRow;this.$changedLines=null;var n=this.layerConfig;if(e>n.lastRow+1)return;if(t<n.firstRow)return;if(t===Infinity){this.$showGutter&&this.$gutterLayer.update(n),this.$textLayer.update(n);return}return this.$textLayer.updateLines(n,e,t),!0},this.$getLongestLine=function(){var e=this.session.getScreenWidth();return this.showInvisibles&&!this.session.$useWrapMode&&(e+=1),Math.max(this.$size.scrollerWidth-2*this.$padding,Math.round(e*this.characterWidth))},this.updateFrontMarkers=function(){this.$markerFront.setMarkers(this.session.getMarkers(!0)),this.$loop.schedule(this.CHANGE_MARKER_FRONT)},this.updateBackMarkers=function(){this.$markerBack.setMarkers(this.session.getMarkers()),this.$loop.schedule(this.CHANGE_MARKER_BACK)},this.addGutterDecoration=function(e,t){this.$gutterLayer.addGutterDecoration(e,t)},this.removeGutterDecoration=function(e,t){this.$gutterLayer.removeGutterDecoration(e,t)},this.updateBreakpoints=function(e){this.$loop.schedule(this.CHANGE_GUTTER)},this.setAnnotations=function(e){this.$gutterLayer.setAnnotations(e),this.$loop.schedule(this.CHANGE_GUTTER)},this.updateCursor=function(){this.$loop.schedule(this.CHANGE_CURSOR)},this.hideCursor=function(){this.$cursorLayer.hideCursor()},this.showCursor=function(){this.$cursorLayer.showCursor()},this.scrollSelectionIntoView=function(e,t,n){this.scrollCursorIntoView(e,n),this.scrollCursorIntoView(t,n)},this.scrollCursorIntoView=function(e,t,n){if(this.$size.scrollerHeight===0)return;var r=this.$cursorLayer.getPixelPosition(e),i=r.left,s=r.top,o=n&&n.top||0,u=n&&n.bottom||0,a=this.$scrollAnimation?this.session.getScrollTop():this.scrollTop;a+o>s?(t&&a+o>s+this.lineHeight&&(s-=t*this.$size.scrollerHeight),s===0&&(s=-this.scrollMargin.top),this.session.setScrollTop(s)):a+this.$size.scrollerHeight-u<s+this.lineHeight&&(t&&a+this.$size.scrollerHeight-u<s-this.lineHeight&&(s+=t*this.$size.scrollerHeight),this.session.setScrollTop(s+this.lineHeight-this.$size.scrollerHeight));var f=this.scrollLeft;f>i?(i<this.$padding+2*this.layerConfig.characterWidth&&(i=-this.scrollMargin.left),this.session.setScrollLeft(i)):f+this.$size.scrollerWidth<i+this.characterWidth?this.session.setScrollLeft(Math.round(i+this.characterWidth-this.$size.scrollerWidth)):f<=this.$padding&&i-f<this.characterWidth&&this.session.setScrollLeft(0)},this.getScrollTop=function(){return this.session.getScrollTop()},this.getScrollLeft=function(){return this.session.getScrollLeft()},this.getScrollTopRow=function(){return this.scrollTop/this.lineHeight},this.getScrollBottomRow=function(){return Math.max(0,Math.floor((this.scrollTop+this.$size.scrollerHeight)/this.lineHeight)-1)},this.scrollToRow=function(e){this.session.setScrollTop(e*this.lineHeight)},this.alignCursor=function(e,t){typeof e==\"number\"&&(e={row:e,column:0});var n=this.$cursorLayer.getPixelPosition(e),r=this.$size.scrollerHeight-this.lineHeight,i=n.top-r*(t||0);return this.session.setScrollTop(i),i},this.STEPS=8,this.$calcSteps=function(e,t){var n=0,r=this.STEPS,i=[],s=function(e,t,n){return n*(Math.pow(e-1,3)+1)+t};for(n=0;n<r;++n)i.push(s(n/this.STEPS,e,t-e));return i},this.scrollToLine=function(e,t,n,r){var i=this.$cursorLayer.getPixelPosition({row:e,column:0}),s=i.top;t&&(s-=this.$size.scrollerHeight/2);var o=this.scrollTop;this.session.setScrollTop(s),n!==!1&&this.animateScrolling(o,r)},this.animateScrolling=function(e,t){var n=this.scrollTop;if(!this.$animatedScroll)return;var r=this;if(e==n)return;if(this.$scrollAnimation){var i=this.$scrollAnimation.steps;if(i.length){e=i[0];if(e==n)return}}var s=r.$calcSteps(e,n);this.$scrollAnimation={from:e,to:n,steps:s},clearInterval(this.$timer),r.session.setScrollTop(s.shift()),r.session.$scrollTop=n,this.$timer=setInterval(function(){s.length?(r.session.setScrollTop(s.shift()),r.session.$scrollTop=n):n!=null?(r.session.$scrollTop=-1,r.session.setScrollTop(n),n=null):(r.$timer=clearInterval(r.$timer),r.$scrollAnimation=null,t&&t())},10)},this.scrollToY=function(e){this.scrollTop!==e&&(this.$loop.schedule(this.CHANGE_SCROLL),this.scrollTop=e)},this.scrollToX=function(e){this.scrollLeft!==e&&(this.scrollLeft=e),this.$loop.schedule(this.CHANGE_H_SCROLL)},this.scrollTo=function(e,t){this.session.setScrollTop(t),this.session.setScrollLeft(t)},this.scrollBy=function(e,t){t&&this.session.setScrollTop(this.session.getScrollTop()+t),e&&this.session.setScrollLeft(this.session.getScrollLeft()+e)},this.isScrollableBy=function(e,t){if(t<0&&this.session.getScrollTop()>=1-this.scrollMargin.top)return!0;if(t>0&&this.session.getScrollTop()+this.$size.scrollerHeight-this.layerConfig.maxHeight<-1+this.scrollMargin.bottom)return!0;if(e<0&&this.session.getScrollLeft()>=1-this.scrollMargin.left)return!0;if(e>0&&this.session.getScrollLeft()+this.$size.scrollerWidth-this.layerConfig.width<-1+this.scrollMargin.right)return!0},this.pixelToScreenCoordinates=function(e,t){var n=this.scroller.getBoundingClientRect(),r=(e+this.scrollLeft-n.left-this.$padding)/this.characterWidth,i=Math.floor((t+this.scrollTop-n.top)/this.lineHeight),s=Math.round(r);return{row:i,column:s,side:r-s>0?1:-1}},this.screenToTextCoordinates=function(e,t){var n=this.scroller.getBoundingClientRect(),r=Math.round((e+this.scrollLeft-n.left-this.$padding)/this.characterWidth),i=(t+this.scrollTop-n.top)/this.lineHeight;return this.session.screenToDocumentPosition(i,Math.max(r,0))},this.textToScreenCoordinates=function(e,t){var n=this.scroller.getBoundingClientRect(),r=this.session.documentToScreenPosition(e,t),i=this.$padding+Math.round(r.column*this.characterWidth),s=r.row*this.lineHeight;return{pageX:n.left+i-this.scrollLeft,pageY:n.top+s-this.scrollTop}},this.visualizeFocus=function(){i.addCssClass(this.container,\"ace_focus\")},this.visualizeBlur=function(){i.removeCssClass(this.container,\"ace_focus\")},this.showComposition=function(e){this.$composition||(this.$composition={keepTextAreaAtCursor:this.$keepTextAreaAtCursor,cssText:this.textarea.style.cssText}),this.$keepTextAreaAtCursor=!0,i.addCssClass(this.textarea,\"ace_composition\"),this.textarea.style.cssText=\"\",this.$moveTextAreaToCursor()},this.setCompositionText=function(e){this.$moveTextAreaToCursor()},this.hideComposition=function(){if(!this.$composition)return;i.removeCssClass(this.textarea,\"ace_composition\"),this.$keepTextAreaAtCursor=this.$composition.keepTextAreaAtCursor,this.textarea.style.cssText=this.$composition.cssText,this.$composition=null},this.setTheme=function(e,t){function o(r){if(n.$themeId!=e)return t&&t();if(!r||!r.cssClass)throw new Error(\"couldn't load module \"+e+\" or it didn't call define\");i.importCssString(r.cssText,r.cssClass,n.container.ownerDocument),n.theme&&i.removeCssClass(n.container,n.theme.cssClass);var s=\"padding\"in r?r.padding:\"padding\"in(n.theme||{})?4:n.$padding;n.$padding&&s!=n.$padding&&n.setPadding(s),n.$theme=r.cssClass,n.theme=r,i.addCssClass(n.container,r.cssClass),i.setCssClass(n.container,\"ace_dark\",r.isDark),n.$size&&(n.$size.width=0,n.$updateSizeAsync()),n._dispatchEvent(\"themeLoaded\",{theme:r}),t&&t()}var n=this;this.$themeId=e,n._dispatchEvent(\"themeChange\",{theme:e});if(!e||typeof e==\"string\"){var r=e||this.$options.theme.initialValue;s.loadModule([\"theme\",r],o)}else o(e)},this.getTheme=function(){return this.$themeId},this.setStyle=function(e,t){i.setCssClass(this.container,e,t!==!1)},this.unsetStyle=function(e){i.removeCssClass(this.container,e)},this.setCursorStyle=function(e){this.scroller.style.cursor!=e&&(this.scroller.style.cursor=e)},this.setMouseCursor=function(e){this.scroller.style.cursor=e},this.destroy=function(){this.$textLayer.destroy(),this.$cursorLayer.destroy()}}).call(g.prototype),s.defineOptions(g.prototype,\"renderer\",{animatedScroll:{initialValue:!1},showInvisibles:{set:function(e){this.$textLayer.setShowInvisibles(e)&&this.$loop.schedule(this.CHANGE_TEXT)},initialValue:!1},showPrintMargin:{set:function(){this.$updatePrintMargin()},initialValue:!0},printMarginColumn:{set:function(){this.$updatePrintMargin()},initialValue:80},printMargin:{set:function(e){typeof e==\"number\"&&(this.$printMarginColumn=e),this.$showPrintMargin=!!e,this.$updatePrintMargin()},get:function(){return this.$showPrintMargin&&this.$printMarginColumn}},showGutter:{set:function(e){this.$gutter.style.display=e?\"block\":\"none\",this.$loop.schedule(this.CHANGE_FULL),this.onGutterResize()},initialValue:!0},fadeFoldWidgets:{set:function(e){i.setCssClass(this.$gutter,\"ace_fade-fold-widgets\",e)},initialValue:!1},showFoldWidgets:{set:function(e){this.$gutterLayer.setShowFoldWidgets(e)},initialValue:!0},showLineNumbers:{set:function(e){this.$gutterLayer.setShowLineNumbers(e),this.$loop.schedule(this.CHANGE_GUTTER)},initialValue:!0},displayIndentGuides:{set:function(e){this.$textLayer.setDisplayIndentGuides(e)&&this.$loop.schedule(this.CHANGE_TEXT)},initialValue:!0},highlightGutterLine:{set:function(e){if(!this.$gutterLineHighlight){this.$gutterLineHighlight=i.createElement(\"div\"),this.$gutterLineHighlight.className=\"ace_gutter-active-line\",this.$gutter.appendChild(this.$gutterLineHighlight);return}this.$gutterLineHighlight.style.display=e?\"\":\"none\",this.$cursorLayer.$pixelPos&&this.$updateGutterLineHighlight()},initialValue:!1,value:!0},hScrollBarAlwaysVisible:{set:function(e){(!this.$hScrollBarAlwaysVisible||!this.$horizScroll)&&this.$loop.schedule(this.CHANGE_SCROLL)},initialValue:!1},vScrollBarAlwaysVisible:{set:function(e){(!this.$vScrollBarAlwaysVisible||!this.$vScroll)&&this.$loop.schedule(this.CHANGE_SCROLL)},initialValue:!1},fontSize:{set:function(e){typeof e==\"number\"&&(e+=\"px\"),this.container.style.fontSize=e,this.updateFontSize()},initialValue:12},fontFamily:{set:function(e){this.container.style.fontFamily=e,this.updateFontSize()}},maxLines:{set:function(e){this.updateFull()}},minLines:{set:function(e){this.updateFull()}},maxPixelHeight:{set:function(e){this.updateFull()},initialValue:0},scrollPastEnd:{set:function(e){e=+e||0;if(this.$scrollPastEnd==e)return;this.$scrollPastEnd=e,this.$loop.schedule(this.CHANGE_SCROLL)},initialValue:0,handlesSet:!0},fixedWidthGutter:{set:function(e){this.$gutterLayer.$fixedWidth=!!e,this.$loop.schedule(this.CHANGE_GUTTER)}},theme:{set:function(e){this.setTheme(e)},get:function(){return this.$themeId||this.theme},initialValue:\"./theme/textmate\",handlesSet:!0}}),t.VirtualRenderer=g}),define(\"ace/worker/worker_client\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/net\",\"ace/lib/event_emitter\",\"ace/config\"],function(e,t,n){\"use strict\";function u(e){var t=\"importScripts('\"+i.qualifyURL(e)+\"');\";try{return new Blob([t],{type:\"application/javascript\"})}catch(n){var r=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder,s=new r;return s.append(t),s.getBlob(\"application/javascript\")}}function a(e){var t=u(e),n=window.URL||window.webkitURL,r=n.createObjectURL(t);return new Worker(r)}var r=e(\"../lib/oop\"),i=e(\"../lib/net\"),s=e(\"../lib/event_emitter\").EventEmitter,o=e(\"../config\"),f=function(t,n,r,i,s){this.$sendDeltaQueue=this.$sendDeltaQueue.bind(this),this.changeListener=this.changeListener.bind(this),this.onMessage=this.onMessage.bind(this),e.nameToUrl&&!e.toUrl&&(e.toUrl=e.nameToUrl);if(o.get(\"packaged\")||!e.toUrl)i=i||o.moduleUrl(n,\"worker\");else{var u=this.$normalizePath;i=i||u(e.toUrl(\"ace/worker/worker.js\",null,\"_\"));var f={};t.forEach(function(t){f[t]=u(e.toUrl(t,null,\"_\").replace(/(\\.js)?(\\?.*)?$/,\"\"))})}this.$worker=a(i),s&&this.send(\"importScripts\",s),this.$worker.postMessage({init:!0,tlns:f,module:n,classname:r}),this.callbackId=1,this.callbacks={},this.$worker.onmessage=this.onMessage};(function(){r.implement(this,s),this.onMessage=function(e){var t=e.data;switch(t.type){case\"event\":this._signal(t.name,{data:t.data});break;case\"call\":var n=this.callbacks[t.id];n&&(n(t.data),delete this.callbacks[t.id]);break;case\"error\":this.reportError(t.data);break;case\"log\":window.console&&console.log&&console.log.apply(console,t.data)}},this.reportError=function(e){window.console&&console.error&&console.error(e)},this.$normalizePath=function(e){return i.qualifyURL(e)},this.terminate=function(){this._signal(\"terminate\",{}),this.deltaQueue=null,this.$worker.terminate(),this.$worker=null,this.$doc&&this.$doc.off(\"change\",this.changeListener),this.$doc=null},this.send=function(e,t){this.$worker.postMessage({command:e,args:t})},this.call=function(e,t,n){if(n){var r=this.callbackId++;this.callbacks[r]=n,t.push(r)}this.send(e,t)},this.emit=function(e,t){try{this.$worker.postMessage({event:e,data:{data:t.data}})}catch(n){console.error(n.stack)}},this.attachToDocument=function(e){this.$doc&&this.terminate(),this.$doc=e,this.call(\"setValue\",[e.getValue()]),e.on(\"change\",this.changeListener)},this.changeListener=function(e){this.deltaQueue||(this.deltaQueue=[],setTimeout(this.$sendDeltaQueue,0)),e.action==\"insert\"?this.deltaQueue.push(e.start,e.lines):this.deltaQueue.push(e.start,e.end)},this.$sendDeltaQueue=function(){var e=this.deltaQueue;if(!e)return;this.deltaQueue=null,e.length>50&&e.length>this.$doc.getLength()>>1?this.call(\"setValue\",[this.$doc.getValue()]):this.emit(\"change\",{data:e})}}).call(f.prototype);var l=function(e,t,n){this.$sendDeltaQueue=this.$sendDeltaQueue.bind(this),this.changeListener=this.changeListener.bind(this),this.callbackId=1,this.callbacks={},this.messageBuffer=[];var r=null,i=!1,u=Object.create(s),a=this;this.$worker={},this.$worker.terminate=function(){},this.$worker.postMessage=function(e){a.messageBuffer.push(e),r&&(i?setTimeout(f):f())},this.setEmitSync=function(e){i=e};var f=function(){var e=a.messageBuffer.shift();e.command?r[e.command].apply(r,e.args):e.event&&u._signal(e.event,e.data)};u.postMessage=function(e){a.onMessage({data:e})},u.callback=function(e,t){this.postMessage({type:\"call\",id:t,data:e})},u.emit=function(e,t){this.postMessage({type:\"event\",name:e,data:t})},o.loadModule([\"worker\",t],function(e){r=new e[n](u);while(a.messageBuffer.length)f()})};l.prototype=f.prototype,t.UIWorkerClient=l,t.WorkerClient=f,t.createWorker=a}),define(\"ace/placeholder\",[\"require\",\"exports\",\"module\",\"ace/range\",\"ace/lib/event_emitter\",\"ace/lib/oop\"],function(e,t,n){\"use strict\";var r=e(\"./range\").Range,i=e(\"./lib/event_emitter\").EventEmitter,s=e(\"./lib/oop\"),o=function(e,t,n,r,i,s){var o=this;this.length=t,this.session=e,this.doc=e.getDocument(),this.mainClass=i,this.othersClass=s,this.$onUpdate=this.onUpdate.bind(this),this.doc.on(\"change\",this.$onUpdate),this.$others=r,this.$onCursorChange=function(){setTimeout(function(){o.onCursorChange()})},this.$pos=n;var u=e.getUndoManager().$undoStack||e.getUndoManager().$undostack||{length:-1};this.$undoStackDepth=u.length,this.setup(),e.selection.on(\"changeCursor\",this.$onCursorChange)};(function(){s.implement(this,i),this.setup=function(){var e=this,t=this.doc,n=this.session;this.selectionBefore=n.selection.toJSON(),n.selection.inMultiSelectMode&&n.selection.toSingleRange(),this.pos=t.createAnchor(this.$pos.row,this.$pos.column);var i=this.pos;i.$insertRight=!0,i.detach(),i.markerId=n.addMarker(new r(i.row,i.column,i.row,i.column+this.length),this.mainClass,null,!1),this.others=[],this.$others.forEach(function(n){var r=t.createAnchor(n.row,n.column);r.$insertRight=!0,r.detach(),e.others.push(r)}),n.setUndoSelect(!1)},this.showOtherMarkers=function(){if(this.othersActive)return;var e=this.session,t=this;this.othersActive=!0,this.others.forEach(function(n){n.markerId=e.addMarker(new r(n.row,n.column,n.row,n.column+t.length),t.othersClass,null,!1)})},this.hideOtherMarkers=function(){if(!this.othersActive)return;this.othersActive=!1;for(var e=0;e<this.others.length;e++)this.session.removeMarker(this.others[e].markerId)},this.onUpdate=function(e){if(this.$updating)return this.updateAnchors(e);var t=e;if(t.start.row!==t.end.row)return;if(t.start.row!==this.pos.row)return;this.$updating=!0;var n=e.action===\"insert\"?t.end.column-t.start.column:t.start.column-t.end.column,i=t.start.column>=this.pos.column&&t.start.column<=this.pos.column+this.length+1,s=t.start.column-this.pos.column;this.updateAnchors(e),i&&(this.length+=n);if(i&&!this.session.$fromUndo)if(e.action===\"insert\")for(var o=this.others.length-1;o>=0;o--){var u=this.others[o],a={row:u.row,column:u.column+s};this.doc.insertMergedLines(a,e.lines)}else if(e.action===\"remove\")for(var o=this.others.length-1;o>=0;o--){var u=this.others[o],a={row:u.row,column:u.column+s};this.doc.remove(new r(a.row,a.column,a.row,a.column-n))}this.$updating=!1,this.updateMarkers()},this.updateAnchors=function(e){this.pos.onChange(e);for(var t=this.others.length;t--;)this.others[t].onChange(e);this.updateMarkers()},this.updateMarkers=function(){if(this.$updating)return;var e=this,t=this.session,n=function(n,i){t.removeMarker(n.markerId),n.markerId=t.addMarker(new r(n.row,n.column,n.row,n.column+e.length),i,null,!1)};n(this.pos,this.mainClass);for(var i=this.others.length;i--;)n(this.others[i],this.othersClass)},this.onCursorChange=function(e){if(this.$updating||!this.session)return;var t=this.session.selection.getCursor();t.row===this.pos.row&&t.column>=this.pos.column&&t.column<=this.pos.column+this.length?(this.showOtherMarkers(),this._emit(\"cursorEnter\",e)):(this.hideOtherMarkers(),this._emit(\"cursorLeave\",e))},this.detach=function(){this.session.removeMarker(this.pos&&this.pos.markerId),this.hideOtherMarkers(),this.doc.removeEventListener(\"change\",this.$onUpdate),this.session.selection.removeEventListener(\"changeCursor\",this.$onCursorChange),this.session.setUndoSelect(!0),this.session=null},this.cancel=function(){if(this.$undoStackDepth===-1)return;var e=this.session.getUndoManager(),t=(e.$undoStack||e.$undostack).length-this.$undoStackDepth;for(var n=0;n<t;n++)e.undo(!0);this.selectionBefore&&this.session.selection.fromJSON(this.selectionBefore)}}).call(o.prototype),t.PlaceHolder=o}),define(\"ace/mouse/multi_select_handler\",[\"require\",\"exports\",\"module\",\"ace/lib/event\",\"ace/lib/useragent\"],function(e,t,n){function s(e,t){return e.row==t.row&&e.column==t.column}function o(e){var t=e.domEvent,n=t.altKey,o=t.shiftKey,u=t.ctrlKey,a=e.getAccelKey(),f=e.getButton();u&&i.isMac&&(f=t.button);if(e.editor.inMultiSelectMode&&f==2){e.editor.textInput.onContextMenu(e.domEvent);return}if(!u&&!n&&!a){f===0&&e.editor.inMultiSelectMode&&e.editor.exitMultiSelectMode();return}if(f!==0)return;var l=e.editor,c=l.selection,h=l.inMultiSelectMode,p=e.getDocumentPosition(),d=c.getCursor(),v=e.inSelection()||c.isEmpty()&&s(p,d),m=e.x,g=e.y,y=function(e){m=e.clientX,g=e.clientY},b=l.session,w=l.renderer.pixelToScreenCoordinates(m,g),E=w,S;if(l.$mouseHandler.$enableJumpToDef)u&&n||a&&n?S=o?\"block\":\"add\":n&&l.$blockSelectEnabled&&(S=\"block\");else if(a&&!n){S=\"add\";if(!h&&o)return}else n&&l.$blockSelectEnabled&&(S=\"block\");S&&i.isMac&&t.ctrlKey&&l.$mouseHandler.cancelContextMenu();if(S==\"add\"){if(!h&&v)return;if(!h){var x=c.toOrientedRange();l.addSelectionMarker(x)}var T=c.rangeList.rangeAtPoint(p);l.$blockScrolling++,l.inVirtualSelectionMode=!0,o&&(T=null,x=c.ranges[0]||x,l.removeSelectionMarker(x)),l.once(\"mouseup\",function(){var e=c.toOrientedRange();T&&e.isEmpty()&&s(T.cursor,e.cursor)?c.substractPoint(e.cursor):(o?c.substractPoint(x.cursor):x&&(l.removeSelectionMarker(x),c.addRange(x)),c.addRange(e)),l.$blockScrolling--,l.inVirtualSelectionMode=!1})}else if(S==\"block\"){e.stop(),l.inVirtualSelectionMode=!0;var N,C=[],k=function(){var e=l.renderer.pixelToScreenCoordinates(m,g),t=b.screenToDocumentPosition(e.row,e.column);if(s(E,e)&&s(t,c.lead))return;E=e,l.$blockScrolling++,l.selection.moveToPosition(t),l.renderer.scrollCursorIntoView(),l.removeSelectionMarkers(C),C=c.rectangularRangeBlock(E,w),l.$mouseHandler.$clickSelection&&C.length==1&&C[0].isEmpty()&&(C[0]=l.$mouseHandler.$clickSelection.clone()),C.forEach(l.addSelectionMarker,l),l.updateSelectionMarkers(),l.$blockScrolling--};l.$blockScrolling++,h&&!a?c.toSingleRange():!h&&a&&(N=c.toOrientedRange(),l.addSelectionMarker(N)),o?w=b.documentToScreenPosition(c.lead):c.moveToPosition(p),l.$blockScrolling--,E={row:-1,column:-1};var L=function(e){clearInterval(O),l.removeSelectionMarkers(C),C.length||(C=[c.toOrientedRange()]),l.$blockScrolling++,N&&(l.removeSelectionMarker(N),c.toSingleRange(N));for(var t=0;t<C.length;t++)c.addRange(C[t]);l.inVirtualSelectionMode=!1,l.$mouseHandler.$clickSelection=null,l.$blockScrolling--},A=k;r.capture(l.container,y,L);var O=setInterval(function(){A()},20);return e.preventDefault()}}var r=e(\"../lib/event\"),i=e(\"../lib/useragent\");t.onMouseDown=o}),define(\"ace/commands/multi_select_commands\",[\"require\",\"exports\",\"module\",\"ace/keyboard/hash_handler\"],function(e,t,n){t.defaultCommands=[{name:\"addCursorAbove\",exec:function(e){e.selectMoreLines(-1)},bindKey:{win:\"Ctrl-Alt-Up\",mac:\"Ctrl-Alt-Up\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"addCursorBelow\",exec:function(e){e.selectMoreLines(1)},bindKey:{win:\"Ctrl-Alt-Down\",mac:\"Ctrl-Alt-Down\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"addCursorAboveSkipCurrent\",exec:function(e){e.selectMoreLines(-1,!0)},bindKey:{win:\"Ctrl-Alt-Shift-Up\",mac:\"Ctrl-Alt-Shift-Up\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"addCursorBelowSkipCurrent\",exec:function(e){e.selectMoreLines(1,!0)},bindKey:{win:\"Ctrl-Alt-Shift-Down\",mac:\"Ctrl-Alt-Shift-Down\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectMoreBefore\",exec:function(e){e.selectMore(-1)},bindKey:{win:\"Ctrl-Alt-Left\",mac:\"Ctrl-Alt-Left\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectMoreAfter\",exec:function(e){e.selectMore(1)},bindKey:{win:\"Ctrl-Alt-Right\",mac:\"Ctrl-Alt-Right\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectNextBefore\",exec:function(e){e.selectMore(-1,!0)},bindKey:{win:\"Ctrl-Alt-Shift-Left\",mac:\"Ctrl-Alt-Shift-Left\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"selectNextAfter\",exec:function(e){e.selectMore(1,!0)},bindKey:{win:\"Ctrl-Alt-Shift-Right\",mac:\"Ctrl-Alt-Shift-Right\"},scrollIntoView:\"cursor\",readOnly:!0},{name:\"splitIntoLines\",exec:function(e){e.multiSelect.splitIntoLines()},bindKey:{win:\"Ctrl-Alt-L\",mac:\"Ctrl-Alt-L\"},readOnly:!0},{name:\"alignCursors\",exec:function(e){e.alignCursors()},bindKey:{win:\"Ctrl-Alt-A\",mac:\"Ctrl-Alt-A\"},scrollIntoView:\"cursor\"},{name:\"findAll\",exec:function(e){e.findAll()},bindKey:{win:\"Ctrl-Alt-K\",mac:\"Ctrl-Alt-G\"},scrollIntoView:\"cursor\",readOnly:!0}],t.multiSelectCommands=[{name:\"singleSelection\",bindKey:\"esc\",exec:function(e){e.exitMultiSelectMode()},scrollIntoView:\"cursor\",readOnly:!0,isAvailable:function(e){return e&&e.inMultiSelectMode}}];var r=e(\"../keyboard/hash_handler\").HashHandler;t.keyboardHandler=new r(t.multiSelectCommands)}),define(\"ace/multi_select\",[\"require\",\"exports\",\"module\",\"ace/range_list\",\"ace/range\",\"ace/selection\",\"ace/mouse/multi_select_handler\",\"ace/lib/event\",\"ace/lib/lang\",\"ace/commands/multi_select_commands\",\"ace/search\",\"ace/edit_session\",\"ace/editor\",\"ace/config\"],function(e,t,n){function h(e,t,n){return c.$options.wrap=!0,c.$options.needle=t,c.$options.backwards=n==-1,c.find(e)}function v(e,t){return e.row==t.row&&e.column==t.column}function m(e){if(e.$multiselectOnSessionChange)return;e.$onAddRange=e.$onAddRange.bind(e),e.$onRemoveRange=e.$onRemoveRange.bind(e),e.$onMultiSelect=e.$onMultiSelect.bind(e),e.$onSingleSelect=e.$onSingleSelect.bind(e),e.$multiselectOnSessionChange=t.onSessionChange.bind(e),e.$checkMultiselectChange=e.$checkMultiselectChange.bind(e),e.$multiselectOnSessionChange(e),e.on(\"changeSession\",e.$multiselectOnSessionChange),e.on(\"mousedown\",o),e.commands.addCommands(f.defaultCommands),g(e)}function g(e){function r(t){n&&(e.renderer.setMouseCursor(\"\"),n=!1)}var t=e.textInput.getElement(),n=!1;u.addListener(t,\"keydown\",function(t){var i=t.keyCode==18&&!(t.ctrlKey||t.shiftKey||t.metaKey);e.$blockSelectEnabled&&i?n||(e.renderer.setMouseCursor(\"crosshair\"),n=!0):n&&r()}),u.addListener(t,\"keyup\",r),u.addListener(t,\"blur\",r)}var r=e(\"./range_list\").RangeList,i=e(\"./range\").Range,s=e(\"./selection\").Selection,o=e(\"./mouse/multi_select_handler\").onMouseDown,u=e(\"./lib/event\"),a=e(\"./lib/lang\"),f=e(\"./commands/multi_select_commands\");t.commands=f.defaultCommands.concat(f.multiSelectCommands);var l=e(\"./search\").Search,c=new l,p=e(\"./edit_session\").EditSession;(function(){this.getSelectionMarkers=function(){return this.$selectionMarkers}}).call(p.prototype),function(){this.ranges=null,this.rangeList=null,this.addRange=function(e,t){if(!e)return;if(!this.inMultiSelectMode&&this.rangeCount===0){var n=this.toOrientedRange();this.rangeList.add(n),this.rangeList.add(e);if(this.rangeList.ranges.length!=2)return this.rangeList.removeAll(),t||this.fromOrientedRange(e);this.rangeList.removeAll(),this.rangeList.add(n),this.$onAddRange(n)}e.cursor||(e.cursor=e.end);var r=this.rangeList.add(e);return this.$onAddRange(e),r.length&&this.$onRemoveRange(r),this.rangeCount>1&&!this.inMultiSelectMode&&(this._signal(\"multiSelect\"),this.inMultiSelectMode=!0,this.session.$undoSelect=!1,this.rangeList.attach(this.session)),t||this.fromOrientedRange(e)},this.toSingleRange=function(e){e=e||this.ranges[0];var t=this.rangeList.removeAll();t.length&&this.$onRemoveRange(t),e&&this.fromOrientedRange(e)},this.substractPoint=function(e){var t=this.rangeList.substractPoint(e);if(t)return this.$onRemoveRange(t),t[0]},this.mergeOverlappingRanges=function(){var e=this.rangeList.merge();e.length?this.$onRemoveRange(e):this.ranges[0]&&this.fromOrientedRange(this.ranges[0])},this.$onAddRange=function(e){this.rangeCount=this.rangeList.ranges.length,this.ranges.unshift(e),this._signal(\"addRange\",{range:e})},this.$onRemoveRange=function(e){this.rangeCount=this.rangeList.ranges.length;if(this.rangeCount==1&&this.inMultiSelectMode){var t=this.rangeList.ranges.pop();e.push(t),this.rangeCount=0}for(var n=e.length;n--;){var r=this.ranges.indexOf(e[n]);this.ranges.splice(r,1)}this._signal(\"removeRange\",{ranges:e}),this.rangeCount===0&&this.inMultiSelectMode&&(this.inMultiSelectMode=!1,this._signal(\"singleSelect\"),this.session.$undoSelect=!0,this.rangeList.detach(this.session)),t=t||this.ranges[0],t&&!t.isEqual(this.getRange())&&this.fromOrientedRange(t)},this.$initRangeList=function(){if(this.rangeList)return;this.rangeList=new r,this.ranges=[],this.rangeCount=0},this.getAllRanges=function(){return this.rangeCount?this.rangeList.ranges.concat():[this.getRange()]},this.splitIntoLines=function(){if(this.rangeCount>1){var e=this.rangeList.ranges,t=e[e.length-1],n=i.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(n,t.cursor==t.start)}else{var n=this.getRange(),r=this.isBackwards(),s=n.start.row,o=n.end.row;if(s==o){if(r)var u=n.end,a=n.start;else var u=n.start,a=n.end;this.addRange(i.fromPoints(a,a)),this.addRange(i.fromPoints(u,u));return}var f=[],l=this.getLineRange(s,!0);l.start.column=n.start.column,f.push(l);for(var c=s+1;c<o;c++)f.push(this.getLineRange(c,!0));l=this.getLineRange(o,!0),l.end.column=n.end.column,f.push(l),f.forEach(this.addRange,this)}},this.toggleBlockSelection=function(){if(this.rangeCount>1){var e=this.rangeList.ranges,t=e[e.length-1],n=i.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(n,t.cursor==t.start)}else{var r=this.session.documentToScreenPosition(this.selectionLead),s=this.session.documentToScreenPosition(this.selectionAnchor),o=this.rectangularRangeBlock(r,s);o.forEach(this.addRange,this)}},this.rectangularRangeBlock=function(e,t,n){var r=[],s=e.column<t.column;if(s)var o=e.column,u=t.column;else var o=t.column,u=e.column;var a=e.row<t.row;if(a)var f=e.row,l=t.row;else var f=t.row,l=e.row;o<0&&(o=0),f<0&&(f=0),f==l&&(n=!0);for(var c=f;c<=l;c++){var h=i.fromPoints(this.session.screenToDocumentPosition(c,o),this.session.screenToDocumentPosition(c,u));if(h.isEmpty()){if(p&&v(h.end,p))break;var p=h.end}h.cursor=s?h.start:h.end,r.push(h)}a&&r.reverse();if(!n){var d=r.length-1;while(r[d].isEmpty()&&d>0)d--;if(d>0){var m=0;while(r[m].isEmpty())m++}for(var g=d;g>=m;g--)r[g].isEmpty()&&r.splice(g,1)}return r}}.call(s.prototype);var d=e(\"./editor\").Editor;(function(){this.updateSelectionMarkers=function(){this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.addSelectionMarker=function(e){e.cursor||(e.cursor=e.end);var t=this.getSelectionStyle();return e.marker=this.session.addMarker(e,\"ace_selection\",t),this.session.$selectionMarkers.push(e),this.session.selectionMarkerCount=this.session.$selectionMarkers.length,e},this.removeSelectionMarker=function(e){if(!e.marker)return;this.session.removeMarker(e.marker);var t=this.session.$selectionMarkers.indexOf(e);t!=-1&&this.session.$selectionMarkers.splice(t,1),this.session.selectionMarkerCount=this.session.$selectionMarkers.length},this.removeSelectionMarkers=function(e){var t=this.session.$selectionMarkers;for(var n=e.length;n--;){var r=e[n];if(!r.marker)continue;this.session.removeMarker(r.marker);var i=t.indexOf(r);i!=-1&&t.splice(i,1)}this.session.selectionMarkerCount=t.length},this.$onAddRange=function(e){this.addSelectionMarker(e.range),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onRemoveRange=function(e){this.removeSelectionMarkers(e.ranges),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onMultiSelect=function(e){if(this.inMultiSelectMode)return;this.inMultiSelectMode=!0,this.setStyle(\"ace_multiselect\"),this.keyBinding.addKeyboardHandler(f.keyboardHandler),this.commands.setDefaultHandler(\"exec\",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onSingleSelect=function(e){if(this.session.multiSelect.inVirtualMode)return;this.inMultiSelectMode=!1,this.unsetStyle(\"ace_multiselect\"),this.keyBinding.removeKeyboardHandler(f.keyboardHandler),this.commands.removeDefaultHandler(\"exec\",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers(),this._emit(\"changeSelection\")},this.$onMultiSelectExec=function(e){var t=e.command,n=e.editor;if(!n.multiSelect)return;if(!t.multiSelectAction){var r=t.exec(n,e.args||{});n.multiSelect.addRange(n.multiSelect.toOrientedRange()),n.multiSelect.mergeOverlappingRanges()}else t.multiSelectAction==\"forEach\"?r=n.forEachSelection(t,e.args):t.multiSelectAction==\"forEachLine\"?r=n.forEachSelection(t,e.args,!0):t.multiSelectAction==\"single\"?(n.exitMultiSelectMode(),r=t.exec(n,e.args||{})):r=t.multiSelectAction(n,e.args||{});return r},this.forEachSelection=function(e,t,n){if(this.inVirtualSelectionMode)return;var r=n&&n.keepOrder,i=n==1||n&&n.$byLines,o=this.session,u=this.selection,a=u.rangeList,f=(r?u:a).ranges,l;if(!f.length)return e.exec?e.exec(this,t||{}):e(this,t||{});var c=u._eventRegistry;u._eventRegistry={};var h=new s(o);this.inVirtualSelectionMode=!0;for(var p=f.length;p--;){if(i)while(p>0&&f[p].start.row==f[p-1].end.row)p--;h.fromOrientedRange(f[p]),h.index=p,this.selection=o.selection=h;var d=e.exec?e.exec(this,t||{}):e(this,t||{});!l&&d!==undefined&&(l=d),h.toOrientedRange(f[p])}h.detach(),this.selection=o.selection=u,this.inVirtualSelectionMode=!1,u._eventRegistry=c,u.mergeOverlappingRanges();var v=this.renderer.$scrollAnimation;return this.onCursorChange(),this.onSelectionChange(),v&&v.from==v.to&&this.renderer.animateScrolling(v.from),l},this.exitMultiSelectMode=function(){if(!this.inMultiSelectMode||this.inVirtualSelectionMode)return;this.multiSelect.toSingleRange()},this.getSelectedText=function(){var e=\"\";if(this.inMultiSelectMode&&!this.inVirtualSelectionMode){var t=this.multiSelect.rangeList.ranges,n=[];for(var r=0;r<t.length;r++)n.push(this.session.getTextRange(t[r]));var i=this.session.getDocument().getNewLineCharacter();e=n.join(i),e.length==(n.length-1)*i.length&&(e=\"\")}else this.selection.isEmpty()||(e=this.session.getTextRange(this.getSelectionRange()));return e},this.$checkMultiselectChange=function(e,t){if(this.inMultiSelectMode&&!this.inVirtualSelectionMode){var n=this.multiSelect.ranges[0];if(this.multiSelect.isEmpty()&&t==this.multiSelect.anchor)return;var r=t==this.multiSelect.anchor?n.cursor==n.start?n.end:n.start:n.cursor;(r.row!=t.row||this.session.$clipPositionToDocument(r.row,r.column).column!=t.column)&&this.multiSelect.toSingleRange(this.multiSelect.toOrientedRange())}},this.findAll=function(e,t,n){t=t||{},t.needle=e||t.needle;if(t.needle==undefined){var r=this.selection.isEmpty()?this.selection.getWordRange():this.selection.getRange();t.needle=this.session.getTextRange(r)}this.$search.set(t);var i=this.$search.findAll(this.session);if(!i.length)return 0;this.$blockScrolling+=1;var s=this.multiSelect;n||s.toSingleRange(i[0]);for(var o=i.length;o--;)s.addRange(i[o],!0);return r&&s.rangeList.rangeAtPoint(r.start)&&s.addRange(r,!0),this.$blockScrolling-=1,i.length},this.selectMoreLines=function(e,t){var n=this.selection.toOrientedRange(),r=n.cursor==n.end,s=this.session.documentToScreenPosition(n.cursor);this.selection.$desiredColumn&&(s.column=this.selection.$desiredColumn);var o=this.session.screenToDocumentPosition(s.row+e,s.column);if(!n.isEmpty())var u=this.session.documentToScreenPosition(r?n.end:n.start),a=this.session.screenToDocumentPosition(u.row+e,u.column);else var a=o;if(r){var f=i.fromPoints(o,a);f.cursor=f.start}else{var f=i.fromPoints(a,o);f.cursor=f.end}f.desiredColumn=s.column;if(!this.selection.inMultiSelectMode)this.selection.addRange(n);else if(t)var l=n.cursor;this.selection.addRange(f),l&&this.selection.substractPoint(l)},this.transposeSelections=function(e){var t=this.session,n=t.multiSelect,r=n.ranges;for(var i=r.length;i--;){var s=r[i];if(s.isEmpty()){var o=t.getWordRange(s.start.row,s.start.column);s.start.row=o.start.row,s.start.column=o.start.column,s.end.row=o.end.row,s.end.column=o.end.column}}n.mergeOverlappingRanges();var u=[];for(var i=r.length;i--;){var s=r[i];u.unshift(t.getTextRange(s))}e<0?u.unshift(u.pop()):u.push(u.shift());for(var i=r.length;i--;){var s=r[i],o=s.clone();t.replace(s,u[i]),s.start.row=o.start.row,s.start.column=o.start.column}},this.selectMore=function(e,t,n){var r=this.session,i=r.multiSelect,s=i.toOrientedRange();if(s.isEmpty()){s=r.getWordRange(s.start.row,s.start.column),s.cursor=e==-1?s.start:s.end,this.multiSelect.addRange(s);if(n)return}var o=r.getTextRange(s),u=h(r,o,e);u&&(u.cursor=e==-1?u.start:u.end,this.$blockScrolling+=1,this.session.unfold(u),this.multiSelect.addRange(u),this.$blockScrolling-=1,this.renderer.scrollCursorIntoView(null,.5)),t&&this.multiSelect.substractPoint(s.cursor)},this.alignCursors=function(){var e=this.session,t=e.multiSelect,n=t.ranges,r=-1,s=n.filter(function(e){if(e.cursor.row==r)return!0;r=e.cursor.row});if(!n.length||s.length==n.length-1){var o=this.selection.getRange(),u=o.start.row,f=o.end.row,l=u==f;if(l){var c=this.session.getLength(),h;do h=this.session.getLine(f);while(/[=:]/.test(h)&&++f<c);do h=this.session.getLine(u);while(/[=:]/.test(h)&&--u>0);u<0&&(u=0),f>=c&&(f=c-1)}var p=this.session.removeFullLines(u,f);p=this.$reAlignText(p,l),this.session.insert({row:u,column:0},p.join(\"\\n\")+\"\\n\"),l||(o.start.column=0,o.end.column=p[p.length-1].length),this.selection.setRange(o)}else{s.forEach(function(e){t.substractPoint(e.cursor)});var d=0,v=Infinity,m=n.map(function(t){var n=t.cursor,r=e.getLine(n.row),i=r.substr(n.column).search(/\\S/g);return i==-1&&(i=0),n.column>d&&(d=n.column),i<v&&(v=i),i});n.forEach(function(t,n){var r=t.cursor,s=d-r.column,o=m[n]-v;s>o?e.insert(r,a.stringRepeat(\" \",s-o)):e.remove(new i(r.row,r.column,r.row,r.column-s+o)),t.start.column=t.end.column=d,t.start.row=t.end.row=r.row,t.cursor=t.end}),t.fromOrientedRange(n[0]),this.renderer.updateCursor(),this.renderer.updateBackMarkers()}},this.$reAlignText=function(e,t){function u(e){return a.stringRepeat(\" \",e)}function f(e){return e[2]?u(i)+e[2]+u(s-e[2].length+o)+e[4].replace(/^([=:])\\s+/,\"$1 \"):e[0]}function l(e){return e[2]?u(i+s-e[2].length)+e[2]+u(o,\" \")+e[4].replace(/^([=:])\\s+/,\"$1 \"):e[0]}function c(e){return e[2]?u(i)+e[2]+u(o)+e[4].replace(/^([=:])\\s+/,\"$1 \"):e[0]}var n=!0,r=!0,i,s,o;return e.map(function(e){var t=e.match(/(\\s*)(.*?)(\\s*)([=:].*)/);return t?i==null?(i=t[1].length,s=t[2].length,o=t[3].length,t):(i+s+o!=t[1].length+t[2].length+t[3].length&&(r=!1),i!=t[1].length&&(n=!1),i>t[1].length&&(i=t[1].length),s<t[2].length&&(s=t[2].length),o>t[3].length&&(o=t[3].length),t):[e]}).map(t?f:n?r?l:f:c)}}).call(d.prototype),t.onSessionChange=function(e){var t=e.session;t&&!t.multiSelect&&(t.$selectionMarkers=[],t.selection.$initRangeList(),t.multiSelect=t.selection),this.multiSelect=t&&t.multiSelect;var n=e.oldSession;n&&(n.multiSelect.off(\"addRange\",this.$onAddRange),n.multiSelect.off(\"removeRange\",this.$onRemoveRange),n.multiSelect.off(\"multiSelect\",this.$onMultiSelect),n.multiSelect.off(\"singleSelect\",this.$onSingleSelect),n.multiSelect.lead.off(\"change\",this.$checkMultiselectChange),n.multiSelect.anchor.off(\"change\",this.$checkMultiselectChange)),t&&(t.multiSelect.on(\"addRange\",this.$onAddRange),t.multiSelect.on(\"removeRange\",this.$onRemoveRange),t.multiSelect.on(\"multiSelect\",this.$onMultiSelect),t.multiSelect.on(\"singleSelect\",this.$onSingleSelect),t.multiSelect.lead.on(\"change\",this.$checkMultiselectChange),t.multiSelect.anchor.on(\"change\",this.$checkMultiselectChange)),t&&this.inMultiSelectMode!=t.selection.inMultiSelectMode&&(t.selection.inMultiSelectMode?this.$onMultiSelect():this.$onSingleSelect())},t.MultiSelect=m,e(\"./config\").defineOptions(d.prototype,\"editor\",{enableMultiselect:{set:function(e){m(this),e?(this.on(\"changeSession\",this.$multiselectOnSessionChange),this.on(\"mousedown\",o)):(this.off(\"changeSession\",this.$multiselectOnSessionChange),this.off(\"mousedown\",o))},value:!0},enableBlockSelect:{set:function(e){this.$blockSelectEnabled=e},value:!0}})}),define(\"ace/mode/folding/fold_mode\",[\"require\",\"exports\",\"module\",\"ace/range\"],function(e,t,n){\"use strict\";var r=e(\"../../range\").Range,i=t.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(e,t,n){var r=e.getLine(n);return this.foldingStartMarker.test(r)?\"start\":t==\"markbeginend\"&&this.foldingStopMarker&&this.foldingStopMarker.test(r)?\"end\":\"\"},this.getFoldWidgetRange=function(e,t,n){return null},this.indentationBlock=function(e,t,n){var i=/\\S/,s=e.getLine(t),o=s.search(i);if(o==-1)return;var u=n||s.length,a=e.getLength(),f=t,l=t;while(++t<a){var c=e.getLine(t).search(i);if(c==-1)continue;if(c<=o)break;l=t}if(l>f){var h=e.getLine(l).length;return new r(f,u,l,h)}},this.openingBracketBlock=function(e,t,n,i,s){var o={row:n,column:i+1},u=e.$findClosingBracket(t,o,s);if(!u)return;var a=e.foldWidgets[u.row];return a==null&&(a=e.getFoldWidget(u.row)),a==\"start\"&&u.row>o.row&&(u.row--,u.column=e.getLine(u.row).length),r.fromPoints(o,u)},this.closingBracketBlock=function(e,t,n,i,s){var o={row:n,column:i},u=e.$findOpeningBracket(t,o);if(!u)return;return u.column++,o.column--,r.fromPoints(u,o)}}).call(i.prototype)}),define(\"ace/theme/textmate\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\"],function(e,t,n){\"use strict\";t.isDark=!1,t.cssClass=\"ace-tm\",t.cssText='.ace-tm .ace_gutter {background: #f0f0f0;color: #333;}.ace-tm .ace_print-margin {width: 1px;background: #e8e8e8;}.ace-tm .ace_fold {background-color: #6B72E6;}.ace-tm {background-color: #FFFFFF;color: black;}.ace-tm .ace_cursor {color: black;}.ace-tm .ace_invisible {color: rgb(191, 191, 191);}.ace-tm .ace_storage,.ace-tm .ace_keyword {color: blue;}.ace-tm .ace_constant {color: rgb(197, 6, 11);}.ace-tm .ace_constant.ace_buildin {color: rgb(88, 72, 246);}.ace-tm .ace_constant.ace_language {color: rgb(88, 92, 246);}.ace-tm .ace_constant.ace_library {color: rgb(6, 150, 14);}.ace-tm .ace_invalid {background-color: rgba(255, 0, 0, 0.1);color: red;}.ace-tm .ace_support.ace_function {color: rgb(60, 76, 114);}.ace-tm .ace_support.ace_constant {color: rgb(6, 150, 14);}.ace-tm .ace_support.ace_type,.ace-tm .ace_support.ace_class {color: rgb(109, 121, 222);}.ace-tm .ace_keyword.ace_operator {color: rgb(104, 118, 135);}.ace-tm .ace_string {color: rgb(3, 106, 7);}.ace-tm .ace_comment {color: rgb(76, 136, 107);}.ace-tm .ace_comment.ace_doc {color: rgb(0, 102, 255);}.ace-tm .ace_comment.ace_doc.ace_tag {color: rgb(128, 159, 191);}.ace-tm .ace_constant.ace_numeric {color: rgb(0, 0, 205);}.ace-tm .ace_variable {color: rgb(49, 132, 149);}.ace-tm .ace_xml-pe {color: rgb(104, 104, 91);}.ace-tm .ace_entity.ace_name.ace_function {color: #0000A2;}.ace-tm .ace_heading {color: rgb(12, 7, 255);}.ace-tm .ace_list {color:rgb(185, 6, 144);}.ace-tm .ace_meta.ace_tag {color:rgb(0, 22, 142);}.ace-tm .ace_string.ace_regex {color: rgb(255, 0, 0)}.ace-tm .ace_marker-layer .ace_selection {background: rgb(181, 213, 255);}.ace-tm.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px white;}.ace-tm .ace_marker-layer .ace_step {background: rgb(252, 255, 0);}.ace-tm .ace_marker-layer .ace_stack {background: rgb(164, 229, 101);}.ace-tm .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgb(192, 192, 192);}.ace-tm .ace_marker-layer .ace_active-line {background: rgba(0, 0, 0, 0.07);}.ace-tm .ace_gutter-active-line {background-color : #dcdcdc;}.ace-tm .ace_marker-layer .ace_selected-word {background: rgb(250, 250, 255);border: 1px solid rgb(200, 200, 250);}.ace-tm .ace_indent-guide {background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;}';var r=e(\"../lib/dom\");r.importCssString(t.cssText,t.cssClass)}),define(\"ace/line_widgets\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/dom\",\"ace/range\"],function(e,t,n){\"use strict\";function o(e){this.session=e,this.session.widgetManager=this,this.session.getRowLength=this.getRowLength,this.session.$getWidgetScreenLength=this.$getWidgetScreenLength,this.updateOnChange=this.updateOnChange.bind(this),this.renderWidgets=this.renderWidgets.bind(this),this.measureWidgets=this.measureWidgets.bind(this),this.session._changedWidgets=[],this.$onChangeEditor=this.$onChangeEditor.bind(this),this.session.on(\"change\",this.updateOnChange),this.session.on(\"changeFold\",this.updateOnFold),this.session.on(\"changeEditor\",this.$onChangeEditor)}var r=e(\"./lib/oop\"),i=e(\"./lib/dom\"),s=e(\"./range\").Range;(function(){this.getRowLength=function(e){var t;return this.lineWidgets?t=this.lineWidgets[e]&&this.lineWidgets[e].rowCount||0:t=0,!this.$useWrapMode||!this.$wrapData[e]?1+t:this.$wrapData[e].length+1+t},this.$getWidgetScreenLength=function(){var e=0;return this.lineWidgets.forEach(function(t){t&&t.rowCount&&!t.hidden&&(e+=t.rowCount)}),e},this.$onChangeEditor=function(e){this.attach(e.editor)},this.attach=function(e){e&&e.widgetManager&&e.widgetManager!=this&&e.widgetManager.detach();if(this.editor==e)return;this.detach(),this.editor=e,e&&(e.widgetManager=this,e.renderer.on(\"beforeRender\",this.measureWidgets),e.renderer.on(\"afterRender\",this.renderWidgets))},this.detach=function(e){var t=this.editor;if(!t)return;this.editor=null,t.widgetManager=null,t.renderer.off(\"beforeRender\",this.measureWidgets),t.renderer.off(\"afterRender\",this.renderWidgets);var n=this.session.lineWidgets;n&&n.forEach(function(e){e&&e.el&&e.el.parentNode&&(e._inDocument=!1,e.el.parentNode.removeChild(e.el))})},this.updateOnFold=function(e,t){var n=t.lineWidgets;if(!n||!e.action)return;var r=e.data,i=r.start.row,s=r.end.row,o=e.action==\"add\";for(var u=i+1;u<s;u++)n[u]&&(n[u].hidden=o);n[s]&&(o?n[i]?n[s].hidden=o:n[i]=n[s]:(n[i]==n[s]&&(n[i]=undefined),n[s].hidden=o))},this.updateOnChange=function(e){var t=this.session.lineWidgets;if(!t)return;var n=e.start.row,r=e.end.row-n;if(r!==0)if(e.action==\"remove\"){var i=t.splice(n+1,r);i.forEach(function(e){e&&this.removeLineWidget(e)},this),this.$updateRows()}else{var s=new Array(r);s.unshift(n,0),t.splice.apply(t,s),this.$updateRows()}},this.$updateRows=function(){var e=this.session.lineWidgets;if(!e)return;var t=!0;e.forEach(function(e,n){if(e){t=!1,e.row=n;while(e.$oldWidget)e.$oldWidget.row=n,e=e.$oldWidget}}),t&&(this.session.lineWidgets=null)},this.addLineWidget=function(e){this.session.lineWidgets||(this.session.lineWidgets=new Array(this.session.getLength()));var t=this.session.lineWidgets[e.row];t&&(e.$oldWidget=t,t.el&&t.el.parentNode&&(t.el.parentNode.removeChild(t.el),t._inDocument=!1)),this.session.lineWidgets[e.row]=e,e.session=this.session;var n=this.editor.renderer;e.html&&!e.el&&(e.el=i.createElement(\"div\"),e.el.innerHTML=e.html),e.el&&(i.addCssClass(e.el,\"ace_lineWidgetContainer\"),e.el.style.position=\"absolute\",e.el.style.zIndex=5,n.container.appendChild(e.el),e._inDocument=!0),e.coverGutter||(e.el.style.zIndex=3),e.pixelHeight==null&&(e.pixelHeight=e.el.offsetHeight),e.rowCount==null&&(e.rowCount=e.pixelHeight/n.layerConfig.lineHeight);var r=this.session.getFoldAt(e.row,0);e.$fold=r;if(r){var s=this.session.lineWidgets;e.row==r.end.row&&!s[r.start.row]?s[r.start.row]=e:e.hidden=!0}return this.session._emit(\"changeFold\",{data:{start:{row:e.row}}}),this.$updateRows(),this.renderWidgets(null,n),this.onWidgetChanged(e),e},this.removeLineWidget=function(e){e._inDocument=!1,e.session=null,e.el&&e.el.parentNode&&e.el.parentNode.removeChild(e.el);if(e.editor&&e.editor.destroy)try{e.editor.destroy()}catch(t){}if(this.session.lineWidgets){var n=this.session.lineWidgets[e.row];if(n==e)this.session.lineWidgets[e.row]=e.$oldWidget,e.$oldWidget&&this.onWidgetChanged(e.$oldWidget);else while(n){if(n.$oldWidget==e){n.$oldWidget=e.$oldWidget;break}n=n.$oldWidget}}this.session._emit(\"changeFold\",{data:{start:{row:e.row}}}),this.$updateRows()},this.getWidgetsAtRow=function(e){var t=this.session.lineWidgets,n=t&&t[e],r=[];while(n)r.push(n),n=n.$oldWidget;return r},this.onWidgetChanged=function(e){this.session._changedWidgets.push(e),this.editor&&this.editor.renderer.updateFull()},this.measureWidgets=function(e,t){var n=this.session._changedWidgets,r=t.layerConfig;if(!n||!n.length)return;var i=Infinity;for(var s=0;s<n.length;s++){var o=n[s];if(!o||!o.el)continue;if(o.session!=this.session)continue;if(!o._inDocument){if(this.session.lineWidgets[o.row]!=o)continue;o._inDocument=!0,t.container.appendChild(o.el)}o.h=o.el.offsetHeight,o.fixedWidth||(o.w=o.el.offsetWidth,o.screenWidth=Math.ceil(o.w/r.characterWidth));var u=o.h/r.lineHeight;o.coverLine&&(u-=this.session.getRowLineCount(o.row),u<0&&(u=0)),o.rowCount!=u&&(o.rowCount=u,o.row<i&&(i=o.row))}i!=Infinity&&(this.session._emit(\"changeFold\",{data:{start:{row:i}}}),this.session.lineWidgetWidth=null),this.session._changedWidgets=[]},this.renderWidgets=function(e,t){var n=t.layerConfig,r=this.session.lineWidgets;if(!r)return;var i=Math.min(this.firstRow,n.firstRow),s=Math.max(this.lastRow,n.lastRow,r.length);while(i>0&&!r[i])i--;this.firstRow=n.firstRow,this.lastRow=n.lastRow,t.$cursorLayer.config=n;for(var o=i;o<=s;o++){var u=r[o];if(!u||!u.el)continue;if(u.hidden){u.el.style.top=-100-(u.pixelHeight||0)+\"px\";continue}u._inDocument||(u._inDocument=!0,t.container.appendChild(u.el));var a=t.$cursorLayer.getPixelPosition({row:o,column:0},!0).top;u.coverLine||(a+=n.lineHeight*this.session.getRowLineCount(u.row)),u.el.style.top=a-n.offset+\"px\";var f=u.coverGutter?0:t.gutterWidth;u.fixedWidth||(f-=t.scrollLeft),u.el.style.left=f+\"px\",u.fullWidth&&u.screenWidth&&(u.el.style.minWidth=n.width+2*n.padding+\"px\"),u.fixedWidth?u.el.style.right=t.scrollBar.getWidth()+\"px\":u.el.style.right=\"\"}}}).call(o.prototype),t.LineWidgets=o}),define(\"ace/ext/error_marker\",[\"require\",\"exports\",\"module\",\"ace/line_widgets\",\"ace/lib/dom\",\"ace/range\"],function(e,t,n){\"use strict\";function o(e,t,n){var r=0,i=e.length-1;while(r<=i){var s=r+i>>1,o=n(t,e[s]);if(o>0)r=s+1;else{if(!(o<0))return s;i=s-1}}return-(r+1)}function u(e,t,n){var r=e.getAnnotations().sort(s.comparePoints);if(!r.length)return;var i=o(r,{row:t,column:-1},s.comparePoints);i<0&&(i=-i-1),i>=r.length?i=n>0?0:r.length-1:i===0&&n<0&&(i=r.length-1);var u=r[i];if(!u||!n)return;if(u.row===t){do u=r[i+=n];while(u&&u.row===t);if(!u)return r.slice()}var a=[];t=u.row;do a[n<0?\"unshift\":\"push\"](u),u=r[i+=n];while(u&&u.row==t);return a.length&&a}var r=e(\"../line_widgets\").LineWidgets,i=e(\"../lib/dom\"),s=e(\"../range\").Range;t.showErrorMarker=function(e,t){var n=e.session;n.widgetManager||(n.widgetManager=new r(n),n.widgetManager.attach(e));var s=e.getCursorPosition(),o=s.row,a=n.widgetManager.getWidgetsAtRow(o).filter(function(e){return e.type==\"errorMarker\"})[0];a?a.destroy():o-=t;var f=u(n,o,t),l;if(f){var c=f[0];s.column=(c.pos&&typeof c.column!=\"number\"?c.pos.sc:c.column)||0,s.row=c.row,l=e.renderer.$gutterLayer.$annotations[s.row]}else{if(a)return;l={text:[\"Looks good!\"],className:\"ace_ok\"}}e.session.unfold(s.row),e.selection.moveToPosition(s);var h={row:s.row,fixedWidth:!0,coverGutter:!0,el:i.createElement(\"div\"),type:\"errorMarker\"},p=h.el.appendChild(i.createElement(\"div\")),d=h.el.appendChild(i.createElement(\"div\"));d.className=\"error_widget_arrow \"+l.className;var v=e.renderer.$cursorLayer.getPixelPosition(s).left;d.style.left=v+e.renderer.gutterWidth-5+\"px\",h.el.className=\"error_widget_wrapper\",p.className=\"error_widget \"+l.className,p.innerHTML=l.text.join(\"<br>\"),p.appendChild(i.createElement(\"div\"));var m=function(e,t,n){if(t===0&&(n===\"esc\"||n===\"return\"))return h.destroy(),{command:\"null\"}};h.destroy=function(){if(e.$mouseHandler.isMousePressed)return;e.keyBinding.removeKeyboardHandler(m),n.widgetManager.removeLineWidget(h),e.off(\"changeSelection\",h.destroy),e.off(\"changeSession\",h.destroy),e.off(\"mouseup\",h.destroy),e.off(\"change\",h.destroy)},e.keyBinding.addKeyboardHandler(m),e.on(\"changeSelection\",h.destroy),e.on(\"changeSession\",h.destroy),e.on(\"mouseup\",h.destroy),e.on(\"change\",h.destroy),e.session.widgetManager.addLineWidget(h),h.el.onmousedown=e.focus.bind(e),e.renderer.scrollCursorIntoView(null,.5,{bottom:h.el.offsetHeight})},i.importCssString(\"    .error_widget_wrapper {        background: inherit;        color: inherit;        border:none    }    .error_widget {        border-top: solid 2px;        border-bottom: solid 2px;        margin: 5px 0;        padding: 10px 40px;        white-space: pre-wrap;    }    .error_widget.ace_error, .error_widget_arrow.ace_error{        border-color: #ff5a5a    }    .error_widget.ace_warning, .error_widget_arrow.ace_warning{        border-color: #F1D817    }    .error_widget.ace_info, .error_widget_arrow.ace_info{        border-color: #5a5a5a    }    .error_widget.ace_ok, .error_widget_arrow.ace_ok{        border-color: #5aaa5a    }    .error_widget_arrow {        position: absolute;        border: solid 5px;        border-top-color: transparent!important;        border-right-color: transparent!important;        border-left-color: transparent!important;        top: -5px;    }\",\"\")}),define(\"ace/ace\",[\"require\",\"exports\",\"module\",\"ace/lib/fixoldbrowsers\",\"ace/lib/dom\",\"ace/lib/event\",\"ace/editor\",\"ace/edit_session\",\"ace/undomanager\",\"ace/virtual_renderer\",\"ace/worker/worker_client\",\"ace/keyboard/hash_handler\",\"ace/placeholder\",\"ace/multi_select\",\"ace/mode/folding/fold_mode\",\"ace/theme/textmate\",\"ace/ext/error_marker\",\"ace/config\"],function(e,t,n){\"use strict\";e(\"./lib/fixoldbrowsers\");var r=e(\"./lib/dom\"),i=e(\"./lib/event\"),s=e(\"./editor\").Editor,o=e(\"./edit_session\").EditSession,u=e(\"./undomanager\").UndoManager,a=e(\"./virtual_renderer\").VirtualRenderer;e(\"./worker/worker_client\"),e(\"./keyboard/hash_handler\"),e(\"./placeholder\"),e(\"./multi_select\"),e(\"./mode/folding/fold_mode\"),e(\"./theme/textmate\"),e(\"./ext/error_marker\"),t.config=e(\"./config\"),t.require=e,typeof define==\"function\"&&(t.define=define),t.edit=function(e){if(typeof e==\"string\"){var n=e;e=document.getElementById(n);if(!e)throw new Error(\"ace.edit can't find div #\"+n)}if(e&&e.env&&e.env.editor instanceof s)return e.env.editor;var o=\"\";if(e&&/input|textarea/i.test(e.tagName)){var u=e;o=u.value,e=r.createElement(\"pre\"),u.parentNode.replaceChild(e,u)}else e&&(o=r.getInnerText(e),e.innerHTML=\"\");var f=t.createEditSession(o),l=new s(new a(e));l.setSession(f);var c={document:f,editor:l,onResize:l.resize.bind(l,null)};return u&&(c.textarea=u),i.addListener(window,\"resize\",c.onResize),l.on(\"destroy\",function(){i.removeListener(window,\"resize\",c.onResize),c.editor.container.env=null}),l.container.env=l.env=c,l},t.createEditSession=function(e,t){var n=new o(e,t);return n.setUndoManager(new u),n},t.EditSession=o,t.UndoManager=u,t.version=\"1.2.8\"});\n            (function() {\n                window.require([\"ace/ace\"], function(a) {\n                    if (a) {\n                        a.config.init(true);\n                        a.define = window.define;\n                    }\n                    if (!window.ace)\n                        window.ace = a;\n                    for (var key in a) if (a.hasOwnProperty(key))\n                        window.ace[key] = a[key];\n                });\n            })();\n        "
  },
  {
    "path": "lib/ace/ext-language_tools.js",
    "content": "ace.define(\"ace/snippets\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\",\"ace/lib/lang\",\"ace/range\",\"ace/anchor\",\"ace/keyboard/hash_handler\",\"ace/tokenizer\",\"ace/lib/dom\",\"ace/editor\"], function(require, exports, module) {\n\"use strict\";\nvar oop = require(\"./lib/oop\");\nvar EventEmitter = require(\"./lib/event_emitter\").EventEmitter;\nvar lang = require(\"./lib/lang\");\nvar Range = require(\"./range\").Range;\nvar Anchor = require(\"./anchor\").Anchor;\nvar HashHandler = require(\"./keyboard/hash_handler\").HashHandler;\nvar Tokenizer = require(\"./tokenizer\").Tokenizer;\nvar comparePoints = Range.comparePoints;\n\nvar SnippetManager = function() {\n    this.snippetMap = {};\n    this.snippetNameMap = {};\n};\n\n(function() {\n    oop.implement(this, EventEmitter);\n    \n    this.getTokenizer = function() {\n        function TabstopToken(str, _, stack) {\n            str = str.substr(1);\n            if (/^\\d+$/.test(str) && !stack.inFormatString)\n                return [{tabstopId: parseInt(str, 10)}];\n            return [{text: str}];\n        }\n        function escape(ch) {\n            return \"(?:[^\\\\\\\\\" + ch + \"]|\\\\\\\\.)\";\n        }\n        SnippetManager.$tokenizer = new Tokenizer({\n            start: [\n                {regex: /:/, onMatch: function(val, state, stack) {\n                    if (stack.length && stack[0].expectIf) {\n                        stack[0].expectIf = false;\n                        stack[0].elseBranch = stack[0];\n                        return [stack[0]];\n                    }\n                    return \":\";\n                }},\n                {regex: /\\\\./, onMatch: function(val, state, stack) {\n                    var ch = val[1];\n                    if (ch == \"}\" && stack.length) {\n                        val = ch;\n                    }else if (\"`$\\\\\".indexOf(ch) != -1) {\n                        val = ch;\n                    } else if (stack.inFormatString) {\n                        if (ch == \"n\")\n                            val = \"\\n\";\n                        else if (ch == \"t\")\n                            val = \"\\n\";\n                        else if (\"ulULE\".indexOf(ch) != -1) {\n                            val = {changeCase: ch, local: ch > \"a\"};\n                        }\n                    }\n\n                    return [val];\n                }},\n                {regex: /}/, onMatch: function(val, state, stack) {\n                    return [stack.length ? stack.shift() : val];\n                }},\n                {regex: /\\$(?:\\d+|\\w+)/, onMatch: TabstopToken},\n                {regex: /\\$\\{[\\dA-Z_a-z]+/, onMatch: function(str, state, stack) {\n                    var t = TabstopToken(str.substr(1), state, stack);\n                    stack.unshift(t[0]);\n                    return t;\n                }, next: \"snippetVar\"},\n                {regex: /\\n/, token: \"newline\", merge: false}\n            ],\n            snippetVar: [\n                {regex: \"\\\\|\" + escape(\"\\\\|\") + \"*\\\\|\", onMatch: function(val, state, stack) {\n                    stack[0].choices = val.slice(1, -1).split(\",\");\n                }, next: \"start\"},\n                {regex: \"/(\" + escape(\"/\") + \"+)/(?:(\" + escape(\"/\") + \"*)/)(\\\\w*):?\",\n                 onMatch: function(val, state, stack) {\n                    var ts = stack[0];\n                    ts.fmtString = val;\n\n                    val = this.splitRegex.exec(val);\n                    ts.guard = val[1];\n                    ts.fmt = val[2];\n                    ts.flag = val[3];\n                    return \"\";\n                }, next: \"start\"},\n                {regex: \"`\" + escape(\"`\") + \"*`\", onMatch: function(val, state, stack) {\n                    stack[0].code = val.splice(1, -1);\n                    return \"\";\n                }, next: \"start\"},\n                {regex: \"\\\\?\", onMatch: function(val, state, stack) {\n                    if (stack[0])\n                        stack[0].expectIf = true;\n                }, next: \"start\"},\n                {regex: \"([^:}\\\\\\\\]|\\\\\\\\.)*:?\", token: \"\", next: \"start\"}\n            ],\n            formatString: [\n                {regex: \"/(\" + escape(\"/\") + \"+)/\", token: \"regex\"},\n                {regex: \"\", onMatch: function(val, state, stack) {\n                    stack.inFormatString = true;\n                }, next: \"start\"}\n            ]\n        });\n        SnippetManager.prototype.getTokenizer = function() {\n            return SnippetManager.$tokenizer;\n        };\n        return SnippetManager.$tokenizer;\n    };\n\n    this.tokenizeTmSnippet = function(str, startState) {\n        return this.getTokenizer().getLineTokens(str, startState).tokens.map(function(x) {\n            return x.value || x;\n        });\n    };\n\n    this.$getDefaultValue = function(editor, name) {\n        if (/^[A-Z]\\d+$/.test(name)) {\n            var i = name.substr(1);\n            return (this.variables[name[0] + \"__\"] || {})[i];\n        }\n        if (/^\\d+$/.test(name)) {\n            return (this.variables.__ || {})[name];\n        }\n        name = name.replace(/^TM_/, \"\");\n\n        if (!editor)\n            return;\n        var s = editor.session;\n        switch(name) {\n            case \"CURRENT_WORD\":\n                var r = s.getWordRange();\n            case \"SELECTION\":\n            case \"SELECTED_TEXT\":\n                return s.getTextRange(r);\n            case \"CURRENT_LINE\":\n                return s.getLine(editor.getCursorPosition().row);\n            case \"PREV_LINE\": // not possible in textmate\n                return s.getLine(editor.getCursorPosition().row - 1);\n            case \"LINE_INDEX\":\n                return editor.getCursorPosition().column;\n            case \"LINE_NUMBER\":\n                return editor.getCursorPosition().row + 1;\n            case \"SOFT_TABS\":\n                return s.getUseSoftTabs() ? \"YES\" : \"NO\";\n            case \"TAB_SIZE\":\n                return s.getTabSize();\n            case \"FILENAME\":\n            case \"FILEPATH\":\n                return \"\";\n            case \"FULLNAME\":\n                return \"Ace\";\n        }\n    };\n    this.variables = {};\n    this.getVariableValue = function(editor, varName) {\n        if (this.variables.hasOwnProperty(varName))\n            return this.variables[varName](editor, varName) || \"\";\n        return this.$getDefaultValue(editor, varName) || \"\";\n    };\n    this.tmStrFormat = function(str, ch, editor) {\n        var flag = ch.flag || \"\";\n        var re = ch.guard;\n        re = new RegExp(re, flag.replace(/[^gi]/, \"\"));\n        var fmtTokens = this.tokenizeTmSnippet(ch.fmt, \"formatString\");\n        var _self = this;\n        var formatted = str.replace(re, function() {\n            _self.variables.__ = arguments;\n            var fmtParts = _self.resolveVariables(fmtTokens, editor);\n            var gChangeCase = \"E\";\n            for (var i  = 0; i < fmtParts.length; i++) {\n                var ch = fmtParts[i];\n                if (typeof ch == \"object\") {\n                    fmtParts[i] = \"\";\n                    if (ch.changeCase && ch.local) {\n                        var next = fmtParts[i + 1];\n                        if (next && typeof next == \"string\") {\n                            if (ch.changeCase == \"u\")\n                                fmtParts[i] = next[0].toUpperCase();\n                            else\n                                fmtParts[i] = next[0].toLowerCase();\n                            fmtParts[i + 1] = next.substr(1);\n                        }\n                    } else if (ch.changeCase) {\n                        gChangeCase = ch.changeCase;\n                    }\n                } else if (gChangeCase == \"U\") {\n                    fmtParts[i] = ch.toUpperCase();\n                } else if (gChangeCase == \"L\") {\n                    fmtParts[i] = ch.toLowerCase();\n                }\n            }\n            return fmtParts.join(\"\");\n        });\n        this.variables.__ = null;\n        return formatted;\n    };\n\n    this.resolveVariables = function(snippet, editor) {\n        var result = [];\n        for (var i = 0; i < snippet.length; i++) {\n            var ch = snippet[i];\n            if (typeof ch == \"string\") {\n                result.push(ch);\n            } else if (typeof ch != \"object\") {\n                continue;\n            } else if (ch.skip) {\n                gotoNext(ch);\n            } else if (ch.processed < i) {\n                continue;\n            } else if (ch.text) {\n                var value = this.getVariableValue(editor, ch.text);\n                if (value && ch.fmtString)\n                    value = this.tmStrFormat(value, ch);\n                ch.processed = i;\n                if (ch.expectIf == null) {\n                    if (value) {\n                        result.push(value);\n                        gotoNext(ch);\n                    }\n                } else {\n                    if (value) {\n                        ch.skip = ch.elseBranch;\n                    } else\n                        gotoNext(ch);\n                }\n            } else if (ch.tabstopId != null) {\n                result.push(ch);\n            } else if (ch.changeCase != null) {\n                result.push(ch);\n            }\n        }\n        function gotoNext(ch) {\n            var i1 = snippet.indexOf(ch, i + 1);\n            if (i1 != -1)\n                i = i1;\n        }\n        return result;\n    };\n\n    this.insertSnippetForSelection = function(editor, snippetText) {\n        var cursor = editor.getCursorPosition();\n        var line = editor.session.getLine(cursor.row);\n        var tabString = editor.session.getTabString();\n        var indentString = line.match(/^\\s*/)[0];\n        \n        if (cursor.column < indentString.length)\n            indentString = indentString.slice(0, cursor.column);\n\n        snippetText = snippetText.replace(/\\r/g, \"\");\n        var tokens = this.tokenizeTmSnippet(snippetText);\n        tokens = this.resolveVariables(tokens, editor);\n        tokens = tokens.map(function(x) {\n            if (x == \"\\n\")\n                return x + indentString;\n            if (typeof x == \"string\")\n                return x.replace(/\\t/g, tabString);\n            return x;\n        });\n        var tabstops = [];\n        tokens.forEach(function(p, i) {\n            if (typeof p != \"object\")\n                return;\n            var id = p.tabstopId;\n            var ts = tabstops[id];\n            if (!ts) {\n                ts = tabstops[id] = [];\n                ts.index = id;\n                ts.value = \"\";\n            }\n            if (ts.indexOf(p) !== -1)\n                return;\n            ts.push(p);\n            var i1 = tokens.indexOf(p, i + 1);\n            if (i1 === -1)\n                return;\n\n            var value = tokens.slice(i + 1, i1);\n            var isNested = value.some(function(t) {return typeof t === \"object\"});          \n            if (isNested && !ts.value) {\n                ts.value = value;\n            } else if (value.length && (!ts.value || typeof ts.value !== \"string\")) {\n                ts.value = value.join(\"\");\n            }\n        });\n        tabstops.forEach(function(ts) {ts.length = 0});\n        var expanding = {};\n        function copyValue(val) {\n            var copy = [];\n            for (var i = 0; i < val.length; i++) {\n                var p = val[i];\n                if (typeof p == \"object\") {\n                    if (expanding[p.tabstopId])\n                        continue;\n                    var j = val.lastIndexOf(p, i - 1);\n                    p = copy[j] || {tabstopId: p.tabstopId};\n                }\n                copy[i] = p;\n            }\n            return copy;\n        }\n        for (var i = 0; i < tokens.length; i++) {\n            var p = tokens[i];\n            if (typeof p != \"object\")\n                continue;\n            var id = p.tabstopId;\n            var i1 = tokens.indexOf(p, i + 1);\n            if (expanding[id]) {\n                if (expanding[id] === p)\n                    expanding[id] = null;\n                continue;\n            }\n            \n            var ts = tabstops[id];\n            var arg = typeof ts.value == \"string\" ? [ts.value] : copyValue(ts.value);\n            arg.unshift(i + 1, Math.max(0, i1 - i));\n            arg.push(p);\n            expanding[id] = p;\n            tokens.splice.apply(tokens, arg);\n\n            if (ts.indexOf(p) === -1)\n                ts.push(p);\n        }\n        var row = 0, column = 0;\n        var text = \"\";\n        tokens.forEach(function(t) {\n            if (typeof t === \"string\") {\n                var lines = t.split(\"\\n\");\n                if (lines.length > 1){\n                    column = lines[lines.length - 1].length;\n                    row += lines.length - 1;\n                } else\n                    column += t.length;\n                text += t;\n            } else {\n                if (!t.start)\n                    t.start = {row: row, column: column};\n                else\n                    t.end = {row: row, column: column};\n            }\n        });\n        var range = editor.getSelectionRange();\n        var end = editor.session.replace(range, text);\n\n        var tabstopManager = new TabstopManager(editor);\n        var selectionId = editor.inVirtualSelectionMode && editor.selection.index;\n        tabstopManager.addTabstops(tabstops, range.start, end, selectionId);\n    };\n    \n    this.insertSnippet = function(editor, snippetText) {\n        var self = this;\n        if (editor.inVirtualSelectionMode)\n            return self.insertSnippetForSelection(editor, snippetText);\n        \n        editor.forEachSelection(function() {\n            self.insertSnippetForSelection(editor, snippetText);\n        }, null, {keepOrder: true});\n        \n        if (editor.tabstopManager)\n            editor.tabstopManager.tabNext();\n    };\n\n    this.$getScope = function(editor) {\n        var scope = editor.session.$mode.$id || \"\";\n        scope = scope.split(\"/\").pop();\n        if (scope === \"html\" || scope === \"php\") {\n            if (scope === \"php\" && !editor.session.$mode.inlinePhp) \n                scope = \"html\";\n            var c = editor.getCursorPosition();\n            var state = editor.session.getState(c.row);\n            if (typeof state === \"object\") {\n                state = state[0];\n            }\n            if (state.substring) {\n                if (state.substring(0, 3) == \"js-\")\n                    scope = \"javascript\";\n                else if (state.substring(0, 4) == \"css-\")\n                    scope = \"css\";\n                else if (state.substring(0, 4) == \"php-\")\n                    scope = \"php\";\n            }\n        }\n        \n        return scope;\n    };\n\n    this.getActiveScopes = function(editor) {\n        var scope = this.$getScope(editor);\n        var scopes = [scope];\n        var snippetMap = this.snippetMap;\n        if (snippetMap[scope] && snippetMap[scope].includeScopes) {\n            scopes.push.apply(scopes, snippetMap[scope].includeScopes);\n        }\n        scopes.push(\"_\");\n        return scopes;\n    };\n\n    this.expandWithTab = function(editor, options) {\n        var self = this;\n        var result = editor.forEachSelection(function() {\n            return self.expandSnippetForSelection(editor, options);\n        }, null, {keepOrder: true});\n        if (result && editor.tabstopManager)\n            editor.tabstopManager.tabNext();\n        return result;\n    };\n    \n    this.expandSnippetForSelection = function(editor, options) {\n        var cursor = editor.getCursorPosition();\n        var line = editor.session.getLine(cursor.row);\n        var before = line.substring(0, cursor.column);\n        var after = line.substr(cursor.column);\n\n        var snippetMap = this.snippetMap;\n        var snippet;\n        this.getActiveScopes(editor).some(function(scope) {\n            var snippets = snippetMap[scope];\n            if (snippets)\n                snippet = this.findMatchingSnippet(snippets, before, after);\n            return !!snippet;\n        }, this);\n        if (!snippet)\n            return false;\n        if (options && options.dryRun)\n            return true;\n        editor.session.doc.removeInLine(cursor.row,\n            cursor.column - snippet.replaceBefore.length,\n            cursor.column + snippet.replaceAfter.length\n        );\n\n        this.variables.M__ = snippet.matchBefore;\n        this.variables.T__ = snippet.matchAfter;\n        this.insertSnippetForSelection(editor, snippet.content);\n\n        this.variables.M__ = this.variables.T__ = null;\n        return true;\n    };\n\n    this.findMatchingSnippet = function(snippetList, before, after) {\n        for (var i = snippetList.length; i--;) {\n            var s = snippetList[i];\n            if (s.startRe && !s.startRe.test(before))\n                continue;\n            if (s.endRe && !s.endRe.test(after))\n                continue;\n            if (!s.startRe && !s.endRe)\n                continue;\n\n            s.matchBefore = s.startRe ? s.startRe.exec(before) : [\"\"];\n            s.matchAfter = s.endRe ? s.endRe.exec(after) : [\"\"];\n            s.replaceBefore = s.triggerRe ? s.triggerRe.exec(before)[0] : \"\";\n            s.replaceAfter = s.endTriggerRe ? s.endTriggerRe.exec(after)[0] : \"\";\n            return s;\n        }\n    };\n\n    this.snippetMap = {};\n    this.snippetNameMap = {};\n    this.register = function(snippets, scope) {\n        var snippetMap = this.snippetMap;\n        var snippetNameMap = this.snippetNameMap;\n        var self = this;\n        \n        if (!snippets) \n            snippets = [];\n        \n        function wrapRegexp(src) {\n            if (src && !/^\\^?\\(.*\\)\\$?$|^\\\\b$/.test(src))\n                src = \"(?:\" + src + \")\";\n\n            return src || \"\";\n        }\n        function guardedRegexp(re, guard, opening) {\n            re = wrapRegexp(re);\n            guard = wrapRegexp(guard);\n            if (opening) {\n                re = guard + re;\n                if (re && re[re.length - 1] != \"$\")\n                    re = re + \"$\";\n            } else {\n                re = re + guard;\n                if (re && re[0] != \"^\")\n                    re = \"^\" + re;\n            }\n            return new RegExp(re);\n        }\n\n        function addSnippet(s) {\n            if (!s.scope)\n                s.scope = scope || \"_\";\n            scope = s.scope;\n            if (!snippetMap[scope]) {\n                snippetMap[scope] = [];\n                snippetNameMap[scope] = {};\n            }\n\n            var map = snippetNameMap[scope];\n            if (s.name) {\n                var old = map[s.name];\n                if (old)\n                    self.unregister(old);\n                map[s.name] = s;\n            }\n            snippetMap[scope].push(s);\n\n            if (s.tabTrigger && !s.trigger) {\n                if (!s.guard && /^\\w/.test(s.tabTrigger))\n                    s.guard = \"\\\\b\";\n                s.trigger = lang.escapeRegExp(s.tabTrigger);\n            }\n            \n            if (!s.trigger && !s.guard && !s.endTrigger && !s.endGuard)\n                return;\n            \n            s.startRe = guardedRegexp(s.trigger, s.guard, true);\n            s.triggerRe = new RegExp(s.trigger, \"\", true);\n\n            s.endRe = guardedRegexp(s.endTrigger, s.endGuard, true);\n            s.endTriggerRe = new RegExp(s.endTrigger, \"\", true);\n        }\n\n        if (snippets && snippets.content)\n            addSnippet(snippets);\n        else if (Array.isArray(snippets))\n            snippets.forEach(addSnippet);\n        \n        this._signal(\"registerSnippets\", {scope: scope});\n    };\n    this.unregister = function(snippets, scope) {\n        var snippetMap = this.snippetMap;\n        var snippetNameMap = this.snippetNameMap;\n\n        function removeSnippet(s) {\n            var nameMap = snippetNameMap[s.scope||scope];\n            if (nameMap && nameMap[s.name]) {\n                delete nameMap[s.name];\n                var map = snippetMap[s.scope||scope];\n                var i = map && map.indexOf(s);\n                if (i >= 0)\n                    map.splice(i, 1);\n            }\n        }\n        if (snippets.content)\n            removeSnippet(snippets);\n        else if (Array.isArray(snippets))\n            snippets.forEach(removeSnippet);\n    };\n    this.parseSnippetFile = function(str) {\n        str = str.replace(/\\r/g, \"\");\n        var list = [], snippet = {};\n        var re = /^#.*|^({[\\s\\S]*})\\s*$|^(\\S+) (.*)$|^((?:\\n*\\t.*)+)/gm;\n        var m;\n        while (m = re.exec(str)) {\n            if (m[1]) {\n                try {\n                    snippet = JSON.parse(m[1]);\n                    list.push(snippet);\n                } catch (e) {}\n            } if (m[4]) {\n                snippet.content = m[4].replace(/^\\t/gm, \"\");\n                list.push(snippet);\n                snippet = {};\n            } else {\n                var key = m[2], val = m[3];\n                if (key == \"regex\") {\n                    var guardRe = /\\/((?:[^\\/\\\\]|\\\\.)*)|$/g;\n                    snippet.guard = guardRe.exec(val)[1];\n                    snippet.trigger = guardRe.exec(val)[1];\n                    snippet.endTrigger = guardRe.exec(val)[1];\n                    snippet.endGuard = guardRe.exec(val)[1];\n                } else if (key == \"snippet\") {\n                    snippet.tabTrigger = val.match(/^\\S*/)[0];\n                    if (!snippet.name)\n                        snippet.name = val;\n                } else {\n                    snippet[key] = val;\n                }\n            }\n        }\n        return list;\n    };\n    this.getSnippetByName = function(name, editor) {\n        var snippetMap = this.snippetNameMap;\n        var snippet;\n        this.getActiveScopes(editor).some(function(scope) {\n            var snippets = snippetMap[scope];\n            if (snippets)\n                snippet = snippets[name];\n            return !!snippet;\n        }, this);\n        return snippet;\n    };\n\n}).call(SnippetManager.prototype);\n\n\nvar TabstopManager = function(editor) {\n    if (editor.tabstopManager)\n        return editor.tabstopManager;\n    editor.tabstopManager = this;\n    this.$onChange = this.onChange.bind(this);\n    this.$onChangeSelection = lang.delayedCall(this.onChangeSelection.bind(this)).schedule;\n    this.$onChangeSession = this.onChangeSession.bind(this);\n    this.$onAfterExec = this.onAfterExec.bind(this);\n    this.attach(editor);\n};\n(function() {\n    this.attach = function(editor) {\n        this.index = 0;\n        this.ranges = [];\n        this.tabstops = [];\n        this.$openTabstops = null;\n        this.selectedTabstop = null;\n\n        this.editor = editor;\n        this.editor.on(\"change\", this.$onChange);\n        this.editor.on(\"changeSelection\", this.$onChangeSelection);\n        this.editor.on(\"changeSession\", this.$onChangeSession);\n        this.editor.commands.on(\"afterExec\", this.$onAfterExec);\n        this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler);\n    };\n    this.detach = function() {\n        this.tabstops.forEach(this.removeTabstopMarkers, this);\n        this.ranges = null;\n        this.tabstops = null;\n        this.selectedTabstop = null;\n        this.editor.removeListener(\"change\", this.$onChange);\n        this.editor.removeListener(\"changeSelection\", this.$onChangeSelection);\n        this.editor.removeListener(\"changeSession\", this.$onChangeSession);\n        this.editor.commands.removeListener(\"afterExec\", this.$onAfterExec);\n        this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler);\n        this.editor.tabstopManager = null;\n        this.editor = null;\n    };\n\n    this.onChange = function(delta) {\n        var changeRange = delta;\n        var isRemove = delta.action[0] == \"r\";\n        var start = delta.start;\n        var end = delta.end;\n        var startRow = start.row;\n        var endRow = end.row;\n        var lineDif = endRow - startRow;\n        var colDiff = end.column - start.column;\n\n        if (isRemove) {\n            lineDif = -lineDif;\n            colDiff = -colDiff;\n        }\n        if (!this.$inChange && isRemove) {\n            var ts = this.selectedTabstop;\n            var changedOutside = ts && !ts.some(function(r) {\n                return comparePoints(r.start, start) <= 0 && comparePoints(r.end, end) >= 0;\n            });\n            if (changedOutside)\n                return this.detach();\n        }\n        var ranges = this.ranges;\n        for (var i = 0; i < ranges.length; i++) {\n            var r = ranges[i];\n            if (r.end.row < start.row)\n                continue;\n\n            if (isRemove && comparePoints(start, r.start) < 0 && comparePoints(end, r.end) > 0) {\n                this.removeRange(r);\n                i--;\n                continue;\n            }\n\n            if (r.start.row == startRow && r.start.column > start.column)\n                r.start.column += colDiff;\n            if (r.end.row == startRow && r.end.column >= start.column)\n                r.end.column += colDiff;\n            if (r.start.row >= startRow)\n                r.start.row += lineDif;\n            if (r.end.row >= startRow)\n                r.end.row += lineDif;\n\n            if (comparePoints(r.start, r.end) > 0)\n                this.removeRange(r);\n        }\n        if (!ranges.length)\n            this.detach();\n    };\n    this.updateLinkedFields = function() {\n        var ts = this.selectedTabstop;\n        if (!ts || !ts.hasLinkedRanges)\n            return;\n        this.$inChange = true;\n        var session = this.editor.session;\n        var text = session.getTextRange(ts.firstNonLinked);\n        for (var i = ts.length; i--;) {\n            var range = ts[i];\n            if (!range.linked)\n                continue;\n            var fmt = exports.snippetManager.tmStrFormat(text, range.original);\n            session.replace(range, fmt);\n        }\n        this.$inChange = false;\n    };\n    this.onAfterExec = function(e) {\n        if (e.command && !e.command.readOnly)\n            this.updateLinkedFields();\n    };\n    this.onChangeSelection = function() {\n        if (!this.editor)\n            return;\n        var lead = this.editor.selection.lead;\n        var anchor = this.editor.selection.anchor;\n        var isEmpty = this.editor.selection.isEmpty();\n        for (var i = this.ranges.length; i--;) {\n            if (this.ranges[i].linked)\n                continue;\n            var containsLead = this.ranges[i].contains(lead.row, lead.column);\n            var containsAnchor = isEmpty || this.ranges[i].contains(anchor.row, anchor.column);\n            if (containsLead && containsAnchor)\n                return;\n        }\n        this.detach();\n    };\n    this.onChangeSession = function() {\n        this.detach();\n    };\n    this.tabNext = function(dir) {\n        var max = this.tabstops.length;\n        var index = this.index + (dir || 1);\n        index = Math.min(Math.max(index, 1), max);\n        if (index == max)\n            index = 0;\n        this.selectTabstop(index);\n        if (index === 0)\n            this.detach();\n    };\n    this.selectTabstop = function(index) {\n        this.$openTabstops = null;\n        var ts = this.tabstops[this.index];\n        if (ts)\n            this.addTabstopMarkers(ts);\n        this.index = index;\n        ts = this.tabstops[this.index];\n        if (!ts || !ts.length)\n            return;\n        \n        this.selectedTabstop = ts;\n        if (!this.editor.inVirtualSelectionMode) {        \n            var sel = this.editor.multiSelect;\n            sel.toSingleRange(ts.firstNonLinked.clone());\n            for (var i = ts.length; i--;) {\n                if (ts.hasLinkedRanges && ts[i].linked)\n                    continue;\n                sel.addRange(ts[i].clone(), true);\n            }\n            if (sel.ranges[0])\n                sel.addRange(sel.ranges[0].clone());\n        } else {\n            this.editor.selection.setRange(ts.firstNonLinked);\n        }\n        \n        this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler);\n    };\n    this.addTabstops = function(tabstops, start, end) {\n        if (!this.$openTabstops)\n            this.$openTabstops = [];\n        if (!tabstops[0]) {\n            var p = Range.fromPoints(end, end);\n            moveRelative(p.start, start);\n            moveRelative(p.end, start);\n            tabstops[0] = [p];\n            tabstops[0].index = 0;\n        }\n\n        var i = this.index;\n        var arg = [i + 1, 0];\n        var ranges = this.ranges;\n        tabstops.forEach(function(ts, index) {\n            var dest = this.$openTabstops[index] || ts;\n                \n            for (var i = ts.length; i--;) {\n                var p = ts[i];\n                var range = Range.fromPoints(p.start, p.end || p.start);\n                movePoint(range.start, start);\n                movePoint(range.end, start);\n                range.original = p;\n                range.tabstop = dest;\n                ranges.push(range);\n                if (dest != ts)\n                    dest.unshift(range);\n                else\n                    dest[i] = range;\n                if (p.fmtString) {\n                    range.linked = true;\n                    dest.hasLinkedRanges = true;\n                } else if (!dest.firstNonLinked)\n                    dest.firstNonLinked = range;\n            }\n            if (!dest.firstNonLinked)\n                dest.hasLinkedRanges = false;\n            if (dest === ts) {\n                arg.push(dest);\n                this.$openTabstops[index] = dest;\n            }\n            this.addTabstopMarkers(dest);\n        }, this);\n        \n        if (arg.length > 2) {\n            if (this.tabstops.length)\n                arg.push(arg.splice(2, 1)[0]);\n            this.tabstops.splice.apply(this.tabstops, arg);\n        }\n    };\n\n    this.addTabstopMarkers = function(ts) {\n        var session = this.editor.session;\n        ts.forEach(function(range) {\n            if  (!range.markerId)\n                range.markerId = session.addMarker(range, \"ace_snippet-marker\", \"text\");\n        });\n    };\n    this.removeTabstopMarkers = function(ts) {\n        var session = this.editor.session;\n        ts.forEach(function(range) {\n            session.removeMarker(range.markerId);\n            range.markerId = null;\n        });\n    };\n    this.removeRange = function(range) {\n        var i = range.tabstop.indexOf(range);\n        range.tabstop.splice(i, 1);\n        i = this.ranges.indexOf(range);\n        this.ranges.splice(i, 1);\n        this.editor.session.removeMarker(range.markerId);\n        if (!range.tabstop.length) {\n            i = this.tabstops.indexOf(range.tabstop);\n            if (i != -1)\n                this.tabstops.splice(i, 1);\n            if (!this.tabstops.length)\n                this.detach();\n        }\n    };\n\n    this.keyboardHandler = new HashHandler();\n    this.keyboardHandler.bindKeys({\n        \"Tab\": function(ed) {\n            if (exports.snippetManager && exports.snippetManager.expandWithTab(ed)) {\n                return;\n            }\n\n            ed.tabstopManager.tabNext(1);\n        },\n        \"Shift-Tab\": function(ed) {\n            ed.tabstopManager.tabNext(-1);\n        },\n        \"Esc\": function(ed) {\n            ed.tabstopManager.detach();\n        },\n        \"Return\": function(ed) {\n            return false;\n        }\n    });\n}).call(TabstopManager.prototype);\n\n\n\nvar changeTracker = {};\nchangeTracker.onChange = Anchor.prototype.onChange;\nchangeTracker.setPosition = function(row, column) {\n    this.pos.row = row;\n    this.pos.column = column;\n};\nchangeTracker.update = function(pos, delta, $insertRight) {\n    this.$insertRight = $insertRight;\n    this.pos = pos; \n    this.onChange(delta);\n};\n\nvar movePoint = function(point, diff) {\n    if (point.row == 0)\n        point.column += diff.column;\n    point.row += diff.row;\n};\n\nvar moveRelative = function(point, start) {\n    if (point.row == start.row)\n        point.column -= start.column;\n    point.row -= start.row;\n};\n\n\nrequire(\"./lib/dom\").importCssString(\"\\\n.ace_snippet-marker {\\\n    -moz-box-sizing: border-box;\\\n    box-sizing: border-box;\\\n    background: rgba(194, 193, 208, 0.09);\\\n    border: 1px dotted rgba(211, 208, 235, 0.62);\\\n    position: absolute;\\\n}\");\n\nexports.snippetManager = new SnippetManager();\n\n\nvar Editor = require(\"./editor\").Editor;\n(function() {\n    this.insertSnippet = function(content, options) {\n        return exports.snippetManager.insertSnippet(this, content, options);\n    };\n    this.expandSnippet = function(options) {\n        return exports.snippetManager.expandWithTab(this, options);\n    };\n}).call(Editor.prototype);\n\n});\n\nace.define(\"ace/autocomplete/popup\",[\"require\",\"exports\",\"module\",\"ace/virtual_renderer\",\"ace/editor\",\"ace/range\",\"ace/lib/event\",\"ace/lib/lang\",\"ace/lib/dom\"], function(require, exports, module) {\n\"use strict\";\n\nvar Renderer = require(\"../virtual_renderer\").VirtualRenderer;\nvar Editor = require(\"../editor\").Editor;\nvar Range = require(\"../range\").Range;\nvar event = require(\"../lib/event\");\nvar lang = require(\"../lib/lang\");\nvar dom = require(\"../lib/dom\");\n\nvar $singleLineEditor = function(el) {\n    var renderer = new Renderer(el);\n\n    renderer.$maxLines = 4;\n\n    var editor = new Editor(renderer);\n\n    editor.setHighlightActiveLine(false);\n    editor.setShowPrintMargin(false);\n    editor.renderer.setShowGutter(false);\n    editor.renderer.setHighlightGutterLine(false);\n\n    editor.$mouseHandler.$focusWaitTimout = 0;\n    editor.$highlightTagPending = true;\n\n    return editor;\n};\n\nvar AcePopup = function(parentNode) {\n    var el = dom.createElement(\"div\");\n    var popup = new $singleLineEditor(el);\n\n    if (parentNode)\n        parentNode.appendChild(el);\n    el.style.display = \"none\";\n    popup.renderer.content.style.cursor = \"default\";\n    popup.renderer.setStyle(\"ace_autocomplete\");\n\n    popup.setOption(\"displayIndentGuides\", false);\n    popup.setOption(\"dragDelay\", 150);\n\n    var noop = function(){};\n\n    popup.focus = noop;\n    popup.$isFocused = true;\n\n    popup.renderer.$cursorLayer.restartTimer = noop;\n    popup.renderer.$cursorLayer.element.style.opacity = 0;\n\n    popup.renderer.$maxLines = 8;\n    popup.renderer.$keepTextAreaAtCursor = false;\n\n    popup.setHighlightActiveLine(false);\n    popup.session.highlight(\"\");\n    popup.session.$searchHighlight.clazz = \"ace_highlight-marker\";\n\n    popup.on(\"mousedown\", function(e) {\n        var pos = e.getDocumentPosition();\n        popup.selection.moveToPosition(pos);\n        selectionMarker.start.row = selectionMarker.end.row = pos.row;\n        e.stop();\n    });\n\n    var lastMouseEvent;\n    var hoverMarker = new Range(-1,0,-1,Infinity);\n    var selectionMarker = new Range(-1,0,-1,Infinity);\n    selectionMarker.id = popup.session.addMarker(selectionMarker, \"ace_active-line\", \"fullLine\");\n    popup.setSelectOnHover = function(val) {\n        if (!val) {\n            hoverMarker.id = popup.session.addMarker(hoverMarker, \"ace_line-hover\", \"fullLine\");\n        } else if (hoverMarker.id) {\n            popup.session.removeMarker(hoverMarker.id);\n            hoverMarker.id = null;\n        }\n    };\n    popup.setSelectOnHover(false);\n    popup.on(\"mousemove\", function(e) {\n        if (!lastMouseEvent) {\n            lastMouseEvent = e;\n            return;\n        }\n        if (lastMouseEvent.x == e.x && lastMouseEvent.y == e.y) {\n            return;\n        }\n        lastMouseEvent = e;\n        lastMouseEvent.scrollTop = popup.renderer.scrollTop;\n        var row = lastMouseEvent.getDocumentPosition().row;\n        if (hoverMarker.start.row != row) {\n            if (!hoverMarker.id)\n                popup.setRow(row);\n            setHoverMarker(row);\n        }\n    });\n    popup.renderer.on(\"beforeRender\", function() {\n        if (lastMouseEvent && hoverMarker.start.row != -1) {\n            lastMouseEvent.$pos = null;\n            var row = lastMouseEvent.getDocumentPosition().row;\n            if (!hoverMarker.id)\n                popup.setRow(row);\n            setHoverMarker(row, true);\n        }\n    });\n    popup.renderer.on(\"afterRender\", function() {\n        var row = popup.getRow();\n        var t = popup.renderer.$textLayer;\n        var selected = t.element.childNodes[row - t.config.firstRow];\n        if (selected == t.selectedNode)\n            return;\n        if (t.selectedNode)\n            dom.removeCssClass(t.selectedNode, \"ace_selected\");\n        t.selectedNode = selected;\n        if (selected)\n            dom.addCssClass(selected, \"ace_selected\");\n    });\n    var hideHoverMarker = function() { setHoverMarker(-1) };\n    var setHoverMarker = function(row, suppressRedraw) {\n        if (row !== hoverMarker.start.row) {\n            hoverMarker.start.row = hoverMarker.end.row = row;\n            if (!suppressRedraw)\n                popup.session._emit(\"changeBackMarker\");\n            popup._emit(\"changeHoverMarker\");\n        }\n    };\n    popup.getHoveredRow = function() {\n        return hoverMarker.start.row;\n    };\n\n    event.addListener(popup.container, \"mouseout\", hideHoverMarker);\n    popup.on(\"hide\", hideHoverMarker);\n    popup.on(\"changeSelection\", hideHoverMarker);\n\n    popup.session.doc.getLength = function() {\n        return popup.data.length;\n    };\n    popup.session.doc.getLine = function(i) {\n        var data = popup.data[i];\n        if (typeof data == \"string\")\n            return data;\n        return (data && data.value) || \"\";\n    };\n\n    var bgTokenizer = popup.session.bgTokenizer;\n    bgTokenizer.$tokenizeRow = function(row) {\n        var data = popup.data[row];\n        var tokens = [];\n        if (!data)\n            return tokens;\n        if (typeof data == \"string\")\n            data = {value: data};\n        if (!data.caption)\n            data.caption = data.value || data.name;\n\n        var last = -1;\n        var flag, c;\n        for (var i = 0; i < data.caption.length; i++) {\n            c = data.caption[i];\n            flag = data.matchMask & (1 << i) ? 1 : 0;\n            if (last !== flag) {\n                tokens.push({type: data.className || \"\" + ( flag ? \"completion-highlight\" : \"\"), value: c});\n                last = flag;\n            } else {\n                tokens[tokens.length - 1].value += c;\n            }\n        }\n\n        if (data.meta) {\n            var maxW = popup.renderer.$size.scrollerWidth / popup.renderer.layerConfig.characterWidth;\n            var metaData = data.meta;\n            if (metaData.length + data.caption.length > maxW - 2) {\n                metaData = metaData.substr(0, maxW - data.caption.length - 3) + \"\\u2026\"\n            }\n            tokens.push({type: \"rightAlignedText\", value: metaData});\n        }\n        return tokens;\n    };\n    bgTokenizer.$updateOnChange = noop;\n    bgTokenizer.start = noop;\n\n    popup.session.$computeWidth = function() {\n        return this.screenWidth = 0;\n    };\n\n    popup.$blockScrolling = Infinity;\n    popup.isOpen = false;\n    popup.isTopdown = false;\n    popup.autoSelect = true;\n\n    popup.data = [];\n    popup.setData = function(list) {\n        popup.setValue(lang.stringRepeat(\"\\n\", list.length), -1);\n        popup.data = list || [];\n        popup.setRow(0);\n    };\n    popup.getData = function(row) {\n        return popup.data[row];\n    };\n\n    popup.getRow = function() {\n        return selectionMarker.start.row;\n    };\n    popup.setRow = function(line) {\n        line = Math.max(this.autoSelect ? 0 : -1, Math.min(this.data.length, line));\n        if (selectionMarker.start.row != line) {\n            popup.selection.clearSelection();\n            selectionMarker.start.row = selectionMarker.end.row = line || 0;\n            popup.session._emit(\"changeBackMarker\");\n            popup.moveCursorTo(line || 0, 0);\n            if (popup.isOpen)\n                popup._signal(\"select\");\n        }\n    };\n\n    popup.on(\"changeSelection\", function() {\n        if (popup.isOpen)\n            popup.setRow(popup.selection.lead.row);\n        popup.renderer.scrollCursorIntoView();\n    });\n\n    popup.hide = function() {\n        this.container.style.display = \"none\";\n        this._signal(\"hide\");\n        popup.isOpen = false;\n    };\n    popup.show = function(pos, lineHeight, topdownOnly) {\n        var el = this.container;\n        var screenHeight = window.innerHeight;\n        var screenWidth = window.innerWidth;\n        var renderer = this.renderer;\n        var maxH = renderer.$maxLines * lineHeight * 1.4;\n        var top = pos.top + this.$borderSize;\n        var allowTopdown = top > screenHeight / 2 && !topdownOnly;\n        if (allowTopdown && top + lineHeight + maxH > screenHeight) {\n            renderer.$maxPixelHeight = top - 2 * this.$borderSize;\n            el.style.top = \"\";\n            el.style.bottom = screenHeight - top + \"px\";\n            popup.isTopdown = false;\n        } else {\n            top += lineHeight;\n            renderer.$maxPixelHeight = screenHeight - top - 0.2 * lineHeight;\n            el.style.top = top + \"px\";\n            el.style.bottom = \"\";\n            popup.isTopdown = true;\n        }\n\n        el.style.display = \"\";\n        this.renderer.$textLayer.checkForSizeChanges();\n\n        var left = pos.left;\n        if (left + el.offsetWidth > screenWidth)\n            left = screenWidth - el.offsetWidth;\n\n        el.style.left = left + \"px\";\n\n        this._signal(\"show\");\n        lastMouseEvent = null;\n        popup.isOpen = true;\n    };\n\n    popup.getTextLeftOffset = function() {\n        return this.$borderSize + this.renderer.$padding + this.$imageSize;\n    };\n\n    popup.$imageSize = 0;\n    popup.$borderSize = 1;\n\n    return popup;\n};\n\ndom.importCssString(\"\\\n.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line {\\\n    background-color: #CAD6FA;\\\n    z-index: 1;\\\n}\\\n.ace_editor.ace_autocomplete .ace_line-hover {\\\n    border: 1px solid #abbffe;\\\n    margin-top: -1px;\\\n    background: rgba(233,233,253,0.4);\\\n}\\\n.ace_editor.ace_autocomplete .ace_line-hover {\\\n    position: absolute;\\\n    z-index: 2;\\\n}\\\n.ace_editor.ace_autocomplete .ace_scroller {\\\n   background: none;\\\n   border: none;\\\n   box-shadow: none;\\\n}\\\n.ace_rightAlignedText {\\\n    color: gray;\\\n    display: inline-block;\\\n    position: absolute;\\\n    right: 4px;\\\n    text-align: right;\\\n    z-index: -1;\\\n}\\\n.ace_editor.ace_autocomplete .ace_completion-highlight{\\\n    color: #000;\\\n    text-shadow: 0 0 0.01em;\\\n}\\\n.ace_editor.ace_autocomplete {\\\n    width: 280px;\\\n    z-index: 200000;\\\n    background: #fbfbfb;\\\n    color: #444;\\\n    border: 1px lightgray solid;\\\n    position: fixed;\\\n    box-shadow: 2px 3px 5px rgba(0,0,0,.2);\\\n    line-height: 1.4;\\\n}\");\n\nexports.AcePopup = AcePopup;\n\n});\n\nace.define(\"ace/autocomplete/util\",[\"require\",\"exports\",\"module\"], function(require, exports, module) {\n\"use strict\";\n\nexports.parForEach = function(array, fn, callback) {\n    var completed = 0;\n    var arLength = array.length;\n    if (arLength === 0)\n        callback();\n    for (var i = 0; i < arLength; i++) {\n        fn(array[i], function(result, err) {\n            completed++;\n            if (completed === arLength)\n                callback(result, err);\n        });\n    }\n};\n\nvar ID_REGEX = /[a-zA-Z_0-9\\$\\-\\u00A2-\\uFFFF]/;\n\nexports.retrievePrecedingIdentifier = function(text, pos, regex) {\n    regex = regex || ID_REGEX;\n    var buf = [];\n    for (var i = pos-1; i >= 0; i--) {\n        if (regex.test(text[i]))\n            buf.push(text[i]);\n        else\n            break;\n    }\n    return buf.reverse().join(\"\");\n};\n\nexports.retrieveFollowingIdentifier = function(text, pos, regex) {\n    regex = regex || ID_REGEX;\n    var buf = [];\n    for (var i = pos; i < text.length; i++) {\n        if (regex.test(text[i]))\n            buf.push(text[i]);\n        else\n            break;\n    }\n    return buf;\n};\n\nexports.getCompletionPrefix = function (editor) {\n    var pos = editor.getCursorPosition();\n    var line = editor.session.getLine(pos.row);\n    var prefix;\n    editor.completers.forEach(function(completer) {\n        if (completer.identifierRegexps) {\n            completer.identifierRegexps.forEach(function(identifierRegex) {\n                if (!prefix && identifierRegex)\n                    prefix = this.retrievePrecedingIdentifier(line, pos.column, identifierRegex);\n            }.bind(this));\n        }\n    }.bind(this));\n    return prefix || this.retrievePrecedingIdentifier(line, pos.column);\n};\n\n});\n\nace.define(\"ace/autocomplete\",[\"require\",\"exports\",\"module\",\"ace/keyboard/hash_handler\",\"ace/autocomplete/popup\",\"ace/autocomplete/util\",\"ace/lib/event\",\"ace/lib/lang\",\"ace/lib/dom\",\"ace/snippets\"], function(require, exports, module) {\n\"use strict\";\n\nvar HashHandler = require(\"./keyboard/hash_handler\").HashHandler;\nvar AcePopup = require(\"./autocomplete/popup\").AcePopup;\nvar util = require(\"./autocomplete/util\");\nvar event = require(\"./lib/event\");\nvar lang = require(\"./lib/lang\");\nvar dom = require(\"./lib/dom\");\nvar snippetManager = require(\"./snippets\").snippetManager;\n\nvar Autocomplete = function() {\n    this.autoInsert = false;\n    this.autoSelect = true;\n    this.exactMatch = false;\n    this.gatherCompletionsId = 0;\n    this.keyboardHandler = new HashHandler();\n    this.keyboardHandler.bindKeys(this.commands);\n\n    this.blurListener = this.blurListener.bind(this);\n    this.changeListener = this.changeListener.bind(this);\n    this.mousedownListener = this.mousedownListener.bind(this);\n    this.mousewheelListener = this.mousewheelListener.bind(this);\n\n    this.changeTimer = lang.delayedCall(function() {\n        this.updateCompletions(true);\n    }.bind(this));\n\n    this.tooltipTimer = lang.delayedCall(this.updateDocTooltip.bind(this), 50);\n};\n\n(function() {\n\n    this.$init = function() {\n        this.popup = new AcePopup(document.body || document.documentElement);\n        this.popup.on(\"click\", function(e) {\n            this.insertMatch();\n            e.stop();\n        }.bind(this));\n        this.popup.focus = this.editor.focus.bind(this.editor);\n        this.popup.on(\"show\", this.tooltipTimer.bind(null, null));\n        this.popup.on(\"select\", this.tooltipTimer.bind(null, null));\n        this.popup.on(\"changeHoverMarker\", this.tooltipTimer.bind(null, null));\n        return this.popup;\n    };\n\n    this.getPopup = function() {\n        return this.popup || this.$init();\n    };\n\n    this.openPopup = function(editor, prefix, keepPopupPosition) {\n        if (!this.popup)\n            this.$init();\n\n    this.popup.autoSelect = this.autoSelect;\n\n        this.popup.setData(this.completions.filtered);\n\n        editor.keyBinding.addKeyboardHandler(this.keyboardHandler);\n        \n        var renderer = editor.renderer;\n        this.popup.setRow(this.autoSelect ? 0 : -1);\n        if (!keepPopupPosition) {\n            this.popup.setTheme(editor.getTheme());\n            this.popup.setFontSize(editor.getFontSize());\n\n            var lineHeight = renderer.layerConfig.lineHeight;\n\n            var pos = renderer.$cursorLayer.getPixelPosition(this.base, true);\n            pos.left -= this.popup.getTextLeftOffset();\n\n            var rect = editor.container.getBoundingClientRect();\n            pos.top += rect.top - renderer.layerConfig.offset;\n            pos.left += rect.left - editor.renderer.scrollLeft;\n            pos.left += renderer.gutterWidth;\n\n            this.popup.show(pos, lineHeight);\n        } else if (keepPopupPosition && !prefix) {\n            this.detach();\n        }\n    };\n\n    this.detach = function() {\n        this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler);\n        this.editor.off(\"changeSelection\", this.changeListener);\n        this.editor.off(\"blur\", this.blurListener);\n        this.editor.off(\"mousedown\", this.mousedownListener);\n        this.editor.off(\"mousewheel\", this.mousewheelListener);\n        this.changeTimer.cancel();\n        this.hideDocTooltip();\n\n        this.gatherCompletionsId += 1;\n        if (this.popup && this.popup.isOpen)\n            this.popup.hide();\n\n        if (this.base)\n            this.base.detach();\n        this.activated = false;\n        this.completions = this.base = null;\n    };\n\n    this.changeListener = function(e) {\n        var cursor = this.editor.selection.lead;\n        if (cursor.row != this.base.row || cursor.column < this.base.column) {\n            this.detach();\n        }\n        if (this.activated)\n            this.changeTimer.schedule();\n        else\n            this.detach();\n    };\n\n    this.blurListener = function(e) {\n        var el = document.activeElement;\n        var text = this.editor.textInput.getElement();\n        var fromTooltip = e.relatedTarget && this.tooltipNode && this.tooltipNode.contains(e.relatedTarget);\n        var container = this.popup && this.popup.container;\n        if (el != text && el.parentNode != container && !fromTooltip\n            && el != this.tooltipNode && e.relatedTarget != text\n        ) {\n            this.detach();\n        }\n    };\n\n    this.mousedownListener = function(e) {\n        this.detach();\n    };\n\n    this.mousewheelListener = function(e) {\n        this.detach();\n    };\n\n    this.goTo = function(where) {\n        var row = this.popup.getRow();\n        var max = this.popup.session.getLength() - 1;\n\n        switch(where) {\n            case \"up\": row = row <= 0 ? max : row - 1; break;\n            case \"down\": row = row >= max ? -1 : row + 1; break;\n            case \"start\": row = 0; break;\n            case \"end\": row = max; break;\n        }\n\n        this.popup.setRow(row);\n    };\n\n    this.insertMatch = function(data, options) {\n        if (!data)\n            data = this.popup.getData(this.popup.getRow());\n        if (!data)\n            return false;\n\n        if (data.completer && data.completer.insertMatch) {\n            data.completer.insertMatch(this.editor, data);\n        } else {\n            if (this.completions.filterText) {\n                var ranges = this.editor.selection.getAllRanges();\n                for (var i = 0, range; range = ranges[i]; i++) {\n                    range.start.column -= this.completions.filterText.length;\n                    this.editor.session.remove(range);\n                }\n            }\n            if (data.snippet)\n                snippetManager.insertSnippet(this.editor, data.snippet);\n            else\n                this.editor.execCommand(\"insertstring\", data.value || data);\n        }\n        this.detach();\n    };\n\n\n    this.commands = {\n        \"Up\": function(editor) { editor.completer.goTo(\"up\"); },\n        \"Down\": function(editor) { editor.completer.goTo(\"down\"); },\n        \"Ctrl-Up|Ctrl-Home\": function(editor) { editor.completer.goTo(\"start\"); },\n        \"Ctrl-Down|Ctrl-End\": function(editor) { editor.completer.goTo(\"end\"); },\n\n        \"Esc\": function(editor) { editor.completer.detach(); },\n        \"Return\": function(editor) { return editor.completer.insertMatch(); },\n        \"Shift-Return\": function(editor) { editor.completer.insertMatch(null, {deleteSuffix: true}); },\n        \"Tab\": function(editor) {\n            var result = editor.completer.insertMatch();\n            if (!result && !editor.tabstopManager)\n                editor.completer.goTo(\"down\");\n            else\n                return result;\n        },\n\n        \"PageUp\": function(editor) { editor.completer.popup.gotoPageUp(); },\n        \"PageDown\": function(editor) { editor.completer.popup.gotoPageDown(); }\n    };\n\n    this.gatherCompletions = function(editor, callback) {\n        var session = editor.getSession();\n        var pos = editor.getCursorPosition();\n\n        var prefix = util.getCompletionPrefix(editor);\n\n        this.base = session.doc.createAnchor(pos.row, pos.column - prefix.length);\n        this.base.$insertRight = true;\n\n        var matches = [];\n        var total = editor.completers.length;\n        editor.completers.forEach(function(completer, i) {\n            completer.getCompletions(editor, session, pos, prefix, function(err, results) {\n                if (!err && results)\n                    matches = matches.concat(results);\n                callback(null, {\n                    prefix: util.getCompletionPrefix(editor),\n                    matches: matches,\n                    finished: (--total === 0)\n                });\n            });\n        });\n        return true;\n    };\n\n    this.showPopup = function(editor) {\n        if (this.editor)\n            this.detach();\n\n        this.activated = true;\n\n        this.editor = editor;\n        if (editor.completer != this) {\n            if (editor.completer)\n                editor.completer.detach();\n            editor.completer = this;\n        }\n\n        editor.on(\"changeSelection\", this.changeListener);\n        editor.on(\"blur\", this.blurListener);\n        editor.on(\"mousedown\", this.mousedownListener);\n        editor.on(\"mousewheel\", this.mousewheelListener);\n\n        this.updateCompletions();\n    };\n\n    this.updateCompletions = function(keepPopupPosition) {\n        if (keepPopupPosition && this.base && this.completions) {\n            var pos = this.editor.getCursorPosition();\n            var prefix = this.editor.session.getTextRange({start: this.base, end: pos});\n            if (prefix == this.completions.filterText)\n                return;\n            this.completions.setFilter(prefix);\n            if (!this.completions.filtered.length)\n                return this.detach();\n            if (this.completions.filtered.length == 1\n            && this.completions.filtered[0].value == prefix\n            && !this.completions.filtered[0].snippet)\n                return this.detach();\n            this.openPopup(this.editor, prefix, keepPopupPosition);\n            return;\n        }\n        var _id = this.gatherCompletionsId;\n        this.gatherCompletions(this.editor, function(err, results) {\n            var detachIfFinished = function() {\n                if (!results.finished) return;\n                return this.detach();\n            }.bind(this);\n\n            var prefix = results.prefix;\n            var matches = results && results.matches;\n\n            if (!matches || !matches.length)\n                return detachIfFinished();\n            if (prefix.indexOf(results.prefix) !== 0 || _id != this.gatherCompletionsId)\n                return;\n\n            this.completions = new FilteredList(matches);\n\n            if (this.exactMatch)\n                this.completions.exactMatch = true;\n\n            this.completions.setFilter(prefix);\n            var filtered = this.completions.filtered;\n            if (!filtered.length)\n                return detachIfFinished();\n            if (filtered.length == 1 && filtered[0].value == prefix && !filtered[0].snippet)\n                return detachIfFinished();\n            if (this.autoInsert && filtered.length == 1 && results.finished)\n                return this.insertMatch(filtered[0]);\n\n            this.openPopup(this.editor, prefix, keepPopupPosition);\n        }.bind(this));\n    };\n\n    this.cancelContextMenu = function() {\n        this.editor.$mouseHandler.cancelContextMenu();\n    };\n\n    this.updateDocTooltip = function() {\n        var popup = this.popup;\n        var all = popup.data;\n        var selected = all && (all[popup.getHoveredRow()] || all[popup.getRow()]);\n        var doc = null;\n        if (!selected || !this.editor || !this.popup.isOpen)\n            return this.hideDocTooltip();\n        this.editor.completers.some(function(completer) {\n            if (completer.getDocTooltip)\n                doc = completer.getDocTooltip(selected);\n            return doc;\n        });\n        if (!doc)\n            doc = selected;\n\n        if (typeof doc == \"string\")\n            doc = {docText: doc};\n        if (!doc || !(doc.docHTML || doc.docText))\n            return this.hideDocTooltip();\n        this.showDocTooltip(doc);\n    };\n\n    this.showDocTooltip = function(item) {\n        if (!this.tooltipNode) {\n            this.tooltipNode = dom.createElement(\"div\");\n            this.tooltipNode.className = \"ace_tooltip ace_doc-tooltip\";\n            this.tooltipNode.style.margin = 0;\n            this.tooltipNode.style.pointerEvents = \"auto\";\n            this.tooltipNode.tabIndex = -1;\n            this.tooltipNode.onblur = this.blurListener.bind(this);\n            this.tooltipNode.onclick = this.onTooltipClick.bind(this);\n        }\n\n        var tooltipNode = this.tooltipNode;\n        if (item.docHTML) {\n            tooltipNode.innerHTML = item.docHTML;\n        } else if (item.docText) {\n            tooltipNode.textContent = item.docText;\n        }\n\n        if (!tooltipNode.parentNode)\n            document.body.appendChild(tooltipNode);\n        var popup = this.popup;\n        var rect = popup.container.getBoundingClientRect();\n        tooltipNode.style.top = popup.container.style.top;\n        tooltipNode.style.bottom = popup.container.style.bottom;\n\n        if (window.innerWidth - rect.right < 320) {\n            tooltipNode.style.right = window.innerWidth - rect.left + \"px\";\n            tooltipNode.style.left = \"\";\n        } else {\n            tooltipNode.style.left = (rect.right + 1) + \"px\";\n            tooltipNode.style.right = \"\";\n        }\n        tooltipNode.style.display = \"block\";\n    };\n\n    this.hideDocTooltip = function() {\n        this.tooltipTimer.cancel();\n        if (!this.tooltipNode) return;\n        var el = this.tooltipNode;\n        if (!this.editor.isFocused() && document.activeElement == el)\n            this.editor.focus();\n        this.tooltipNode = null;\n        if (el.parentNode)\n            el.parentNode.removeChild(el);\n    };\n    \n    this.onTooltipClick = function(e) {\n        var a = e.target;\n        while (a && a != this.tooltipNode) {\n            if (a.nodeName == \"A\" && a.href) {\n                a.rel = \"noreferrer\";\n                a.target = \"_blank\";\n                break;\n            }\n            a = a.parentNode;\n        }\n    }\n\n}).call(Autocomplete.prototype);\n\nAutocomplete.startCommand = {\n    name: \"startAutocomplete\",\n    exec: function(editor) {\n        if (!editor.completer)\n            editor.completer = new Autocomplete();\n        editor.completer.autoInsert = false;\n        editor.completer.autoSelect = true;\n        editor.completer.showPopup(editor);\n        editor.completer.cancelContextMenu();\n    },\n    bindKey: \"Ctrl-Space|Ctrl-Shift-Space|Alt-Space\"\n};\n\nvar FilteredList = function(array, filterText) {\n    this.all = array;\n    this.filtered = array;\n    this.filterText = filterText || \"\";\n    this.exactMatch = false;\n};\n(function(){\n    this.setFilter = function(str) {\n        if (str.length > this.filterText && str.lastIndexOf(this.filterText, 0) === 0)\n            var matches = this.filtered;\n        else\n            var matches = this.all;\n\n        this.filterText = str;\n        matches = this.filterCompletions(matches, this.filterText);\n        matches = matches.sort(function(a, b) {\n            return b.exactMatch - a.exactMatch || b.score - a.score;\n        });\n        var prev = null;\n        matches = matches.filter(function(item){\n            var caption = item.snippet || item.caption || item.value;\n            if (caption === prev) return false;\n            prev = caption;\n            return true;\n        });\n\n        this.filtered = matches;\n    };\n    this.filterCompletions = function(items, needle) {\n        var results = [];\n        var upper = needle.toUpperCase();\n        var lower = needle.toLowerCase();\n        loop: for (var i = 0, item; item = items[i]; i++) {\n            var caption = item.value || item.caption || item.snippet;\n            if (!caption) continue;\n            var lastIndex = -1;\n            var matchMask = 0;\n            var penalty = 0;\n            var index, distance;\n\n            if (this.exactMatch) {\n                if (needle !== caption.substr(0, needle.length))\n                    continue loop;\n            }else{\n                for (var j = 0; j < needle.length; j++) {\n                    var i1 = caption.indexOf(lower[j], lastIndex + 1);\n                    var i2 = caption.indexOf(upper[j], lastIndex + 1);\n                    index = (i1 >= 0) ? ((i2 < 0 || i1 < i2) ? i1 : i2) : i2;\n                    if (index < 0)\n                        continue loop;\n                    distance = index - lastIndex - 1;\n                    if (distance > 0) {\n                        if (lastIndex === -1)\n                            penalty += 10;\n                        penalty += distance;\n                    }\n                    matchMask = matchMask | (1 << index);\n                    lastIndex = index;\n                }\n            }\n            item.matchMask = matchMask;\n            item.exactMatch = penalty ? 0 : 1;\n            item.score = (item.score || 0) - penalty;\n            results.push(item);\n        }\n        return results;\n    };\n}).call(FilteredList.prototype);\n\nexports.Autocomplete = Autocomplete;\nexports.FilteredList = FilteredList;\n\n});\n\nace.define(\"ace/autocomplete/text_completer\",[\"require\",\"exports\",\"module\",\"ace/range\"], function(require, exports, module) {\n    var Range = require(\"../range\").Range;\n    \n    var splitRegex = /[^a-zA-Z_0-9\\$\\-\\u00C0-\\u1FFF\\u2C00-\\uD7FF\\w]+/;\n\n    function getWordIndex(doc, pos) {\n        var textBefore = doc.getTextRange(Range.fromPoints({row: 0, column:0}, pos));\n        return textBefore.split(splitRegex).length - 1;\n    }\n    function wordDistance(doc, pos) {\n        var prefixPos = getWordIndex(doc, pos);\n        var words = doc.getValue().split(splitRegex);\n        var wordScores = Object.create(null);\n        \n        var currentWord = words[prefixPos];\n\n        words.forEach(function(word, idx) {\n            if (!word || word === currentWord) return;\n\n            var distance = Math.abs(prefixPos - idx);\n            var score = words.length - distance;\n            if (wordScores[word]) {\n                wordScores[word] = Math.max(score, wordScores[word]);\n            } else {\n                wordScores[word] = score;\n            }\n        });\n        return wordScores;\n    }\n\n    exports.getCompletions = function(editor, session, pos, prefix, callback) {\n        var wordScore = wordDistance(session, pos, prefix);\n        var wordList = Object.keys(wordScore);\n        callback(null, wordList.map(function(word) {\n            return {\n                caption: word,\n                value: word,\n                score: wordScore[word],\n                meta: \"local\"\n            };\n        }));\n    };\n});\n\nace.define(\"ace/ext/language_tools\",[\"require\",\"exports\",\"module\",\"ace/snippets\",\"ace/autocomplete\",\"ace/config\",\"ace/lib/lang\",\"ace/autocomplete/util\",\"ace/autocomplete/text_completer\",\"ace/editor\",\"ace/config\"], function(require, exports, module) {\n\"use strict\";\n\nvar snippetManager = require(\"../snippets\").snippetManager;\nvar Autocomplete = require(\"../autocomplete\").Autocomplete;\nvar config = require(\"../config\");\nvar lang = require(\"../lib/lang\");\nvar util = require(\"../autocomplete/util\");\n\nvar textCompleter = require(\"../autocomplete/text_completer\");\nvar keyWordCompleter = {\n    getCompletions: function(editor, session, pos, prefix, callback) {\n        if (session.$mode.completer) {\n            return session.$mode.completer.getCompletions(editor, session, pos, prefix, callback);\n        }\n        var state = editor.session.getState(pos.row);\n        var completions = session.$mode.getCompletions(state, session, pos, prefix);\n        callback(null, completions);\n    }\n};\n\nvar snippetCompleter = {\n    getCompletions: function(editor, session, pos, prefix, callback) {\n        var snippetMap = snippetManager.snippetMap;\n        var completions = [];\n        snippetManager.getActiveScopes(editor).forEach(function(scope) {\n            var snippets = snippetMap[scope] || [];\n            for (var i = snippets.length; i--;) {\n                var s = snippets[i];\n                var caption = s.name || s.tabTrigger;\n                if (!caption)\n                    continue;\n                completions.push({\n                    caption: caption,\n                    snippet: s.content,\n                    meta: s.tabTrigger && !s.name ? s.tabTrigger + \"\\u21E5 \" : \"snippet\",\n                    type: \"snippet\"\n                });\n            }\n        }, this);\n        callback(null, completions);\n    },\n    getDocTooltip: function(item) {\n        if (item.type == \"snippet\" && !item.docHTML) {\n            item.docHTML = [\n                \"<b>\", lang.escapeHTML(item.caption), \"</b>\", \"<hr></hr>\",\n                lang.escapeHTML(item.snippet)\n            ].join(\"\");\n        }\n    }\n};\n\nvar completers = [snippetCompleter, textCompleter, keyWordCompleter];\nexports.setCompleters = function(val) {\n    completers.length = 0;\n    if (val) completers.push.apply(completers, val);\n};\nexports.addCompleter = function(completer) {\n    completers.push(completer);\n};\nexports.textCompleter = textCompleter;\nexports.keyWordCompleter = keyWordCompleter;\nexports.snippetCompleter = snippetCompleter;\n\nvar expandSnippet = {\n    name: \"expandSnippet\",\n    exec: function(editor) {\n        return snippetManager.expandWithTab(editor);\n    },\n    bindKey: \"Tab\"\n};\n\nvar onChangeMode = function(e, editor) {\n    loadSnippetsForMode(editor.session.$mode);\n};\n\nvar loadSnippetsForMode = function(mode) {\n    var id = mode.$id;\n    if (!snippetManager.files)\n        snippetManager.files = {};\n    loadSnippetFile(id);\n    if (mode.modes)\n        mode.modes.forEach(loadSnippetsForMode);\n};\n\nvar loadSnippetFile = function(id) {\n    if (!id || snippetManager.files[id])\n        return;\n    var snippetFilePath = id.replace(\"mode\", \"snippets\");\n    snippetManager.files[id] = {};\n    config.loadModule(snippetFilePath, function(m) {\n        if (m) {\n            snippetManager.files[id] = m;\n            if (!m.snippets && m.snippetText)\n                m.snippets = snippetManager.parseSnippetFile(m.snippetText);\n            snippetManager.register(m.snippets || [], m.scope);\n            if (m.includeScopes) {\n                snippetManager.snippetMap[m.scope].includeScopes = m.includeScopes;\n                m.includeScopes.forEach(function(x) {\n                    loadSnippetFile(\"ace/mode/\" + x);\n                });\n            }\n        }\n    });\n};\n\nvar doLiveAutocomplete = function(e) {\n    var editor = e.editor;\n    var hasCompleter = editor.completer && editor.completer.activated;\n    if (e.command.name === \"backspace\") {\n        if (hasCompleter && !util.getCompletionPrefix(editor))\n            editor.completer.detach();\n    }\n    else if (e.command.name === \"insertstring\") {\n        var prefix = util.getCompletionPrefix(editor);\n        if (prefix && !hasCompleter) {\n            if (!editor.completer) {\n                editor.completer = new Autocomplete();\n            }\n            editor.completer.autoInsert = false;\n            editor.completer.showPopup(editor);\n        }\n    }\n};\n\nvar Editor = require(\"../editor\").Editor;\nrequire(\"../config\").defineOptions(Editor.prototype, \"editor\", {\n    enableBasicAutocompletion: {\n        set: function(val) {\n            if (val) {\n                if (!this.completers)\n                    this.completers = Array.isArray(val)? val: completers;\n                this.commands.addCommand(Autocomplete.startCommand);\n            } else {\n                this.commands.removeCommand(Autocomplete.startCommand);\n            }\n        },\n        value: false\n    },\n    enableLiveAutocompletion: {\n        set: function(val) {\n            if (val) {\n                if (!this.completers)\n                    this.completers = Array.isArray(val)? val: completers;\n                this.commands.on('afterExec', doLiveAutocomplete);\n            } else {\n                this.commands.removeListener('afterExec', doLiveAutocomplete);\n            }\n        },\n        value: false\n    },\n    enableSnippets: {\n        set: function(val) {\n            if (val) {\n                this.commands.addCommand(expandSnippet);\n                this.on(\"changeMode\", onChangeMode);\n                onChangeMode(null, this);\n            } else {\n                this.commands.removeCommand(expandSnippet);\n                this.off(\"changeMode\", onChangeMode);\n            }\n        },\n        value: false\n    }\n});\n});\n                (function() {\n                    ace.require([\"ace/ext/language_tools\"], function() {});\n                })();\n            "
  },
  {
    "path": "lib/ace/mode-javascript.js",
    "content": "ace.define(\"ace/mode/doc_comment_highlight_rules\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/mode/text_highlight_rules\"], function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar DocCommentHighlightRules = function() {\n    this.$rules = {\n        \"start\" : [ {\n            token : \"comment.doc.tag\",\n            regex : \"@[\\\\w\\\\d_]+\" // TODO: fix email addresses\n        }, \n        DocCommentHighlightRules.getTagRule(),\n        {\n            defaultToken : \"comment.doc\",\n            caseInsensitive: true\n        }]\n    };\n};\n\noop.inherits(DocCommentHighlightRules, TextHighlightRules);\n\nDocCommentHighlightRules.getTagRule = function(start) {\n    return {\n        token : \"comment.doc.tag.storage.type\",\n        regex : \"\\\\b(?:TODO|FIXME|XXX|HACK)\\\\b\"\n    };\n}\n\nDocCommentHighlightRules.getStartRule = function(start) {\n    return {\n        token : \"comment.doc\", // doc comment\n        regex : \"\\\\/\\\\*(?=\\\\*)\",\n        next  : start\n    };\n};\n\nDocCommentHighlightRules.getEndRule = function (start) {\n    return {\n        token : \"comment.doc\", // closing comment\n        regex : \"\\\\*\\\\/\",\n        next  : start\n    };\n};\n\n\nexports.DocCommentHighlightRules = DocCommentHighlightRules;\n\n});\n\nace.define(\"ace/mode/javascript_highlight_rules\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/mode/doc_comment_highlight_rules\",\"ace/mode/text_highlight_rules\"], function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar DocCommentHighlightRules = require(\"./doc_comment_highlight_rules\").DocCommentHighlightRules;\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\nvar identifierRe = \"[a-zA-Z\\\\$_\\u00a1-\\uffff][a-zA-Z\\\\d\\\\$_\\u00a1-\\uffff]*\";\n\nvar JavaScriptHighlightRules = function(options) {\n    var keywordMapper = this.createKeywordMapper({\n        \"variable.language\":\n            \"Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|\"  + // Constructors\n            \"Namespace|QName|XML|XMLList|\"                                             + // E4X\n            \"ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|\"   +\n            \"Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|\"                    +\n            \"Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|\"   + // Errors\n            \"SyntaxError|TypeError|URIError|\"                                          +\n            \"decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|\" + // Non-constructor functions\n            \"isNaN|parseFloat|parseInt|\"                                               +\n            \"JSON|Math|\"                                                               + // Other\n            \"this|arguments|prototype|window|document\"                                 , // Pseudo\n        \"keyword\":\n            \"const|yield|import|get|set|async|await|\" +\n            \"break|case|catch|continue|default|delete|do|else|finally|for|function|\" +\n            \"if|in|of|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|\" +\n            \"__parent__|__count__|escape|unescape|with|__proto__|\" +\n            \"class|enum|extends|super|export|implements|private|public|interface|package|protected|static\",\n        \"storage.type\":\n            \"const|let|var|function\",\n        \"constant.language\":\n            \"null|Infinity|NaN|undefined\",\n        \"support.function\":\n            \"alert\",\n        \"keyword.wickfunctions\":\n            window.wickDocsKeywords,\n        \"constant.language.boolean\": \"true|false\"\n    }, \"identifier\");\n    var kwBeforeRe = \"case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void\";\n\n    var escapedRe = \"\\\\\\\\(?:x[0-9a-fA-F]{2}|\" + // hex\n        \"u[0-9a-fA-F]{4}|\" + // unicode\n        \"u{[0-9a-fA-F]{1,6}}|\" + // es6 unicode\n        \"[0-2][0-7]{0,2}|\" + // oct\n        \"3[0-7][0-7]?|\" + // oct\n        \"[4-7][0-7]?|\" + //oct\n        \".)\";\n\n    this.$rules = {\n        \"no_regex\" : [\n            DocCommentHighlightRules.getStartRule(\"doc-start\"),\n            comments(\"no_regex\"),\n            {\n                token : \"string\",\n                regex : \"'(?=.)\",\n                next  : \"qstring\"\n            }, {\n                token : \"string\",\n                regex : '\"(?=.)',\n                next  : \"qqstring\"\n            }, {\n                token : \"constant.numeric\", // hexadecimal, octal and binary\n                regex : /0(?:[xX][0-9a-fA-F]+|[oO][0-7]+|[bB][01]+)\\b/\n            }, {\n                token : \"constant.numeric\", // decimal integers and floats\n                regex : /(?:\\d\\d*(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+\\b)?/\n            }, {\n                token : [\n                    \"storage.type\", \"punctuation.operator\", \"support.function\",\n                    \"punctuation.operator\", \"entity.name.function\", \"text\",\"keyword.operator\"\n                ],\n                regex : \"(\" + identifierRe + \")(\\\\.)(prototype)(\\\\.)(\" + identifierRe +\")(\\\\s*)(=)\",\n                next: \"function_arguments\"\n            }, {\n                token : [\n                    \"storage.type\", \"punctuation.operator\", \"entity.name.function\", \"text\",\n                    \"keyword.operator\", \"text\", \"storage.type\", \"text\", \"paren.lparen\"\n                ],\n                regex : \"(\" + identifierRe + \")(\\\\.)(\" + identifierRe +\")(\\\\s*)(=)(\\\\s*)(function)(\\\\s*)(\\\\()\",\n                next: \"function_arguments\"\n            }, {\n                token : [ 'keyword.wickfunctions' ],\n                regex : \"([.])\\w{0,100}\"\n            }, {\n                token : [\n                    \"entity.name.function\", \"text\", \"keyword.operator\", \"text\", \"storage.type\",\n                    \"text\", \"paren.lparen\"\n                ],\n                regex : \"(\" + identifierRe +\")(\\\\s*)(=)(\\\\s*)(function)(\\\\s*)(\\\\()\",\n                next: \"function_arguments\"\n            }, {\n                token : [\n                    \"storage.type\", \"punctuation.operator\", \"entity.name.function\", \"text\",\n                    \"keyword.operator\", \"text\",\n                    \"storage.type\", \"text\", \"entity.name.function\", \"text\", \"paren.lparen\"\n                ],\n                regex : \"(\" + identifierRe + \")(\\\\.)(\" + identifierRe +\")(\\\\s*)(=)(\\\\s*)(function)(\\\\s+)(\\\\w+)(\\\\s*)(\\\\()\",\n                next: \"function_arguments\"\n            }, {\n                token : [\n                    \"storage.type\", \"text\", \"entity.name.function\", \"text\", \"paren.lparen\"\n                ],\n                regex : \"(function)(\\\\s+)(\" + identifierRe + \")(\\\\s*)(\\\\()\",\n                next: \"function_arguments\"\n            }, {\n                token : [\n                    \"entity.name.function\", \"text\", \"punctuation.operator\",\n                    \"text\", \"storage.type\", \"text\", \"paren.lparen\"\n                ],\n                regex : \"(\" + identifierRe + \")(\\\\s*)(:)(\\\\s*)(function)(\\\\s*)(\\\\()\",\n                next: \"function_arguments\"\n            }, {\n                token : [\n                    \"text\", \"text\", \"storage.type\", \"text\", \"paren.lparen\"\n                ],\n                regex : \"(:)(\\\\s*)(function)(\\\\s*)(\\\\()\",\n                next: \"function_arguments\"\n            }, {\n                token : \"keyword\",\n                regex : \"from(?=\\\\s*('|\\\"))\"\n            }, {\n                token : \"keyword\",\n                regex : \"(?:\" + kwBeforeRe + \")\\\\b\",\n                next : \"start\"\n            }, {\n                token : [\"support.constant\"],\n                regex : /that\\b/\n            }, {\n                token : [\"storage.type\", \"punctuation.operator\", \"support.function.firebug\"],\n                regex : /(console)(\\.)(warn|info|log|error|time|trace|timeEnd|assert)\\b/\n            }, {\n                token : keywordMapper,\n                regex : identifierRe\n            }, {\n                token : \"punctuation.operator\",\n                regex : /[.](?![.])/,\n                next  : \"property\"\n            }, {\n                token : \"storage.type\",\n                regex : /=>/\n            }, {\n                token : \"keyword.operator\",\n                regex : /--|\\+\\+|\\.{3}|===|==|=|!=|!==|<+=?|>+=?|!|&&|\\|\\||\\?:|[!$%&*+\\-~\\/^]=?/,\n                next  : \"start\"\n            }, {\n                token : \"punctuation.operator\",\n                regex : /[?:,;.]/,\n                next  : \"start\"\n            }, {\n                token : \"paren.lparen\",\n                regex : /[\\[({]/,\n                next  : \"start\"\n            }, {\n                token : \"paren.rparen\",\n                regex : /[\\])}]/\n            }, {\n                token: \"comment\",\n                regex: /^#!.*$/\n            }\n        ],\n        property: [{\n                token : \"text\",\n                regex : \"\\\\s+\"\n            }, {\n                token : [\n                    \"storage.type\", \"punctuation.operator\", \"entity.name.function\", \"text\",\n                    \"keyword.operator\", \"text\",\n                    \"storage.type\", \"text\", \"entity.name.function\", \"text\", \"paren.lparen\"\n                ],\n                regex : \"(\" + identifierRe + \")(\\\\.)(\" + identifierRe +\")(\\\\s*)(=)(\\\\s*)(function)(?:(\\\\s+)(\\\\w+))?(\\\\s*)(\\\\()\",\n                next: \"function_arguments\"\n            }, {\n                token : \"punctuation.operator\",\n                regex : /[.](?![.])/\n            }, {\n                token : \"support.function\",\n                regex : /(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:op|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\\b(?=\\()/\n            }, {\n                token : \"support.function.dom\",\n                regex : /(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName|ClassName)|ById)|Attribute(?:Node)?)|blur)\\b(?=\\()/\n            }, {\n                token :  \"support.constant\",\n                regex : /(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\\b/\n            }, {\n                token : \"identifier\",\n                regex : identifierRe\n            }, {\n                regex: \"\",\n                token: \"empty\",\n                next: \"no_regex\"\n            }\n        ],\n        \"start\": [\n            DocCommentHighlightRules.getStartRule(\"doc-start\"),\n            comments(\"start\"),\n            {\n                token: \"string.regexp\",\n                regex: \"\\\\/\",\n                next: \"regex\"\n            }, {\n                token : \"text\",\n                regex : \"\\\\s+|^$\",\n                next : \"start\"\n            }, {\n                token: \"empty\",\n                regex: \"\",\n                next: \"no_regex\"\n            }\n        ],\n        \"regex\": [\n            {\n                token: \"regexp.keyword.operator\",\n                regex: \"\\\\\\\\(?:u[\\\\da-fA-F]{4}|x[\\\\da-fA-F]{2}|.)\"\n            }, {\n                token: \"string.regexp\",\n                regex: \"/[sxngimy]*\",\n                next: \"no_regex\"\n            }, {\n                token : \"invalid\",\n                regex: /\\{\\d+\\b,?\\d*\\}[+*]|[+*$^?][+*]|[$^][?]|\\?{3,}/\n            }, {\n                token : \"constant.language.escape\",\n                regex: /\\(\\?[:=!]|\\)|\\{\\d+\\b,?\\d*\\}|[+*]\\?|[()$^+*?.]/\n            }, {\n                token : \"constant.language.delimiter\",\n                regex: /\\|/\n            }, {\n                token: \"constant.language.escape\",\n                regex: /\\[\\^?/,\n                next: \"regex_character_class\"\n            }, {\n                token: \"empty\",\n                regex: \"$\",\n                next: \"no_regex\"\n            }, {\n                defaultToken: \"string.regexp\"\n            }\n        ],\n        \"regex_character_class\": [\n            {\n                token: \"regexp.charclass.keyword.operator\",\n                regex: \"\\\\\\\\(?:u[\\\\da-fA-F]{4}|x[\\\\da-fA-F]{2}|.)\"\n            }, {\n                token: \"constant.language.escape\",\n                regex: \"]\",\n                next: \"regex\"\n            }, {\n                token: \"constant.language.escape\",\n                regex: \"-\"\n            }, {\n                token: \"empty\",\n                regex: \"$\",\n                next: \"no_regex\"\n            }, {\n                defaultToken: \"string.regexp.charachterclass\"\n            }\n        ],\n        \"function_arguments\": [\n            {\n                token: \"variable.parameter\",\n                regex: identifierRe\n            }, {\n                token: \"punctuation.operator\",\n                regex: \"[, ]+\"\n            }, {\n                token: \"punctuation.operator\",\n                regex: \"$\"\n            }, {\n                token: \"empty\",\n                regex: \"\",\n                next: \"no_regex\"\n            }\n        ],\n        \"qqstring\" : [\n            {\n                token : \"constant.language.escape\",\n                regex : escapedRe\n            }, {\n                token : \"string\",\n                regex : \"\\\\\\\\$\",\n                consumeLineEnd  : true\n            }, {\n                token : \"string\",\n                regex : '\"|$',\n                next  : \"no_regex\"\n            }, {\n                defaultToken: \"string\"\n            }\n        ],\n        \"qstring\" : [\n            {\n                token : \"constant.language.escape\",\n                regex : escapedRe\n            }, {\n                token : \"string\",\n                regex : \"\\\\\\\\$\",\n                consumeLineEnd  : true\n            }, {\n                token : \"string\",\n                regex : \"'|$\",\n                next  : \"no_regex\"\n            }, {\n                defaultToken: \"string\"\n            }\n        ]\n    };\n\n\n    if (!options || !options.noES6) {\n        this.$rules.no_regex.unshift({\n            regex: \"[{}]\", onMatch: function(val, state, stack) {\n                this.next = val == \"{\" ? this.nextState : \"\";\n                if (val == \"{\" && stack.length) {\n                    stack.unshift(\"start\", state);\n                }\n                else if (val == \"}\" && stack.length) {\n                    stack.shift();\n                    this.next = stack.shift();\n                    if (this.next.indexOf(\"string\") != -1 || this.next.indexOf(\"jsx\") != -1)\n                        return \"paren.quasi.end\";\n                }\n                return val == \"{\" ? \"paren.lparen\" : \"paren.rparen\";\n            },\n            nextState: \"start\"\n        }, {\n            token : \"string.quasi.start\",\n            regex : /`/,\n            push  : [{\n                token : \"constant.language.escape\",\n                regex : escapedRe\n            }, {\n                token : \"paren.quasi.start\",\n                regex : /\\${/,\n                push  : \"start\"\n            }, {\n                token : \"string.quasi.end\",\n                regex : /`/,\n                next  : \"pop\"\n            }, {\n                defaultToken: \"string.quasi\"\n            }]\n        });\n\n        if (!options || options.jsx != false)\n            JSX.call(this);\n    }\n\n    this.embedRules(DocCommentHighlightRules, \"doc-\",\n        [ DocCommentHighlightRules.getEndRule(\"no_regex\") ]);\n\n    this.normalizeRules();\n};\n\noop.inherits(JavaScriptHighlightRules, TextHighlightRules);\n\nfunction JSX() {\n    var tagRegex = identifierRe.replace(\"\\\\d\", \"\\\\d\\\\-\");\n    var jsxTag = {\n        onMatch : function(val, state, stack) {\n            var offset = val.charAt(1) == \"/\" ? 2 : 1;\n            if (offset == 1) {\n                if (state != this.nextState)\n                    stack.unshift(this.next, this.nextState, 0);\n                else\n                    stack.unshift(this.next);\n                stack[2]++;\n            } else if (offset == 2) {\n                if (state == this.nextState) {\n                    stack[1]--;\n                    if (!stack[1] || stack[1] < 0) {\n                        stack.shift();\n                        stack.shift();\n                    }\n                }\n            }\n            return [{\n                type: \"meta.tag.punctuation.\" + (offset == 1 ? \"\" : \"end-\") + \"tag-open.xml\",\n                value: val.slice(0, offset)\n            }, {\n                type: \"meta.tag.tag-name.xml\",\n                value: val.substr(offset)\n            }];\n        },\n        regex : \"</?\" + tagRegex + \"\",\n        next: \"jsxAttributes\",\n        nextState: \"jsx\"\n    };\n    this.$rules.start.unshift(jsxTag);\n    var jsxJsRule = {\n        regex: \"{\",\n        token: \"paren.quasi.start\",\n        push: \"start\"\n    };\n    this.$rules.jsx = [\n        jsxJsRule,\n        jsxTag,\n        {include : \"reference\"},\n        {defaultToken: \"string\"}\n    ];\n    this.$rules.jsxAttributes = [{\n        token : \"meta.tag.punctuation.tag-close.xml\",\n        regex : \"/?>\",\n        onMatch : function(value, currentState, stack) {\n            if (currentState == stack[0])\n                stack.shift();\n            if (value.length == 2) {\n                if (stack[0] == this.nextState)\n                    stack[1]--;\n                if (!stack[1] || stack[1] < 0) {\n                    stack.splice(0, 2);\n                }\n            }\n            this.next = stack[0] || \"start\";\n            return [{type: this.token, value: value}];\n        },\n        nextState: \"jsx\"\n    },\n    jsxJsRule,\n    comments(\"jsxAttributes\"),\n    {\n        token : \"entity.other.attribute-name.xml\",\n        regex : tagRegex\n    }, {\n        token : \"keyword.operator.attribute-equals.xml\",\n        regex : \"=\"\n    }, {\n        token : \"text.tag-whitespace.xml\",\n        regex : \"\\\\s+\"\n    }, {\n        token : \"string.attribute-value.xml\",\n        regex : \"'\",\n        stateName : \"jsx_attr_q\",\n        push : [\n            {token : \"string.attribute-value.xml\", regex: \"'\", next: \"pop\"},\n            {include : \"reference\"},\n            {defaultToken : \"string.attribute-value.xml\"}\n        ]\n    }, {\n        token : \"string.attribute-value.xml\",\n        regex : '\"',\n        stateName : \"jsx_attr_qq\",\n        push : [\n            {token : \"string.attribute-value.xml\", regex: '\"', next: \"pop\"},\n            {include : \"reference\"},\n            {defaultToken : \"string.attribute-value.xml\"}\n        ]\n    },\n    jsxTag\n    ];\n    this.$rules.reference = [{\n        token : \"constant.language.escape.reference.xml\",\n        regex : \"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\\\.-]+;)\"\n    }];\n}\n\nfunction comments(next) {\n    return [\n        {\n            token : \"comment\", // multi line comment\n            regex : /\\/\\*/,\n            next: [\n                DocCommentHighlightRules.getTagRule(),\n                {token : \"comment\", regex : \"\\\\*\\\\/\", next : next || \"pop\"},\n                {defaultToken : \"comment\", caseInsensitive: true}\n            ]\n        }, {\n            token : \"comment\",\n            regex : \"\\\\/\\\\/\",\n            next: [\n                DocCommentHighlightRules.getTagRule(),\n                {token : \"comment\", regex : \"$|^\", next : next || \"pop\"},\n                {defaultToken : \"comment\", caseInsensitive: true}\n            ]\n        }\n    ];\n}\nexports.JavaScriptHighlightRules = JavaScriptHighlightRules;\n});\n\nace.define(\"ace/mode/matching_brace_outdent\",[\"require\",\"exports\",\"module\",\"ace/range\"], function(require, exports, module) {\n\"use strict\";\n\nvar Range = require(\"../range\").Range;\n\nvar MatchingBraceOutdent = function() {};\n\n(function() {\n\n    this.checkOutdent = function(line, input) {\n        if (! /^\\s+$/.test(line))\n            return false;\n\n        return /^\\s*\\}/.test(input);\n    };\n\n    this.autoOutdent = function(doc, row) {\n        var line = doc.getLine(row);\n        var match = line.match(/^(\\s*\\})/);\n\n        if (!match) return 0;\n\n        var column = match[1].length;\n        var openBracePos = doc.findMatchingBracket({row: row, column: column});\n\n        if (!openBracePos || openBracePos.row == row) return 0;\n\n        var indent = this.$getIndent(doc.getLine(openBracePos.row));\n        doc.replace(new Range(row, 0, row, column-1), indent);\n    };\n\n    this.$getIndent = function(line) {\n        return line.match(/^\\s*/)[0];\n    };\n\n}).call(MatchingBraceOutdent.prototype);\n\nexports.MatchingBraceOutdent = MatchingBraceOutdent;\n});\n\nace.define(\"ace/mode/folding/cstyle\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/range\",\"ace/mode/folding/fold_mode\"], function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../../lib/oop\");\nvar Range = require(\"../../range\").Range;\nvar BaseFoldMode = require(\"./fold_mode\").FoldMode;\n\nvar FoldMode = exports.FoldMode = function(commentRegex) {\n    if (commentRegex) {\n        this.foldingStartMarker = new RegExp(\n            this.foldingStartMarker.source.replace(/\\|[^|]*?$/, \"|\" + commentRegex.start)\n        );\n        this.foldingStopMarker = new RegExp(\n            this.foldingStopMarker.source.replace(/\\|[^|]*?$/, \"|\" + commentRegex.end)\n        );\n    }\n};\noop.inherits(FoldMode, BaseFoldMode);\n\n(function() {\n    \n    this.foldingStartMarker = /(\\{|\\[)[^\\}\\]]*$|^\\s*(\\/\\*)/;\n    this.foldingStopMarker = /^[^\\[\\{]*(\\}|\\])|^[\\s\\*]*(\\*\\/)/;\n    this.singleLineBlockCommentRe= /^\\s*(\\/\\*).*\\*\\/\\s*$/;\n    this.tripleStarBlockCommentRe = /^\\s*(\\/\\*\\*\\*).*\\*\\/\\s*$/;\n    this.startRegionRe = /^\\s*(\\/\\*|\\/\\/)#?region\\b/;\n    this._getFoldWidgetBase = this.getFoldWidget;\n    this.getFoldWidget = function(session, foldStyle, row) {\n        var line = session.getLine(row);\n    \n        if (this.singleLineBlockCommentRe.test(line)) {\n            if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))\n                return \"\";\n        }\n    \n        var fw = this._getFoldWidgetBase(session, foldStyle, row);\n    \n        if (!fw && this.startRegionRe.test(line))\n            return \"start\"; // lineCommentRegionStart\n    \n        return fw;\n    };\n\n    this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {\n        var line = session.getLine(row);\n        \n        if (this.startRegionRe.test(line))\n            return this.getCommentRegionBlock(session, line, row);\n        \n        var match = line.match(this.foldingStartMarker);\n        if (match) {\n            var i = match.index;\n\n            if (match[1])\n                return this.openingBracketBlock(session, match[1], row, i);\n                \n            var range = session.getCommentFoldRange(row, i + match[0].length, 1);\n            \n            if (range && !range.isMultiLine()) {\n                if (forceMultiline) {\n                    range = this.getSectionRange(session, row);\n                } else if (foldStyle != \"all\")\n                    range = null;\n            }\n            \n            return range;\n        }\n\n        if (foldStyle === \"markbegin\")\n            return;\n\n        var match = line.match(this.foldingStopMarker);\n        if (match) {\n            var i = match.index + match[0].length;\n\n            if (match[1])\n                return this.closingBracketBlock(session, match[1], row, i);\n\n            return session.getCommentFoldRange(row, i, -1);\n        }\n    };\n    \n    this.getSectionRange = function(session, row) {\n        var line = session.getLine(row);\n        var startIndent = line.search(/\\S/);\n        var startRow = row;\n        var startColumn = line.length;\n        row = row + 1;\n        var endRow = row;\n        var maxRow = session.getLength();\n        while (++row < maxRow) {\n            line = session.getLine(row);\n            var indent = line.search(/\\S/);\n            if (indent === -1)\n                continue;\n            if  (startIndent > indent)\n                break;\n            var subRange = this.getFoldWidgetRange(session, \"all\", row);\n            \n            if (subRange) {\n                if (subRange.start.row <= startRow) {\n                    break;\n                } else if (subRange.isMultiLine()) {\n                    row = subRange.end.row;\n                } else if (startIndent == indent) {\n                    break;\n                }\n            }\n            endRow = row;\n        }\n        \n        return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);\n    };\n    this.getCommentRegionBlock = function(session, line, row) {\n        var startColumn = line.search(/\\s*$/);\n        var maxRow = session.getLength();\n        var startRow = row;\n        \n        var re = /^\\s*(?:\\/\\*|\\/\\/|--)#?(end)?region\\b/;\n        var depth = 1;\n        while (++row < maxRow) {\n            line = session.getLine(row);\n            var m = re.exec(line);\n            if (!m) continue;\n            if (m[1]) depth--;\n            else depth++;\n\n            if (!depth) break;\n        }\n\n        var endRow = row;\n        if (endRow > startRow) {\n            return new Range(startRow, startColumn, endRow, line.length);\n        }\n    };\n\n}).call(FoldMode.prototype);\n\n});\n\nace.define(\"ace/mode/javascript\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/mode/text\",\"ace/mode/javascript_highlight_rules\",\"ace/mode/matching_brace_outdent\",\"ace/worker/worker_client\",\"ace/mode/behaviour/cstyle\",\"ace/mode/folding/cstyle\"], function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar JavaScriptHighlightRules = require(\"./javascript_highlight_rules\").JavaScriptHighlightRules;\nvar MatchingBraceOutdent = require(\"./matching_brace_outdent\").MatchingBraceOutdent;\nvar WorkerClient = require(\"../worker/worker_client\").WorkerClient;\nvar CstyleBehaviour = require(\"./behaviour/cstyle\").CstyleBehaviour;\nvar CStyleFoldMode = require(\"./folding/cstyle\").FoldMode;\n\nvar Mode = function() {\n    this.HighlightRules = JavaScriptHighlightRules;\n    \n    this.$outdent = new MatchingBraceOutdent();\n    this.$behaviour = new CstyleBehaviour();\n    this.foldingRules = new CStyleFoldMode();\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n\n    this.lineCommentStart = \"//\";\n    this.blockComment = {start: \"/*\", end: \"*/\"};\n    this.$quotes = {'\"': '\"', \"'\": \"'\", \"`\": \"`\"};\n\n    this.getNextLineIndent = function(state, line, tab) {\n        var indent = this.$getIndent(line);\n\n        var tokenizedLine = this.getTokenizer().getLineTokens(line, state);\n        var tokens = tokenizedLine.tokens;\n        var endState = tokenizedLine.state;\n\n        if (tokens.length && tokens[tokens.length-1].type == \"comment\") {\n            return indent;\n        }\n\n        if (state == \"start\" || state == \"no_regex\") {\n            var match = line.match(/^.*(?:\\bcase\\b.*:|[\\{\\(\\[])\\s*$/);\n            if (match) {\n                indent += tab;\n            }\n        } else if (state == \"doc-start\") {\n            if (endState == \"start\" || endState == \"no_regex\") {\n                return \"\";\n            }\n            var match = line.match(/^\\s*(\\/?)\\*/);\n            if (match) {\n                if (match[1]) {\n                    indent += \" \";\n                }\n                indent += \"* \";\n            }\n        }\n\n        return indent;\n    };\n\n    this.checkOutdent = function(state, line, input) {\n        return this.$outdent.checkOutdent(line, input);\n    };\n\n    this.autoOutdent = function(state, doc, row) {\n        this.$outdent.autoOutdent(doc, row);\n    };\n\n    this.createWorker = function(session) {\n        var worker = new WorkerClient([\"ace\"], \"ace/mode/javascript_worker\", \"JavaScriptWorker\");\n        worker.attachToDocument(session.getDocument());\n\n        worker.on(\"annotate\", function(results) {\n            session.setAnnotations(results.data);\n        });\n\n        worker.on(\"terminate\", function() {\n            session.clearAnnotations();\n        });\n\n        return worker;\n    };\n\n    this.$id = \"ace/mode/javascript\";\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});"
  },
  {
    "path": "lib/ace/theme-chrome.js",
    "content": "define(\"ace/theme/chrome\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\"], function(require, exports, module) {\n\nexports.isDark = false;\nexports.cssClass = \"ace-chrome\";\nexports.cssText = \".ace-chrome .ace_gutter {\\\nbackground: #ebebeb;\\\ncolor: #333;\\\noverflow : hidden;\\\n}\\\n.ace-chrome .ace_print-margin {\\\nwidth: 1px;\\\nbackground: #e8e8e8;\\\n}\\\n.ace-chrome {\\\nbackground-color: #FFFFFF;\\\ncolor: black;\\\n}\\\n.ace-chrome .ace_cursor {\\\ncolor: black;\\\n}\\\n.ace-chrome .ace_invisible {\\\ncolor: rgb(191, 191, 191);\\\n}\\\n.ace-chrome .ace_constant.ace_buildin {\\\ncolor: rgb(88, 72, 246);\\\n}\\\n.ace-chrome .ace_constant.ace_language {\\\ncolor: rgb(88, 92, 246);\\\n}\\\n.ace-chrome .ace_constant.ace_library {\\\ncolor: rgb(6, 150, 14);\\\n}\\\n.ace-chrome .ace_invalid {\\\nbackground-color: rgb(153, 0, 0);\\\ncolor: white;\\\n}\\\n.ace-chrome .ace_fold {\\\n}\\\n.ace-chrome .ace_support.ace_function {\\\ncolor: rgb(60, 76, 114);\\\n}\\\n.ace-chrome .ace_support.ace_constant {\\\ncolor: rgb(6, 150, 14);\\\n}\\\n.ace-chrome .ace_support.ace_type,\\\n.ace-chrome .ace_support.ace_class\\\n.ace-chrome .ace_support.ace_other {\\\ncolor: rgb(109, 121, 222);\\\n}\\\n.ace-chrome .ace_variable.ace_parameter {\\\nfont-style:italic;\\\ncolor:#FD971F;\\\n}\\\n.ace-chrome .ace_keyword.ace_operator {\\\ncolor: rgb(104, 118, 135);\\\n}\\\n.ace-chrome .ace_comment {\\\ncolor: #236e24;\\\n}\\\n.ace-chrome .ace_comment.ace_doc {\\\ncolor: #236e24;\\\n}\\\n.ace-chrome .ace_comment.ace_doc.ace_tag {\\\ncolor: #236e24;\\\n}\\\n.ace-chrome .ace_constant.ace_numeric {\\\ncolor: rgb(0, 0, 205);\\\n}\\\n.ace-chrome .ace_variable {\\\ncolor: rgb(49, 132, 149);\\\n}\\\n.ace-chrome .ace_xml-pe {\\\ncolor: rgb(104, 104, 91);\\\n}\\\n.ace-chrome .ace_entity.ace_name.ace_function {\\\ncolor: #0000A2;\\\n}\\\n.ace-chrome .ace_heading {\\\ncolor: rgb(12, 7, 255);\\\n}\\\n.ace-chrome .ace_list {\\\ncolor:rgb(185, 6, 144);\\\n}\\\n.ace-chrome .ace_marker-layer .ace_selection {\\\nbackground: rgb(181, 213, 255);\\\n}\\\n.ace-chrome .ace_marker-layer .ace_step {\\\nbackground: rgb(252, 255, 0);\\\n}\\\n.ace-chrome .ace_marker-layer .ace_stack {\\\nbackground: rgb(164, 229, 101);\\\n}\\\n.ace-chrome .ace_marker-layer .ace_bracket {\\\nmargin: -1px 0 0 -1px;\\\nborder: 1px solid rgb(192, 192, 192);\\\n}\\\n.ace-chrome .ace_marker-layer .ace_active-line {\\\nbackground: rgba(0, 0, 0, 0.07);\\\n}\\\n.ace-chrome .ace_gutter-active-line {\\\nbackground-color : #dcdcdc;\\\n}\\\n.ace-chrome .ace_marker-layer .ace_selected-word {\\\nbackground: rgb(250, 250, 255);\\\nborder: 1px solid rgb(200, 200, 250);\\\n}\\\n.ace-chrome .ace_storage,\\\n.ace-chrome .ace_keyword,\\\n.ace-chrome .ace_meta.ace_tag {\\\ncolor: rgb(147, 15, 128);\\\n}\\\n.ace-chrome .ace_string.ace_regex {\\\ncolor: rgb(255, 0, 0)\\\n}\\\n.ace-chrome .ace_string {\\\ncolor: #1A1AA6;\\\n}\\\n.ace-chrome .ace_entity.ace_other.ace_attribute-name {\\\ncolor: #994409;\\\n}\\\n.ace-chrome .ace_indent-guide {\\\nbackground: url(\\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\\\") right repeat-y;\\\n}\\\n\";\n\nvar dom = require(\"../lib/dom\");\ndom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "lib/ace/theme-idle_fingers.css",
    "content": ".ace-idle-fingers .ace_gutter {\n  background: #3b3b3b;\n  color: rgb(153,153,153)\n}\n\n.ace-idle-fingers .ace_print-margin {\n  width: 1px;\n  background: #3b3b3b\n}\n\n.ace-idle-fingers {\n  background-color: #323232;\n  color: #FFFFFF\n}\n\n.ace-idle-fingers .ace_cursor {\n  color: #91FF00\n}\n\n.ace-idle-fingers .ace_marker-layer .ace_selection {\n  background: rgba(90, 100, 126, 0.88)\n}\n\n.ace-idle-fingers.ace_multiselect .ace_selection.ace_start {\n  box-shadow: 0 0 3px 0px #323232;\n}\n\n.ace-idle-fingers .ace_marker-layer .ace_step {\n  background: rgb(102, 82, 0)\n}\n\n.ace-idle-fingers .ace_marker-layer .ace_bracket {\n  margin: -1px 0 0 -1px;\n  border: 1px solid #404040\n}\n\n.ace-idle-fingers .ace_marker-layer .ace_active-line {\n  background: #353637\n}\n\n.ace-idle-fingers .ace_gutter-active-line {\n  background-color: #353637\n}\n\n.ace-idle-fingers .ace_marker-layer .ace_selected-word {\n  border: 1px solid rgba(90, 100, 126, 0.88)\n}\n\n.ace-idle-fingers .ace_invisible {\n  color: #404040\n}\n\n.ace-idle-fingers .ace_keyword,\n.ace-idle-fingers .ace_meta {\n  color: #CC7833\n}\n\n.ace-idle-fingers .ace_constant,\n.ace-idle-fingers .ace_constant.ace_character,\n.ace-idle-fingers .ace_constant.ace_character.ace_escape,\n.ace-idle-fingers .ace_constant.ace_other,\n.ace-idle-fingers .ace_support.ace_constant {\n  color: #6C99BB\n}\n\n.ace-idle-fingers .ace_invalid {\n  color: #FFFFFF;\n  background-color: #FF0000\n}\n\n.ace-idle-fingers .ace_fold {\n  background-color: #CC7833;\n  border-color: #FFFFFF\n}\n\n.ace-idle-fingers .ace_support.ace_function {\n  color: #B83426\n}\n\n.ace-idle-fingers .ace_variable.ace_parameter {\n  font-style: italic\n}\n\n.ace-idle-fingers .ace_string {\n  color: #A5C261\n}\n\n.ace-idle-fingers .ace_string.ace_regexp {\n  color: #CCCC33\n}\n\n.ace-idle-fingers .ace_comment {\n  font-style: italic;\n  color: #BC9458\n}\n\n.ace-idle-fingers .ace_meta.ace_tag {\n  color: #FFE5BB\n}\n\n.ace-idle-fingers .ace_entity.ace_name {\n  color: #FFC66D\n}\n\n.ace-idle-fingers .ace_collab.ace_user1 {\n  color: #323232;\n  background-color: #FFF980\n}\n\n.ace-idle-fingers .ace_indent-guide {\n  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWMwMjLyZYiPj/8PAAreAwAI1+g0AAAAAElFTkSuQmCC) right repeat-y\n}"
  },
  {
    "path": "lib/ace/theme-idle_fingers.js",
    "content": "ace.define(\"ace/theme/idle_fingers\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\"], function(require, exports, module) {\n\nexports.isDark = true;\nexports.cssClass = \"ace-idle-fingers\";\nexports.cssText = \".ace-idle-fingers .ace_gutter {\\\nbackground: #3b3b3b;\\\ncolor: rgb(153,153,153)\\\n}\\\n.ace-idle-fingers .ace_print-margin {\\\nwidth: 1px;\\\nbackground: #3b3b3b\\\n}\\\n.ace-idle-fingers {\\\nbackground-color: #323232;\\\ncolor: #FFFFFF\\\n}\\\n.ace-idle-fingers .ace_cursor {\\\ncolor: #91FF00\\\n}\\\n.ace-idle-fingers .ace_marker-layer .ace_selection {\\\nbackground: rgba(90, 100, 126, 0.88)\\\n}\\\n.ace-idle-fingers.ace_multiselect .ace_selection.ace_start {\\\nbox-shadow: 0 0 3px 0px #323232;\\\n}\\\n.ace-idle-fingers .ace_marker-layer .ace_step {\\\nbackground: rgb(102, 82, 0)\\\n}\\\n.ace-idle-fingers .ace_marker-layer .ace_bracket {\\\nmargin: -1px 0 0 -1px;\\\nborder: 1px solid #404040\\\n}\\\n.ace-idle-fingers .ace_marker-layer .ace_active-line {\\\nbackground: #353637\\\n}\\\n.ace-idle-fingers .ace_gutter-active-line {\\\nbackground-color: #353637\\\n}\\\n.ace-idle-fingers .ace_marker-layer .ace_selected-word {\\\nborder: 1px solid rgba(90, 100, 126, 0.88)\\\n}\\\n.ace-idle-fingers .ace_invisible {\\\ncolor: #404040\\\n}\\\n.ace-idle-fingers .ace_keyword,\\\n.ace-idle-fingers .ace_meta {\\\ncolor: #CC7833\\\n}\\\n.ace-idle-fingers .ace_constant,\\\n.ace-idle-fingers .ace_constant.ace_character,\\\n.ace-idle-fingers .ace_constant.ace_character.ace_escape,\\\n.ace-idle-fingers .ace_constant.ace_other,\\\n.ace-idle-fingers .ace_support.ace_constant {\\\ncolor: #6C99BB\\\n}\\\n.ace-idle-fingers .ace_invalid {\\\ncolor: #FFFFFF;\\\nbackground-color: #FF0000\\\n}\\\n.ace-idle-fingers .ace_fold {\\\nbackground-color: #CC7833;\\\nborder-color: #FFFFFF\\\n}\\\n.ace-idle-fingers .ace_support.ace_function {\\\ncolor: #B83426\\\n}\\\n.ace-idle-fingers .ace_variable.ace_parameter {\\\nfont-style: italic\\\n}\\\n.ace-idle-fingers .ace_string {\\\ncolor: #A5C261\\\n}\\\n.ace-idle-fingers .ace_string.ace_regexp {\\\ncolor: #CCCC33\\\n}\\\n.ace-idle-fingers .ace_comment {\\\nfont-style: italic;\\\ncolor: #BC9458\\\n}\\\n.ace-idle-fingers .ace_meta.ace_tag {\\\ncolor: #FFE5BB\\\n}\\\n.ace-idle-fingers .ace_entity.ace_name {\\\ncolor: #FFC66D\\\n}\\\n.ace-idle-fingers .ace_collab.ace_user1 {\\\ncolor: #323232;\\\nbackground-color: #FFF980\\\n}\\\n.ace-idle-fingers .ace_indent-guide {\\\nbackground: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWMwMjLyZYiPj/8PAAreAwAI1+g0AAAAAElFTkSuQmCC) right repeat-y\\\n}\";\n\nvar dom = require(\"../lib/dom\");\ndom.importCssString(exports.cssText, exports.cssClass);\n});"
  },
  {
    "path": "lib/ace/theme-tomorrow.js",
    "content": "ace.define(\"ace/theme/tomorrow\",[\"require\",\"exports\",\"module\",\"ace/lib/dom\"], function(require, exports, module) {\n\nexports.isDark = false;\nexports.cssClass = \"ace-tomorrow\";\nexports.cssText = \".ace-tomorrow .ace_gutter {\\\nbackground: #f6f6f6;\\\ncolor: #4D4D4C\\\n}\\\n.ace-tomorrow .ace_print-margin {\\\nwidth: 1px;\\\nbackground: #f6f6f6\\\n}\\\n.ace-tomorrow {\\\nbackground-color: #FFFFFF;\\\ncolor: #4D4D4C\\\n}\\\n.ace-tomorrow .ace_cursor {\\\ncolor: #AEAFAD\\\n}\\\n.ace-tomorrow .ace_marker-layer .ace_selection {\\\nbackground: #D6D6D6\\\n}\\\n.ace-tomorrow.ace_multiselect .ace_selection.ace_start {\\\nbox-shadow: 0 0 3px 0px #FFFFFF;\\\n}\\\n.ace-tomorrow .ace_marker-layer .ace_step {\\\nbackground: rgb(255, 255, 0)\\\n}\\\n.ace-tomorrow .ace_marker-layer .ace_bracket {\\\nmargin: -1px 0 0 -1px;\\\nborder: 1px solid #D1D1D1\\\n}\\\n.ace-tomorrow .ace_marker-layer .ace_active-line {\\\nbackground: #EFEFEF\\\n}\\\n.ace-tomorrow .ace_gutter-active-line {\\\nbackground-color : #dcdcdc\\\n}\\\n.ace-tomorrow .ace_marker-layer .ace_selected-word {\\\nborder: 1px solid #D6D6D6\\\n}\\\n.ace-tomorrow .ace_invisible {\\\ncolor: #D1D1D1\\\n}\\\n.ace-tomorrow .ace_keyword,\\\n.ace-tomorrow .ace_meta,\\\n.ace-tomorrow .ace_storage,\\\n.ace-tomorrow .ace_storage.ace_type,\\\n.ace-tomorrow .ace_support.ace_type {\\\ncolor: #8959A8\\\n}\\\n.ace-tomorrow .ace_keyword.ace_operator {\\\ncolor: #3E999F\\\n}\\\n.ace-tomorrow .ace_constant.ace_character,\\\n.ace-tomorrow .ace_constant.ace_language,\\\n.ace-tomorrow .ace_constant.ace_numeric,\\\n.ace-tomorrow .ace_keyword.ace_other.ace_unit,\\\n.ace-tomorrow .ace_support.ace_constant,\\\n.ace-tomorrow .ace_variable.ace_parameter {\\\ncolor: #F5871F\\\n}\\\n.ace-tomorrow .ace_constant.ace_other {\\\ncolor: #666969\\\n}\\\n.ace-tomorrow .ace_invalid {\\\ncolor: #FFFFFF;\\\nbackground-color: #C82829\\\n}\\\n.ace-tomorrow .ace_invalid.ace_deprecated {\\\ncolor: #FFFFFF;\\\nbackground-color: #8959A8\\\n}\\\n.ace-tomorrow .ace_fold {\\\nbackground-color: #4271AE;\\\nborder-color: #4D4D4C\\\n}\\\n.ace-tomorrow .ace_entity.ace_name.ace_function,\\\n.ace-tomorrow .ace_support.ace_function,\\\n.ace-tomorrow .ace_variable {\\\ncolor: #4271AE\\\n}\\\n.ace-tomorrow .ace_support.ace_class,\\\n.ace-tomorrow .ace_support.ace_type {\\\ncolor: #C99E00\\\n}\\\n.ace-tomorrow .ace_heading,\\\n.ace-tomorrow .ace_markup.ace_heading,\\\n.ace-tomorrow .ace_string {\\\ncolor: #718C00\\\n}\\\n.ace-tomorrow .ace_entity.ace_name.ace_tag,\\\n.ace-tomorrow .ace_entity.ace_other.ace_attribute-name,\\\n.ace-tomorrow .ace_meta.ace_tag,\\\n.ace-tomorrow .ace_string.ace_regexp,\\\n.ace-tomorrow .ace_variable {\\\ncolor: #C82829\\\n}\\\n.ace-tomorrow .ace_comment {\\\ncolor: #8E908C\\\n}\\\n.ace-tomorrow .ace_indent-guide {\\\nbackground: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bdu3f/BwAlfgctduB85QAAAABJRU5ErkJggg==) right repeat-y\\\n}\";\n\nvar dom = require(\"../lib/dom\");\ndom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "lib/ace/worker-javascript.js",
    "content": "\"no use strict\";\n;(function(window) {\nif (typeof window.window != \"undefined\" && window.document)\n    return;\nif (window.require && window.define)\n    return;\n\nif (!window.console) {\n    window.console = function() {\n        var msgs = Array.prototype.slice.call(arguments, 0);\n        postMessage({type: \"log\", data: msgs});\n    };\n    window.console.error =\n    window.console.warn = \n    window.console.log =\n    window.console.trace = window.console;\n}\nwindow.window = window;\nwindow.ace = window;\n\n// wick specific - using this for regex thing to squash missing semicolon error\nString.prototype.splice = function(start, delCount, newSubStr) {\n    return this.slice(0, start) + newSubStr + this.slice(start + Math.abs(delCount));\n};\n\nwindow.onerror = function(message, file, line, col, err) {\n    postMessage({type: \"error\", data: {\n        message: message,\n        data: err.data,\n        file: file,\n        line: line, \n        col: col,\n        stack: err.stack\n    }});\n};\n\nwindow.normalizeModule = function(parentId, moduleName) {\n    // normalize plugin requires\n    if (moduleName.indexOf(\"!\") !== -1) {\n        var chunks = moduleName.split(\"!\");\n        return window.normalizeModule(parentId, chunks[0]) + \"!\" + window.normalizeModule(parentId, chunks[1]);\n    }\n    // normalize relative requires\n    if (moduleName.charAt(0) == \".\") {\n        var base = parentId.split(\"/\").slice(0, -1).join(\"/\");\n        moduleName = (base ? base + \"/\" : \"\") + moduleName;\n        \n        while (moduleName.indexOf(\".\") !== -1 && previous != moduleName) {\n            var previous = moduleName;\n            moduleName = moduleName.replace(/^\\.\\//, \"\").replace(/\\/\\.\\//, \"/\").replace(/[^\\/]+\\/\\.\\.\\//, \"\");\n        }\n    }\n    \n    return moduleName;\n};\n\nwindow.require = function require(parentId, id) {\n    if (!id) {\n        id = parentId;\n        parentId = null;\n    }\n    if (!id.charAt)\n        throw new Error(\"worker.js require() accepts only (parentId, id) as arguments\");\n\n    id = window.normalizeModule(parentId, id);\n\n    var module = window.require.modules[id];\n    if (module) {\n        if (!module.initialized) {\n            module.initialized = true;\n            module.exports = module.factory().exports;\n        }\n        return module.exports;\n    }\n   \n    if (!window.require.tlns)\n        return console.log(\"unable to load \" + id);\n    \n    var path = resolveModuleId(id, window.require.tlns);\n    if (path.slice(-3) != \".js\") path += \".js\";\n    \n    window.require.id = id;\n    window.require.modules[id] = {}; // prevent infinite loop on broken modules\n    importScripts(path);\n    return window.require(parentId, id);\n};\nfunction resolveModuleId(id, paths) {\n    var testPath = id, tail = \"\";\n    while (testPath) {\n        var alias = paths[testPath];\n        if (typeof alias == \"string\") {\n            return alias + tail;\n        } else if (alias) {\n            return  alias.location.replace(/\\/*$/, \"/\") + (tail || alias.main || alias.name);\n        } else if (alias === false) {\n            return \"\";\n        }\n        var i = testPath.lastIndexOf(\"/\");\n        if (i === -1) break;\n        tail = testPath.substr(i) + tail;\n        testPath = testPath.slice(0, i);\n    }\n    return id;\n}\nwindow.require.modules = {};\nwindow.require.tlns = {};\n\nwindow.define = function(id, deps, factory) {\n    if (arguments.length == 2) {\n        factory = deps;\n        if (typeof id != \"string\") {\n            deps = id;\n            id = window.require.id;\n        }\n    } else if (arguments.length == 1) {\n        factory = id;\n        deps = [];\n        id = window.require.id;\n    }\n    \n    if (typeof factory != \"function\") {\n        window.require.modules[id] = {\n            exports: factory,\n            initialized: true\n        };\n        return;\n    }\n\n    if (!deps.length)\n        // If there is no dependencies, we inject \"require\", \"exports\" and\n        // \"module\" as dependencies, to provide CommonJS compatibility.\n        deps = [\"require\", \"exports\", \"module\"];\n\n    var req = function(childId) {\n        return window.require(id, childId);\n    };\n\n    window.require.modules[id] = {\n        exports: {},\n        factory: function() {\n            var module = this;\n            var returnExports = factory.apply(this, deps.map(function(dep) {\n                switch (dep) {\n                    // Because \"require\", \"exports\" and \"module\" aren't actual\n                    // dependencies, we must handle them seperately.\n                    case \"require\": return req;\n                    case \"exports\": return module.exports;\n                    case \"module\":  return module;\n                    // But for all other dependencies, we can just go ahead and\n                    // require them.\n                    default:        return req(dep);\n                }\n            }));\n            if (returnExports)\n                module.exports = returnExports;\n            return module;\n        }\n    };\n};\nwindow.define.amd = {};\nrequire.tlns = {};\nwindow.initBaseUrls  = function initBaseUrls(topLevelNamespaces) {\n    for (var i in topLevelNamespaces)\n        require.tlns[i] = topLevelNamespaces[i];\n};\n\nwindow.initSender = function initSender() {\n\n    var EventEmitter = window.require(\"ace/lib/event_emitter\").EventEmitter;\n    var oop = window.require(\"ace/lib/oop\");\n    \n    var Sender = function() {};\n    \n    (function() {\n        \n        oop.implement(this, EventEmitter);\n                \n        this.callback = function(data, callbackId) {\n            postMessage({\n                type: \"call\",\n                id: callbackId,\n                data: data\n            });\n        };\n    \n        this.emit = function(name, data) {\n            postMessage({\n                type: \"event\",\n                name: name,\n                data: data\n            });\n        };\n        \n    }).call(Sender.prototype);\n    \n    return new Sender();\n};\n\nvar main = window.main = null;\nvar sender = window.sender = null;\n\nwindow.onmessage = function(e) {\n    var msg = e.data;\n    if (msg.event && sender) {\n        sender._signal(msg.event, msg.data);\n    }\n    else if (msg.command) {\n        if (main[msg.command])\n            main[msg.command].apply(main, msg.args);\n        else if (window[msg.command])\n            window[msg.command].apply(window, msg.args);\n        else\n            throw new Error(\"Unknown command:\" + msg.command);\n    }\n    else if (msg.init) {\n        window.initBaseUrls(msg.tlns);\n        require(\"ace/lib/es5-shim\");\n        sender = window.sender = window.initSender();\n        var clazz = require(msg.module)[msg.classname];\n        main = window.main = new clazz(sender);\n    }\n};\n})(this);\n\ndefine(\"ace/lib/oop\",[\"require\",\"exports\",\"module\"], function(require, exports, module) {\n\"use strict\";\n\nexports.inherits = function(ctor, superCtor) {\n    ctor.super_ = superCtor;\n    ctor.prototype = Object.create(superCtor.prototype, {\n        constructor: {\n            value: ctor,\n            enumerable: false,\n            writable: true,\n            configurable: true\n        }\n    });\n};\n\nexports.mixin = function(obj, mixin) {\n    for (var key in mixin) {\n        obj[key] = mixin[key];\n    }\n    return obj;\n};\n\nexports.implement = function(proto, mixin) {\n    exports.mixin(proto, mixin);\n};\n\n});\n\ndefine(\"ace/range\",[\"require\",\"exports\",\"module\"], function(require, exports, module) {\n\"use strict\";\nvar comparePoints = function(p1, p2) {\n    return p1.row - p2.row || p1.column - p2.column;\n};\nvar Range = function(startRow, startColumn, endRow, endColumn) {\n    this.start = {\n        row: startRow,\n        column: startColumn\n    };\n\n    this.end = {\n        row: endRow,\n        column: endColumn\n    };\n};\n\n(function() {\n    this.isEqual = function(range) {\n        return this.start.row === range.start.row &&\n            this.end.row === range.end.row &&\n            this.start.column === range.start.column &&\n            this.end.column === range.end.column;\n    };\n    this.toString = function() {\n        return (\"Range: [\" + this.start.row + \"/\" + this.start.column +\n            \"] -> [\" + this.end.row + \"/\" + this.end.column + \"]\");\n    };\n\n    this.contains = function(row, column) {\n        return this.compare(row, column) == 0;\n    };\n    this.compareRange = function(range) {\n        var cmp,\n            end = range.end,\n            start = range.start;\n\n        cmp = this.compare(end.row, end.column);\n        if (cmp == 1) {\n            cmp = this.compare(start.row, start.column);\n            if (cmp == 1) {\n                return 2;\n            } else if (cmp == 0) {\n                return 1;\n            } else {\n                return 0;\n            }\n        } else if (cmp == -1) {\n            return -2;\n        } else {\n            cmp = this.compare(start.row, start.column);\n            if (cmp == -1) {\n                return -1;\n            } else if (cmp == 1) {\n                return 42;\n            } else {\n                return 0;\n            }\n        }\n    };\n    this.comparePoint = function(p) {\n        return this.compare(p.row, p.column);\n    };\n    this.containsRange = function(range) {\n        return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0;\n    };\n    this.intersects = function(range) {\n        var cmp = this.compareRange(range);\n        return (cmp == -1 || cmp == 0 || cmp == 1);\n    };\n    this.isEnd = function(row, column) {\n        return this.end.row == row && this.end.column == column;\n    };\n    this.isStart = function(row, column) {\n        return this.start.row == row && this.start.column == column;\n    };\n    this.setStart = function(row, column) {\n        if (typeof row == \"object\") {\n            this.start.column = row.column;\n            this.start.row = row.row;\n        } else {\n            this.start.row = row;\n            this.start.column = column;\n        }\n    };\n    this.setEnd = function(row, column) {\n        if (typeof row == \"object\") {\n            this.end.column = row.column;\n            this.end.row = row.row;\n        } else {\n            this.end.row = row;\n            this.end.column = column;\n        }\n    };\n    this.inside = function(row, column) {\n        if (this.compare(row, column) == 0) {\n            if (this.isEnd(row, column) || this.isStart(row, column)) {\n                return false;\n            } else {\n                return true;\n            }\n        }\n        return false;\n    };\n    this.insideStart = function(row, column) {\n        if (this.compare(row, column) == 0) {\n            if (this.isEnd(row, column)) {\n                return false;\n            } else {\n                return true;\n            }\n        }\n        return false;\n    };\n    this.insideEnd = function(row, column) {\n        if (this.compare(row, column) == 0) {\n            if (this.isStart(row, column)) {\n                return false;\n            } else {\n                return true;\n            }\n        }\n        return false;\n    };\n    this.compare = function(row, column) {\n        if (!this.isMultiLine()) {\n            if (row === this.start.row) {\n                return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0);\n            }\n        }\n\n        if (row < this.start.row)\n            return -1;\n\n        if (row > this.end.row)\n            return 1;\n\n        if (this.start.row === row)\n            return column >= this.start.column ? 0 : -1;\n\n        if (this.end.row === row)\n            return column <= this.end.column ? 0 : 1;\n\n        return 0;\n    };\n    this.compareStart = function(row, column) {\n        if (this.start.row == row && this.start.column == column) {\n            return -1;\n        } else {\n            return this.compare(row, column);\n        }\n    };\n    this.compareEnd = function(row, column) {\n        if (this.end.row == row && this.end.column == column) {\n            return 1;\n        } else {\n            return this.compare(row, column);\n        }\n    };\n    this.compareInside = function(row, column) {\n        if (this.end.row == row && this.end.column == column) {\n            return 1;\n        } else if (this.start.row == row && this.start.column == column) {\n            return -1;\n        } else {\n            return this.compare(row, column);\n        }\n    };\n    this.clipRows = function(firstRow, lastRow) {\n        if (this.end.row > lastRow)\n            var end = {row: lastRow + 1, column: 0};\n        else if (this.end.row < firstRow)\n            var end = {row: firstRow, column: 0};\n\n        if (this.start.row > lastRow)\n            var start = {row: lastRow + 1, column: 0};\n        else if (this.start.row < firstRow)\n            var start = {row: firstRow, column: 0};\n\n        return Range.fromPoints(start || this.start, end || this.end);\n    };\n    this.extend = function(row, column) {\n        var cmp = this.compare(row, column);\n\n        if (cmp == 0)\n            return this;\n        else if (cmp == -1)\n            var start = {row: row, column: column};\n        else\n            var end = {row: row, column: column};\n\n        return Range.fromPoints(start || this.start, end || this.end);\n    };\n\n    this.isEmpty = function() {\n        return (this.start.row === this.end.row && this.start.column === this.end.column);\n    };\n    this.isMultiLine = function() {\n        return (this.start.row !== this.end.row);\n    };\n    this.clone = function() {\n        return Range.fromPoints(this.start, this.end);\n    };\n    this.collapseRows = function() {\n        if (this.end.column == 0)\n            return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0)\n        else\n            return new Range(this.start.row, 0, this.end.row, 0)\n    };\n    this.toScreenRange = function(session) {\n        var screenPosStart = session.documentToScreenPosition(this.start);\n        var screenPosEnd = session.documentToScreenPosition(this.end);\n\n        return new Range(\n            screenPosStart.row, screenPosStart.column,\n            screenPosEnd.row, screenPosEnd.column\n        );\n    };\n    this.moveBy = function(row, column) {\n        this.start.row += row;\n        this.start.column += column;\n        this.end.row += row;\n        this.end.column += column;\n    };\n\n}).call(Range.prototype);\nRange.fromPoints = function(start, end) {\n    return new Range(start.row, start.column, end.row, end.column);\n};\nRange.comparePoints = comparePoints;\n\nRange.comparePoints = function(p1, p2) {\n    return p1.row - p2.row || p1.column - p2.column;\n};\n\n\nexports.Range = Range;\n});\n\ndefine(\"ace/apply_delta\",[\"require\",\"exports\",\"module\"], function(require, exports, module) {\n\"use strict\";\n\nfunction throwDeltaError(delta, errorText){\n    console.log(\"Invalid Delta:\", delta);\n    throw \"Invalid Delta: \" + errorText;\n}\n\nfunction positionInDocument(docLines, position) {\n    return position.row    >= 0 && position.row    <  docLines.length &&\n           position.column >= 0 && position.column <= docLines[position.row].length;\n}\n\nfunction validateDelta(docLines, delta) {\n    if (delta.action != \"insert\" && delta.action != \"remove\")\n        throwDeltaError(delta, \"delta.action must be 'insert' or 'remove'\");\n    if (!(delta.lines instanceof Array))\n        throwDeltaError(delta, \"delta.lines must be an Array\");\n    if (!delta.start || !delta.end)\n       throwDeltaError(delta, \"delta.start/end must be an present\");\n    var start = delta.start;\n    if (!positionInDocument(docLines, delta.start))\n        throwDeltaError(delta, \"delta.start must be contained in document\");\n    var end = delta.end;\n    if (delta.action == \"remove\" && !positionInDocument(docLines, end))\n        throwDeltaError(delta, \"delta.end must contained in document for 'remove' actions\");\n    var numRangeRows = end.row - start.row;\n    var numRangeLastLineChars = (end.column - (numRangeRows == 0 ? start.column : 0));\n    if (numRangeRows != delta.lines.length - 1 || delta.lines[numRangeRows].length != numRangeLastLineChars)\n        throwDeltaError(delta, \"delta.range must match delta lines\");\n}\n\nexports.applyDelta = function(docLines, delta, doNotValidate) {\n    \n    var row = delta.start.row;\n    var startColumn = delta.start.column;\n    var line = docLines[row] || \"\";\n    switch (delta.action) {\n        case \"insert\":\n            var lines = delta.lines;\n            if (lines.length === 1) {\n                docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn);\n            } else {\n                var args = [row, 1].concat(delta.lines);\n                docLines.splice.apply(docLines, args);\n                docLines[row] = line.substring(0, startColumn) + docLines[row];\n                docLines[row + delta.lines.length - 1] += line.substring(startColumn);\n            }\n            break;\n        case \"remove\":\n            var endColumn = delta.end.column;\n            var endRow = delta.end.row;\n            if (row === endRow) {\n                docLines[row] = line.substring(0, startColumn) + line.substring(endColumn);\n            } else {\n                docLines.splice(\n                    row, endRow - row + 1,\n                    line.substring(0, startColumn) + docLines[endRow].substring(endColumn)\n                );\n            }\n            break;\n    }\n}\n});\n\ndefine(\"ace/lib/event_emitter\",[\"require\",\"exports\",\"module\"], function(require, exports, module) {\n\"use strict\";\n\nvar EventEmitter = {};\nvar stopPropagation = function() { this.propagationStopped = true; };\nvar preventDefault = function() { this.defaultPrevented = true; };\n\nEventEmitter._emit =\nEventEmitter._dispatchEvent = function(eventName, e) {\n    this._eventRegistry || (this._eventRegistry = {});\n    this._defaultHandlers || (this._defaultHandlers = {});\n\n    var listeners = this._eventRegistry[eventName] || [];\n    var defaultHandler = this._defaultHandlers[eventName];\n    if (!listeners.length && !defaultHandler)\n        return;\n\n    if (typeof e != \"object\" || !e)\n        e = {};\n\n    if (!e.type)\n        e.type = eventName;\n    if (!e.stopPropagation)\n        e.stopPropagation = stopPropagation;\n    if (!e.preventDefault)\n        e.preventDefault = preventDefault;\n\n    listeners = listeners.slice();\n    for (var i=0; i<listeners.length; i++) {\n        listeners[i](e, this);\n        if (e.propagationStopped)\n            break;\n    }\n    \n    if (defaultHandler && !e.defaultPrevented)\n        return defaultHandler(e, this);\n};\n\n\nEventEmitter._signal = function(eventName, e) {\n    var listeners = (this._eventRegistry || {})[eventName];\n    if (!listeners)\n        return;\n    listeners = listeners.slice();\n    for (var i=0; i<listeners.length; i++)\n        listeners[i](e, this);\n};\n\nEventEmitter.once = function(eventName, callback) {\n    var _self = this;\n    callback && this.addEventListener(eventName, function newCallback() {\n        _self.removeEventListener(eventName, newCallback);\n        callback.apply(null, arguments);\n    });\n};\n\n\nEventEmitter.setDefaultHandler = function(eventName, callback) {\n    var handlers = this._defaultHandlers\n    if (!handlers)\n        handlers = this._defaultHandlers = {_disabled_: {}};\n    \n    if (handlers[eventName]) {\n        var old = handlers[eventName];\n        var disabled = handlers._disabled_[eventName];\n        if (!disabled)\n            handlers._disabled_[eventName] = disabled = [];\n        disabled.push(old);\n        var i = disabled.indexOf(callback);\n        if (i != -1) \n            disabled.splice(i, 1);\n    }\n    handlers[eventName] = callback;\n};\nEventEmitter.removeDefaultHandler = function(eventName, callback) {\n    var handlers = this._defaultHandlers\n    if (!handlers)\n        return;\n    var disabled = handlers._disabled_[eventName];\n    \n    if (handlers[eventName] == callback) {\n        var old = handlers[eventName];\n        if (disabled)\n            this.setDefaultHandler(eventName, disabled.pop());\n    } else if (disabled) {\n        var i = disabled.indexOf(callback);\n        if (i != -1)\n            disabled.splice(i, 1);\n    }\n};\n\nEventEmitter.on =\nEventEmitter.addEventListener = function(eventName, callback, capturing) {\n    this._eventRegistry = this._eventRegistry || {};\n\n    var listeners = this._eventRegistry[eventName];\n    if (!listeners)\n        listeners = this._eventRegistry[eventName] = [];\n\n    if (listeners.indexOf(callback) == -1)\n        listeners[capturing ? \"unshift\" : \"push\"](callback);\n    return callback;\n};\n\nEventEmitter.off =\nEventEmitter.removeListener =\nEventEmitter.removeEventListener = function(eventName, callback) {\n    this._eventRegistry = this._eventRegistry || {};\n\n    var listeners = this._eventRegistry[eventName];\n    if (!listeners)\n        return;\n\n    var index = listeners.indexOf(callback);\n    if (index !== -1)\n        listeners.splice(index, 1);\n};\n\nEventEmitter.removeAllListeners = function(eventName) {\n    if (this._eventRegistry) this._eventRegistry[eventName] = [];\n};\n\nexports.EventEmitter = EventEmitter;\n\n});\n\ndefine(\"ace/anchor\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/lib/event_emitter\"], function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"./lib/oop\");\nvar EventEmitter = require(\"./lib/event_emitter\").EventEmitter;\n\nvar Anchor = exports.Anchor = function(doc, row, column) {\n    this.$onChange = this.onChange.bind(this);\n    this.attach(doc);\n    \n    if (typeof column == \"undefined\")\n        this.setPosition(row.row, row.column);\n    else\n        this.setPosition(row, column);\n};\n\n(function() {\n\n    oop.implement(this, EventEmitter);\n    this.getPosition = function() {\n        return this.$clipPositionToDocument(this.row, this.column);\n    };\n    this.getDocument = function() {\n        return this.document;\n    };\n    this.$insertRight = false;\n    this.onChange = function(delta) {\n        if (delta.start.row == delta.end.row && delta.start.row != this.row)\n            return;\n\n        if (delta.start.row > this.row)\n            return;\n            \n        var point = $getTransformedPoint(delta, {row: this.row, column: this.column}, this.$insertRight);\n        this.setPosition(point.row, point.column, true);\n    };\n    \n    function $pointsInOrder(point1, point2, equalPointsInOrder) {\n        var bColIsAfter = equalPointsInOrder ? point1.column <= point2.column : point1.column < point2.column;\n        return (point1.row < point2.row) || (point1.row == point2.row && bColIsAfter);\n    }\n            \n    function $getTransformedPoint(delta, point, moveIfEqual) {\n        var deltaIsInsert = delta.action == \"insert\";\n        var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.end.row    - delta.start.row);\n        var deltaColShift = (deltaIsInsert ? 1 : -1) * (delta.end.column - delta.start.column);\n        var deltaStart = delta.start;\n        var deltaEnd = deltaIsInsert ? deltaStart : delta.end; // Collapse insert range.\n        if ($pointsInOrder(point, deltaStart, moveIfEqual)) {\n            return {\n                row: point.row,\n                column: point.column\n            };\n        }\n        if ($pointsInOrder(deltaEnd, point, !moveIfEqual)) {\n            return {\n                row: point.row + deltaRowShift,\n                column: point.column + (point.row == deltaEnd.row ? deltaColShift : 0)\n            };\n        }\n        \n        return {\n            row: deltaStart.row,\n            column: deltaStart.column\n        };\n    }\n    this.setPosition = function(row, column, noClip) {\n        var pos;\n        if (noClip) {\n            pos = {\n                row: row,\n                column: column\n            };\n        } else {\n            pos = this.$clipPositionToDocument(row, column);\n        }\n\n        if (this.row == pos.row && this.column == pos.column)\n            return;\n\n        var old = {\n            row: this.row,\n            column: this.column\n        };\n\n        this.row = pos.row;\n        this.column = pos.column;\n        this._signal(\"change\", {\n            old: old,\n            value: pos\n        });\n    };\n    this.detach = function() {\n        this.document.removeEventListener(\"change\", this.$onChange);\n    };\n    this.attach = function(doc) {\n        this.document = doc || this.document;\n        this.document.on(\"change\", this.$onChange);\n    };\n    this.$clipPositionToDocument = function(row, column) {\n        var pos = {};\n\n        if (row >= this.document.getLength()) {\n            pos.row = Math.max(0, this.document.getLength() - 1);\n            pos.column = this.document.getLine(pos.row).length;\n        }\n        else if (row < 0) {\n            pos.row = 0;\n            pos.column = 0;\n        }\n        else {\n            pos.row = row;\n            pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column));\n        }\n\n        if (column < 0)\n            pos.column = 0;\n\n        return pos;\n    };\n\n}).call(Anchor.prototype);\n\n});\n\ndefine(\"ace/document\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/apply_delta\",\"ace/lib/event_emitter\",\"ace/range\",\"ace/anchor\"], function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"./lib/oop\");\nvar applyDelta = require(\"./apply_delta\").applyDelta;\nvar EventEmitter = require(\"./lib/event_emitter\").EventEmitter;\nvar Range = require(\"./range\").Range;\nvar Anchor = require(\"./anchor\").Anchor;\n\nvar Document = function(textOrLines) {\n    this.$lines = [\"\"];\n    if (textOrLines.length === 0) {\n        this.$lines = [\"\"];\n    } else if (Array.isArray(textOrLines)) {\n        this.insertMergedLines({row: 0, column: 0}, textOrLines);\n    } else {\n        this.insert({row: 0, column:0}, textOrLines);\n    }\n};\n\n(function() {\n\n    oop.implement(this, EventEmitter);\n    this.setValue = function(text) {\n        var len = this.getLength() - 1;\n        this.remove(new Range(0, 0, len, this.getLine(len).length));\n        this.insert({row: 0, column: 0}, text);\n    };\n    this.getValue = function() {\n        return this.getAllLines().join(this.getNewLineCharacter());\n    };\n    this.createAnchor = function(row, column) {\n        return new Anchor(this, row, column);\n    };\n    if (\"aaa\".split(/a/).length === 0) {\n        this.$split = function(text) {\n            return text.replace(/\\r\\n|\\r/g, \"\\n\").split(\"\\n\");\n        };\n    } else {\n        this.$split = function(text) {\n            return text.split(/\\r\\n|\\r|\\n/);\n        };\n    }\n\n\n    this.$detectNewLine = function(text) {\n        var match = text.match(/^.*?(\\r\\n|\\r|\\n)/m);\n        this.$autoNewLine = match ? match[1] : \"\\n\";\n        this._signal(\"changeNewLineMode\");\n    };\n    this.getNewLineCharacter = function() {\n        switch (this.$newLineMode) {\n          case \"windows\":\n            return \"\\r\\n\";\n          case \"unix\":\n            return \"\\n\";\n          default:\n            return this.$autoNewLine || \"\\n\";\n        }\n    };\n\n    this.$autoNewLine = \"\";\n    this.$newLineMode = \"auto\";\n    this.setNewLineMode = function(newLineMode) {\n        if (this.$newLineMode === newLineMode)\n            return;\n\n        this.$newLineMode = newLineMode;\n        this._signal(\"changeNewLineMode\");\n    };\n    this.getNewLineMode = function() {\n        return this.$newLineMode;\n    };\n    this.isNewLine = function(text) {\n        return (text == \"\\r\\n\" || text == \"\\r\" || text == \"\\n\");\n    };\n    this.getLine = function(row) {\n        return this.$lines[row] || \"\";\n    };\n    this.getLines = function(firstRow, lastRow) {\n        return this.$lines.slice(firstRow, lastRow + 1);\n    };\n    this.getAllLines = function() {\n        return this.getLines(0, this.getLength());\n    };\n    this.getLength = function() {\n        return this.$lines.length;\n    };\n    this.getTextRange = function(range) {\n        return this.getLinesForRange(range).join(this.getNewLineCharacter());\n    };\n    this.getLinesForRange = function(range) {\n        var lines;\n        if (range.start.row === range.end.row) {\n            lines = [this.getLine(range.start.row).substring(range.start.column, range.end.column)];\n        } else {\n            lines = this.getLines(range.start.row, range.end.row);\n            lines[0] = (lines[0] || \"\").substring(range.start.column);\n            var l = lines.length - 1;\n            if (range.end.row - range.start.row == l)\n                lines[l] = lines[l].substring(0, range.end.column);\n        }\n        return lines;\n    };\n    this.insertLines = function(row, lines) {\n        console.warn(\"Use of document.insertLines is deprecated. Use the insertFullLines method instead.\");\n        return this.insertFullLines(row, lines);\n    };\n    this.removeLines = function(firstRow, lastRow) {\n        console.warn(\"Use of document.removeLines is deprecated. Use the removeFullLines method instead.\");\n        return this.removeFullLines(firstRow, lastRow);\n    };\n    this.insertNewLine = function(position) {\n        console.warn(\"Use of document.insertNewLine is deprecated. Use insertMergedLines(position, [\\'\\', \\'\\']) instead.\");\n        return this.insertMergedLines(position, [\"\", \"\"]);\n    };\n    this.insert = function(position, text) {\n        if (this.getLength() <= 1)\n            this.$detectNewLine(text);\n        \n        return this.insertMergedLines(position, this.$split(text));\n    };\n    this.insertInLine = function(position, text) {\n        var start = this.clippedPos(position.row, position.column);\n        var end = this.pos(position.row, position.column + text.length);\n        \n        this.applyDelta({\n            start: start,\n            end: end,\n            action: \"insert\",\n            lines: [text]\n        }, true);\n        \n        return this.clonePos(end);\n    };\n    \n    this.clippedPos = function(row, column) {\n        var length = this.getLength();\n        if (row === undefined) {\n            row = length;\n        } else if (row < 0) {\n            row = 0;\n        } else if (row >= length) {\n            row = length - 1;\n            column = undefined;\n        }\n        var line = this.getLine(row);\n        if (column == undefined)\n            column = line.length;\n        column = Math.min(Math.max(column, 0), line.length);\n        return {row: row, column: column};\n    };\n    \n    this.clonePos = function(pos) {\n        return {row: pos.row, column: pos.column};\n    };\n    \n    this.pos = function(row, column) {\n        return {row: row, column: column};\n    };\n    \n    this.$clipPosition = function(position) {\n        var length = this.getLength();\n        if (position.row >= length) {\n            position.row = Math.max(0, length - 1);\n            position.column = this.getLine(length - 1).length;\n        } else {\n            position.row = Math.max(0, position.row);\n            position.column = Math.min(Math.max(position.column, 0), this.getLine(position.row).length);\n        }\n        return position;\n    };\n    this.insertFullLines = function(row, lines) {\n        row = Math.min(Math.max(row, 0), this.getLength());\n        var column = 0;\n        if (row < this.getLength()) {\n            lines = lines.concat([\"\"]);\n            column = 0;\n        } else {\n            lines = [\"\"].concat(lines);\n            row--;\n            column = this.$lines[row].length;\n        }\n        this.insertMergedLines({row: row, column: column}, lines);\n    };    \n    this.insertMergedLines = function(position, lines) {\n        var start = this.clippedPos(position.row, position.column);\n        var end = {\n            row: start.row + lines.length - 1,\n            column: (lines.length == 1 ? start.column : 0) + lines[lines.length - 1].length\n        };\n        \n        this.applyDelta({\n            start: start,\n            end: end,\n            action: \"insert\",\n            lines: lines\n        });\n        \n        return this.clonePos(end);\n    };\n    this.remove = function(range) {\n        var start = this.clippedPos(range.start.row, range.start.column);\n        var end = this.clippedPos(range.end.row, range.end.column);\n        this.applyDelta({\n            start: start,\n            end: end,\n            action: \"remove\",\n            lines: this.getLinesForRange({start: start, end: end})\n        });\n        return this.clonePos(start);\n    };\n    this.removeInLine = function(row, startColumn, endColumn) {\n        var start = this.clippedPos(row, startColumn);\n        var end = this.clippedPos(row, endColumn);\n        \n        this.applyDelta({\n            start: start,\n            end: end,\n            action: \"remove\",\n            lines: this.getLinesForRange({start: start, end: end})\n        }, true);\n        \n        return this.clonePos(start);\n    };\n    this.removeFullLines = function(firstRow, lastRow) {\n        firstRow = Math.min(Math.max(0, firstRow), this.getLength() - 1);\n        lastRow  = Math.min(Math.max(0, lastRow ), this.getLength() - 1);\n        var deleteFirstNewLine = lastRow == this.getLength() - 1 && firstRow > 0;\n        var deleteLastNewLine  = lastRow  < this.getLength() - 1;\n        var startRow = ( deleteFirstNewLine ? firstRow - 1                  : firstRow                    );\n        var startCol = ( deleteFirstNewLine ? this.getLine(startRow).length : 0                           );\n        var endRow   = ( deleteLastNewLine  ? lastRow + 1                   : lastRow                     );\n        var endCol   = ( deleteLastNewLine  ? 0                             : this.getLine(endRow).length ); \n        var range = new Range(startRow, startCol, endRow, endCol);\n        var deletedLines = this.$lines.slice(firstRow, lastRow + 1);\n        \n        this.applyDelta({\n            start: range.start,\n            end: range.end,\n            action: \"remove\",\n            lines: this.getLinesForRange(range)\n        });\n        return deletedLines;\n    };\n    this.removeNewLine = function(row) {\n        if (row < this.getLength() - 1 && row >= 0) {\n            this.applyDelta({\n                start: this.pos(row, this.getLine(row).length),\n                end: this.pos(row + 1, 0),\n                action: \"remove\",\n                lines: [\"\", \"\"]\n            });\n        }\n    };\n    this.replace = function(range, text) {\n        if (!(range instanceof Range))\n            range = Range.fromPoints(range.start, range.end);\n        if (text.length === 0 && range.isEmpty())\n            return range.start;\n        if (text == this.getTextRange(range))\n            return range.end;\n\n        this.remove(range);\n        var end;\n        if (text) {\n            end = this.insert(range.start, text);\n        }\n        else {\n            end = range.start;\n        }\n        \n        return end;\n    };\n    this.applyDeltas = function(deltas) {\n        for (var i=0; i<deltas.length; i++) {\n            this.applyDelta(deltas[i]);\n        }\n    };\n    this.revertDeltas = function(deltas) {\n        for (var i=deltas.length-1; i>=0; i--) {\n            this.revertDelta(deltas[i]);\n        }\n    };\n    this.applyDelta = function(delta, doNotValidate) {\n        var isInsert = delta.action == \"insert\";\n        if (isInsert ? delta.lines.length <= 1 && !delta.lines[0]\n            : !Range.comparePoints(delta.start, delta.end)) {\n            return;\n        }\n        \n        if (isInsert && delta.lines.length > 20000)\n            this.$splitAndapplyLargeDelta(delta, 20000);\n        applyDelta(this.$lines, delta, doNotValidate);\n        this._signal(\"change\", delta);\n    };\n    \n    this.$splitAndapplyLargeDelta = function(delta, MAX) {\n        var lines = delta.lines;\n        var l = lines.length;\n        var row = delta.start.row; \n        var column = delta.start.column;\n        var from = 0, to = 0;\n        do {\n            from = to;\n            to += MAX - 1;\n            var chunk = lines.slice(from, to);\n            if (to > l) {\n                delta.lines = chunk;\n                delta.start.row = row + from;\n                delta.start.column = column;\n                break;\n            }\n            chunk.push(\"\");\n            this.applyDelta({\n                start: this.pos(row + from, column),\n                end: this.pos(row + to, column = 0),\n                action: delta.action,\n                lines: chunk\n            }, true);\n        } while(true);\n    };\n    this.revertDelta = function(delta) {\n        this.applyDelta({\n            start: this.clonePos(delta.start),\n            end: this.clonePos(delta.end),\n            action: (delta.action == \"insert\" ? \"remove\" : \"insert\"),\n            lines: delta.lines.slice()\n        });\n    };\n    this.indexToPosition = function(index, startRow) {\n        var lines = this.$lines || this.getAllLines();\n        var newlineLength = this.getNewLineCharacter().length;\n        for (var i = startRow || 0, l = lines.length; i < l; i++) {\n            index -= lines[i].length + newlineLength;\n            if (index < 0)\n                return {row: i, column: index + lines[i].length + newlineLength};\n        }\n        return {row: l-1, column: lines[l-1].length};\n    };\n    this.positionToIndex = function(pos, startRow) {\n        var lines = this.$lines || this.getAllLines();\n        var newlineLength = this.getNewLineCharacter().length;\n        var index = 0;\n        var row = Math.min(pos.row, lines.length);\n        for (var i = startRow || 0; i < row; ++i)\n            index += lines[i].length + newlineLength;\n\n        return index + pos.column;\n    };\n\n}).call(Document.prototype);\n\nexports.Document = Document;\n});\n\ndefine(\"ace/lib/lang\",[\"require\",\"exports\",\"module\"], function(require, exports, module) {\n\"use strict\";\n\nexports.last = function(a) {\n    return a[a.length - 1];\n};\n\nexports.stringReverse = function(string) {\n    return string.split(\"\").reverse().join(\"\");\n};\n\nexports.stringRepeat = function (string, count) {\n    var result = '';\n    while (count > 0) {\n        if (count & 1)\n            result += string;\n\n        if (count >>= 1)\n            string += string;\n    }\n    return result;\n};\n\nvar trimBeginRegexp = /^\\s\\s*/;\nvar trimEndRegexp = /\\s\\s*$/;\n\nexports.stringTrimLeft = function (string) {\n    return string.replace(trimBeginRegexp, '');\n};\n\nexports.stringTrimRight = function (string) {\n    return string.replace(trimEndRegexp, '');\n};\n\nexports.copyObject = function(obj) {\n    var copy = {};\n    for (var key in obj) {\n        copy[key] = obj[key];\n    }\n    return copy;\n};\n\nexports.copyArray = function(array){\n    var copy = [];\n    for (var i=0, l=array.length; i<l; i++) {\n        if (array[i] && typeof array[i] == \"object\")\n            copy[i] = this.copyObject( array[i] );\n        else \n            copy[i] = array[i];\n    }\n    return copy;\n};\n\nexports.deepCopy = function deepCopy(obj) {\n    if (typeof obj !== \"object\" || !obj)\n        return obj;\n    var copy;\n    if (Array.isArray(obj)) {\n        copy = [];\n        for (var key = 0; key < obj.length; key++) {\n            copy[key] = deepCopy(obj[key]);\n        }\n        return copy;\n    }\n    var cons = obj.constructor;\n    if (cons === RegExp)\n        return obj;\n    \n    copy = cons();\n    for (var key in obj) {\n        copy[key] = deepCopy(obj[key]);\n    }\n    return copy;\n};\n\nexports.arrayToMap = function(arr) {\n    var map = {};\n    for (var i=0; i<arr.length; i++) {\n        map[arr[i]] = 1;\n    }\n    return map;\n\n};\n\nexports.createMap = function(props) {\n    var map = Object.create(null);\n    for (var i in props) {\n        map[i] = props[i];\n    }\n    return map;\n};\nexports.arrayRemove = function(array, value) {\n  for (var i = 0; i <= array.length; i++) {\n    if (value === array[i]) {\n      array.splice(i, 1);\n    }\n  }\n};\n\nexports.escapeRegExp = function(str) {\n    return str.replace(/([.*+?^${}()|[\\]\\/\\\\])/g, '\\\\$1');\n};\n\nexports.escapeHTML = function(str) {\n    return str.replace(/&/g, \"&#38;\").replace(/\"/g, \"&#34;\").replace(/'/g, \"&#39;\").replace(/</g, \"&#60;\");\n};\n\nexports.getMatchOffsets = function(string, regExp) {\n    var matches = [];\n\n    string.replace(regExp, function(str) {\n        matches.push({\n            offset: arguments[arguments.length-2],\n            length: str.length\n        });\n    });\n\n    return matches;\n};\nexports.deferredCall = function(fcn) {\n    var timer = null;\n    var callback = function() {\n        timer = null;\n        fcn();\n    };\n\n    var deferred = function(timeout) {\n        deferred.cancel();\n        timer = setTimeout(callback, timeout || 0);\n        return deferred;\n    };\n\n    deferred.schedule = deferred;\n\n    deferred.call = function() {\n        this.cancel();\n        fcn();\n        return deferred;\n    };\n\n    deferred.cancel = function() {\n        clearTimeout(timer);\n        timer = null;\n        return deferred;\n    };\n    \n    deferred.isPending = function() {\n        return timer;\n    };\n\n    return deferred;\n};\n\n\nexports.delayedCall = function(fcn, defaultTimeout) {\n    var timer = null;\n    var callback = function() {\n        timer = null;\n        fcn();\n    };\n\n    var _self = function(timeout) {\n        if (timer == null)\n            timer = setTimeout(callback, timeout || defaultTimeout);\n    };\n\n    _self.delay = function(timeout) {\n        timer && clearTimeout(timer);\n        timer = setTimeout(callback, timeout || defaultTimeout);\n    };\n    _self.schedule = _self;\n\n    _self.call = function() {\n        this.cancel();\n        fcn();\n    };\n\n    _self.cancel = function() {\n        timer && clearTimeout(timer);\n        timer = null;\n    };\n\n    _self.isPending = function() {\n        return timer;\n    };\n\n    return _self;\n};\n});\n\ndefine(\"ace/worker/mirror\",[\"require\",\"exports\",\"module\",\"ace/range\",\"ace/document\",\"ace/lib/lang\"], function(require, exports, module) {\n\"use strict\";\n\nvar Range = require(\"../range\").Range;\nvar Document = require(\"../document\").Document;\nvar lang = require(\"../lib/lang\");\n    \nvar Mirror = exports.Mirror = function(sender) {\n    this.sender = sender;\n    var doc = this.doc = new Document(\"\");\n    \n    var deferredUpdate = this.deferredUpdate = lang.delayedCall(this.onUpdate.bind(this));\n    \n    var _self = this;\n    sender.on(\"change\", function(e) {\n        var data = e.data;\n        if (data[0].start) {\n            doc.applyDeltas(data);\n        } else {\n            for (var i = 0; i < data.length; i += 2) {\n                if (Array.isArray(data[i+1])) {\n                    var d = {action: \"insert\", start: data[i], lines: data[i+1]};\n                } else {\n                    var d = {action: \"remove\", start: data[i], end: data[i+1]};\n                }\n                doc.applyDelta(d, true);\n            }\n        }\n        if (_self.$timeout)\n            return deferredUpdate.schedule(_self.$timeout);\n        _self.onUpdate();\n    });\n};\n\n(function() {\n    \n    this.$timeout = 500;\n    \n    this.setTimeout = function(timeout) {\n        this.$timeout = timeout;\n    };\n    \n    this.setValue = function(value) {\n        this.doc.setValue(value);\n        this.deferredUpdate.schedule(this.$timeout);\n    };\n    \n    this.getValue = function(callbackId) {\n        this.sender.callback(this.doc.getValue(), callbackId);\n    };\n    \n    this.onUpdate = function() {\n    };\n    \n    this.isPending = function() {\n        return this.deferredUpdate.isPending();\n    };\n    \n}).call(Mirror.prototype);\n\n});\n\ndefine(\"ace/mode/javascript/jshint\",[\"require\",\"exports\",\"module\"], function(require, exports, module) {\nmodule.exports = (function outer (modules, cache, entry) {\n    var previousRequire = typeof require == \"function\" && require;\n    function newRequire(name, jumped){\n        if(!cache[name]) {\n            if(!modules[name]) {\n                var currentRequire = typeof require == \"function\" && require;\n                if (!jumped && currentRequire) return currentRequire(name, true);\n                if (previousRequire) return previousRequire(name, true);\n                var err = new Error('Cannot find module \\'' + name + '\\'');\n                err.code = 'MODULE_NOT_FOUND';\n                throw err;\n            }\n            var m = cache[name] = {exports:{}};\n            modules[name][0].call(m.exports, function(x){\n                var id = modules[name][1][x];\n                return newRequire(id ? id : x);\n            },m,m.exports,outer,modules,cache,entry);\n        }\n        return cache[name].exports;\n    }\n    for(var i=0;i<entry.length;i++) newRequire(entry[i]);\n    return newRequire(entry[0]);\n})\n({\"/node_modules/browserify/node_modules/events/events.js\":[function(_dereq_,module,exports){\n\nfunction EventEmitter() {\n  this._events = this._events || {};\n  this._maxListeners = this._maxListeners || undefined;\n}\nmodule.exports = EventEmitter;\nEventEmitter.EventEmitter = EventEmitter;\n\nEventEmitter.prototype._events = undefined;\nEventEmitter.prototype._maxListeners = undefined;\nEventEmitter.defaultMaxListeners = 10;\nEventEmitter.prototype.setMaxListeners = function(n) {\n  if (!isNumber(n) || n < 0 || isNaN(n))\n    throw TypeError('n must be a positive number');\n  this._maxListeners = n;\n  return this;\n};\n\nEventEmitter.prototype.emit = function(type) {\n  var er, handler, len, args, i, listeners;\n\n  if (!this._events)\n    this._events = {};\n  if (type === 'error') {\n    if (!this._events.error ||\n        (isObject(this._events.error) && !this._events.error.length)) {\n      er = arguments[1];\n      if (er instanceof Error) {\n        throw er; // Unhandled 'error' event\n      }\n      throw TypeError('Uncaught, unspecified \"error\" event.');\n    }\n  }\n\n  handler = this._events[type];\n\n  if (isUndefined(handler))\n    return false;\n\n  if (isFunction(handler)) {\n    switch (arguments.length) {\n      case 1:\n        handler.call(this);\n        break;\n      case 2:\n        handler.call(this, arguments[1]);\n        break;\n      case 3:\n        handler.call(this, arguments[1], arguments[2]);\n        break;\n      default:\n        len = arguments.length;\n        args = new Array(len - 1);\n        for (i = 1; i < len; i++)\n          args[i - 1] = arguments[i];\n        handler.apply(this, args);\n    }\n  } else if (isObject(handler)) {\n    len = arguments.length;\n    args = new Array(len - 1);\n    for (i = 1; i < len; i++)\n      args[i - 1] = arguments[i];\n\n    listeners = handler.slice();\n    len = listeners.length;\n    for (i = 0; i < len; i++)\n      listeners[i].apply(this, args);\n  }\n\n  return true;\n};\n\nEventEmitter.prototype.addListener = function(type, listener) {\n  var m;\n\n  if (!isFunction(listener))\n    throw TypeError('listener must be a function');\n\n  if (!this._events)\n    this._events = {};\n  if (this._events.newListener)\n    this.emit('newListener', type,\n              isFunction(listener.listener) ?\n              listener.listener : listener);\n\n  if (!this._events[type])\n    this._events[type] = listener;\n  else if (isObject(this._events[type]))\n    this._events[type].push(listener);\n  else\n    this._events[type] = [this._events[type], listener];\n  if (isObject(this._events[type]) && !this._events[type].warned) {\n    var m;\n    if (!isUndefined(this._maxListeners)) {\n      m = this._maxListeners;\n    } else {\n      m = EventEmitter.defaultMaxListeners;\n    }\n\n    if (m && m > 0 && this._events[type].length > m) {\n      this._events[type].warned = true;\n      console.error('(node) warning: possible EventEmitter memory ' +\n                    'leak detected. %d listeners added. ' +\n                    'Use emitter.setMaxListeners() to increase limit.',\n                    this._events[type].length);\n      if (typeof console.trace === 'function') {\n        console.trace();\n      }\n    }\n  }\n\n  return this;\n};\n\nEventEmitter.prototype.on = EventEmitter.prototype.addListener;\n\nEventEmitter.prototype.once = function(type, listener) {\n  if (!isFunction(listener))\n    throw TypeError('listener must be a function');\n\n  var fired = false;\n\n  function g() {\n    this.removeListener(type, g);\n\n    if (!fired) {\n      fired = true;\n      listener.apply(this, arguments);\n    }\n  }\n\n  g.listener = listener;\n  this.on(type, g);\n\n  return this;\n};\nEventEmitter.prototype.removeListener = function(type, listener) {\n  var list, position, length, i;\n\n  if (!isFunction(listener))\n    throw TypeError('listener must be a function');\n\n  if (!this._events || !this._events[type])\n    return this;\n\n  list = this._events[type];\n  length = list.length;\n  position = -1;\n\n  if (list === listener ||\n      (isFunction(list.listener) && list.listener === listener)) {\n    delete this._events[type];\n    if (this._events.removeListener)\n      this.emit('removeListener', type, listener);\n\n  } else if (isObject(list)) {\n    for (i = length; i-- > 0;) {\n      if (list[i] === listener ||\n          (list[i].listener && list[i].listener === listener)) {\n        position = i;\n        break;\n      }\n    }\n\n    if (position < 0)\n      return this;\n\n    if (list.length === 1) {\n      list.length = 0;\n      delete this._events[type];\n    } else {\n      list.splice(position, 1);\n    }\n\n    if (this._events.removeListener)\n      this.emit('removeListener', type, listener);\n  }\n\n  return this;\n};\n\nEventEmitter.prototype.removeAllListeners = function(type) {\n  var key, listeners;\n\n  if (!this._events)\n    return this;\n  if (!this._events.removeListener) {\n    if (arguments.length === 0)\n      this._events = {};\n    else if (this._events[type])\n      delete this._events[type];\n    return this;\n  }\n  if (arguments.length === 0) {\n    for (key in this._events) {\n      if (key === 'removeListener') continue;\n      this.removeAllListeners(key);\n    }\n    this.removeAllListeners('removeListener');\n    this._events = {};\n    return this;\n  }\n\n  listeners = this._events[type];\n\n  if (isFunction(listeners)) {\n    this.removeListener(type, listeners);\n  } else {\n    while (listeners.length)\n      this.removeListener(type, listeners[listeners.length - 1]);\n  }\n  delete this._events[type];\n\n  return this;\n};\n\nEventEmitter.prototype.listeners = function(type) {\n  var ret;\n  if (!this._events || !this._events[type])\n    ret = [];\n  else if (isFunction(this._events[type]))\n    ret = [this._events[type]];\n  else\n    ret = this._events[type].slice();\n  return ret;\n};\n\nEventEmitter.listenerCount = function(emitter, type) {\n  var ret;\n  if (!emitter._events || !emitter._events[type])\n    ret = 0;\n  else if (isFunction(emitter._events[type]))\n    ret = 1;\n  else\n    ret = emitter._events[type].length;\n  return ret;\n};\n\nfunction isFunction(arg) {\n  return typeof arg === 'function';\n}\n\nfunction isNumber(arg) {\n  return typeof arg === 'number';\n}\n\nfunction isObject(arg) {\n  return typeof arg === 'object' && arg !== null;\n}\n\nfunction isUndefined(arg) {\n  return arg === void 0;\n}\n\n},{}],\"/node_modules/jshint/data/ascii-identifier-data.js\":[function(_dereq_,module,exports){\nvar identifierStartTable = [];\n\nfor (var i = 0; i < 128; i++) {\n  identifierStartTable[i] =\n    i === 36 ||           // $\n    i >= 65 && i <= 90 || // A-Z\n    i === 95 ||           // _\n    i >= 97 && i <= 122;  // a-z\n}\n\nvar identifierPartTable = [];\n\nfor (var i = 0; i < 128; i++) {\n  identifierPartTable[i] =\n    identifierStartTable[i] || // $, _, A-Z, a-z\n    i >= 48 && i <= 57;        // 0-9\n}\n\nmodule.exports = {\n  asciiIdentifierStartTable: identifierStartTable,\n  asciiIdentifierPartTable: identifierPartTable\n};\n\n},{}],\"/node_modules/jshint/lodash.js\":[function(_dereq_,module,exports){\n(function (global){\n;(function() {\n\n  var undefined;\n\n  var VERSION = '3.7.0';\n\n  var FUNC_ERROR_TEXT = 'Expected a function';\n\n  var argsTag = '[object Arguments]',\n      arrayTag = '[object Array]',\n      boolTag = '[object Boolean]',\n      dateTag = '[object Date]',\n      errorTag = '[object Error]',\n      funcTag = '[object Function]',\n      mapTag = '[object Map]',\n      numberTag = '[object Number]',\n      objectTag = '[object Object]',\n      regexpTag = '[object RegExp]',\n      setTag = '[object Set]',\n      stringTag = '[object String]',\n      weakMapTag = '[object WeakMap]';\n\n  var arrayBufferTag = '[object ArrayBuffer]',\n      float32Tag = '[object Float32Array]',\n      float64Tag = '[object Float64Array]',\n      int8Tag = '[object Int8Array]',\n      int16Tag = '[object Int16Array]',\n      int32Tag = '[object Int32Array]',\n      uint8Tag = '[object Uint8Array]',\n      uint8ClampedTag = '[object Uint8ClampedArray]',\n      uint16Tag = '[object Uint16Array]',\n      uint32Tag = '[object Uint32Array]';\n\n  var reIsDeepProp = /\\.|\\[(?:[^[\\]]+|([\"'])(?:(?!\\1)[^\\n\\\\]|\\\\.)*?)\\1\\]/,\n      reIsPlainProp = /^\\w*$/,\n      rePropName = /[^.[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\\2)[^\\n\\\\]|\\\\.)*?)\\2)\\]/g;\n\n  var reRegExpChars = /[.*+?^${}()|[\\]\\/\\\\]/g,\n      reHasRegExpChars = RegExp(reRegExpChars.source);\n\n  var reEscapeChar = /\\\\(\\\\)?/g;\n\n  var reFlags = /\\w*$/;\n\n  var reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n  var typedArrayTags = {};\n  typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =\n  typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =\n  typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =\n  typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =\n  typedArrayTags[uint32Tag] = true;\n  typedArrayTags[argsTag] = typedArrayTags[arrayTag] =\n  typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =\n  typedArrayTags[dateTag] = typedArrayTags[errorTag] =\n  typedArrayTags[funcTag] = typedArrayTags[mapTag] =\n  typedArrayTags[numberTag] = typedArrayTags[objectTag] =\n  typedArrayTags[regexpTag] = typedArrayTags[setTag] =\n  typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;\n\n  var cloneableTags = {};\n  cloneableTags[argsTag] = cloneableTags[arrayTag] =\n  cloneableTags[arrayBufferTag] = cloneableTags[boolTag] =\n  cloneableTags[dateTag] = cloneableTags[float32Tag] =\n  cloneableTags[float64Tag] = cloneableTags[int8Tag] =\n  cloneableTags[int16Tag] = cloneableTags[int32Tag] =\n  cloneableTags[numberTag] = cloneableTags[objectTag] =\n  cloneableTags[regexpTag] = cloneableTags[stringTag] =\n  cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =\n  cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;\n  cloneableTags[errorTag] = cloneableTags[funcTag] =\n  cloneableTags[mapTag] = cloneableTags[setTag] =\n  cloneableTags[weakMapTag] = false;\n\n  var objectTypes = {\n    'function': true,\n    'object': true\n  };\n\n  var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;\n\n  var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;\n\n  var freeGlobal = freeExports && freeModule && typeof global == 'object' && global && global.Object && global;\n\n  var freeSelf = objectTypes[typeof self] && self && self.Object && self;\n\n  var freeWindow = objectTypes[typeof window] && window && window.Object && window;\n\n  var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;\n\n  var root = freeGlobal || ((freeWindow !== (this && this.window)) && freeWindow) || freeSelf || this;\n\n  function baseFindIndex(array, predicate, fromRight) {\n    var length = array.length,\n        index = fromRight ? length : -1;\n\n    while ((fromRight ? index-- : ++index < length)) {\n      if (predicate(array[index], index, array)) {\n        return index;\n      }\n    }\n    return -1;\n  }\n\n  function baseIndexOf(array, value, fromIndex) {\n    if (value !== value) {\n      return indexOfNaN(array, fromIndex);\n    }\n    var index = fromIndex - 1,\n        length = array.length;\n\n    while (++index < length) {\n      if (array[index] === value) {\n        return index;\n      }\n    }\n    return -1;\n  }\n\n  function baseIsFunction(value) {\n    return typeof value == 'function' || false;\n  }\n\n  function baseToString(value) {\n    if (typeof value == 'string') {\n      return value;\n    }\n    return value == null ? '' : (value + '');\n  }\n\n  function indexOfNaN(array, fromIndex, fromRight) {\n    var length = array.length,\n        index = fromIndex + (fromRight ? 0 : -1);\n\n    while ((fromRight ? index-- : ++index < length)) {\n      var other = array[index];\n      if (other !== other) {\n        return index;\n      }\n    }\n    return -1;\n  }\n\n  function isObjectLike(value) {\n    return !!value && typeof value == 'object';\n  }\n\n  var arrayProto = Array.prototype,\n      objectProto = Object.prototype;\n\n  var fnToString = Function.prototype.toString;\n\n  var hasOwnProperty = objectProto.hasOwnProperty;\n\n  var objToString = objectProto.toString;\n\n  var reIsNative = RegExp('^' +\n    escapeRegExp(objToString)\n    .replace(/toString|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g, '$1.*?') + '$'\n  );\n\n  var ArrayBuffer = isNative(ArrayBuffer = root.ArrayBuffer) && ArrayBuffer,\n      bufferSlice = isNative(bufferSlice = ArrayBuffer && new ArrayBuffer(0).slice) && bufferSlice,\n      floor = Math.floor,\n      getOwnPropertySymbols = isNative(getOwnPropertySymbols = Object.getOwnPropertySymbols) && getOwnPropertySymbols,\n      getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,\n      push = arrayProto.push,\n      preventExtensions = isNative(Object.preventExtensions = Object.preventExtensions) && preventExtensions,\n      propertyIsEnumerable = objectProto.propertyIsEnumerable,\n      Uint8Array = isNative(Uint8Array = root.Uint8Array) && Uint8Array;\n\n  var Float64Array = (function() {\n    try {\n      var func = isNative(func = root.Float64Array) && func,\n          result = new func(new ArrayBuffer(10), 0, 1) && func;\n    } catch(e) {}\n    return result;\n  }());\n\n  var nativeAssign = (function() {\n    var object = { '1': 0 },\n        func = preventExtensions && isNative(func = Object.assign) && func;\n\n    try { func(preventExtensions(object), 'xo'); } catch(e) {}\n    return !object[1] && func;\n  }());\n\n  var nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray,\n      nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys,\n      nativeMax = Math.max,\n      nativeMin = Math.min;\n\n  var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY;\n\n  var MAX_ARRAY_LENGTH = Math.pow(2, 32) - 1,\n      MAX_ARRAY_INDEX =  MAX_ARRAY_LENGTH - 1,\n      HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;\n\n  var FLOAT64_BYTES_PER_ELEMENT = Float64Array ? Float64Array.BYTES_PER_ELEMENT : 0;\n\n  var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1;\n\n  function lodash() {\n  }\n\n  var support = lodash.support = {};\n\n  (function(x) {\n    var Ctor = function() { this.x = x; },\n        object = { '0': x, 'length': x },\n        props = [];\n\n    Ctor.prototype = { 'valueOf': x, 'y': x };\n    for (var key in new Ctor) { props.push(key); }\n\n    support.funcDecomp = /\\bthis\\b/.test(function() { return this; });\n\n    support.funcNames = typeof Function.name == 'string';\n\n    try {\n      support.nonEnumArgs = !propertyIsEnumerable.call(arguments, 1);\n    } catch(e) {\n      support.nonEnumArgs = true;\n    }\n  }(1, 0));\n\n  function arrayCopy(source, array) {\n    var index = -1,\n        length = source.length;\n\n    array || (array = Array(length));\n    while (++index < length) {\n      array[index] = source[index];\n    }\n    return array;\n  }\n\n  function arrayEach(array, iteratee) {\n    var index = -1,\n        length = array.length;\n\n    while (++index < length) {\n      if (iteratee(array[index], index, array) === false) {\n        break;\n      }\n    }\n    return array;\n  }\n\n  function arrayFilter(array, predicate) {\n    var index = -1,\n        length = array.length,\n        resIndex = -1,\n        result = [];\n\n    while (++index < length) {\n      var value = array[index];\n      if (predicate(value, index, array)) {\n        result[++resIndex] = value;\n      }\n    }\n    return result;\n  }\n\n  function arrayMap(array, iteratee) {\n    var index = -1,\n        length = array.length,\n        result = Array(length);\n\n    while (++index < length) {\n      result[index] = iteratee(array[index], index, array);\n    }\n    return result;\n  }\n\n  function arrayMax(array) {\n    var index = -1,\n        length = array.length,\n        result = NEGATIVE_INFINITY;\n\n    while (++index < length) {\n      var value = array[index];\n      if (value > result) {\n        result = value;\n      }\n    }\n    return result;\n  }\n\n  function arraySome(array, predicate) {\n    var index = -1,\n        length = array.length;\n\n    while (++index < length) {\n      if (predicate(array[index], index, array)) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  function assignWith(object, source, customizer) {\n    var props = keys(source);\n    push.apply(props, getSymbols(source));\n\n    var index = -1,\n        length = props.length;\n\n    while (++index < length) {\n      var key = props[index],\n          value = object[key],\n          result = customizer(value, source[key], key, object, source);\n\n      if ((result === result ? (result !== value) : (value === value)) ||\n          (value === undefined && !(key in object))) {\n        object[key] = result;\n      }\n    }\n    return object;\n  }\n\n  var baseAssign = nativeAssign || function(object, source) {\n    return source == null\n      ? object\n      : baseCopy(source, getSymbols(source), baseCopy(source, keys(source), object));\n  };\n\n  function baseCopy(source, props, object) {\n    object || (object = {});\n\n    var index = -1,\n        length = props.length;\n\n    while (++index < length) {\n      var key = props[index];\n      object[key] = source[key];\n    }\n    return object;\n  }\n\n  function baseCallback(func, thisArg, argCount) {\n    var type = typeof func;\n    if (type == 'function') {\n      return thisArg === undefined\n        ? func\n        : bindCallback(func, thisArg, argCount);\n    }\n    if (func == null) {\n      return identity;\n    }\n    if (type == 'object') {\n      return baseMatches(func);\n    }\n    return thisArg === undefined\n      ? property(func)\n      : baseMatchesProperty(func, thisArg);\n  }\n\n  function baseClone(value, isDeep, customizer, key, object, stackA, stackB) {\n    var result;\n    if (customizer) {\n      result = object ? customizer(value, key, object) : customizer(value);\n    }\n    if (result !== undefined) {\n      return result;\n    }\n    if (!isObject(value)) {\n      return value;\n    }\n    var isArr = isArray(value);\n    if (isArr) {\n      result = initCloneArray(value);\n      if (!isDeep) {\n        return arrayCopy(value, result);\n      }\n    } else {\n      var tag = objToString.call(value),\n          isFunc = tag == funcTag;\n\n      if (tag == objectTag || tag == argsTag || (isFunc && !object)) {\n        result = initCloneObject(isFunc ? {} : value);\n        if (!isDeep) {\n          return baseAssign(result, value);\n        }\n      } else {\n        return cloneableTags[tag]\n          ? initCloneByTag(value, tag, isDeep)\n          : (object ? value : {});\n      }\n    }\n    stackA || (stackA = []);\n    stackB || (stackB = []);\n\n    var length = stackA.length;\n    while (length--) {\n      if (stackA[length] == value) {\n        return stackB[length];\n      }\n    }\n    stackA.push(value);\n    stackB.push(result);\n\n    (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) {\n      result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB);\n    });\n    return result;\n  }\n\n  var baseEach = createBaseEach(baseForOwn);\n\n  function baseFilter(collection, predicate) {\n    var result = [];\n    baseEach(collection, function(value, index, collection) {\n      if (predicate(value, index, collection)) {\n        result.push(value);\n      }\n    });\n    return result;\n  }\n\n  var baseFor = createBaseFor();\n\n  function baseForIn(object, iteratee) {\n    return baseFor(object, iteratee, keysIn);\n  }\n\n  function baseForOwn(object, iteratee) {\n    return baseFor(object, iteratee, keys);\n  }\n\n  function baseGet(object, path, pathKey) {\n    if (object == null) {\n      return;\n    }\n    if (pathKey !== undefined && pathKey in toObject(object)) {\n      path = [pathKey];\n    }\n    var index = -1,\n        length = path.length;\n\n    while (object != null && ++index < length) {\n      var result = object = object[path[index]];\n    }\n    return result;\n  }\n\n  function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) {\n    if (value === other) {\n      return value !== 0 || (1 / value == 1 / other);\n    }\n    var valType = typeof value,\n        othType = typeof other;\n\n    if ((valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object') ||\n        value == null || other == null) {\n      return value !== value && other !== other;\n    }\n    return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB);\n  }\n\n  function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) {\n    var objIsArr = isArray(object),\n        othIsArr = isArray(other),\n        objTag = arrayTag,\n        othTag = arrayTag;\n\n    if (!objIsArr) {\n      objTag = objToString.call(object);\n      if (objTag == argsTag) {\n        objTag = objectTag;\n      } else if (objTag != objectTag) {\n        objIsArr = isTypedArray(object);\n      }\n    }\n    if (!othIsArr) {\n      othTag = objToString.call(other);\n      if (othTag == argsTag) {\n        othTag = objectTag;\n      } else if (othTag != objectTag) {\n        othIsArr = isTypedArray(other);\n      }\n    }\n    var objIsObj = objTag == objectTag,\n        othIsObj = othTag == objectTag,\n        isSameTag = objTag == othTag;\n\n    if (isSameTag && !(objIsArr || objIsObj)) {\n      return equalByTag(object, other, objTag);\n    }\n    if (!isLoose) {\n      var valWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),\n          othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');\n\n      if (valWrapped || othWrapped) {\n        return equalFunc(valWrapped ? object.value() : object, othWrapped ? other.value() : other, customizer, isLoose, stackA, stackB);\n      }\n    }\n    if (!isSameTag) {\n      return false;\n    }\n    stackA || (stackA = []);\n    stackB || (stackB = []);\n\n    var length = stackA.length;\n    while (length--) {\n      if (stackA[length] == object) {\n        return stackB[length] == other;\n      }\n    }\n    stackA.push(object);\n    stackB.push(other);\n\n    var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB);\n\n    stackA.pop();\n    stackB.pop();\n\n    return result;\n  }\n\n  function baseIsMatch(object, props, values, strictCompareFlags, customizer) {\n    var index = -1,\n        length = props.length,\n        noCustomizer = !customizer;\n\n    while (++index < length) {\n      if ((noCustomizer && strictCompareFlags[index])\n            ? values[index] !== object[props[index]]\n            : !(props[index] in object)\n          ) {\n        return false;\n      }\n    }\n    index = -1;\n    while (++index < length) {\n      var key = props[index],\n          objValue = object[key],\n          srcValue = values[index];\n\n      if (noCustomizer && strictCompareFlags[index]) {\n        var result = objValue !== undefined || (key in object);\n      } else {\n        result = customizer ? customizer(objValue, srcValue, key) : undefined;\n        if (result === undefined) {\n          result = baseIsEqual(srcValue, objValue, customizer, true);\n        }\n      }\n      if (!result) {\n        return false;\n      }\n    }\n    return true;\n  }\n\n  function baseMatches(source) {\n    var props = keys(source),\n        length = props.length;\n\n    if (!length) {\n      return constant(true);\n    }\n    if (length == 1) {\n      var key = props[0],\n          value = source[key];\n\n      if (isStrictComparable(value)) {\n        return function(object) {\n          if (object == null) {\n            return false;\n          }\n          return object[key] === value && (value !== undefined || (key in toObject(object)));\n        };\n      }\n    }\n    var values = Array(length),\n        strictCompareFlags = Array(length);\n\n    while (length--) {\n      value = source[props[length]];\n      values[length] = value;\n      strictCompareFlags[length] = isStrictComparable(value);\n    }\n    return function(object) {\n      return object != null && baseIsMatch(toObject(object), props, values, strictCompareFlags);\n    };\n  }\n\n  function baseMatchesProperty(path, value) {\n    var isArr = isArray(path),\n        isCommon = isKey(path) && isStrictComparable(value),\n        pathKey = (path + '');\n\n    path = toPath(path);\n    return function(object) {\n      if (object == null) {\n        return false;\n      }\n      var key = pathKey;\n      object = toObject(object);\n      if ((isArr || !isCommon) && !(key in object)) {\n        object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));\n        if (object == null) {\n          return false;\n        }\n        key = last(path);\n        object = toObject(object);\n      }\n      return object[key] === value\n        ? (value !== undefined || (key in object))\n        : baseIsEqual(value, object[key], null, true);\n    };\n  }\n\n  function baseMerge(object, source, customizer, stackA, stackB) {\n    if (!isObject(object)) {\n      return object;\n    }\n    var isSrcArr = isLength(source.length) && (isArray(source) || isTypedArray(source));\n    if (!isSrcArr) {\n      var props = keys(source);\n      push.apply(props, getSymbols(source));\n    }\n    arrayEach(props || source, function(srcValue, key) {\n      if (props) {\n        key = srcValue;\n        srcValue = source[key];\n      }\n      if (isObjectLike(srcValue)) {\n        stackA || (stackA = []);\n        stackB || (stackB = []);\n        baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB);\n      }\n      else {\n        var value = object[key],\n            result = customizer ? customizer(value, srcValue, key, object, source) : undefined,\n            isCommon = result === undefined;\n\n        if (isCommon) {\n          result = srcValue;\n        }\n        if ((isSrcArr || result !== undefined) &&\n            (isCommon || (result === result ? (result !== value) : (value === value)))) {\n          object[key] = result;\n        }\n      }\n    });\n    return object;\n  }\n\n  function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) {\n    var length = stackA.length,\n        srcValue = source[key];\n\n    while (length--) {\n      if (stackA[length] == srcValue) {\n        object[key] = stackB[length];\n        return;\n      }\n    }\n    var value = object[key],\n        result = customizer ? customizer(value, srcValue, key, object, source) : undefined,\n        isCommon = result === undefined;\n\n    if (isCommon) {\n      result = srcValue;\n      if (isLength(srcValue.length) && (isArray(srcValue) || isTypedArray(srcValue))) {\n        result = isArray(value)\n          ? value\n          : (getLength(value) ? arrayCopy(value) : []);\n      }\n      else if (isPlainObject(srcValue) || isArguments(srcValue)) {\n        result = isArguments(value)\n          ? toPlainObject(value)\n          : (isPlainObject(value) ? value : {});\n      }\n      else {\n        isCommon = false;\n      }\n    }\n    stackA.push(srcValue);\n    stackB.push(result);\n\n    if (isCommon) {\n      object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB);\n    } else if (result === result ? (result !== value) : (value === value)) {\n      object[key] = result;\n    }\n  }\n\n  function baseProperty(key) {\n    return function(object) {\n      return object == null ? undefined : object[key];\n    };\n  }\n\n  function basePropertyDeep(path) {\n    var pathKey = (path + '');\n    path = toPath(path);\n    return function(object) {\n      return baseGet(object, path, pathKey);\n    };\n  }\n\n  function baseSlice(array, start, end) {\n    var index = -1,\n        length = array.length;\n\n    start = start == null ? 0 : (+start || 0);\n    if (start < 0) {\n      start = -start > length ? 0 : (length + start);\n    }\n    end = (end === undefined || end > length) ? length : (+end || 0);\n    if (end < 0) {\n      end += length;\n    }\n    length = start > end ? 0 : ((end - start) >>> 0);\n    start >>>= 0;\n\n    var result = Array(length);\n    while (++index < length) {\n      result[index] = array[index + start];\n    }\n    return result;\n  }\n\n  function baseSome(collection, predicate) {\n    var result;\n\n    baseEach(collection, function(value, index, collection) {\n      result = predicate(value, index, collection);\n      return !result;\n    });\n    return !!result;\n  }\n\n  function baseValues(object, props) {\n    var index = -1,\n        length = props.length,\n        result = Array(length);\n\n    while (++index < length) {\n      result[index] = object[props[index]];\n    }\n    return result;\n  }\n\n  function binaryIndex(array, value, retHighest) {\n    var low = 0,\n        high = array ? array.length : low;\n\n    if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {\n      while (low < high) {\n        var mid = (low + high) >>> 1,\n            computed = array[mid];\n\n        if (retHighest ? (computed <= value) : (computed < value)) {\n          low = mid + 1;\n        } else {\n          high = mid;\n        }\n      }\n      return high;\n    }\n    return binaryIndexBy(array, value, identity, retHighest);\n  }\n\n  function binaryIndexBy(array, value, iteratee, retHighest) {\n    value = iteratee(value);\n\n    var low = 0,\n        high = array ? array.length : 0,\n        valIsNaN = value !== value,\n        valIsUndef = value === undefined;\n\n    while (low < high) {\n      var mid = floor((low + high) / 2),\n          computed = iteratee(array[mid]),\n          isReflexive = computed === computed;\n\n      if (valIsNaN) {\n        var setLow = isReflexive || retHighest;\n      } else if (valIsUndef) {\n        setLow = isReflexive && (retHighest || computed !== undefined);\n      } else {\n        setLow = retHighest ? (computed <= value) : (computed < value);\n      }\n      if (setLow) {\n        low = mid + 1;\n      } else {\n        high = mid;\n      }\n    }\n    return nativeMin(high, MAX_ARRAY_INDEX);\n  }\n\n  function bindCallback(func, thisArg, argCount) {\n    if (typeof func != 'function') {\n      return identity;\n    }\n    if (thisArg === undefined) {\n      return func;\n    }\n    switch (argCount) {\n      case 1: return function(value) {\n        return func.call(thisArg, value);\n      };\n      case 3: return function(value, index, collection) {\n        return func.call(thisArg, value, index, collection);\n      };\n      case 4: return function(accumulator, value, index, collection) {\n        return func.call(thisArg, accumulator, value, index, collection);\n      };\n      case 5: return function(value, other, key, object, source) {\n        return func.call(thisArg, value, other, key, object, source);\n      };\n    }\n    return function() {\n      return func.apply(thisArg, arguments);\n    };\n  }\n\n  function bufferClone(buffer) {\n    return bufferSlice.call(buffer, 0);\n  }\n  if (!bufferSlice) {\n    bufferClone = !(ArrayBuffer && Uint8Array) ? constant(null) : function(buffer) {\n      var byteLength = buffer.byteLength,\n          floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0,\n          offset = floatLength * FLOAT64_BYTES_PER_ELEMENT,\n          result = new ArrayBuffer(byteLength);\n\n      if (floatLength) {\n        var view = new Float64Array(result, 0, floatLength);\n        view.set(new Float64Array(buffer, 0, floatLength));\n      }\n      if (byteLength != offset) {\n        view = new Uint8Array(result, offset);\n        view.set(new Uint8Array(buffer, offset));\n      }\n      return result;\n    };\n  }\n\n  function createAssigner(assigner) {\n    return restParam(function(object, sources) {\n      var index = -1,\n          length = object == null ? 0 : sources.length,\n          customizer = length > 2 && sources[length - 2],\n          guard = length > 2 && sources[2],\n          thisArg = length > 1 && sources[length - 1];\n\n      if (typeof customizer == 'function') {\n        customizer = bindCallback(customizer, thisArg, 5);\n        length -= 2;\n      } else {\n        customizer = typeof thisArg == 'function' ? thisArg : null;\n        length -= (customizer ? 1 : 0);\n      }\n      if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n        customizer = length < 3 ? null : customizer;\n        length = 1;\n      }\n      while (++index < length) {\n        var source = sources[index];\n        if (source) {\n          assigner(object, source, customizer);\n        }\n      }\n      return object;\n    });\n  }\n\n  function createBaseEach(eachFunc, fromRight) {\n    return function(collection, iteratee) {\n      var length = collection ? getLength(collection) : 0;\n      if (!isLength(length)) {\n        return eachFunc(collection, iteratee);\n      }\n      var index = fromRight ? length : -1,\n          iterable = toObject(collection);\n\n      while ((fromRight ? index-- : ++index < length)) {\n        if (iteratee(iterable[index], index, iterable) === false) {\n          break;\n        }\n      }\n      return collection;\n    };\n  }\n\n  function createBaseFor(fromRight) {\n    return function(object, iteratee, keysFunc) {\n      var iterable = toObject(object),\n          props = keysFunc(object),\n          length = props.length,\n          index = fromRight ? length : -1;\n\n      while ((fromRight ? index-- : ++index < length)) {\n        var key = props[index];\n        if (iteratee(iterable[key], key, iterable) === false) {\n          break;\n        }\n      }\n      return object;\n    };\n  }\n\n  function createFindIndex(fromRight) {\n    return function(array, predicate, thisArg) {\n      if (!(array && array.length)) {\n        return -1;\n      }\n      predicate = getCallback(predicate, thisArg, 3);\n      return baseFindIndex(array, predicate, fromRight);\n    };\n  }\n\n  function createForEach(arrayFunc, eachFunc) {\n    return function(collection, iteratee, thisArg) {\n      return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection))\n        ? arrayFunc(collection, iteratee)\n        : eachFunc(collection, bindCallback(iteratee, thisArg, 3));\n    };\n  }\n\n  function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) {\n    var index = -1,\n        arrLength = array.length,\n        othLength = other.length,\n        result = true;\n\n    if (arrLength != othLength && !(isLoose && othLength > arrLength)) {\n      return false;\n    }\n    while (result && ++index < arrLength) {\n      var arrValue = array[index],\n          othValue = other[index];\n\n      result = undefined;\n      if (customizer) {\n        result = isLoose\n          ? customizer(othValue, arrValue, index)\n          : customizer(arrValue, othValue, index);\n      }\n      if (result === undefined) {\n        if (isLoose) {\n          var othIndex = othLength;\n          while (othIndex--) {\n            othValue = other[othIndex];\n            result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB);\n            if (result) {\n              break;\n            }\n          }\n        } else {\n          result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB);\n        }\n      }\n    }\n    return !!result;\n  }\n\n  function equalByTag(object, other, tag) {\n    switch (tag) {\n      case boolTag:\n      case dateTag:\n        return +object == +other;\n\n      case errorTag:\n        return object.name == other.name && object.message == other.message;\n\n      case numberTag:\n        return (object != +object)\n          ? other != +other\n          : (object == 0 ? ((1 / object) == (1 / other)) : object == +other);\n\n      case regexpTag:\n      case stringTag:\n        return object == (other + '');\n    }\n    return false;\n  }\n\n  function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) {\n    var objProps = keys(object),\n        objLength = objProps.length,\n        othProps = keys(other),\n        othLength = othProps.length;\n\n    if (objLength != othLength && !isLoose) {\n      return false;\n    }\n    var skipCtor = isLoose,\n        index = -1;\n\n    while (++index < objLength) {\n      var key = objProps[index],\n          result = isLoose ? key in other : hasOwnProperty.call(other, key);\n\n      if (result) {\n        var objValue = object[key],\n            othValue = other[key];\n\n        result = undefined;\n        if (customizer) {\n          result = isLoose\n            ? customizer(othValue, objValue, key)\n            : customizer(objValue, othValue, key);\n        }\n        if (result === undefined) {\n          result = (objValue && objValue === othValue) || equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB);\n        }\n      }\n      if (!result) {\n        return false;\n      }\n      skipCtor || (skipCtor = key == 'constructor');\n    }\n    if (!skipCtor) {\n      var objCtor = object.constructor,\n          othCtor = other.constructor;\n\n      if (objCtor != othCtor &&\n          ('constructor' in object && 'constructor' in other) &&\n          !(typeof objCtor == 'function' && objCtor instanceof objCtor &&\n            typeof othCtor == 'function' && othCtor instanceof othCtor)) {\n        return false;\n      }\n    }\n    return true;\n  }\n\n  function getCallback(func, thisArg, argCount) {\n    var result = lodash.callback || callback;\n    result = result === callback ? baseCallback : result;\n    return argCount ? result(func, thisArg, argCount) : result;\n  }\n\n  function getIndexOf(collection, target, fromIndex) {\n    var result = lodash.indexOf || indexOf;\n    result = result === indexOf ? baseIndexOf : result;\n    return collection ? result(collection, target, fromIndex) : result;\n  }\n\n  var getLength = baseProperty('length');\n\n  var getSymbols = !getOwnPropertySymbols ? constant([]) : function(object) {\n    return getOwnPropertySymbols(toObject(object));\n  };\n\n  function initCloneArray(array) {\n    var length = array.length,\n        result = new array.constructor(length);\n\n    if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {\n      result.index = array.index;\n      result.input = array.input;\n    }\n    return result;\n  }\n\n  function initCloneObject(object) {\n    var Ctor = object.constructor;\n    if (!(typeof Ctor == 'function' && Ctor instanceof Ctor)) {\n      Ctor = Object;\n    }\n    return new Ctor;\n  }\n\n  function initCloneByTag(object, tag, isDeep) {\n    var Ctor = object.constructor;\n    switch (tag) {\n      case arrayBufferTag:\n        return bufferClone(object);\n\n      case boolTag:\n      case dateTag:\n        return new Ctor(+object);\n\n      case float32Tag: case float64Tag:\n      case int8Tag: case int16Tag: case int32Tag:\n      case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:\n        var buffer = object.buffer;\n        return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length);\n\n      case numberTag:\n      case stringTag:\n        return new Ctor(object);\n\n      case regexpTag:\n        var result = new Ctor(object.source, reFlags.exec(object));\n        result.lastIndex = object.lastIndex;\n    }\n    return result;\n  }\n\n  function isIndex(value, length) {\n    value = +value;\n    length = length == null ? MAX_SAFE_INTEGER : length;\n    return value > -1 && value % 1 == 0 && value < length;\n  }\n\n  function isIterateeCall(value, index, object) {\n    if (!isObject(object)) {\n      return false;\n    }\n    var type = typeof index;\n    if (type == 'number') {\n      var length = getLength(object),\n          prereq = isLength(length) && isIndex(index, length);\n    } else {\n      prereq = type == 'string' && index in object;\n    }\n    if (prereq) {\n      var other = object[index];\n      return value === value ? (value === other) : (other !== other);\n    }\n    return false;\n  }\n\n  function isKey(value, object) {\n    var type = typeof value;\n    if ((type == 'string' && reIsPlainProp.test(value)) || type == 'number') {\n      return true;\n    }\n    if (isArray(value)) {\n      return false;\n    }\n    var result = !reIsDeepProp.test(value);\n    return result || (object != null && value in toObject(object));\n  }\n\n  function isLength(value) {\n    return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n  }\n\n  function isStrictComparable(value) {\n    return value === value && (value === 0 ? ((1 / value) > 0) : !isObject(value));\n  }\n\n  function shimIsPlainObject(value) {\n    var Ctor,\n        support = lodash.support;\n\n    if (!(isObjectLike(value) && objToString.call(value) == objectTag) ||\n        (!hasOwnProperty.call(value, 'constructor') &&\n          (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) {\n      return false;\n    }\n    var result;\n    baseForIn(value, function(subValue, key) {\n      result = key;\n    });\n    return result === undefined || hasOwnProperty.call(value, result);\n  }\n\n  function shimKeys(object) {\n    var props = keysIn(object),\n        propsLength = props.length,\n        length = propsLength && object.length,\n        support = lodash.support;\n\n    var allowIndexes = length && isLength(length) &&\n      (isArray(object) || (support.nonEnumArgs && isArguments(object)));\n\n    var index = -1,\n        result = [];\n\n    while (++index < propsLength) {\n      var key = props[index];\n      if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) {\n        result.push(key);\n      }\n    }\n    return result;\n  }\n\n  function toObject(value) {\n    return isObject(value) ? value : Object(value);\n  }\n\n  function toPath(value) {\n    if (isArray(value)) {\n      return value;\n    }\n    var result = [];\n    baseToString(value).replace(rePropName, function(match, number, quote, string) {\n      result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));\n    });\n    return result;\n  }\n\n  var findLastIndex = createFindIndex(true);\n\n  function indexOf(array, value, fromIndex) {\n    var length = array ? array.length : 0;\n    if (!length) {\n      return -1;\n    }\n    if (typeof fromIndex == 'number') {\n      fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex;\n    } else if (fromIndex) {\n      var index = binaryIndex(array, value),\n          other = array[index];\n\n      if (value === value ? (value === other) : (other !== other)) {\n        return index;\n      }\n      return -1;\n    }\n    return baseIndexOf(array, value, fromIndex || 0);\n  }\n\n  function last(array) {\n    var length = array ? array.length : 0;\n    return length ? array[length - 1] : undefined;\n  }\n\n  function slice(array, start, end) {\n    var length = array ? array.length : 0;\n    if (!length) {\n      return [];\n    }\n    if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {\n      start = 0;\n      end = length;\n    }\n    return baseSlice(array, start, end);\n  }\n\n  function unzip(array) {\n    var index = -1,\n        length = (array && array.length && arrayMax(arrayMap(array, getLength))) >>> 0,\n        result = Array(length);\n\n    while (++index < length) {\n      result[index] = arrayMap(array, baseProperty(index));\n    }\n    return result;\n  }\n\n  var zip = restParam(unzip);\n\n  var forEach = createForEach(arrayEach, baseEach);\n\n  function includes(collection, target, fromIndex, guard) {\n    var length = collection ? getLength(collection) : 0;\n    if (!isLength(length)) {\n      collection = values(collection);\n      length = collection.length;\n    }\n    if (!length) {\n      return false;\n    }\n    if (typeof fromIndex != 'number' || (guard && isIterateeCall(target, fromIndex, guard))) {\n      fromIndex = 0;\n    } else {\n      fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0);\n    }\n    return (typeof collection == 'string' || !isArray(collection) && isString(collection))\n      ? (fromIndex < length && collection.indexOf(target, fromIndex) > -1)\n      : (getIndexOf(collection, target, fromIndex) > -1);\n  }\n\n  function reject(collection, predicate, thisArg) {\n    var func = isArray(collection) ? arrayFilter : baseFilter;\n    predicate = getCallback(predicate, thisArg, 3);\n    return func(collection, function(value, index, collection) {\n      return !predicate(value, index, collection);\n    });\n  }\n\n  function some(collection, predicate, thisArg) {\n    var func = isArray(collection) ? arraySome : baseSome;\n    if (thisArg && isIterateeCall(collection, predicate, thisArg)) {\n      predicate = null;\n    }\n    if (typeof predicate != 'function' || thisArg !== undefined) {\n      predicate = getCallback(predicate, thisArg, 3);\n    }\n    return func(collection, predicate);\n  }\n\n  function restParam(func, start) {\n    if (typeof func != 'function') {\n      throw new TypeError(FUNC_ERROR_TEXT);\n    }\n    start = nativeMax(start === undefined ? (func.length - 1) : (+start || 0), 0);\n    return function() {\n      var args = arguments,\n          index = -1,\n          length = nativeMax(args.length - start, 0),\n          rest = Array(length);\n\n      while (++index < length) {\n        rest[index] = args[start + index];\n      }\n      switch (start) {\n        case 0: return func.call(this, rest);\n        case 1: return func.call(this, args[0], rest);\n        case 2: return func.call(this, args[0], args[1], rest);\n      }\n      var otherArgs = Array(start + 1);\n      index = -1;\n      while (++index < start) {\n        otherArgs[index] = args[index];\n      }\n      otherArgs[start] = rest;\n      return func.apply(this, otherArgs);\n    };\n  }\n\n  function clone(value, isDeep, customizer, thisArg) {\n    if (isDeep && typeof isDeep != 'boolean' && isIterateeCall(value, isDeep, customizer)) {\n      isDeep = false;\n    }\n    else if (typeof isDeep == 'function') {\n      thisArg = customizer;\n      customizer = isDeep;\n      isDeep = false;\n    }\n    customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 1);\n    return baseClone(value, isDeep, customizer);\n  }\n\n  function isArguments(value) {\n    var length = isObjectLike(value) ? value.length : undefined;\n    return isLength(length) && objToString.call(value) == argsTag;\n  }\n\n  var isArray = nativeIsArray || function(value) {\n    return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag;\n  };\n\n  function isEmpty(value) {\n    if (value == null) {\n      return true;\n    }\n    var length = getLength(value);\n    if (isLength(length) && (isArray(value) || isString(value) || isArguments(value) ||\n        (isObjectLike(value) && isFunction(value.splice)))) {\n      return !length;\n    }\n    return !keys(value).length;\n  }\n\n  var isFunction = !(baseIsFunction(/x/) || (Uint8Array && !baseIsFunction(Uint8Array))) ? baseIsFunction : function(value) {\n    return objToString.call(value) == funcTag;\n  };\n\n  function isObject(value) {\n    var type = typeof value;\n    return type == 'function' || (!!value && type == 'object');\n  }\n\n  function isNative(value) {\n    if (value == null) {\n      return false;\n    }\n    if (objToString.call(value) == funcTag) {\n      return reIsNative.test(fnToString.call(value));\n    }\n    return isObjectLike(value) && reIsHostCtor.test(value);\n  }\n\n  function isNumber(value) {\n    return typeof value == 'number' || (isObjectLike(value) && objToString.call(value) == numberTag);\n  }\n\n  var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {\n    if (!(value && objToString.call(value) == objectTag)) {\n      return false;\n    }\n    var valueOf = value.valueOf,\n        objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);\n\n    return objProto\n      ? (value == objProto || getPrototypeOf(value) == objProto)\n      : shimIsPlainObject(value);\n  };\n\n  function isString(value) {\n    return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag);\n  }\n\n  function isTypedArray(value) {\n    return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)];\n  }\n\n  function toPlainObject(value) {\n    return baseCopy(value, keysIn(value));\n  }\n\n  var assign = createAssigner(function(object, source, customizer) {\n    return customizer\n      ? assignWith(object, source, customizer)\n      : baseAssign(object, source);\n  });\n\n  function has(object, path) {\n    if (object == null) {\n      return false;\n    }\n    var result = hasOwnProperty.call(object, path);\n    if (!result && !isKey(path)) {\n      path = toPath(path);\n      object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));\n      path = last(path);\n      result = object != null && hasOwnProperty.call(object, path);\n    }\n    return result;\n  }\n\n  var keys = !nativeKeys ? shimKeys : function(object) {\n    if (object) {\n      var Ctor = object.constructor,\n          length = object.length;\n    }\n    if ((typeof Ctor == 'function' && Ctor.prototype === object) ||\n        (typeof object != 'function' && isLength(length))) {\n      return shimKeys(object);\n    }\n    return isObject(object) ? nativeKeys(object) : [];\n  };\n\n  function keysIn(object) {\n    if (object == null) {\n      return [];\n    }\n    if (!isObject(object)) {\n      object = Object(object);\n    }\n    var length = object.length;\n    length = (length && isLength(length) &&\n      (isArray(object) || (support.nonEnumArgs && isArguments(object))) && length) || 0;\n\n    var Ctor = object.constructor,\n        index = -1,\n        isProto = typeof Ctor == 'function' && Ctor.prototype === object,\n        result = Array(length),\n        skipIndexes = length > 0;\n\n    while (++index < length) {\n      result[index] = (index + '');\n    }\n    for (var key in object) {\n      if (!(skipIndexes && isIndex(key, length)) &&\n          !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {\n        result.push(key);\n      }\n    }\n    return result;\n  }\n\n  var merge = createAssigner(baseMerge);\n\n  function values(object) {\n    return baseValues(object, keys(object));\n  }\n\n  function escapeRegExp(string) {\n    string = baseToString(string);\n    return (string && reHasRegExpChars.test(string))\n      ? string.replace(reRegExpChars, '\\\\$&')\n      : string;\n  }\n\n  function callback(func, thisArg, guard) {\n    if (guard && isIterateeCall(func, thisArg, guard)) {\n      thisArg = null;\n    }\n    return baseCallback(func, thisArg);\n  }\n\n  function constant(value) {\n    return function() {\n      return value;\n    };\n  }\n\n  function identity(value) {\n    return value;\n  }\n\n  function property(path) {\n    return isKey(path) ? baseProperty(path) : basePropertyDeep(path);\n  }\n  lodash.assign = assign;\n  lodash.callback = callback;\n  lodash.constant = constant;\n  lodash.forEach = forEach;\n  lodash.keys = keys;\n  lodash.keysIn = keysIn;\n  lodash.merge = merge;\n  lodash.property = property;\n  lodash.reject = reject;\n  lodash.restParam = restParam;\n  lodash.slice = slice;\n  lodash.toPlainObject = toPlainObject;\n  lodash.unzip = unzip;\n  lodash.values = values;\n  lodash.zip = zip;\n\n  lodash.each = forEach;\n  lodash.extend = assign;\n  lodash.iteratee = callback;\n  lodash.clone = clone;\n  lodash.escapeRegExp = escapeRegExp;\n  lodash.findLastIndex = findLastIndex;\n  lodash.has = has;\n  lodash.identity = identity;\n  lodash.includes = includes;\n  lodash.indexOf = indexOf;\n  lodash.isArguments = isArguments;\n  lodash.isArray = isArray;\n  lodash.isEmpty = isEmpty;\n  lodash.isFunction = isFunction;\n  lodash.isNative = isNative;\n  lodash.isNumber = isNumber;\n  lodash.isObject = isObject;\n  lodash.isPlainObject = isPlainObject;\n  lodash.isString = isString;\n  lodash.isTypedArray = isTypedArray;\n  lodash.last = last;\n  lodash.some = some;\n\n  lodash.any = some;\n  lodash.contains = includes;\n  lodash.include = includes;\n\n  lodash.VERSION = VERSION;\n  if (freeExports && freeModule) {\n    if (moduleExports) {\n      (freeModule.exports = lodash)._ = lodash;\n    }\n    else {\n      freeExports._ = lodash;\n    }\n  }\n  else {\n    root._ = lodash;\n  }\n}.call(this));\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{}],\"/node_modules/jshint/src/jshint.js\":[function(_dereq_,module,exports){\n\nvar _            = _dereq_(\"../lodash\");\nvar events       = _dereq_(\"events\");\nvar vars         = _dereq_(\"./vars.js\");\nvar messages     = _dereq_(\"./messages.js\");\nvar Lexer        = _dereq_(\"./lex.js\").Lexer;\nvar reg          = _dereq_(\"./reg.js\");\nvar state        = _dereq_(\"./state.js\").state;\nvar style        = _dereq_(\"./style.js\");\nvar options      = _dereq_(\"./options.js\");\nvar scopeManager = _dereq_(\"./scope-manager.js\");\n\nvar JSHINT = (function() {\n  \"use strict\";\n\n  var api, // Extension API\n    bang = {\n      \"<\"  : true,\n      \"<=\" : true,\n      \"==\" : true,\n      \"===\": true,\n      \"!==\": true,\n      \"!=\" : true,\n      \">\"  : true,\n      \">=\" : true,\n      \"+\"  : true,\n      \"-\"  : true,\n      \"*\"  : true,\n      \"/\"  : true,\n      \"%\"  : true\n    },\n\n    declared, // Globals that were declared using /*global ... */ syntax.\n\n    functionicity = [\n      \"closure\", \"exception\", \"global\", \"label\",\n      \"outer\", \"unused\", \"var\"\n    ],\n\n    functions, // All of the functions\n\n    inblock,\n    indent,\n    lookahead,\n    lex,\n    member,\n    membersOnly,\n    predefined,    // Global variables defined by option\n\n    stack,\n    urls,\n\n    extraModules = [],\n    emitter = new events.EventEmitter();\n\n  function checkOption(name, t) {\n    name = name.trim();\n\n    if (/^[+-]W\\d{3}$/g.test(name)) {\n      return true;\n    }\n\n    if (options.validNames.indexOf(name) === -1) {\n      if (t.type !== \"jslint\" && !_.has(options.removed, name)) {\n        error(\"E001\", t, name);\n        return false;\n      }\n    }\n\n    return true;\n  }\n\n  function isString(obj) {\n    return Object.prototype.toString.call(obj) === \"[object String]\";\n  }\n\n  function isIdentifier(tkn, value) {\n    if (!tkn)\n      return false;\n\n    if (!tkn.identifier || tkn.value !== value)\n      return false;\n\n    return true;\n  }\n\n  function isReserved(token) {\n    if (!token.reserved) {\n      return false;\n    }\n    var meta = token.meta;\n\n    if (meta && meta.isFutureReservedWord && state.inES5()) {\n      if (!meta.es5) {\n        return false;\n      }\n      if (meta.strictOnly) {\n        if (!state.option.strict && !state.isStrict()) {\n          return false;\n        }\n      }\n\n      if (token.isProperty) {\n        return false;\n      }\n    }\n\n    return true;\n  }\n\n  function supplant(str, data) {\n    return str.replace(/\\{([^{}]*)\\}/g, function(a, b) {\n      var r = data[b];\n      return typeof r === \"string\" || typeof r === \"number\" ? r : a;\n    });\n  }\n\n  function combine(dest, src) {\n    Object.keys(src).forEach(function(name) {\n      if (_.has(JSHINT.blacklist, name)) return;\n      dest[name] = src[name];\n    });\n  }\n\n  function processenforceall() {\n    if (state.option.enforceall) {\n      for (var enforceopt in options.bool.enforcing) {\n        if (state.option[enforceopt] === undefined &&\n            !options.noenforceall[enforceopt]) {\n          state.option[enforceopt] = true;\n        }\n      }\n      for (var relaxopt in options.bool.relaxing) {\n        if (state.option[relaxopt] === undefined) {\n          state.option[relaxopt] = false;\n        }\n      }\n    }\n  }\n\n  function assume() {\n    processenforceall();\n    if (!state.option.esversion && !state.option.moz) {\n      if (state.option.es3) {\n        state.option.esversion = 3;\n      } else if (state.option.esnext) {\n        state.option.esversion = 6;\n      } else {\n        state.option.esversion = 5;\n      }\n    }\n\n    if (state.inES5()) {\n      combine(predefined, vars.ecmaIdentifiers[5]);\n    }\n\n    if (state.inES6()) {\n      combine(predefined, vars.ecmaIdentifiers[6]);\n    }\n\n    if (state.option.module) {\n      if (state.option.strict === true) {\n        state.option.strict = \"global\";\n      }\n      if (!state.inES6()) {\n        warning(\"W134\", state.tokens.next, \"module\", 6);\n      }\n    }\n\n    if (state.option.couch) {\n      combine(predefined, vars.couch);\n    }\n\n    if (state.option.qunit) {\n      combine(predefined, vars.qunit);\n    }\n\n    if (state.option.rhino) {\n      combine(predefined, vars.rhino);\n    }\n\n    if (state.option.shelljs) {\n      combine(predefined, vars.shelljs);\n      combine(predefined, vars.node);\n    }\n    if (state.option.typed) {\n      combine(predefined, vars.typed);\n    }\n\n    if (state.option.phantom) {\n      combine(predefined, vars.phantom);\n      if (state.option.strict === true) {\n        state.option.strict = \"global\";\n      }\n    }\n\n    if (state.option.prototypejs) {\n      combine(predefined, vars.prototypejs);\n    }\n\n    if (state.option.node) {\n      combine(predefined, vars.node);\n      combine(predefined, vars.typed);\n      if (state.option.strict === true) {\n        state.option.strict = \"global\";\n      }\n    }\n\n    if (state.option.devel) {\n      combine(predefined, vars.devel);\n    }\n\n    if (state.option.dojo) {\n      combine(predefined, vars.dojo);\n    }\n\n    if (state.option.browser) {\n      combine(predefined, vars.browser);\n      combine(predefined, vars.typed);\n    }\n\n    if (state.option.browserify) {\n      combine(predefined, vars.browser);\n      combine(predefined, vars.typed);\n      combine(predefined, vars.browserify);\n      if (state.option.strict === true) {\n        state.option.strict = \"global\";\n      }\n    }\n\n    if (state.option.nonstandard) {\n      combine(predefined, vars.nonstandard);\n    }\n\n    if (state.option.jasmine) {\n      combine(predefined, vars.jasmine);\n    }\n\n    if (state.option.jquery) {\n      combine(predefined, vars.jquery);\n    }\n\n    if (state.option.mootools) {\n      combine(predefined, vars.mootools);\n    }\n\n    if (state.option.worker) {\n      combine(predefined, vars.worker);\n    }\n\n    if (state.option.wsh) {\n      combine(predefined, vars.wsh);\n    }\n\n    if (state.option.globalstrict && state.option.strict !== false) {\n      state.option.strict = \"global\";\n    }\n\n    if (state.option.yui) {\n      combine(predefined, vars.yui);\n    }\n\n    if (state.option.mocha) {\n      combine(predefined, vars.mocha);\n    }\n  }\n  function quit(code, line, chr) {\n    var percentage = Math.floor((line / state.lines.length) * 100);\n    var message = messages.errors[code].desc;\n\n    throw {\n      name: \"JSHintError\",\n      line: line,\n      character: chr,\n      message: message + \" (\" + percentage + \"% scanned).\",\n      raw: message,\n      code: code\n    };\n  }\n\n  function removeIgnoredMessages() {\n    var ignored = state.ignoredLines;\n\n    if (_.isEmpty(ignored)) return;\n    JSHINT.errors = _.reject(JSHINT.errors, function(err) { return ignored[err.line] });\n  }\n\n  function warning(code, t, a, b, c, d) {\n    var ch, l, w, msg;\n\n    if (/^W\\d{3}$/.test(code)) {\n      if (state.ignored[code])\n        return;\n\n      msg = messages.warnings[code];\n    } else if (/E\\d{3}/.test(code)) {\n      msg = messages.errors[code];\n    } else if (/I\\d{3}/.test(code)) {\n      msg = messages.info[code];\n    }\n\n    t = t || state.tokens.next || {};\n    if (t.id === \"(end)\") {  // `~\n      t = state.tokens.curr;\n    }\n\n    l = t.line || 0;\n    ch = t.from || 0;\n\n    w = {\n      id: \"(error)\",\n      raw: msg.desc,\n      code: msg.code,\n      evidence: state.lines[l - 1] || \"\",\n      line: l,\n      character: ch,\n      scope: JSHINT.scope,\n      a: a,\n      b: b,\n      c: c,\n      d: d\n    };\n\n    w.reason = supplant(msg.desc, w);\n    JSHINT.errors.push(w);\n\n    removeIgnoredMessages();\n\n    if (JSHINT.errors.length >= state.option.maxerr)\n      quit(\"E043\", l, ch);\n\n    return w;\n  }\n\n  function warningAt(m, l, ch, a, b, c, d) {\n    return warning(m, {\n      line: l,\n      from: ch\n    }, a, b, c, d);\n  }\n\n  function error(m, t, a, b, c, d) {\n    warning(m, t, a, b, c, d);\n  }\n\n  function errorAt(m, l, ch, a, b, c, d) {\n    return error(m, {\n      line: l,\n      from: ch\n    }, a, b, c, d);\n  }\n  function addInternalSrc(elem, src) {\n    var i;\n    i = {\n      id: \"(internal)\",\n      elem: elem,\n      value: src\n    };\n    JSHINT.internals.push(i);\n    return i;\n  }\n\n  function doOption() {\n    var nt = state.tokens.next;\n    var body = nt.body.match(/(-\\s+)?[^\\s,:]+(?:\\s*:\\s*(-\\s+)?[^\\s,]+)?/g) || [];\n\n    var predef = {};\n    if (nt.type === \"globals\") {\n      body.forEach(function(g, idx) {\n        g = g.split(\":\");\n        var key = (g[0] || \"\").trim();\n        var val = (g[1] || \"\").trim();\n\n        if (key === \"-\" || !key.length) {\n          if (idx > 0 && idx === body.length - 1) {\n            return;\n          }\n          error(\"E002\", nt);\n          return;\n        }\n\n        if (key.charAt(0) === \"-\") {\n          key = key.slice(1);\n          val = false;\n\n          JSHINT.blacklist[key] = key;\n          delete predefined[key];\n        } else {\n          predef[key] = (val === \"true\");\n        }\n      });\n\n      combine(predefined, predef);\n\n      for (var key in predef) {\n        if (_.has(predef, key)) {\n          declared[key] = nt;\n        }\n      }\n    }\n\n    if (nt.type === \"exported\") {\n      body.forEach(function(e, idx) {\n        if (!e.length) {\n          if (idx > 0 && idx === body.length - 1) {\n            return;\n          }\n          error(\"E002\", nt);\n          return;\n        }\n\n        state.funct[\"(scope)\"].addExported(e);\n      });\n    }\n\n    if (nt.type === \"members\") {\n      membersOnly = membersOnly || {};\n\n      body.forEach(function(m) {\n        var ch1 = m.charAt(0);\n        var ch2 = m.charAt(m.length - 1);\n\n        if (ch1 === ch2 && (ch1 === \"\\\"\" || ch1 === \"'\")) {\n          m = m\n            .substr(1, m.length - 2)\n            .replace(\"\\\\\\\"\", \"\\\"\");\n        }\n\n        membersOnly[m] = false;\n      });\n    }\n\n    var numvals = [\n      \"maxstatements\",\n      \"maxparams\",\n      \"maxdepth\",\n      \"maxcomplexity\",\n      \"maxerr\",\n      \"maxlen\",\n      \"indent\"\n    ];\n\n    if (nt.type === \"jshint\" || nt.type === \"jslint\") {\n      body.forEach(function(g) {\n        g = g.split(\":\");\n        var key = (g[0] || \"\").trim();\n        var val = (g[1] || \"\").trim();\n\n        if (!checkOption(key, nt)) {\n          return;\n        }\n\n        if (numvals.indexOf(key) >= 0) {\n          if (val !== \"false\") {\n            val = +val;\n\n            if (typeof val !== \"number\" || !isFinite(val) || val <= 0 || Math.floor(val) !== val) {\n              error(\"E032\", nt, g[1].trim());\n              return;\n            }\n\n            state.option[key] = val;\n          } else {\n            state.option[key] = key === \"indent\" ? 4 : false;\n          }\n\n          return;\n        }\n\n        if (key === \"validthis\") {\n\n          if (state.funct[\"(global)\"])\n            return void error(\"E009\");\n\n          if (val !== \"true\" && val !== \"false\")\n            return void error(\"E002\", nt);\n\n          state.option.validthis = (val === \"true\");\n          return;\n        }\n\n        if (key === \"quotmark\") {\n          switch (val) {\n          case \"true\":\n          case \"false\":\n            state.option.quotmark = (val === \"true\");\n            break;\n          case \"double\":\n          case \"single\":\n            state.option.quotmark = val;\n            break;\n          default:\n            error(\"E002\", nt);\n          }\n          return;\n        }\n\n        if (key === \"shadow\") {\n          switch (val) {\n          case \"true\":\n            state.option.shadow = true;\n            break;\n          case \"outer\":\n            state.option.shadow = \"outer\";\n            break;\n          case \"false\":\n          case \"inner\":\n            state.option.shadow = \"inner\";\n            break;\n          default:\n            error(\"E002\", nt);\n          }\n          return;\n        }\n\n        if (key === \"unused\") {\n          switch (val) {\n          case \"true\":\n            state.option.unused = true;\n            break;\n          case \"false\":\n            state.option.unused = false;\n            break;\n          case \"vars\":\n          case \"strict\":\n            state.option.unused = val;\n            break;\n          default:\n            error(\"E002\", nt);\n          }\n          return;\n        }\n\n        if (key === \"latedef\") {\n          switch (val) {\n          case \"true\":\n            state.option.latedef = true;\n            break;\n          case \"false\":\n            state.option.latedef = false;\n            break;\n          case \"nofunc\":\n            state.option.latedef = \"nofunc\";\n            break;\n          default:\n            error(\"E002\", nt);\n          }\n          return;\n        }\n\n        if (key === \"ignore\") {\n          switch (val) {\n          case \"line\":\n            state.ignoredLines[nt.line] = true;\n            removeIgnoredMessages();\n            break;\n          default:\n            error(\"E002\", nt);\n          }\n          return;\n        }\n\n        if (key === \"strict\") {\n          switch (val) {\n          case \"true\":\n            state.option.strict = true;\n            break;\n          case \"false\":\n            state.option.strict = false;\n            break;\n          case \"func\":\n          case \"global\":\n          case \"implied\":\n            state.option.strict = val;\n            break;\n          default:\n            error(\"E002\", nt);\n          }\n          return;\n        }\n\n        if (key === \"module\") {\n          if (!hasParsedCode(state.funct)) {\n            error(\"E055\", state.tokens.next, \"module\");\n          }\n        }\n        var esversions = {\n          es3   : 3,\n          es5   : 5,\n          esnext: 6\n        };\n        if (_.has(esversions, key)) {\n          switch (val) {\n          case \"true\":\n            state.option.moz = false;\n            state.option.esversion = esversions[key];\n            break;\n          case \"false\":\n            if (!state.option.moz) {\n              state.option.esversion = 5;\n            }\n            break;\n          default:\n            error(\"E002\", nt);\n          }\n          return;\n        }\n\n        if (key === \"esversion\") {\n          switch (val) {\n          case \"5\":\n            if (state.inES5(true)) {\n              warning(\"I003\");\n            }\n          case \"3\":\n          case \"6\":\n            state.option.moz = false;\n            state.option.esversion = +val;\n            break;\n          case \"2015\":\n            state.option.moz = false;\n            state.option.esversion = 6;\n            break;\n          default:\n            error(\"E002\", nt);\n          }\n          if (!hasParsedCode(state.funct)) {\n            error(\"E055\", state.tokens.next, \"esversion\");\n          }\n          return;\n        }\n\n        var match = /^([+-])(W\\d{3})$/g.exec(key);\n        if (match) {\n          state.ignored[match[2]] = (match[1] === \"-\");\n          return;\n        }\n\n        var tn;\n        if (val === \"true\" || val === \"false\") {\n          if (nt.type === \"jslint\") {\n            tn = options.renamed[key] || key;\n            state.option[tn] = (val === \"true\");\n\n            if (options.inverted[tn] !== undefined) {\n              state.option[tn] = !state.option[tn];\n            }\n          } else {\n            state.option[key] = (val === \"true\");\n          }\n\n          if (key === \"newcap\") {\n            state.option[\"(explicitNewcap)\"] = true;\n          }\n          return;\n        }\n\n        error(\"E002\", nt);\n      });\n\n      assume();\n    }\n  }\n\n  function peek(p) {\n    var i = p || 0, j = lookahead.length, t;\n\n    if (i < j) {\n      return lookahead[i];\n    }\n\n    while (j <= i) {\n      t = lookahead[j];\n      if (!t) {\n        t = lookahead[j] = lex.token();\n      }\n      j += 1;\n    }\n    if (!t && state.tokens.next.id === \"(end)\") {\n      return state.tokens.next;\n    }\n\n    return t;\n  }\n\n  function peekIgnoreEOL() {\n    var i = 0;\n    var t;\n    do {\n      t = peek(i++);\n    } while (t.id === \"(endline)\");\n    return t;\n  }\n\n  function advance(id, t) {\n\n    switch (state.tokens.curr.id) {\n    case \"(number)\":\n      if (state.tokens.next.id === \".\") {\n        warning(\"W005\", state.tokens.curr);\n      }\n      break;\n    case \"-\":\n      if (state.tokens.next.id === \"-\" || state.tokens.next.id === \"--\") {\n        warning(\"W006\");\n      }\n      break;\n    case \"+\":\n      if (state.tokens.next.id === \"+\" || state.tokens.next.id === \"++\") {\n        warning(\"W007\");\n      }\n      break;\n    }\n\n    if (id && state.tokens.next.id !== id) {\n      if (t) {\n        if (state.tokens.next.id === \"(end)\") {\n          error(\"E019\", t, t.id);\n        } else {\n          error(\"E020\", state.tokens.next, id, t.id, t.line, state.tokens.next.value);\n        }\n      } else if (state.tokens.next.type !== \"(identifier)\" || state.tokens.next.value !== id) {\n        warning(\"W116\", state.tokens.next, id, state.tokens.next.value);\n      }\n    }\n\n    state.tokens.prev = state.tokens.curr;\n    state.tokens.curr = state.tokens.next;\n    for (;;) {\n      state.tokens.next = lookahead.shift() || lex.token();\n\n      if (!state.tokens.next) { // No more tokens left, give up\n        quit(\"E041\", state.tokens.curr.line);\n      }\n\n      if (state.tokens.next.id === \"(end)\" || state.tokens.next.id === \"(error)\") {\n        return;\n      }\n\n      if (state.tokens.next.check) {\n        state.tokens.next.check();\n      }\n\n      if (state.tokens.next.isSpecial) {\n        if (state.tokens.next.type === \"falls through\") {\n          state.tokens.curr.caseFallsThrough = true;\n        } else {\n          doOption();\n        }\n      } else {\n        if (state.tokens.next.id !== \"(endline)\") {\n          break;\n        }\n      }\n    }\n  }\n\n  function isInfix(token) {\n    return token.infix || (!token.identifier && !token.template && !!token.led);\n  }\n\n  function isEndOfExpr() {\n    var curr = state.tokens.curr;\n    var next = state.tokens.next;\n    if (next.id === \";\" || next.id === \"}\" || next.id === \":\") {\n      return true;\n    }\n    if (isInfix(next) === isInfix(curr) || (curr.id === \"yield\" && state.inMoz())) {\n      return curr.line !== startLine(next);\n    }\n    return false;\n  }\n\n  function isBeginOfExpr(prev) {\n    return !prev.left && prev.arity !== \"unary\";\n  }\n\n  function expression(rbp, initial) {\n    var left, isArray = false, isObject = false, isLetExpr = false;\n\n    state.nameStack.push();\n    if (!initial && state.tokens.next.value === \"let\" && peek(0).value === \"(\") {\n      if (!state.inMoz()) {\n        warning(\"W118\", state.tokens.next, \"let expressions\");\n      }\n      isLetExpr = true;\n      state.funct[\"(scope)\"].stack();\n      advance(\"let\");\n      advance(\"(\");\n      state.tokens.prev.fud();\n      advance(\")\");\n    }\n\n    if (state.tokens.next.id === \"(end)\")\n      error(\"E006\", state.tokens.curr);\n\n    var isDangerous =\n      state.option.asi &&\n      state.tokens.prev.line !== startLine(state.tokens.curr) &&\n      _.contains([\"]\", \")\"], state.tokens.prev.id) &&\n      _.contains([\"[\", \"(\"], state.tokens.curr.id);\n\n    if (isDangerous)\n      warning(\"W014\", state.tokens.curr, state.tokens.curr.id);\n\n    advance();\n\n    if (initial) {\n      state.funct[\"(verb)\"] = state.tokens.curr.value;\n      state.tokens.curr.beginsStmt = true;\n    }\n\n    if (initial === true && state.tokens.curr.fud) {\n      left = state.tokens.curr.fud();\n    } else {\n      if (state.tokens.curr.nud) {\n        left = state.tokens.curr.nud();\n      } else {\n        error(\"E030\", state.tokens.curr, state.tokens.curr.id);\n      }\n      while ((rbp < state.tokens.next.lbp || state.tokens.next.type === \"(template)\") &&\n              !isEndOfExpr()) {\n        isArray = state.tokens.curr.value === \"Array\";\n        isObject = state.tokens.curr.value === \"Object\";\n        if (left && (left.value || (left.first && left.first.value))) {\n          if (left.value !== \"new\" ||\n            (left.first && left.first.value && left.first.value === \".\")) {\n            isArray = false;\n            if (left.value !== state.tokens.curr.value) {\n              isObject = false;\n            }\n          }\n        }\n\n        advance();\n\n        if (isArray && state.tokens.curr.id === \"(\" && state.tokens.next.id === \")\") {\n          warning(\"W009\", state.tokens.curr);\n        }\n\n        if (isObject && state.tokens.curr.id === \"(\" && state.tokens.next.id === \")\") {\n          warning(\"W010\", state.tokens.curr);\n        }\n\n        if (left && state.tokens.curr.led) {\n          left = state.tokens.curr.led(left);\n        } else {\n          error(\"E033\", state.tokens.curr, state.tokens.curr.id);\n        }\n      }\n    }\n    if (isLetExpr) {\n      state.funct[\"(scope)\"].unstack();\n    }\n\n    state.nameStack.pop();\n\n    return left;\n  }\n\n  function startLine(token) {\n    return token.startLine || token.line;\n  }\n\n  function nobreaknonadjacent(left, right) {\n    left = left || state.tokens.curr;\n    right = right || state.tokens.next;\n    if (!state.option.laxbreak && left.line !== startLine(right)) {\n      warning(\"W014\", right, right.value);\n    }\n  }\n\n  function nolinebreak(t) {\n    t = t || state.tokens.curr;\n    if (t.line !== startLine(state.tokens.next)) {\n      warning(\"E022\", t, t.value);\n    }\n  }\n\n  function nobreakcomma(left, right) {\n    if (left.line !== startLine(right)) {\n      if (!state.option.laxcomma) {\n        if (comma.first) {\n          warning(\"I001\");\n          comma.first = false;\n        }\n        warning(\"W014\", left, right.value);\n      }\n    }\n  }\n\n  function comma(opts) {\n    opts = opts || {};\n\n    if (!opts.peek) {\n      nobreakcomma(state.tokens.curr, state.tokens.next);\n      advance(\",\");\n    } else {\n      nobreakcomma(state.tokens.prev, state.tokens.curr);\n    }\n\n    if (state.tokens.next.identifier && !(opts.property && state.inES5())) {\n      switch (state.tokens.next.value) {\n      case \"break\":\n      case \"case\":\n      case \"catch\":\n      case \"continue\":\n      case \"default\":\n      case \"do\":\n      case \"else\":\n      case \"finally\":\n      case \"for\":\n      case \"if\":\n      case \"in\":\n      case \"instanceof\":\n      case \"return\":\n      case \"switch\":\n      case \"throw\":\n      case \"try\":\n      case \"var\":\n      case \"let\":\n      case \"while\":\n      case \"with\":\n        error(\"E024\", state.tokens.next, state.tokens.next.value);\n        return false;\n      }\n    }\n\n    if (state.tokens.next.type === \"(punctuator)\") {\n      switch (state.tokens.next.value) {\n      case \"}\":\n      case \"]\":\n      case \",\":\n        if (opts.allowTrailing) {\n          return true;\n        }\n      case \")\":\n        error(\"E024\", state.tokens.next, state.tokens.next.value);\n        return false;\n      }\n    }\n    return true;\n  }\n\n  function symbol(s, p) {\n    var x = state.syntax[s];\n    if (!x || typeof x !== \"object\") {\n      state.syntax[s] = x = {\n        id: s,\n        lbp: p,\n        value: s\n      };\n    }\n    return x;\n  }\n\n  function delim(s) {\n    var x = symbol(s, 0);\n    x.delim = true;\n    return x;\n  }\n\n  function stmt(s, f) {\n    var x = delim(s);\n    x.identifier = x.reserved = true;\n    x.fud = f;\n    return x;\n  }\n\n  function blockstmt(s, f) {\n    var x = stmt(s, f);\n    x.block = true;\n    return x;\n  }\n\n  function reserveName(x) {\n    var c = x.id.charAt(0);\n    if ((c >= \"a\" && c <= \"z\") || (c >= \"A\" && c <= \"Z\")) {\n      x.identifier = x.reserved = true;\n    }\n    return x;\n  }\n\n  function prefix(s, f) {\n    var x = symbol(s, 150);\n    reserveName(x);\n\n    x.nud = (typeof f === \"function\") ? f : function() {\n      this.arity = \"unary\";\n      this.right = expression(150);\n\n      if (this.id === \"++\" || this.id === \"--\") {\n        if (state.option.plusplus) {\n          warning(\"W016\", this, this.id);\n        } else if (this.right && (!this.right.identifier || isReserved(this.right)) &&\n            this.right.id !== \".\" && this.right.id !== \"[\") {\n          warning(\"W017\", this);\n        }\n\n        if (this.right && this.right.isMetaProperty) {\n          error(\"E031\", this);\n        } else if (this.right && this.right.identifier) {\n          state.funct[\"(scope)\"].block.modify(this.right.value, this);\n        }\n      }\n\n      return this;\n    };\n\n    return x;\n  }\n\n  function type(s, f) {\n    var x = delim(s);\n    x.type = s;\n    x.nud = f;\n    return x;\n  }\n\n  function reserve(name, func) {\n    var x = type(name, func);\n    x.identifier = true;\n    x.reserved = true;\n    return x;\n  }\n\n  function FutureReservedWord(name, meta) {\n    var x = type(name, (meta && meta.nud) || function() {\n      return this;\n    });\n\n    meta = meta || {};\n    meta.isFutureReservedWord = true;\n\n    x.value = name;\n    x.identifier = true;\n    x.reserved = true;\n    x.meta = meta;\n\n    return x;\n  }\n\n  function reservevar(s, v) {\n    return reserve(s, function() {\n      if (typeof v === \"function\") {\n        v(this);\n      }\n      return this;\n    });\n  }\n\n  function infix(s, f, p, w) {\n    var x = symbol(s, p);\n    reserveName(x);\n    x.infix = true;\n    x.led = function(left) {\n      if (!w) {\n        nobreaknonadjacent(state.tokens.prev, state.tokens.curr);\n      }\n      if ((s === \"in\" || s === \"instanceof\") && left.id === \"!\") {\n        warning(\"W018\", left, \"!\");\n      }\n      if (typeof f === \"function\") {\n        return f(left, this);\n      } else {\n        this.left = left;\n        this.right = expression(p);\n        return this;\n      }\n    };\n    return x;\n  }\n\n  function application(s) {\n    var x = symbol(s, 42);\n\n    x.led = function(left) {\n      nobreaknonadjacent(state.tokens.prev, state.tokens.curr);\n\n      this.left = left;\n      this.right = doFunction({ type: \"arrow\", loneArg: left });\n      return this;\n    };\n    return x;\n  }\n\n  function relation(s, f) {\n    var x = symbol(s, 100);\n\n    x.led = function(left) {\n      nobreaknonadjacent(state.tokens.prev, state.tokens.curr);\n      this.left = left;\n      var right = this.right = expression(100);\n\n      if (isIdentifier(left, \"NaN\") || isIdentifier(right, \"NaN\")) {\n        warning(\"W019\", this);\n      } else if (f) {\n        f.apply(this, [left, right]);\n      }\n\n      if (!left || !right) {\n        quit(\"E041\", state.tokens.curr.line);\n      }\n\n      if (left.id === \"!\") {\n        warning(\"W018\", left, \"!\");\n      }\n\n      if (right.id === \"!\") {\n        warning(\"W018\", right, \"!\");\n      }\n\n      return this;\n    };\n    return x;\n  }\n\n  function isPoorRelation(node) {\n    return node &&\n        ((node.type === \"(number)\" && +node.value === 0) ||\n         (node.type === \"(string)\" && node.value === \"\") ||\n         (node.type === \"null\" && !state.option.eqnull) ||\n        node.type === \"true\" ||\n        node.type === \"false\" ||\n        node.type === \"undefined\");\n  }\n\n  var typeofValues = {};\n  typeofValues.legacy = [\n    \"xml\",\n    \"unknown\"\n  ];\n  typeofValues.es3 = [\n    \"undefined\", \"boolean\", \"number\", \"string\", \"function\", \"object\",\n  ];\n  typeofValues.es3 = typeofValues.es3.concat(typeofValues.legacy);\n  typeofValues.es6 = typeofValues.es3.concat(\"symbol\");\n  function isTypoTypeof(left, right, state) {\n    var values;\n\n    if (state.option.notypeof)\n      return false;\n\n    if (!left || !right)\n      return false;\n\n    values = state.inES6() ? typeofValues.es6 : typeofValues.es3;\n\n    if (right.type === \"(identifier)\" && right.value === \"typeof\" && left.type === \"(string)\")\n      return !_.contains(values, left.value);\n\n    return false;\n  }\n\n  function isGlobalEval(left, state) {\n    var isGlobal = false;\n    if (left.type === \"this\" && state.funct[\"(context)\"] === null) {\n      isGlobal = true;\n    }\n    else if (left.type === \"(identifier)\") {\n      if (state.option.node && left.value === \"global\") {\n        isGlobal = true;\n      }\n\n      else if (state.option.browser && (left.value === \"window\" || left.value === \"document\")) {\n        isGlobal = true;\n      }\n    }\n\n    return isGlobal;\n  }\n\n  function findNativePrototype(left) {\n    var natives = [\n      \"Array\", \"ArrayBuffer\", \"Boolean\", \"Collator\", \"DataView\", \"Date\",\n      \"DateTimeFormat\", \"Error\", \"EvalError\", \"Float32Array\", \"Float64Array\",\n      \"Function\", \"Infinity\", \"Intl\", \"Int16Array\", \"Int32Array\", \"Int8Array\",\n      \"Iterator\", \"Number\", \"NumberFormat\", \"Object\", \"RangeError\",\n      \"ReferenceError\", \"RegExp\", \"StopIteration\", \"String\", \"SyntaxError\",\n      \"TypeError\", \"Uint16Array\", \"Uint32Array\", \"Uint8Array\", \"Uint8ClampedArray\",\n      \"URIError\"\n    ];\n\n    function walkPrototype(obj) {\n      if (typeof obj !== \"object\") return;\n      return obj.right === \"prototype\" ? obj : walkPrototype(obj.left);\n    }\n\n    function walkNative(obj) {\n      while (!obj.identifier && typeof obj.left === \"object\")\n        obj = obj.left;\n\n      if (obj.identifier && natives.indexOf(obj.value) >= 0)\n        return obj.value;\n    }\n\n    var prototype = walkPrototype(left);\n    if (prototype) return walkNative(prototype);\n  }\n  function checkLeftSideAssign(left, assignToken, options) {\n\n    var allowDestructuring = options && options.allowDestructuring;\n\n    assignToken = assignToken || left;\n\n    if (state.option.freeze) {\n      var nativeObject = findNativePrototype(left);\n      if (nativeObject)\n        warning(\"W121\", left, nativeObject);\n    }\n\n    if (left.identifier && !left.isMetaProperty) {\n      state.funct[\"(scope)\"].block.reassign(left.value, left);\n    }\n\n    if (left.id === \".\") {\n      if (!left.left || left.left.value === \"arguments\" && !state.isStrict()) {\n        warning(\"E031\", assignToken);\n      }\n\n      state.nameStack.set(state.tokens.prev);\n      return true;\n    } else if (left.id === \"{\" || left.id === \"[\") {\n      if (allowDestructuring && state.tokens.curr.left.destructAssign) {\n        state.tokens.curr.left.destructAssign.forEach(function(t) {\n          if (t.id) {\n            state.funct[\"(scope)\"].block.modify(t.id, t.token);\n          }\n        });\n      } else {\n        if (left.id === \"{\" || !left.left) {\n          warning(\"E031\", assignToken);\n        } else if (left.left.value === \"arguments\" && !state.isStrict()) {\n          warning(\"E031\", assignToken);\n        }\n      }\n\n      if (left.id === \"[\") {\n        state.nameStack.set(left.right);\n      }\n\n      return true;\n    } else if (left.isMetaProperty) {\n      error(\"E031\", assignToken);\n      return true;\n    } else if (left.identifier && !isReserved(left)) {\n      if (state.funct[\"(scope)\"].labeltype(left.value) === \"exception\") {\n        warning(\"W022\", left);\n      }\n      state.nameStack.set(left);\n      return true;\n    }\n\n    if (left === state.syntax[\"function\"]) {\n      warning(\"W023\", state.tokens.curr);\n    }\n\n    return false;\n  }\n\n  function assignop(s, f, p) {\n    var x = infix(s, typeof f === \"function\" ? f : function(left, that) {\n      that.left = left;\n\n      if (left && checkLeftSideAssign(left, that, { allowDestructuring: true })) {\n        that.right = expression(10);\n        return that;\n      }\n\n      error(\"E031\", that);\n    }, p);\n\n    x.exps = true;\n    x.assign = true;\n    return x;\n  }\n\n\n  function bitwise(s, f, p) {\n    var x = symbol(s, p);\n    reserveName(x);\n    x.led = (typeof f === \"function\") ? f : function(left) {\n      if (state.option.bitwise) {\n        warning(\"W016\", this, this.id);\n      }\n      this.left = left;\n      this.right = expression(p);\n      return this;\n    };\n    return x;\n  }\n\n  function bitwiseassignop(s) {\n    return assignop(s, function(left, that) {\n      if (state.option.bitwise) {\n        warning(\"W016\", that, that.id);\n      }\n\n      if (left && checkLeftSideAssign(left, that)) {\n        that.right = expression(10);\n        return that;\n      }\n      error(\"E031\", that);\n    }, 20);\n  }\n\n  function suffix(s) {\n    var x = symbol(s, 150);\n\n    x.led = function(left) {\n      if (state.option.plusplus) {\n        warning(\"W016\", this, this.id);\n      } else if ((!left.identifier || isReserved(left)) && left.id !== \".\" && left.id !== \"[\") {\n        warning(\"W017\", this);\n      }\n\n      if (left.isMetaProperty) {\n        error(\"E031\", this);\n      } else if (left && left.identifier) {\n        state.funct[\"(scope)\"].block.modify(left.value, left);\n      }\n\n      this.left = left;\n      return this;\n    };\n    return x;\n  }\n\n  function optionalidentifier(fnparam, prop, preserve) {\n    if (!state.tokens.next.identifier) {\n      return;\n    }\n\n    if (!preserve) {\n      advance();\n    }\n\n    var curr = state.tokens.curr;\n    var val  = state.tokens.curr.value;\n\n    if (!isReserved(curr)) {\n      return val;\n    }\n\n    if (prop) {\n      if (state.inES5()) {\n        return val;\n      }\n    }\n\n    if (fnparam && val === \"undefined\") {\n      return val;\n    }\n\n    warning(\"W024\", state.tokens.curr, state.tokens.curr.id);\n    return val;\n  }\n  function identifier(fnparam, prop) {\n    var i = optionalidentifier(fnparam, prop, false);\n    if (i) {\n      return i;\n    }\n    if (state.tokens.next.value === \"...\") {\n      if (!state.inES6(true)) {\n        warning(\"W119\", state.tokens.next, \"spread/rest operator\", \"6\");\n      }\n      advance();\n\n      if (checkPunctuator(state.tokens.next, \"...\")) {\n        warning(\"E024\", state.tokens.next, \"...\");\n        while (checkPunctuator(state.tokens.next, \"...\")) {\n          advance();\n        }\n      }\n\n      if (!state.tokens.next.identifier) {\n        warning(\"E024\", state.tokens.curr, \"...\");\n        return;\n      }\n\n      return identifier(fnparam, prop);\n    } else {\n      error(\"E030\", state.tokens.next, state.tokens.next.value);\n      if (state.tokens.next.id !== \";\") {\n        advance();\n      }\n    }\n  }\n\n\n  function reachable(controlToken) {\n    var i = 0, t;\n    if (state.tokens.next.id !== \";\" || controlToken.inBracelessBlock) {\n      return;\n    }\n    for (;;) {\n      do {\n        t = peek(i);\n        i += 1;\n      } while (t.id !== \"(end)\" && t.id === \"(comment)\");\n\n      if (t.reach) {\n        return;\n      }\n      if (t.id !== \"(endline)\") {\n        if (t.id === \"function\") {\n          if (state.option.latedef === true) {\n            warning(\"W026\", t);\n          }\n          break;\n        }\n\n        warning(\"W027\", t, t.value, controlToken.value);\n        break;\n      }\n    }\n  }\n\n  function parseFinalSemicolon() {\n    if (state.tokens.next.id !== \";\") {\n      if (state.tokens.next.isUnclosed) return advance();\n\n      var sameLine = startLine(state.tokens.next) === state.tokens.curr.line &&\n                     state.tokens.next.id !== \"(end)\";\n      var blockEnd = checkPunctuator(state.tokens.next, \"}\");\n\n      if (sameLine && !blockEnd) {\n        errorAt(\"E058\", state.tokens.curr.line, state.tokens.curr.character);\n      } else if (!state.option.asi) {\n        if ((blockEnd && !state.option.lastsemic) || !sameLine) {\n          warningAt(\"W033\", state.tokens.curr.line, state.tokens.curr.character);\n        }\n      }\n    } else {\n      advance(\";\");\n    }\n  }\n\n  function statement() {\n    var i = indent, r, t = state.tokens.next, hasOwnScope = false;\n\n    if (t.id === \";\") {\n      advance(\";\");\n      return;\n    }\n    var res = isReserved(t);\n\n    if (res && t.meta && t.meta.isFutureReservedWord && peek().id === \":\") {\n      warning(\"W024\", t, t.id);\n      res = false;\n    }\n\n    if (t.identifier && !res && peek().id === \":\") {\n      advance();\n      advance(\":\");\n\n      hasOwnScope = true;\n      state.funct[\"(scope)\"].stack();\n      state.funct[\"(scope)\"].block.addBreakLabel(t.value, { token: state.tokens.curr });\n\n      if (!state.tokens.next.labelled && state.tokens.next.value !== \"{\") {\n        warning(\"W028\", state.tokens.next, t.value, state.tokens.next.value);\n      }\n\n      state.tokens.next.label = t.value;\n      t = state.tokens.next;\n    }\n\n    if (t.id === \"{\") {\n      var iscase = (state.funct[\"(verb)\"] === \"case\" && state.tokens.curr.value === \":\");\n      block(true, true, false, false, iscase);\n      return;\n    }\n\n    r = expression(0, true);\n\n    if (r && !(r.identifier && r.value === \"function\") &&\n        !(r.type === \"(punctuator)\" && r.left &&\n          r.left.identifier && r.left.value === \"function\")) {\n      if (!state.isStrict() &&\n          state.option.strict === \"global\") {\n        warning(\"E007\");\n      }\n    }\n\n    if (!t.block) {\n      if (!state.option.expr && (!r || !r.exps)) {\n        warning(\"W030\", state.tokens.curr);\n      } else if (state.option.nonew && r && r.left && r.id === \"(\" && r.left.id === \"new\") {\n        warning(\"W031\", t);\n      }\n      parseFinalSemicolon();\n    }\n\n    indent = i;\n    if (hasOwnScope) {\n      state.funct[\"(scope)\"].unstack();\n    }\n    return r;\n  }\n\n\n  function statements() {\n    var a = [], p;\n\n    while (!state.tokens.next.reach && state.tokens.next.id !== \"(end)\") {\n      if (state.tokens.next.id === \";\") {\n        p = peek();\n\n        if (!p || (p.id !== \"(\" && p.id !== \"[\")) {\n          warning(\"W032\");\n        }\n\n        advance(\";\");\n      } else {\n        a.push(statement());\n      }\n    }\n    return a;\n  }\n  function directives() {\n    var i, p, pn;\n\n    while (state.tokens.next.id === \"(string)\") {\n      p = peek(0);\n      if (p.id === \"(endline)\") {\n        i = 1;\n        do {\n          pn = peek(i++);\n        } while (pn.id === \"(endline)\");\n        if (pn.id === \";\") {\n          p = pn;\n        } else if (pn.value === \"[\" || pn.value === \".\") {\n          break;\n        } else if (!state.option.asi || pn.value === \"(\") {\n          warning(\"W033\", state.tokens.next);\n        }\n      } else if (p.id === \".\" || p.id === \"[\") {\n        break;\n      } else if (p.id !== \";\") {\n        warning(\"W033\", p);\n      }\n\n      advance();\n      var directive = state.tokens.curr.value;\n      if (state.directive[directive] ||\n          (directive === \"use strict\" && state.option.strict === \"implied\")) {\n        warning(\"W034\", state.tokens.curr, directive);\n      }\n      state.directive[directive] = true;\n\n      if (p.id === \";\") {\n        advance(\";\");\n      }\n    }\n\n    if (state.isStrict()) {\n      if (!state.option[\"(explicitNewcap)\"]) {\n        state.option.newcap = true;\n      }\n      state.option.undef = true;\n    }\n  }\n  function block(ordinary, stmt, isfunc, isfatarrow, iscase) {\n    var a,\n      b = inblock,\n      old_indent = indent,\n      m,\n      t,\n      line,\n      d;\n\n    inblock = ordinary;\n\n    t = state.tokens.next;\n\n    var metrics = state.funct[\"(metrics)\"];\n    metrics.nestedBlockDepth += 1;\n    metrics.verifyMaxNestedBlockDepthPerFunction();\n\n    if (state.tokens.next.id === \"{\") {\n      advance(\"{\");\n      state.funct[\"(scope)\"].stack();\n\n      line = state.tokens.curr.line;\n      if (state.tokens.next.id !== \"}\") {\n        indent += state.option.indent;\n        while (!ordinary && state.tokens.next.from > indent) {\n          indent += state.option.indent;\n        }\n\n        if (isfunc) {\n          m = {};\n          for (d in state.directive) {\n            if (_.has(state.directive, d)) {\n              m[d] = state.directive[d];\n            }\n          }\n          directives();\n\n          if (state.option.strict && state.funct[\"(context)\"][\"(global)\"]) {\n            if (!m[\"use strict\"] && !state.isStrict()) {\n              warning(\"E007\");\n            }\n          }\n        }\n\n        a = statements();\n\n        metrics.statementCount += a.length;\n\n        indent -= state.option.indent;\n      }\n\n      advance(\"}\", t);\n\n      if (isfunc) {\n        state.funct[\"(scope)\"].validateParams();\n        if (m) {\n          state.directive = m;\n        }\n      }\n\n      state.funct[\"(scope)\"].unstack();\n\n      indent = old_indent;\n    } else if (!ordinary) {\n      if (isfunc) {\n        state.funct[\"(scope)\"].stack();\n\n        m = {};\n        if (stmt && !isfatarrow && !state.inMoz()) {\n          error(\"W118\", state.tokens.curr, \"function closure expressions\");\n        }\n\n        if (!stmt) {\n          for (d in state.directive) {\n            if (_.has(state.directive, d)) {\n              m[d] = state.directive[d];\n            }\n          }\n        }\n        expression(10);\n\n        if (state.option.strict && state.funct[\"(context)\"][\"(global)\"]) {\n          if (!m[\"use strict\"] && !state.isStrict()) {\n            warning(\"E007\");\n          }\n        }\n\n        state.funct[\"(scope)\"].unstack();\n      } else {\n        error(\"E021\", state.tokens.next, \"{\", state.tokens.next.value);\n      }\n    } else {\n      state.funct[\"(noblockscopedvar)\"] = state.tokens.next.id !== \"for\";\n      state.funct[\"(scope)\"].stack();\n\n      if (!stmt || state.option.curly) {\n        warning(\"W116\", state.tokens.next, \"{\", state.tokens.next.value);\n      }\n\n      state.tokens.next.inBracelessBlock = true;\n      indent += state.option.indent;\n      a = [statement()];\n      indent -= state.option.indent;\n\n      state.funct[\"(scope)\"].unstack();\n      delete state.funct[\"(noblockscopedvar)\"];\n    }\n    switch (state.funct[\"(verb)\"]) {\n    case \"break\":\n    case \"continue\":\n    case \"return\":\n    case \"throw\":\n      if (iscase) {\n        break;\n      }\n    default:\n      state.funct[\"(verb)\"] = null;\n    }\n\n    inblock = b;\n    if (ordinary && state.option.noempty && (!a || a.length === 0)) {\n      warning(\"W035\", state.tokens.prev);\n    }\n    metrics.nestedBlockDepth -= 1;\n    return a;\n  }\n\n\n  function countMember(m) {\n    if (membersOnly && typeof membersOnly[m] !== \"boolean\") {\n      warning(\"W036\", state.tokens.curr, m);\n    }\n    if (typeof member[m] === \"number\") {\n      member[m] += 1;\n    } else {\n      member[m] = 1;\n    }\n  }\n\n  type(\"(number)\", function() {\n    return this;\n  });\n\n  type(\"(string)\", function() {\n    return this;\n  });\n\n  state.syntax[\"(identifier)\"] = {\n    type: \"(identifier)\",\n    lbp: 0,\n    identifier: true,\n\n    nud: function() {\n      var v = this.value;\n      if (state.tokens.next.id === \"=>\") {\n        return this;\n      }\n\n      if (!state.funct[\"(comparray)\"].check(v)) {\n        state.funct[\"(scope)\"].block.use(v, state.tokens.curr);\n      }\n      return this;\n    },\n\n    led: function() {\n      error(\"E033\", state.tokens.next, state.tokens.next.value);\n    }\n  };\n\n  var baseTemplateSyntax = {\n    lbp: 0,\n    identifier: false,\n    template: true,\n  };\n  state.syntax[\"(template)\"] = _.extend({\n    type: \"(template)\",\n    nud: doTemplateLiteral,\n    led: doTemplateLiteral,\n    noSubst: false\n  }, baseTemplateSyntax);\n\n  state.syntax[\"(template middle)\"] = _.extend({\n    type: \"(template middle)\",\n    middle: true,\n    noSubst: false\n  }, baseTemplateSyntax);\n\n  state.syntax[\"(template tail)\"] = _.extend({\n    type: \"(template tail)\",\n    tail: true,\n    noSubst: false\n  }, baseTemplateSyntax);\n\n  state.syntax[\"(no subst template)\"] = _.extend({\n    type: \"(template)\",\n    nud: doTemplateLiteral,\n    led: doTemplateLiteral,\n    noSubst: true,\n    tail: true // mark as tail, since it's always the last component\n  }, baseTemplateSyntax);\n\n  type(\"(regexp)\", function() {\n    return this;\n  });\n\n  delim(\"(endline)\");\n  delim(\"(begin)\");\n  delim(\"(end)\").reach = true;\n  delim(\"(error)\").reach = true;\n  delim(\"}\").reach = true;\n  delim(\")\");\n  delim(\"]\");\n  delim(\"\\\"\").reach = true;\n  delim(\"'\").reach = true;\n  delim(\";\");\n  delim(\":\").reach = true;\n  delim(\"#\");\n\n  reserve(\"else\");\n  reserve(\"case\").reach = true;\n  reserve(\"catch\");\n  reserve(\"default\").reach = true;\n  reserve(\"finally\");\n  reservevar(\"arguments\", function(x) {\n    if (state.isStrict() && state.funct[\"(global)\"]) {\n      warning(\"E008\", x);\n    }\n  });\n  reservevar(\"eval\");\n  reservevar(\"false\");\n  reservevar(\"Infinity\");\n  reservevar(\"null\");\n  reservevar(\"this\", function(x) {\n    if (state.isStrict() && !isMethod() &&\n        !state.option.validthis && ((state.funct[\"(statement)\"] &&\n        state.funct[\"(name)\"].charAt(0) > \"Z\") || state.funct[\"(global)\"])) {\n      warning(\"W040\", x);\n    }\n  });\n  reservevar(\"true\");\n  reservevar(\"undefined\");\n\n  assignop(\"=\", \"assign\", 20);\n  assignop(\"+=\", \"assignadd\", 20);\n  assignop(\"-=\", \"assignsub\", 20);\n  assignop(\"*=\", \"assignmult\", 20);\n  assignop(\"/=\", \"assigndiv\", 20).nud = function() {\n    error(\"E014\");\n  };\n  assignop(\"%=\", \"assignmod\", 20);\n\n  bitwiseassignop(\"&=\");\n  bitwiseassignop(\"|=\");\n  bitwiseassignop(\"^=\");\n  bitwiseassignop(\"<<=\");\n  bitwiseassignop(\">>=\");\n  bitwiseassignop(\">>>=\");\n  infix(\",\", function(left, that) {\n    var expr;\n    that.exprs = [left];\n\n    if (state.option.nocomma) {\n      warning(\"W127\");\n    }\n\n    if (!comma({ peek: true })) {\n      return that;\n    }\n    while (true) {\n      if (!(expr = expression(10))) {\n        break;\n      }\n      that.exprs.push(expr);\n      if (state.tokens.next.value !== \",\" || !comma()) {\n        break;\n      }\n    }\n    return that;\n  }, 10, true);\n\n  infix(\"?\", function(left, that) {\n    increaseComplexityCount();\n    that.left = left;\n    that.right = expression(10);\n    advance(\":\");\n    that[\"else\"] = expression(10);\n    return that;\n  }, 30);\n\n  var orPrecendence = 40;\n  infix(\"||\", function(left, that) {\n    increaseComplexityCount();\n    that.left = left;\n    that.right = expression(orPrecendence);\n    return that;\n  }, orPrecendence);\n  infix(\"&&\", \"and\", 50);\n  bitwise(\"|\", \"bitor\", 70);\n  bitwise(\"^\", \"bitxor\", 80);\n  bitwise(\"&\", \"bitand\", 90);\n  relation(\"==\", function(left, right) {\n    var eqnull = state.option.eqnull &&\n      ((left && left.value) === \"null\" || (right && right.value) === \"null\");\n\n    switch (true) {\n      case !eqnull && state.option.eqeqeq:\n        this.from = this.character;\n        warning(\"W116\", this, \"===\", \"==\");\n        break;\n      case isPoorRelation(left):\n        warning(\"W041\", this, \"===\", left.value);\n        break;\n      case isPoorRelation(right):\n        warning(\"W041\", this, \"===\", right.value);\n        break;\n      case isTypoTypeof(right, left, state):\n        warning(\"W122\", this, right.value);\n        break;\n      case isTypoTypeof(left, right, state):\n        warning(\"W122\", this, left.value);\n        break;\n    }\n\n    return this;\n  });\n  relation(\"===\", function(left, right) {\n    if (isTypoTypeof(right, left, state)) {\n      warning(\"W122\", this, right.value);\n    } else if (isTypoTypeof(left, right, state)) {\n      warning(\"W122\", this, left.value);\n    }\n    return this;\n  });\n  relation(\"!=\", function(left, right) {\n    var eqnull = state.option.eqnull &&\n        ((left && left.value) === \"null\" || (right && right.value) === \"null\");\n\n    if (!eqnull && state.option.eqeqeq) {\n      this.from = this.character;\n      warning(\"W116\", this, \"!==\", \"!=\");\n    } else if (isPoorRelation(left)) {\n      warning(\"W041\", this, \"!==\", left.value);\n    } else if (isPoorRelation(right)) {\n      warning(\"W041\", this, \"!==\", right.value);\n    } else if (isTypoTypeof(right, left, state)) {\n      warning(\"W122\", this, right.value);\n    } else if (isTypoTypeof(left, right, state)) {\n      warning(\"W122\", this, left.value);\n    }\n    return this;\n  });\n  relation(\"!==\", function(left, right) {\n    if (isTypoTypeof(right, left, state)) {\n      warning(\"W122\", this, right.value);\n    } else if (isTypoTypeof(left, right, state)) {\n      warning(\"W122\", this, left.value);\n    }\n    return this;\n  });\n  relation(\"<\");\n  relation(\">\");\n  relation(\"<=\");\n  relation(\">=\");\n  bitwise(\"<<\", \"shiftleft\", 120);\n  bitwise(\">>\", \"shiftright\", 120);\n  bitwise(\">>>\", \"shiftrightunsigned\", 120);\n  infix(\"in\", \"in\", 120);\n  infix(\"instanceof\", \"instanceof\", 120);\n  infix(\"+\", function(left, that) {\n    var right;\n    that.left = left;\n    that.right = right = expression(130);\n\n    if (left && right && left.id === \"(string)\" && right.id === \"(string)\") {\n      left.value += right.value;\n      left.character = right.character;\n      if (!state.option.scripturl && reg.javascriptURL.test(left.value)) {\n        warning(\"W050\", left);\n      }\n      return left;\n    }\n\n    return that;\n  }, 130);\n  prefix(\"+\", \"num\");\n  prefix(\"+++\", function() {\n    warning(\"W007\");\n    this.arity = \"unary\";\n    this.right = expression(150);\n    return this;\n  });\n  infix(\"+++\", function(left) {\n    warning(\"W007\");\n    this.left = left;\n    this.right = expression(130);\n    return this;\n  }, 130);\n  infix(\"-\", \"sub\", 130);\n  prefix(\"-\", \"neg\");\n  prefix(\"---\", function() {\n    warning(\"W006\");\n    this.arity = \"unary\";\n    this.right = expression(150);\n    return this;\n  });\n  infix(\"---\", function(left) {\n    warning(\"W006\");\n    this.left = left;\n    this.right = expression(130);\n    return this;\n  }, 130);\n  infix(\"*\", \"mult\", 140);\n  infix(\"/\", \"div\", 140);\n  infix(\"%\", \"mod\", 140);\n\n  suffix(\"++\");\n  prefix(\"++\", \"preinc\");\n  state.syntax[\"++\"].exps = true;\n\n  suffix(\"--\");\n  prefix(\"--\", \"predec\");\n  state.syntax[\"--\"].exps = true;\n  prefix(\"delete\", function() {\n    var p = expression(10);\n    if (!p) {\n      return this;\n    }\n\n    if (p.id !== \".\" && p.id !== \"[\") {\n      warning(\"W051\");\n    }\n    this.first = p;\n    if (p.identifier && !state.isStrict()) {\n      p.forgiveUndef = true;\n    }\n    return this;\n  }).exps = true;\n\n  prefix(\"~\", function() {\n    if (state.option.bitwise) {\n      warning(\"W016\", this, \"~\");\n    }\n    this.arity = \"unary\";\n    this.right = expression(150);\n    return this;\n  });\n\n  prefix(\"...\", function() {\n    if (!state.inES6(true)) {\n      warning(\"W119\", this, \"spread/rest operator\", \"6\");\n    }\n    if (!state.tokens.next.identifier &&\n        state.tokens.next.type !== \"(string)\" &&\n          !checkPunctuators(state.tokens.next, [\"[\", \"(\"])) {\n\n      error(\"E030\", state.tokens.next, state.tokens.next.value);\n    }\n    expression(150);\n    return this;\n  });\n\n  prefix(\"!\", function() {\n    this.arity = \"unary\";\n    this.right = expression(150);\n\n    if (!this.right) { // '!' followed by nothing? Give up.\n      quit(\"E041\", this.line || 0);\n    }\n\n    if (bang[this.right.id] === true) {\n      warning(\"W018\", this, \"!\");\n    }\n    return this;\n  });\n\n  prefix(\"typeof\", (function() {\n    var p = expression(150);\n    this.first = this.right = p;\n\n    if (!p) { // 'typeof' followed by nothing? Give up.\n      quit(\"E041\", this.line || 0, this.character || 0);\n    }\n    if (p.identifier) {\n      p.forgiveUndef = true;\n    }\n    return this;\n  }));\n  prefix(\"new\", function() {\n    var mp = metaProperty(\"target\", function() {\n      if (!state.inES6(true)) {\n        warning(\"W119\", state.tokens.prev, \"new.target\", \"6\");\n      }\n      var inFunction, c = state.funct;\n      while (c) {\n        inFunction = !c[\"(global)\"];\n        if (!c[\"(arrow)\"]) { break; }\n        c = c[\"(context)\"];\n      }\n      if (!inFunction) {\n        warning(\"W136\", state.tokens.prev, \"new.target\");\n      }\n    });\n    if (mp) { return mp; }\n\n    var c = expression(155), i;\n    if (c && c.id !== \"function\") {\n      if (c.identifier) {\n        c[\"new\"] = true;\n        switch (c.value) {\n        case \"Number\":\n        case \"String\":\n        case \"Boolean\":\n        case \"Math\":\n        case \"JSON\":\n          warning(\"W053\", state.tokens.prev, c.value);\n          break;\n        case \"Symbol\":\n          if (state.inES6()) {\n            warning(\"W053\", state.tokens.prev, c.value);\n          }\n          break;\n        case \"Function\":\n          if (!state.option.evil) {\n            warning(\"W054\");\n          }\n          break;\n        case \"Date\":\n        case \"RegExp\":\n        case \"this\":\n          break;\n        default:\n          if (c.id !== \"function\") {\n            i = c.value.substr(0, 1);\n            if (state.option.newcap && (i < \"A\" || i > \"Z\") &&\n              !state.funct[\"(scope)\"].isPredefined(c.value)) {\n              warning(\"W055\", state.tokens.curr);\n            }\n          }\n        }\n      } else {\n        if (c.id !== \".\" && c.id !== \"[\" && c.id !== \"(\") {\n          warning(\"W056\", state.tokens.curr);\n        }\n      }\n    } else {\n      if (!state.option.supernew)\n        warning(\"W057\", this);\n    }\n    if (state.tokens.next.id !== \"(\" && !state.option.supernew) {\n      warning(\"W058\", state.tokens.curr, state.tokens.curr.value);\n    }\n    this.first = this.right = c;\n    return this;\n  });\n  state.syntax[\"new\"].exps = true;\n\n  prefix(\"void\").exps = true;\n\n  infix(\".\", function(left, that) {\n    var m = identifier(false, true);\n\n    if (typeof m === \"string\") {\n      countMember(m);\n    }\n\n    that.left = left;\n    that.right = m;\n\n    if (m && m === \"hasOwnProperty\" && state.tokens.next.value === \"=\") {\n      warning(\"W001\");\n    }\n\n    if (left && left.value === \"arguments\" && (m === \"callee\" || m === \"caller\")) {\n      if (state.option.noarg)\n        warning(\"W059\", left, m);\n      else if (state.isStrict())\n        error(\"E008\");\n    } else if (!state.option.evil && left && left.value === \"document\" &&\n        (m === \"write\" || m === \"writeln\")) {\n      warning(\"W060\", left);\n    }\n\n    if (!state.option.evil && (m === \"eval\" || m === \"execScript\")) {\n      if (isGlobalEval(left, state)) {\n        warning(\"W061\");\n      }\n    }\n\n    return that;\n  }, 160, true);\n\n  infix(\"(\", function(left, that) {\n    if (state.option.immed && left && !left.immed && left.id === \"function\") {\n      warning(\"W062\");\n    }\n\n    var n = 0;\n    var p = [];\n\n    if (left) {\n      if (left.type === \"(identifier)\") {\n        if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {\n          if (\"Array Number String Boolean Date Object Error Symbol\".indexOf(left.value) === -1) {\n            if (left.value === \"Math\") {\n              warning(\"W063\", left);\n            } else if (state.option.newcap) {\n              warning(\"W064\", left);\n            }\n          }\n        }\n      }\n    }\n\n    if (state.tokens.next.id !== \")\") {\n      for (;;) {\n        p[p.length] = expression(10);\n        n += 1;\n        if (state.tokens.next.id !== \",\") {\n          break;\n        }\n        comma();\n      }\n    }\n\n    advance(\")\");\n\n    if (typeof left === \"object\") {\n      if (!state.inES5() && left.value === \"parseInt\" && n === 1) {\n        warning(\"W065\", state.tokens.curr);\n      }\n      if (!state.option.evil) {\n        if (left.value === \"eval\" || left.value === \"Function\" ||\n            left.value === \"execScript\") {\n          warning(\"W061\", left);\n\n          if (p[0] && [0].id === \"(string)\") {\n            addInternalSrc(left, p[0].value);\n          }\n        } else if (p[0] && p[0].id === \"(string)\" &&\n             (left.value === \"setTimeout\" ||\n            left.value === \"setInterval\")) {\n          warning(\"W066\", left);\n          addInternalSrc(left, p[0].value);\n        } else if (p[0] && p[0].id === \"(string)\" &&\n             left.value === \".\" &&\n             left.left.value === \"window\" &&\n             (left.right === \"setTimeout\" ||\n            left.right === \"setInterval\")) {\n          warning(\"W066\", left);\n          addInternalSrc(left, p[0].value);\n        }\n      }\n      if (!left.identifier && left.id !== \".\" && left.id !== \"[\" && left.id !== \"=>\" &&\n          left.id !== \"(\" && left.id !== \"&&\" && left.id !== \"||\" && left.id !== \"?\" &&\n          !(state.inES6() && left[\"(name)\"])) {\n        warning(\"W067\", that);\n      }\n    }\n\n    that.left = left;\n    return that;\n  }, 155, true).exps = true;\n\n  prefix(\"(\", function() {\n    var pn = state.tokens.next, pn1, i = -1;\n    var ret, triggerFnExpr, first, last;\n    var parens = 1;\n    var opening = state.tokens.curr;\n    var preceeding = state.tokens.prev;\n    var isNecessary = !state.option.singleGroups;\n\n    do {\n      if (pn.value === \"(\") {\n        parens += 1;\n      } else if (pn.value === \")\") {\n        parens -= 1;\n      }\n\n      i += 1;\n      pn1 = pn;\n      pn = peek(i);\n    } while (!(parens === 0 && pn1.value === \")\") && pn.value !== \";\" && pn.type !== \"(end)\");\n\n    if (state.tokens.next.id === \"function\") {\n      triggerFnExpr = state.tokens.next.immed = true;\n    }\n    if (pn.value === \"=>\") {\n      return doFunction({ type: \"arrow\", parsedOpening: true });\n    }\n\n    var exprs = [];\n\n    if (state.tokens.next.id !== \")\") {\n      for (;;) {\n        exprs.push(expression(10));\n\n        if (state.tokens.next.id !== \",\") {\n          break;\n        }\n\n        if (state.option.nocomma) {\n          warning(\"W127\");\n        }\n\n        comma();\n      }\n    }\n\n    advance(\")\", this);\n    if (state.option.immed && exprs[0] && exprs[0].id === \"function\") {\n      if (state.tokens.next.id !== \"(\" &&\n        state.tokens.next.id !== \".\" && state.tokens.next.id !== \"[\") {\n        warning(\"W068\", this);\n      }\n    }\n\n    if (!exprs.length) {\n      return;\n    }\n    if (exprs.length > 1) {\n      ret = Object.create(state.syntax[\",\"]);\n      ret.exprs = exprs;\n\n      first = exprs[0];\n      last = exprs[exprs.length - 1];\n\n      if (!isNecessary) {\n        isNecessary = preceeding.assign || preceeding.delim;\n      }\n    } else {\n      ret = first = last = exprs[0];\n\n      if (!isNecessary) {\n        isNecessary =\n          (opening.beginsStmt && (ret.id === \"{\" || triggerFnExpr || isFunctor(ret))) ||\n          (triggerFnExpr &&\n            (!isEndOfExpr() || state.tokens.prev.id !== \"}\")) ||\n          (isFunctor(ret) && !isEndOfExpr()) ||\n          (ret.id === \"{\" && preceeding.id === \"=>\") ||\n          (ret.type === \"(number)\" &&\n            checkPunctuator(pn, \".\") && /^\\d+$/.test(ret.value));\n      }\n    }\n\n    if (ret) {\n      if (!isNecessary && (first.left || first.right || ret.exprs)) {\n        isNecessary =\n          (!isBeginOfExpr(preceeding) && first.lbp <= preceeding.lbp) ||\n          (!isEndOfExpr() && last.lbp < state.tokens.next.lbp);\n      }\n\n      if (!isNecessary) {\n        warning(\"W126\", opening);\n      }\n\n      ret.paren = true;\n    }\n\n    return ret;\n  });\n\n  application(\"=>\");\n\n  infix(\"[\", function(left, that) {\n    var e = expression(10), s;\n    if (e && e.type === \"(string)\") {\n      if (!state.option.evil && (e.value === \"eval\" || e.value === \"execScript\")) {\n        if (isGlobalEval(left, state)) {\n          warning(\"W061\");\n        }\n      }\n\n      countMember(e.value);\n      if (!state.option.sub && reg.identifier.test(e.value)) {\n        s = state.syntax[e.value];\n        if (!s || !isReserved(s)) {\n          warning(\"W069\", state.tokens.prev, e.value);\n        }\n      }\n    }\n    advance(\"]\", that);\n\n    if (e && e.value === \"hasOwnProperty\" && state.tokens.next.value === \"=\") {\n      warning(\"W001\");\n    }\n\n    that.left = left;\n    that.right = e;\n    return that;\n  }, 160, true);\n\n  function comprehensiveArrayExpression() {\n    var res = {};\n    res.exps = true;\n    state.funct[\"(comparray)\"].stack();\n    var reversed = false;\n    if (state.tokens.next.value !== \"for\") {\n      reversed = true;\n      if (!state.inMoz()) {\n        warning(\"W116\", state.tokens.next, \"for\", state.tokens.next.value);\n      }\n      state.funct[\"(comparray)\"].setState(\"use\");\n      res.right = expression(10);\n    }\n\n    advance(\"for\");\n    if (state.tokens.next.value === \"each\") {\n      advance(\"each\");\n      if (!state.inMoz()) {\n        warning(\"W118\", state.tokens.curr, \"for each\");\n      }\n    }\n    advance(\"(\");\n    state.funct[\"(comparray)\"].setState(\"define\");\n    res.left = expression(130);\n    if (_.contains([\"in\", \"of\"], state.tokens.next.value)) {\n      advance();\n    } else {\n      error(\"E045\", state.tokens.curr);\n    }\n    state.funct[\"(comparray)\"].setState(\"generate\");\n    expression(10);\n\n    advance(\")\");\n    if (state.tokens.next.value === \"if\") {\n      advance(\"if\");\n      advance(\"(\");\n      state.funct[\"(comparray)\"].setState(\"filter\");\n      res.filter = expression(10);\n      advance(\")\");\n    }\n\n    if (!reversed) {\n      state.funct[\"(comparray)\"].setState(\"use\");\n      res.right = expression(10);\n    }\n\n    advance(\"]\");\n    state.funct[\"(comparray)\"].unstack();\n    return res;\n  }\n\n  prefix(\"[\", function() {\n    var blocktype = lookupBlockType();\n    if (blocktype.isCompArray) {\n      if (!state.option.esnext && !state.inMoz()) {\n        warning(\"W118\", state.tokens.curr, \"array comprehension\");\n      }\n      return comprehensiveArrayExpression();\n    } else if (blocktype.isDestAssign) {\n      this.destructAssign = destructuringPattern({ openingParsed: true, assignment: true });\n      return this;\n    }\n    var b = state.tokens.curr.line !== startLine(state.tokens.next);\n    this.first = [];\n    if (b) {\n      indent += state.option.indent;\n      if (state.tokens.next.from === indent + state.option.indent) {\n        indent += state.option.indent;\n      }\n    }\n    while (state.tokens.next.id !== \"(end)\") {\n      while (state.tokens.next.id === \",\") {\n        if (!state.option.elision) {\n          if (!state.inES5()) {\n            warning(\"W070\");\n          } else {\n            warning(\"W128\");\n            do {\n              advance(\",\");\n            } while (state.tokens.next.id === \",\");\n            continue;\n          }\n        }\n        advance(\",\");\n      }\n\n      if (state.tokens.next.id === \"]\") {\n        break;\n      }\n\n      this.first.push(expression(10));\n      if (state.tokens.next.id === \",\") {\n        comma({ allowTrailing: true });\n        if (state.tokens.next.id === \"]\" && !state.inES5()) {\n          warning(\"W070\", state.tokens.curr);\n          break;\n        }\n      } else {\n        break;\n      }\n    }\n    if (b) {\n      indent -= state.option.indent;\n    }\n    advance(\"]\", this);\n    return this;\n  });\n\n\n  function isMethod() {\n    return state.funct[\"(statement)\"] && state.funct[\"(statement)\"].type === \"class\" ||\n           state.funct[\"(context)\"] && state.funct[\"(context)\"][\"(verb)\"] === \"class\";\n  }\n\n\n  function isPropertyName(token) {\n    return token.identifier || token.id === \"(string)\" || token.id === \"(number)\";\n  }\n\n\n  function propertyName(preserveOrToken) {\n    var id;\n    var preserve = true;\n    if (typeof preserveOrToken === \"object\") {\n      id = preserveOrToken;\n    } else {\n      preserve = preserveOrToken;\n      id = optionalidentifier(false, true, preserve);\n    }\n\n    if (!id) {\n      if (state.tokens.next.id === \"(string)\") {\n        id = state.tokens.next.value;\n        if (!preserve) {\n          advance();\n        }\n      } else if (state.tokens.next.id === \"(number)\") {\n        id = state.tokens.next.value.toString();\n        if (!preserve) {\n          advance();\n        }\n      }\n    } else if (typeof id === \"object\") {\n      if (id.id === \"(string)\" || id.id === \"(identifier)\") id = id.value;\n      else if (id.id === \"(number)\") id = id.value.toString();\n    }\n\n    if (id === \"hasOwnProperty\") {\n      warning(\"W001\");\n    }\n\n    return id;\n  }\n  function functionparams(options) {\n    var next;\n    var paramsIds = [];\n    var ident;\n    var tokens = [];\n    var t;\n    var pastDefault = false;\n    var pastRest = false;\n    var arity = 0;\n    var loneArg = options && options.loneArg;\n\n    if (loneArg && loneArg.identifier === true) {\n      state.funct[\"(scope)\"].addParam(loneArg.value, loneArg);\n      return { arity: 1, params: [ loneArg.value ] };\n    }\n\n    next = state.tokens.next;\n\n    if (!options || !options.parsedOpening) {\n      advance(\"(\");\n    }\n\n    if (state.tokens.next.id === \")\") {\n      advance(\")\");\n      return;\n    }\n\n    function addParam(addParamArgs) {\n      state.funct[\"(scope)\"].addParam.apply(state.funct[\"(scope)\"], addParamArgs);\n    }\n\n    for (;;) {\n      arity++;\n      var currentParams = [];\n\n      if (_.contains([\"{\", \"[\"], state.tokens.next.id)) {\n        tokens = destructuringPattern();\n        for (t in tokens) {\n          t = tokens[t];\n          if (t.id) {\n            paramsIds.push(t.id);\n            currentParams.push([t.id, t.token]);\n          }\n        }\n      } else {\n        if (checkPunctuator(state.tokens.next, \"...\")) pastRest = true;\n        ident = identifier(true);\n        if (ident) {\n          paramsIds.push(ident);\n          currentParams.push([ident, state.tokens.curr]);\n        } else {\n          while (!checkPunctuators(state.tokens.next, [\",\", \")\"])) advance();\n        }\n      }\n      if (pastDefault) {\n        if (state.tokens.next.id !== \"=\") {\n          error(\"W138\", state.tokens.current);\n        }\n      }\n      if (state.tokens.next.id === \"=\") {\n        if (!state.inES6()) {\n          warning(\"W119\", state.tokens.next, \"default parameters\", \"6\");\n        }\n        advance(\"=\");\n        pastDefault = true;\n        expression(10);\n      }\n      currentParams.forEach(addParam);\n\n      if (state.tokens.next.id === \",\") {\n        if (pastRest) {\n          warning(\"W131\", state.tokens.next);\n        }\n        comma();\n      } else {\n        advance(\")\", next);\n        return { arity: arity, params: paramsIds };\n      }\n    }\n  }\n\n  function functor(name, token, overwrites) {\n    var funct = {\n      \"(name)\"      : name,\n      \"(breakage)\"  : 0,\n      \"(loopage)\"   : 0,\n      \"(tokens)\"    : {},\n      \"(properties)\": {},\n\n      \"(catch)\"     : false,\n      \"(global)\"    : false,\n\n      \"(line)\"      : null,\n      \"(character)\" : null,\n      \"(metrics)\"   : null,\n      \"(statement)\" : null,\n      \"(context)\"   : null,\n      \"(scope)\"     : null,\n      \"(comparray)\" : null,\n      \"(generator)\" : null,\n      \"(arrow)\"     : null,\n      \"(params)\"    : null\n    };\n\n    if (token) {\n      _.extend(funct, {\n        \"(line)\"     : token.line,\n        \"(character)\": token.character,\n        \"(metrics)\"  : createMetrics(token)\n      });\n    }\n\n    _.extend(funct, overwrites);\n\n    if (funct[\"(context)\"]) {\n      funct[\"(scope)\"] = funct[\"(context)\"][\"(scope)\"];\n      funct[\"(comparray)\"]  = funct[\"(context)\"][\"(comparray)\"];\n    }\n\n    return funct;\n  }\n\n  function isFunctor(token) {\n    return \"(scope)\" in token;\n  }\n  function hasParsedCode(funct) {\n    return funct[\"(global)\"] && !funct[\"(verb)\"];\n  }\n\n  function doTemplateLiteral(left) {\n    var ctx = this.context;\n    var noSubst = this.noSubst;\n    var depth = this.depth;\n\n    if (!noSubst) {\n      while (!end()) {\n        if (!state.tokens.next.template || state.tokens.next.depth > depth) {\n          expression(0); // should probably have different rbp?\n        } else {\n          advance();\n        }\n      }\n    }\n\n    return {\n      id: \"(template)\",\n      type: \"(template)\",\n      tag: left\n    };\n\n    function end() {\n      if (state.tokens.curr.template && state.tokens.curr.tail &&\n          state.tokens.curr.context === ctx) return true;\n      var complete = (state.tokens.next.template && state.tokens.next.tail &&\n                      state.tokens.next.context === ctx);\n      if (complete) advance();\n      return complete || state.tokens.next.isUnclosed;\n    }\n  }\n  function doFunction(options) {\n    var f, token, name, statement, classExprBinding, isGenerator, isArrow, ignoreLoopFunc;\n    var oldOption = state.option;\n    var oldIgnored = state.ignored;\n\n    if (options) {\n      name = options.name;\n      statement = options.statement;\n      classExprBinding = options.classExprBinding;\n      isGenerator = options.type === \"generator\";\n      isArrow = options.type === \"arrow\";\n      ignoreLoopFunc = options.ignoreLoopFunc;\n    }\n\n    state.option = Object.create(state.option);\n    state.ignored = Object.create(state.ignored);\n\n    state.funct = functor(name || state.nameStack.infer(), state.tokens.next, {\n      \"(statement)\": statement,\n      \"(context)\":   state.funct,\n      \"(arrow)\":     isArrow,\n      \"(generator)\": isGenerator\n    });\n\n    f = state.funct;\n    token = state.tokens.curr;\n    token.funct = state.funct;\n\n    functions.push(state.funct);\n    state.funct[\"(scope)\"].stack(\"functionouter\");\n    var internallyAccessibleName = name || classExprBinding;\n    if (internallyAccessibleName) {\n      state.funct[\"(scope)\"].block.add(internallyAccessibleName,\n        classExprBinding ? \"class\" : \"function\", state.tokens.curr, false);\n    }\n    state.funct[\"(scope)\"].stack(\"functionparams\");\n\n    var paramsInfo = functionparams(options);\n\n    if (paramsInfo) {\n      state.funct[\"(params)\"] = paramsInfo.params;\n      state.funct[\"(metrics)\"].arity = paramsInfo.arity;\n      state.funct[\"(metrics)\"].verifyMaxParametersPerFunction();\n    } else {\n      state.funct[\"(metrics)\"].arity = 0;\n    }\n\n    if (isArrow) {\n      if (!state.inES6(true)) {\n        warning(\"W119\", state.tokens.curr, \"arrow function syntax (=>)\", \"6\");\n      }\n\n      if (!options.loneArg) {\n        advance(\"=>\");\n      }\n    }\n\n    block(false, true, true, isArrow);\n\n    if (!state.option.noyield && isGenerator &&\n        state.funct[\"(generator)\"] !== \"yielded\") {\n      warning(\"W124\", state.tokens.curr);\n    }\n\n    state.funct[\"(metrics)\"].verifyMaxStatementsPerFunction();\n    state.funct[\"(metrics)\"].verifyMaxComplexityPerFunction();\n    state.funct[\"(unusedOption)\"] = state.option.unused;\n    state.option = oldOption;\n    state.ignored = oldIgnored;\n    state.funct[\"(last)\"] = state.tokens.curr.line;\n    state.funct[\"(lastcharacter)\"] = state.tokens.curr.character;\n    state.funct[\"(scope)\"].unstack(); // also does usage and label checks\n    state.funct[\"(scope)\"].unstack();\n\n    state.funct = state.funct[\"(context)\"];\n\n    if (!ignoreLoopFunc && !state.option.loopfunc && state.funct[\"(loopage)\"]) {\n      if (f[\"(isCapturing)\"]) {\n        warning(\"W083\", token);\n      }\n    }\n\n    return f;\n  }\n\n  function createMetrics(functionStartToken) {\n    return {\n      statementCount: 0,\n      nestedBlockDepth: -1,\n      ComplexityCount: 1,\n      arity: 0,\n\n      verifyMaxStatementsPerFunction: function() {\n        if (state.option.maxstatements &&\n          this.statementCount > state.option.maxstatements) {\n          warning(\"W071\", functionStartToken, this.statementCount);\n        }\n      },\n\n      verifyMaxParametersPerFunction: function() {\n        if (_.isNumber(state.option.maxparams) &&\n          this.arity > state.option.maxparams) {\n          warning(\"W072\", functionStartToken, this.arity);\n        }\n      },\n\n      verifyMaxNestedBlockDepthPerFunction: function() {\n        if (state.option.maxdepth &&\n          this.nestedBlockDepth > 0 &&\n          this.nestedBlockDepth === state.option.maxdepth + 1) {\n          warning(\"W073\", null, this.nestedBlockDepth);\n        }\n      },\n\n      verifyMaxComplexityPerFunction: function() {\n        var max = state.option.maxcomplexity;\n        var cc = this.ComplexityCount;\n        if (max && cc > max) {\n          warning(\"W074\", functionStartToken, cc);\n        }\n      }\n    };\n  }\n\n  function increaseComplexityCount() {\n    state.funct[\"(metrics)\"].ComplexityCount += 1;\n  }\n\n  function checkCondAssignment(expr) {\n    var id, paren;\n    if (expr) {\n      id = expr.id;\n      paren = expr.paren;\n      if (id === \",\" && (expr = expr.exprs[expr.exprs.length - 1])) {\n        id = expr.id;\n        paren = paren || expr.paren;\n      }\n    }\n    switch (id) {\n    case \"=\":\n    case \"+=\":\n    case \"-=\":\n    case \"*=\":\n    case \"%=\":\n    case \"&=\":\n    case \"|=\":\n    case \"^=\":\n    case \"/=\":\n      if (!paren && !state.option.boss) {\n        warning(\"W084\");\n      }\n    }\n  }\n  function checkProperties(props) {\n    if (state.inES5()) {\n      for (var name in props) {\n        if (props[name] && props[name].setterToken && !props[name].getterToken) {\n          warning(\"W078\", props[name].setterToken);\n        }\n      }\n    }\n  }\n\n  function metaProperty(name, c) {\n    if (checkPunctuator(state.tokens.next, \".\")) {\n      var left = state.tokens.curr.id;\n      advance(\".\");\n      var id = identifier();\n      state.tokens.curr.isMetaProperty = true;\n      if (name !== id) {\n        error(\"E057\", state.tokens.prev, left, id);\n      } else {\n        c();\n      }\n      return state.tokens.curr;\n    }\n  }\n\n  (function(x) {\n    x.nud = function() {\n      var b, f, i, p, t, isGeneratorMethod = false, nextVal;\n      var props = Object.create(null); // All properties, including accessors\n\n      b = state.tokens.curr.line !== startLine(state.tokens.next);\n      if (b) {\n        indent += state.option.indent;\n        if (state.tokens.next.from === indent + state.option.indent) {\n          indent += state.option.indent;\n        }\n      }\n\n      var blocktype = lookupBlockType();\n      if (blocktype.isDestAssign) {\n        this.destructAssign = destructuringPattern({ openingParsed: true, assignment: true });\n        return this;\n      }\n\n      for (;;) {\n        if (state.tokens.next.id === \"}\") {\n          break;\n        }\n\n        nextVal = state.tokens.next.value;\n        if (state.tokens.next.identifier &&\n            (peekIgnoreEOL().id === \",\" || peekIgnoreEOL().id === \"}\")) {\n          if (!state.inES6()) {\n            warning(\"W104\", state.tokens.next, \"object short notation\", \"6\");\n          }\n          i = propertyName(true);\n          saveProperty(props, i, state.tokens.next);\n\n          expression(10);\n\n        } else if (peek().id !== \":\" && (nextVal === \"get\" || nextVal === \"set\")) {\n          advance(nextVal);\n\n          if (!state.inES5()) {\n            error(\"E034\");\n          }\n\n          i = propertyName();\n          if (!i && !state.inES6()) {\n            error(\"E035\");\n          }\n          if (i) {\n            saveAccessor(nextVal, props, i, state.tokens.curr);\n          }\n\n          t = state.tokens.next;\n          f = doFunction();\n          p = f[\"(params)\"];\n          if (nextVal === \"get\" && i && p) {\n            warning(\"W076\", t, p[0], i);\n          } else if (nextVal === \"set\" && i && (!p || p.length !== 1)) {\n            warning(\"W077\", t, i);\n          }\n        } else {\n          if (state.tokens.next.value === \"*\" && state.tokens.next.type === \"(punctuator)\") {\n            if (!state.inES6()) {\n              warning(\"W104\", state.tokens.next, \"generator functions\", \"6\");\n            }\n            advance(\"*\");\n            isGeneratorMethod = true;\n          } else {\n            isGeneratorMethod = false;\n          }\n\n          if (state.tokens.next.id === \"[\") {\n            i = computedPropertyName();\n            state.nameStack.set(i);\n          } else {\n            state.nameStack.set(state.tokens.next);\n            i = propertyName();\n            saveProperty(props, i, state.tokens.next);\n\n            if (typeof i !== \"string\") {\n              break;\n            }\n          }\n\n          if (state.tokens.next.value === \"(\") {\n            if (!state.inES6()) {\n              warning(\"W104\", state.tokens.curr, \"concise methods\", \"6\");\n            }\n            doFunction({ type: isGeneratorMethod ? \"generator\" : null });\n          } else {\n            advance(\":\");\n            expression(10);\n          }\n        }\n\n        countMember(i);\n\n        if (state.tokens.next.id === \",\") {\n          comma({ allowTrailing: true, property: true });\n          if (state.tokens.next.id === \",\") {\n            warning(\"W070\", state.tokens.curr);\n          } else if (state.tokens.next.id === \"}\" && !state.inES5()) {\n            warning(\"W070\", state.tokens.curr);\n          }\n        } else {\n          break;\n        }\n      }\n      if (b) {\n        indent -= state.option.indent;\n      }\n      advance(\"}\", this);\n\n      checkProperties(props);\n\n      return this;\n    };\n    x.fud = function() {\n      error(\"E036\", state.tokens.curr);\n    };\n  }(delim(\"{\")));\n\n  function destructuringPattern(options) {\n    var isAssignment = options && options.assignment;\n\n    if (!state.inES6()) {\n      warning(\"W104\", state.tokens.curr,\n        isAssignment ? \"destructuring assignment\" : \"destructuring binding\", \"6\");\n    }\n\n    return destructuringPatternRecursive(options);\n  }\n\n  function destructuringPatternRecursive(options) {\n    var ids;\n    var identifiers = [];\n    var openingParsed = options && options.openingParsed;\n    var isAssignment = options && options.assignment;\n    var recursiveOptions = isAssignment ? { assignment: isAssignment } : null;\n    var firstToken = openingParsed ? state.tokens.curr : state.tokens.next;\n\n    var nextInnerDE = function() {\n      var ident;\n      if (checkPunctuators(state.tokens.next, [\"[\", \"{\"])) {\n        ids = destructuringPatternRecursive(recursiveOptions);\n        for (var id in ids) {\n          id = ids[id];\n          identifiers.push({ id: id.id, token: id.token });\n        }\n      } else if (checkPunctuator(state.tokens.next, \",\")) {\n        identifiers.push({ id: null, token: state.tokens.curr });\n      } else if (checkPunctuator(state.tokens.next, \"(\")) {\n        advance(\"(\");\n        nextInnerDE();\n        advance(\")\");\n      } else {\n        var is_rest = checkPunctuator(state.tokens.next, \"...\");\n\n        if (isAssignment) {\n          var identifierToken = is_rest ? peek(0) : state.tokens.next;\n          if (!identifierToken.identifier) {\n            warning(\"E030\", identifierToken, identifierToken.value);\n          }\n          var assignTarget = expression(155);\n          if (assignTarget) {\n            checkLeftSideAssign(assignTarget);\n            if (assignTarget.identifier) {\n              ident = assignTarget.value;\n            }\n          }\n        } else {\n          ident = identifier();\n        }\n        if (ident) {\n          identifiers.push({ id: ident, token: state.tokens.curr });\n        }\n        return is_rest;\n      }\n      return false;\n    };\n    var assignmentProperty = function() {\n      var id;\n      if (checkPunctuator(state.tokens.next, \"[\")) {\n        advance(\"[\");\n        expression(10);\n        advance(\"]\");\n        advance(\":\");\n        nextInnerDE();\n      } else if (state.tokens.next.id === \"(string)\" ||\n                 state.tokens.next.id === \"(number)\") {\n        advance();\n        advance(\":\");\n        nextInnerDE();\n      } else {\n        id = identifier();\n        if (checkPunctuator(state.tokens.next, \":\")) {\n          advance(\":\");\n          nextInnerDE();\n        } else if (id) {\n          if (isAssignment) {\n            checkLeftSideAssign(state.tokens.curr);\n          }\n          identifiers.push({ id: id, token: state.tokens.curr });\n        }\n      }\n    };\n    if (checkPunctuator(firstToken, \"[\")) {\n      if (!openingParsed) {\n        advance(\"[\");\n      }\n      if (checkPunctuator(state.tokens.next, \"]\")) {\n        warning(\"W137\", state.tokens.curr);\n      }\n      var element_after_rest = false;\n      while (!checkPunctuator(state.tokens.next, \"]\")) {\n        if (nextInnerDE() && !element_after_rest &&\n            checkPunctuator(state.tokens.next, \",\")) {\n          warning(\"W130\", state.tokens.next);\n          element_after_rest = true;\n        }\n        if (checkPunctuator(state.tokens.next, \"=\")) {\n          if (checkPunctuator(state.tokens.prev, \"...\")) {\n            advance(\"]\");\n          } else {\n            advance(\"=\");\n          }\n          if (state.tokens.next.id === \"undefined\") {\n            warning(\"W080\", state.tokens.prev, state.tokens.prev.value);\n          }\n          expression(10);\n        }\n        if (!checkPunctuator(state.tokens.next, \"]\")) {\n          advance(\",\");\n        }\n      }\n      advance(\"]\");\n    } else if (checkPunctuator(firstToken, \"{\")) {\n\n      if (!openingParsed) {\n        advance(\"{\");\n      }\n      if (checkPunctuator(state.tokens.next, \"}\")) {\n        warning(\"W137\", state.tokens.curr);\n      }\n      while (!checkPunctuator(state.tokens.next, \"}\")) {\n        assignmentProperty();\n        if (checkPunctuator(state.tokens.next, \"=\")) {\n          advance(\"=\");\n          if (state.tokens.next.id === \"undefined\") {\n            warning(\"W080\", state.tokens.prev, state.tokens.prev.value);\n          }\n          expression(10);\n        }\n        if (!checkPunctuator(state.tokens.next, \"}\")) {\n          advance(\",\");\n          if (checkPunctuator(state.tokens.next, \"}\")) {\n            break;\n          }\n        }\n      }\n      advance(\"}\");\n    }\n    return identifiers;\n  }\n\n  function destructuringPatternMatch(tokens, value) {\n    var first = value.first;\n\n    if (!first)\n      return;\n\n    _.zip(tokens, Array.isArray(first) ? first : [ first ]).forEach(function(val) {\n      var token = val[0];\n      var value = val[1];\n\n      if (token && value)\n        token.first = value;\n      else if (token && token.first && !value)\n        warning(\"W080\", token.first, token.first.value);\n    });\n  }\n\n  function blockVariableStatement(type, statement, context) {\n\n    var prefix = context && context.prefix;\n    var inexport = context && context.inexport;\n    var isLet = type === \"let\";\n    var isConst = type === \"const\";\n    var tokens, lone, value, letblock;\n\n    if (!state.inES6()) {\n      warning(\"W104\", state.tokens.curr, type, \"6\");\n    }\n\n    if (isLet && state.tokens.next.value === \"(\") {\n      if (!state.inMoz()) {\n        warning(\"W118\", state.tokens.next, \"let block\");\n      }\n      advance(\"(\");\n      state.funct[\"(scope)\"].stack();\n      letblock = true;\n    } else if (state.funct[\"(noblockscopedvar)\"]) {\n      error(\"E048\", state.tokens.curr, isConst ? \"Const\" : \"Let\");\n    }\n\n    statement.first = [];\n    for (;;) {\n      var names = [];\n      if (_.contains([\"{\", \"[\"], state.tokens.next.value)) {\n        tokens = destructuringPattern();\n        lone = false;\n      } else {\n        tokens = [ { id: identifier(), token: state.tokens.curr } ];\n        lone = true;\n      }\n\n      if (!prefix && isConst && state.tokens.next.id !== \"=\") {\n        warning(\"E012\", state.tokens.curr, state.tokens.curr.value);\n      }\n\n      for (var t in tokens) {\n        if (tokens.hasOwnProperty(t)) {\n          t = tokens[t];\n          if (state.funct[\"(scope)\"].block.isGlobal()) {\n            if (predefined[t.id] === false) {\n              warning(\"W079\", t.token, t.id);\n            }\n          }\n          if (t.id && !state.funct[\"(noblockscopedvar)\"]) {\n            state.funct[\"(scope)\"].addlabel(t.id, {\n              type: type,\n              token: t.token });\n            names.push(t.token);\n\n            if (lone && inexport) {\n              state.funct[\"(scope)\"].setExported(t.token.value, t.token);\n            }\n          }\n        }\n      }\n\n      if (state.tokens.next.id === \"=\") {\n        advance(\"=\");\n        if (!prefix && state.tokens.next.id === \"undefined\") {\n          warning(\"W080\", state.tokens.prev, state.tokens.prev.value);\n        }\n        if (!prefix && peek(0).id === \"=\" && state.tokens.next.identifier) {\n          warning(\"W120\", state.tokens.next, state.tokens.next.value);\n        }\n        value = expression(prefix ? 120 : 10);\n        if (lone) {\n          tokens[0].first = value;\n        } else {\n          destructuringPatternMatch(names, value);\n        }\n      }\n\n      statement.first = statement.first.concat(names);\n\n      if (state.tokens.next.id !== \",\") {\n        break;\n      }\n      comma();\n    }\n    if (letblock) {\n      advance(\")\");\n      block(true, true);\n      statement.block = true;\n      state.funct[\"(scope)\"].unstack();\n    }\n\n    return statement;\n  }\n\n  var conststatement = stmt(\"const\", function(context) {\n    return blockVariableStatement(\"const\", this, context);\n  });\n  conststatement.exps = true;\n\n  var letstatement = stmt(\"let\", function(context) {\n    return blockVariableStatement(\"let\", this, context);\n  });\n  letstatement.exps = true;\n\n  var varstatement = stmt(\"var\", function(context) {\n    var prefix = context && context.prefix;\n    var inexport = context && context.inexport;\n    var tokens, lone, value;\n    var implied = context && context.implied;\n    var report = !(context && context.ignore);\n\n    this.first = [];\n    for (;;) {\n      var names = [];\n      if (_.contains([\"{\", \"[\"], state.tokens.next.value)) {\n        tokens = destructuringPattern();\n        lone = false;\n      } else {\n        tokens = [ { id: identifier(), token: state.tokens.curr } ];\n        lone = true;\n      }\n\n      if (!(prefix && implied) && report && state.option.varstmt) {\n        warning(\"W132\", this);\n      }\n\n      this.first = this.first.concat(names);\n\n      for (var t in tokens) {\n        if (tokens.hasOwnProperty(t)) {\n          t = tokens[t];\n          if (!implied && state.funct[\"(global)\"]) {\n            if (predefined[t.id] === false) {\n              warning(\"W079\", t.token, t.id);\n            } else if (state.option.futurehostile === false) {\n              if ((!state.inES5() && vars.ecmaIdentifiers[5][t.id] === false) ||\n                (!state.inES6() && vars.ecmaIdentifiers[6][t.id] === false)) {\n                warning(\"W129\", t.token, t.id);\n              }\n            }\n          }\n          if (t.id) {\n            if (implied === \"for\") {\n\n              if (!state.funct[\"(scope)\"].has(t.id)) {\n                if (report) warning(\"W088\", t.token, t.id);\n              }\n              state.funct[\"(scope)\"].block.use(t.id, t.token);\n            } else {\n              state.funct[\"(scope)\"].addlabel(t.id, {\n                type: \"var\",\n                token: t.token });\n\n              if (lone && inexport) {\n                state.funct[\"(scope)\"].setExported(t.id, t.token);\n              }\n            }\n            names.push(t.token);\n          }\n        }\n      }\n\n      if (state.tokens.next.id === \"=\") {\n        state.nameStack.set(state.tokens.curr);\n\n        advance(\"=\");\n        if (!prefix && report && !state.funct[\"(loopage)\"] &&\n          state.tokens.next.id === \"undefined\") {\n          warning(\"W080\", state.tokens.prev, state.tokens.prev.value);\n        }\n        if (peek(0).id === \"=\" && state.tokens.next.identifier) {\n          if (!prefix && report &&\n              !state.funct[\"(params)\"] ||\n              state.funct[\"(params)\"].indexOf(state.tokens.next.value) === -1) {\n            warning(\"W120\", state.tokens.next, state.tokens.next.value);\n          }\n        }\n        value = expression(prefix ? 120 : 10);\n        if (lone) {\n          tokens[0].first = value;\n        } else {\n          destructuringPatternMatch(names, value);\n        }\n      }\n\n      if (state.tokens.next.id !== \",\") {\n        break;\n      }\n      comma();\n    }\n\n    return this;\n  });\n  varstatement.exps = true;\n\n  blockstmt(\"class\", function() {\n    return classdef.call(this, true);\n  });\n\n  function classdef(isStatement) {\n    if (!state.inES6()) {\n      warning(\"W104\", state.tokens.curr, \"class\", \"6\");\n    }\n    if (isStatement) {\n      this.name = identifier();\n\n      state.funct[\"(scope)\"].addlabel(this.name, {\n        type: \"class\",\n        token: state.tokens.curr });\n    } else if (state.tokens.next.identifier && state.tokens.next.value !== \"extends\") {\n      this.name = identifier();\n      this.namedExpr = true;\n    } else {\n      this.name = state.nameStack.infer();\n    }\n    classtail(this);\n    return this;\n  }\n\n  function classtail(c) {\n    var wasInClassBody = state.inClassBody;\n    if (state.tokens.next.value === \"extends\") {\n      advance(\"extends\");\n      c.heritage = expression(10);\n    }\n\n    state.inClassBody = true;\n    advance(\"{\");\n    c.body = classbody(c);\n    advance(\"}\");\n    state.inClassBody = wasInClassBody;\n  }\n\n  function classbody(c) {\n    var name;\n    var isStatic;\n    var isGenerator;\n    var getset;\n    var props = Object.create(null);\n    var staticProps = Object.create(null);\n    var computed;\n    for (var i = 0; state.tokens.next.id !== \"}\"; ++i) {\n      name = state.tokens.next;\n      isStatic = false;\n      isGenerator = false;\n      getset = null;\n      if (name.id === \";\") {\n        warning(\"W032\");\n        advance(\";\");\n        continue;\n      }\n\n      if (name.id === \"*\") {\n        isGenerator = true;\n        advance(\"*\");\n        name = state.tokens.next;\n      }\n      if (name.id === \"[\") {\n        name = computedPropertyName();\n        computed = true;\n      } else if (isPropertyName(name)) {\n        advance();\n        computed = false;\n        if (name.identifier && name.value === \"static\") {\n          if (checkPunctuator(state.tokens.next, \"*\")) {\n            isGenerator = true;\n            advance(\"*\");\n          }\n          if (isPropertyName(state.tokens.next) || state.tokens.next.id === \"[\") {\n            computed = state.tokens.next.id === \"[\";\n            isStatic = true;\n            name = state.tokens.next;\n            if (state.tokens.next.id === \"[\") {\n              name = computedPropertyName();\n            } else advance();\n          }\n        }\n\n        if (name.identifier && (name.value === \"get\" || name.value === \"set\")) {\n          if (isPropertyName(state.tokens.next) || state.tokens.next.id === \"[\") {\n            computed = state.tokens.next.id === \"[\";\n            getset = name;\n            name = state.tokens.next;\n            if (state.tokens.next.id === \"[\") {\n              name = computedPropertyName();\n            } else advance();\n          }\n        }\n      } else {\n        warning(\"W052\", state.tokens.next, state.tokens.next.value || state.tokens.next.type);\n        advance();\n        continue;\n      }\n\n      if (!checkPunctuator(state.tokens.next, \"(\")) {\n        error(\"E054\", state.tokens.next, state.tokens.next.value);\n        while (state.tokens.next.id !== \"}\" &&\n               !checkPunctuator(state.tokens.next, \"(\")) {\n          advance();\n        }\n        if (state.tokens.next.value !== \"(\") {\n          doFunction({ statement: c });\n        }\n      }\n\n      if (!computed) {\n        if (getset) {\n          saveAccessor(\n            getset.value, isStatic ? staticProps : props, name.value, name, true, isStatic);\n        } else {\n          if (name.value === \"constructor\") {\n            state.nameStack.set(c);\n          } else {\n            state.nameStack.set(name);\n          }\n          saveProperty(isStatic ? staticProps : props, name.value, name, true, isStatic);\n        }\n      }\n\n      if (getset && name.value === \"constructor\") {\n        var propDesc = getset.value === \"get\" ? \"class getter method\" : \"class setter method\";\n        error(\"E049\", name, propDesc, \"constructor\");\n      } else if (name.value === \"prototype\") {\n        error(\"E049\", name, \"class method\", \"prototype\");\n      }\n\n      propertyName(name);\n\n      doFunction({\n        statement: c,\n        type: isGenerator ? \"generator\" : null,\n        classExprBinding: c.namedExpr ? c.name : null\n      });\n    }\n\n    checkProperties(props);\n  }\n\n  blockstmt(\"function\", function(context) {\n    var inexport = context && context.inexport;\n    var generator = false;\n    if (state.tokens.next.value === \"*\") {\n      advance(\"*\");\n      if (state.inES6({ strict: true })) {\n        generator = true;\n      } else {\n        warning(\"W119\", state.tokens.curr, \"function*\", \"6\");\n      }\n    }\n    if (inblock) {\n      warning(\"W082\", state.tokens.curr);\n    }\n    var i = optionalidentifier();\n\n    state.funct[\"(scope)\"].addlabel(i, {\n      type: \"function\",\n      token: state.tokens.curr });\n\n    if (i === undefined) {\n      warning(\"W025\");\n    } else if (inexport) {\n      state.funct[\"(scope)\"].setExported(i, state.tokens.prev);\n    }\n\n    doFunction({\n      name: i,\n      statement: this,\n      type: generator ? \"generator\" : null,\n      ignoreLoopFunc: inblock // a declaration may already have warned\n    });\n    if (state.tokens.next.id === \"(\" && state.tokens.next.line === state.tokens.curr.line) {\n      error(\"E039\");\n    }\n    return this;\n  });\n\n  prefix(\"function\", function() {\n    var generator = false;\n\n    if (state.tokens.next.value === \"*\") {\n      if (!state.inES6()) {\n        warning(\"W119\", state.tokens.curr, \"function*\", \"6\");\n      }\n      advance(\"*\");\n      generator = true;\n    }\n\n    var i = optionalidentifier();\n    doFunction({ name: i, type: generator ? \"generator\" : null });\n    return this;\n  });\n\n  blockstmt(\"if\", function() {\n    var t = state.tokens.next;\n    increaseComplexityCount();\n    state.condition = true;\n    advance(\"(\");\n    var expr = expression(0);\n    checkCondAssignment(expr);\n    var forinifcheck = null;\n    if (state.option.forin && state.forinifcheckneeded) {\n      state.forinifcheckneeded = false; // We only need to analyze the first if inside the loop\n      forinifcheck = state.forinifchecks[state.forinifchecks.length - 1];\n      if (expr.type === \"(punctuator)\" && expr.value === \"!\") {\n        forinifcheck.type = \"(negative)\";\n      } else {\n        forinifcheck.type = \"(positive)\";\n      }\n    }\n\n    advance(\")\", t);\n    state.condition = false;\n    var s = block(true, true);\n    if (forinifcheck && forinifcheck.type === \"(negative)\") {\n      if (s && s[0] && s[0].type === \"(identifier)\" && s[0].value === \"continue\") {\n        forinifcheck.type = \"(negative-with-continue)\";\n      }\n    }\n\n    if (state.tokens.next.id === \"else\") {\n      advance(\"else\");\n      if (state.tokens.next.id === \"if\" || state.tokens.next.id === \"switch\") {\n        statement();\n      } else {\n        block(true, true);\n      }\n    }\n    return this;\n  });\n\n  blockstmt(\"try\", function() {\n    var b;\n\n    function doCatch() {\n      advance(\"catch\");\n      advance(\"(\");\n\n      state.funct[\"(scope)\"].stack(\"catchparams\");\n\n      if (checkPunctuators(state.tokens.next, [\"[\", \"{\"])) {\n        var tokens = destructuringPattern();\n        _.each(tokens, function(token) {\n          if (token.id) {\n            state.funct[\"(scope)\"].addParam(token.id, token, \"exception\");\n          }\n        });\n      } else if (state.tokens.next.type !== \"(identifier)\") {\n        warning(\"E030\", state.tokens.next, state.tokens.next.value);\n      } else {\n        state.funct[\"(scope)\"].addParam(identifier(), state.tokens.curr, \"exception\");\n      }\n\n      if (state.tokens.next.value === \"if\") {\n        if (!state.inMoz()) {\n          warning(\"W118\", state.tokens.curr, \"catch filter\");\n        }\n        advance(\"if\");\n        expression(0);\n      }\n\n      advance(\")\");\n\n      block(false);\n\n      state.funct[\"(scope)\"].unstack();\n    }\n\n    block(true);\n\n    while (state.tokens.next.id === \"catch\") {\n      increaseComplexityCount();\n      if (b && (!state.inMoz())) {\n        warning(\"W118\", state.tokens.next, \"multiple catch blocks\");\n      }\n      doCatch();\n      b = true;\n    }\n\n    if (state.tokens.next.id === \"finally\") {\n      advance(\"finally\");\n      block(true);\n      return;\n    }\n\n    if (!b) {\n      error(\"E021\", state.tokens.next, \"catch\", state.tokens.next.value);\n    }\n\n    return this;\n  });\n\n  blockstmt(\"while\", function() {\n    var t = state.tokens.next;\n    state.funct[\"(breakage)\"] += 1;\n    state.funct[\"(loopage)\"] += 1;\n    increaseComplexityCount();\n    advance(\"(\");\n    checkCondAssignment(expression(0));\n    advance(\")\", t);\n    block(true, true);\n    state.funct[\"(breakage)\"] -= 1;\n    state.funct[\"(loopage)\"] -= 1;\n    return this;\n  }).labelled = true;\n\n  blockstmt(\"with\", function() {\n    var t = state.tokens.next;\n    if (state.isStrict()) {\n      error(\"E010\", state.tokens.curr);\n    } else if (!state.option.withstmt) {\n      warning(\"W085\", state.tokens.curr);\n    }\n\n    advance(\"(\");\n    expression(0);\n    advance(\")\", t);\n    block(true, true);\n\n    return this;\n  });\n\n  blockstmt(\"switch\", function() {\n    var t = state.tokens.next;\n    var g = false;\n    var noindent = false;\n\n    state.funct[\"(breakage)\"] += 1;\n    advance(\"(\");\n    checkCondAssignment(expression(0));\n    advance(\")\", t);\n    t = state.tokens.next;\n    advance(\"{\");\n\n    if (state.tokens.next.from === indent)\n      noindent = true;\n\n    if (!noindent)\n      indent += state.option.indent;\n\n    this.cases = [];\n\n    for (;;) {\n      switch (state.tokens.next.id) {\n      case \"case\":\n        switch (state.funct[\"(verb)\"]) {\n        case \"yield\":\n        case \"break\":\n        case \"case\":\n        case \"continue\":\n        case \"return\":\n        case \"switch\":\n        case \"throw\":\n          break;\n        default:\n          if (!state.tokens.curr.caseFallsThrough) {\n            warning(\"W086\", state.tokens.curr, \"case\");\n          }\n        }\n\n        advance(\"case\");\n        this.cases.push(expression(0));\n        increaseComplexityCount();\n        g = true;\n        advance(\":\");\n        state.funct[\"(verb)\"] = \"case\";\n        break;\n      case \"default\":\n        switch (state.funct[\"(verb)\"]) {\n        case \"yield\":\n        case \"break\":\n        case \"continue\":\n        case \"return\":\n        case \"throw\":\n          break;\n        default:\n          if (this.cases.length) {\n            if (!state.tokens.curr.caseFallsThrough) {\n              warning(\"W086\", state.tokens.curr, \"default\");\n            }\n          }\n        }\n\n        advance(\"default\");\n        g = true;\n        advance(\":\");\n        break;\n      case \"}\":\n        if (!noindent)\n          indent -= state.option.indent;\n\n        advance(\"}\", t);\n        state.funct[\"(breakage)\"] -= 1;\n        state.funct[\"(verb)\"] = undefined;\n        return;\n      case \"(end)\":\n        error(\"E023\", state.tokens.next, \"}\");\n        return;\n      default:\n        indent += state.option.indent;\n        if (g) {\n          switch (state.tokens.curr.id) {\n          case \",\":\n            error(\"E040\");\n            return;\n          case \":\":\n            g = false;\n            statements();\n            break;\n          default:\n            error(\"E025\", state.tokens.curr);\n            return;\n          }\n        } else {\n          if (state.tokens.curr.id === \":\") {\n            advance(\":\");\n            error(\"E024\", state.tokens.curr, \":\");\n            statements();\n          } else {\n            error(\"E021\", state.tokens.next, \"case\", state.tokens.next.value);\n            return;\n          }\n        }\n        indent -= state.option.indent;\n      }\n    }\n    return this;\n  }).labelled = true;\n\n  stmt(\"debugger\", function() {\n    if (!state.option.debug) {\n      warning(\"W087\", this);\n    }\n    return this;\n  }).exps = true;\n\n  (function() {\n    var x = stmt(\"do\", function() {\n      state.funct[\"(breakage)\"] += 1;\n      state.funct[\"(loopage)\"] += 1;\n      increaseComplexityCount();\n\n      this.first = block(true, true);\n      advance(\"while\");\n      var t = state.tokens.next;\n      advance(\"(\");\n      checkCondAssignment(expression(0));\n      advance(\")\", t);\n      state.funct[\"(breakage)\"] -= 1;\n      state.funct[\"(loopage)\"] -= 1;\n      return this;\n    });\n    x.labelled = true;\n    x.exps = true;\n  }());\n\n  blockstmt(\"for\", function() {\n    var s, t = state.tokens.next;\n    var letscope = false;\n    var foreachtok = null;\n\n    if (t.value === \"each\") {\n      foreachtok = t;\n      advance(\"each\");\n      if (!state.inMoz()) {\n        warning(\"W118\", state.tokens.curr, \"for each\");\n      }\n    }\n\n    increaseComplexityCount();\n    advance(\"(\");\n    var nextop; // contains the token of the \"in\" or \"of\" operator\n    var i = 0;\n    var inof = [\"in\", \"of\"];\n    var level = 0; // BindingPattern \"level\" --- level 0 === no BindingPattern\n    var comma; // First comma punctuator at level 0\n    var initializer; // First initializer at level 0\n    if (checkPunctuators(state.tokens.next, [\"{\", \"[\"])) ++level;\n    do {\n      nextop = peek(i);\n      ++i;\n      if (checkPunctuators(nextop, [\"{\", \"[\"])) ++level;\n      else if (checkPunctuators(nextop, [\"}\", \"]\"])) --level;\n      if (level < 0) break;\n      if (level === 0) {\n        if (!comma && checkPunctuator(nextop, \",\")) comma = nextop;\n        else if (!initializer && checkPunctuator(nextop, \"=\")) initializer = nextop;\n      }\n    } while (level > 0 || !_.contains(inof, nextop.value) && nextop.value !== \";\" &&\n    nextop.type !== \"(end)\"); // Is this a JSCS bug? This looks really weird.\n    if (_.contains(inof, nextop.value)) {\n      if (!state.inES6() && nextop.value === \"of\") {\n        warning(\"W104\", nextop, \"for of\", \"6\");\n      }\n\n      var ok = !(initializer || comma);\n      if (initializer) {\n        error(\"W133\", comma, nextop.value, \"initializer is forbidden\");\n      }\n\n      if (comma) {\n        error(\"W133\", comma, nextop.value, \"more than one ForBinding\");\n      }\n\n      if (state.tokens.next.id === \"var\") {\n        advance(\"var\");\n        state.tokens.curr.fud({ prefix: true });\n      } else if (state.tokens.next.id === \"let\" || state.tokens.next.id === \"const\") {\n        advance(state.tokens.next.id);\n        letscope = true;\n        state.funct[\"(scope)\"].stack();\n        state.tokens.curr.fud({ prefix: true });\n      } else {\n        Object.create(varstatement).fud({ prefix: true, implied: \"for\", ignore: !ok });\n      }\n      advance(nextop.value);\n      expression(20);\n      advance(\")\", t);\n\n      if (nextop.value === \"in\" && state.option.forin) {\n        state.forinifcheckneeded = true;\n\n        if (state.forinifchecks === undefined) {\n          state.forinifchecks = [];\n        }\n        state.forinifchecks.push({\n          type: \"(none)\"\n        });\n      }\n\n      state.funct[\"(breakage)\"] += 1;\n      state.funct[\"(loopage)\"] += 1;\n\n      s = block(true, true);\n\n      if (nextop.value === \"in\" && state.option.forin) {\n        if (state.forinifchecks && state.forinifchecks.length > 0) {\n          var check = state.forinifchecks.pop();\n\n          if (// No if statement or not the first statement in loop body\n              s && s.length > 0 && (typeof s[0] !== \"object\" || s[0].value !== \"if\") ||\n              check.type === \"(positive)\" && s.length > 1 ||\n              check.type === \"(negative)\") {\n            warning(\"W089\", this);\n          }\n        }\n        state.forinifcheckneeded = false;\n      }\n\n      state.funct[\"(breakage)\"] -= 1;\n      state.funct[\"(loopage)\"] -= 1;\n    } else {\n      if (foreachtok) {\n        error(\"E045\", foreachtok);\n      }\n      if (state.tokens.next.id !== \";\") {\n        if (state.tokens.next.id === \"var\") {\n          advance(\"var\");\n          state.tokens.curr.fud();\n        } else if (state.tokens.next.id === \"let\") {\n          advance(\"let\");\n          letscope = true;\n          state.funct[\"(scope)\"].stack();\n          state.tokens.curr.fud();\n        } else {\n          for (;;) {\n            expression(0, \"for\");\n            if (state.tokens.next.id !== \",\") {\n              break;\n            }\n            comma();\n          }\n        }\n      }\n      nolinebreak(state.tokens.curr);\n      advance(\";\");\n      state.funct[\"(loopage)\"] += 1;\n      if (state.tokens.next.id !== \";\") {\n        checkCondAssignment(expression(0));\n      }\n      nolinebreak(state.tokens.curr);\n      advance(\";\");\n      if (state.tokens.next.id === \";\") {\n        error(\"E021\", state.tokens.next, \")\", \";\");\n      }\n      if (state.tokens.next.id !== \")\") {\n        for (;;) {\n          expression(0, \"for\");\n          if (state.tokens.next.id !== \",\") {\n            break;\n          }\n          comma();\n        }\n      }\n      advance(\")\", t);\n      state.funct[\"(breakage)\"] += 1;\n      block(true, true);\n      state.funct[\"(breakage)\"] -= 1;\n      state.funct[\"(loopage)\"] -= 1;\n\n    }\n    if (letscope) {\n      state.funct[\"(scope)\"].unstack();\n    }\n    return this;\n  }).labelled = true;\n\n\n  stmt(\"break\", function() {\n    var v = state.tokens.next.value;\n\n    if (!state.option.asi)\n      nolinebreak(this);\n\n    if (state.tokens.next.id !== \";\" && !state.tokens.next.reach &&\n        state.tokens.curr.line === startLine(state.tokens.next)) {\n      if (!state.funct[\"(scope)\"].funct.hasBreakLabel(v)) {\n        warning(\"W090\", state.tokens.next, v);\n      }\n      this.first = state.tokens.next;\n      advance();\n    } else {\n      if (state.funct[\"(breakage)\"] === 0)\n        warning(\"W052\", state.tokens.next, this.value);\n    }\n\n    reachable(this);\n\n    return this;\n  }).exps = true;\n\n\n  stmt(\"continue\", function() {\n    var v = state.tokens.next.value;\n\n    if (state.funct[\"(breakage)\"] === 0)\n      warning(\"W052\", state.tokens.next, this.value);\n    if (!state.funct[\"(loopage)\"])\n      warning(\"W052\", state.tokens.next, this.value);\n\n    if (!state.option.asi)\n      nolinebreak(this);\n\n    if (state.tokens.next.id !== \";\" && !state.tokens.next.reach) {\n      if (state.tokens.curr.line === startLine(state.tokens.next)) {\n        if (!state.funct[\"(scope)\"].funct.hasBreakLabel(v)) {\n          warning(\"W090\", state.tokens.next, v);\n        }\n        this.first = state.tokens.next;\n        advance();\n      }\n    }\n\n    reachable(this);\n\n    return this;\n  }).exps = true;\n\n\n  stmt(\"return\", function() {\n    if (this.line === startLine(state.tokens.next)) {\n      if (state.tokens.next.id !== \";\" && !state.tokens.next.reach) {\n        this.first = expression(0);\n\n        if (this.first &&\n            this.first.type === \"(punctuator)\" && this.first.value === \"=\" &&\n            !this.first.paren && !state.option.boss) {\n          warningAt(\"W093\", this.first.line, this.first.character);\n        }\n      }\n    } else {\n      if (state.tokens.next.type === \"(punctuator)\" &&\n        [\"[\", \"{\", \"+\", \"-\"].indexOf(state.tokens.next.value) > -1) {\n        nolinebreak(this); // always warn (Line breaking error)\n      }\n    }\n\n    reachable(this);\n\n    return this;\n  }).exps = true;\n\n  (function(x) {\n    x.exps = true;\n    x.lbp = 25;\n  }(prefix(\"yield\", function() {\n    var prev = state.tokens.prev;\n    if (state.inES6(true) && !state.funct[\"(generator)\"]) {\n      if (!(\"(catch)\" === state.funct[\"(name)\"] && state.funct[\"(context)\"][\"(generator)\"])) {\n        error(\"E046\", state.tokens.curr, \"yield\");\n      }\n    } else if (!state.inES6()) {\n      warning(\"W104\", state.tokens.curr, \"yield\", \"6\");\n    }\n    state.funct[\"(generator)\"] = \"yielded\";\n    var delegatingYield = false;\n\n    if (state.tokens.next.value === \"*\") {\n      delegatingYield = true;\n      advance(\"*\");\n    }\n\n    if (this.line === startLine(state.tokens.next) || !state.inMoz()) {\n      if (delegatingYield ||\n          (state.tokens.next.id !== \";\" && !state.option.asi &&\n           !state.tokens.next.reach && state.tokens.next.nud)) {\n\n        nobreaknonadjacent(state.tokens.curr, state.tokens.next);\n        this.first = expression(10);\n\n        if (this.first.type === \"(punctuator)\" && this.first.value === \"=\" &&\n            !this.first.paren && !state.option.boss) {\n          warningAt(\"W093\", this.first.line, this.first.character);\n        }\n      }\n\n      if (state.inMoz() && state.tokens.next.id !== \")\" &&\n          (prev.lbp > 30 || (!prev.assign && !isEndOfExpr()) || prev.id === \"yield\")) {\n        error(\"E050\", this);\n      }\n    } else if (!state.option.asi) {\n      nolinebreak(this); // always warn (Line breaking error)\n    }\n    return this;\n  })));\n\n\n  stmt(\"throw\", function() {\n    nolinebreak(this);\n    this.first = expression(20);\n\n    reachable(this);\n\n    return this;\n  }).exps = true;\n\n  stmt(\"import\", function() {\n    if (!state.inES6()) {\n      warning(\"W119\", state.tokens.curr, \"import\", \"6\");\n    }\n\n    if (state.tokens.next.type === \"(string)\") {\n      advance(\"(string)\");\n      return this;\n    }\n\n    if (state.tokens.next.identifier) {\n      this.name = identifier();\n      state.funct[\"(scope)\"].addlabel(this.name, {\n        type: \"const\",\n        token: state.tokens.curr });\n\n      if (state.tokens.next.value === \",\") {\n        advance(\",\");\n      } else {\n        advance(\"from\");\n        advance(\"(string)\");\n        return this;\n      }\n    }\n\n    if (state.tokens.next.id === \"*\") {\n      advance(\"*\");\n      advance(\"as\");\n      if (state.tokens.next.identifier) {\n        this.name = identifier();\n        state.funct[\"(scope)\"].addlabel(this.name, {\n          type: \"const\",\n          token: state.tokens.curr });\n      }\n    } else {\n      advance(\"{\");\n      for (;;) {\n        if (state.tokens.next.value === \"}\") {\n          advance(\"}\");\n          break;\n        }\n        var importName;\n        if (state.tokens.next.type === \"default\") {\n          importName = \"default\";\n          advance(\"default\");\n        } else {\n          importName = identifier();\n        }\n        if (state.tokens.next.value === \"as\") {\n          advance(\"as\");\n          importName = identifier();\n        }\n        state.funct[\"(scope)\"].addlabel(importName, {\n          type: \"const\",\n          token: state.tokens.curr });\n\n        if (state.tokens.next.value === \",\") {\n          advance(\",\");\n        } else if (state.tokens.next.value === \"}\") {\n          advance(\"}\");\n          break;\n        } else {\n          error(\"E024\", state.tokens.next, state.tokens.next.value);\n          break;\n        }\n      }\n    }\n    advance(\"from\");\n    advance(\"(string)\");\n    return this;\n  }).exps = true;\n\n  stmt(\"export\", function() {\n    var ok = true;\n    var token;\n    var identifier;\n\n    if (!state.inES6()) {\n      warning(\"W119\", state.tokens.curr, \"export\", \"6\");\n      ok = false;\n    }\n\n    if (!state.funct[\"(scope)\"].block.isGlobal()) {\n      error(\"E053\", state.tokens.curr);\n      ok = false;\n    }\n\n    if (state.tokens.next.value === \"*\") {\n      advance(\"*\");\n      advance(\"from\");\n      advance(\"(string)\");\n      return this;\n    }\n\n    if (state.tokens.next.type === \"default\") {\n      state.nameStack.set(state.tokens.next);\n      advance(\"default\");\n      var exportType = state.tokens.next.id;\n      if (exportType === \"function\" || exportType === \"class\") {\n        this.block = true;\n      }\n\n      token = peek();\n\n      expression(10);\n\n      identifier = token.value;\n\n      if (this.block) {\n        state.funct[\"(scope)\"].addlabel(identifier, {\n          type: exportType,\n          token: token });\n\n        state.funct[\"(scope)\"].setExported(identifier, token);\n      }\n\n      return this;\n    }\n\n    if (state.tokens.next.value === \"{\") {\n      advance(\"{\");\n      var exportedTokens = [];\n      for (;;) {\n        if (!state.tokens.next.identifier) {\n          error(\"E030\", state.tokens.next, state.tokens.next.value);\n        }\n        advance();\n\n        exportedTokens.push(state.tokens.curr);\n\n        if (state.tokens.next.value === \"as\") {\n          advance(\"as\");\n          if (!state.tokens.next.identifier) {\n            error(\"E030\", state.tokens.next, state.tokens.next.value);\n          }\n          advance();\n        }\n\n        if (state.tokens.next.value === \",\") {\n          advance(\",\");\n        } else if (state.tokens.next.value === \"}\") {\n          advance(\"}\");\n          break;\n        } else {\n          error(\"E024\", state.tokens.next, state.tokens.next.value);\n          break;\n        }\n      }\n      if (state.tokens.next.value === \"from\") {\n        advance(\"from\");\n        advance(\"(string)\");\n      } else if (ok) {\n        exportedTokens.forEach(function(token) {\n          state.funct[\"(scope)\"].setExported(token.value, token);\n        });\n      }\n      return this;\n    }\n\n    if (state.tokens.next.id === \"var\") {\n      advance(\"var\");\n      state.tokens.curr.fud({ inexport:true });\n    } else if (state.tokens.next.id === \"let\") {\n      advance(\"let\");\n      state.tokens.curr.fud({ inexport:true });\n    } else if (state.tokens.next.id === \"const\") {\n      advance(\"const\");\n      state.tokens.curr.fud({ inexport:true });\n    } else if (state.tokens.next.id === \"function\") {\n      this.block = true;\n      advance(\"function\");\n      state.syntax[\"function\"].fud({ inexport:true });\n    } else if (state.tokens.next.id === \"class\") {\n      this.block = true;\n      advance(\"class\");\n      var classNameToken = state.tokens.next;\n      state.syntax[\"class\"].fud();\n      state.funct[\"(scope)\"].setExported(classNameToken.value, classNameToken);\n    } else {\n      error(\"E024\", state.tokens.next, state.tokens.next.value);\n    }\n\n    return this;\n  }).exps = true;\n\n  FutureReservedWord(\"abstract\");\n  FutureReservedWord(\"boolean\");\n  FutureReservedWord(\"byte\");\n  FutureReservedWord(\"char\");\n  FutureReservedWord(\"class\", { es5: true, nud: classdef });\n  FutureReservedWord(\"double\");\n  FutureReservedWord(\"enum\", { es5: true });\n  FutureReservedWord(\"export\", { es5: true });\n  FutureReservedWord(\"extends\", { es5: true });\n  FutureReservedWord(\"final\");\n  FutureReservedWord(\"float\");\n  FutureReservedWord(\"goto\");\n  FutureReservedWord(\"implements\", { es5: true, strictOnly: true });\n  FutureReservedWord(\"import\", { es5: true });\n  FutureReservedWord(\"int\");\n  FutureReservedWord(\"interface\", { es5: true, strictOnly: true });\n  FutureReservedWord(\"long\");\n  FutureReservedWord(\"native\");\n  FutureReservedWord(\"package\", { es5: true, strictOnly: true });\n  FutureReservedWord(\"private\", { es5: true, strictOnly: true });\n  FutureReservedWord(\"protected\", { es5: true, strictOnly: true });\n  FutureReservedWord(\"public\", { es5: true, strictOnly: true });\n  FutureReservedWord(\"short\");\n  FutureReservedWord(\"static\", { es5: true, strictOnly: true });\n  FutureReservedWord(\"super\", { es5: true });\n  FutureReservedWord(\"synchronized\");\n  FutureReservedWord(\"transient\");\n  FutureReservedWord(\"volatile\");\n\n  var lookupBlockType = function() {\n    var pn, pn1, prev;\n    var i = -1;\n    var bracketStack = 0;\n    var ret = {};\n    if (checkPunctuators(state.tokens.curr, [\"[\", \"{\"])) {\n      bracketStack += 1;\n    }\n    do {\n      prev = i === -1 ? state.tokens.curr : pn;\n      pn = i === -1 ? state.tokens.next : peek(i);\n      pn1 = peek(i + 1);\n      i = i + 1;\n      if (checkPunctuators(pn, [\"[\", \"{\"])) {\n        bracketStack += 1;\n      } else if (checkPunctuators(pn, [\"]\", \"}\"])) {\n        bracketStack -= 1;\n      }\n      if (bracketStack === 1 && pn.identifier && pn.value === \"for\" &&\n          !checkPunctuator(prev, \".\")) {\n        ret.isCompArray = true;\n        ret.notJson = true;\n        break;\n      }\n      if (bracketStack === 0 && checkPunctuators(pn, [\"}\", \"]\"])) {\n        if (pn1.value === \"=\") {\n          ret.isDestAssign = true;\n          ret.notJson = true;\n          break;\n        } else if (pn1.value === \".\") {\n          ret.notJson = true;\n          break;\n        }\n      }\n      if (checkPunctuator(pn, \";\")) {\n        ret.isBlock = true;\n        ret.notJson = true;\n      }\n    } while (bracketStack > 0 && pn.id !== \"(end)\");\n    return ret;\n  };\n\n  function saveProperty(props, name, tkn, isClass, isStatic) {\n    var msg = [\"key\", \"class method\", \"static class method\"];\n    msg = msg[(isClass || false) + (isStatic || false)];\n    if (tkn.identifier) {\n      name = tkn.value;\n    }\n\n    if (props[name] && name !== \"__proto__\") {\n      warning(\"W075\", state.tokens.next, msg, name);\n    } else {\n      props[name] = Object.create(null);\n    }\n\n    props[name].basic = true;\n    props[name].basictkn = tkn;\n  }\n  function saveAccessor(accessorType, props, name, tkn, isClass, isStatic) {\n    var flagName = accessorType === \"get\" ? \"getterToken\" : \"setterToken\";\n    var msg = \"\";\n\n    if (isClass) {\n      if (isStatic) {\n        msg += \"static \";\n      }\n      msg += accessorType + \"ter method\";\n    } else {\n      msg = \"key\";\n    }\n\n    state.tokens.curr.accessorType = accessorType;\n    state.nameStack.set(tkn);\n\n    if (props[name]) {\n      if ((props[name].basic || props[name][flagName]) && name !== \"__proto__\") {\n        warning(\"W075\", state.tokens.next, msg, name);\n      }\n    } else {\n      props[name] = Object.create(null);\n    }\n\n    props[name][flagName] = tkn;\n  }\n\n  function computedPropertyName() {\n    advance(\"[\");\n    if (!state.inES6()) {\n      warning(\"W119\", state.tokens.curr, \"computed property names\", \"6\");\n    }\n    var value = expression(10);\n    advance(\"]\");\n    return value;\n  }\n  function checkPunctuators(token, values) {\n    if (token.type === \"(punctuator)\") {\n      return _.contains(values, token.value);\n    }\n    return false;\n  }\n  function checkPunctuator(token, value) {\n    return token.type === \"(punctuator)\" && token.value === value;\n  }\n  function destructuringAssignOrJsonValue() {\n\n    var block = lookupBlockType();\n    if (block.notJson) {\n      if (!state.inES6() && block.isDestAssign) {\n        warning(\"W104\", state.tokens.curr, \"destructuring assignment\", \"6\");\n      }\n      statements();\n    } else {\n      state.option.laxbreak = true;\n      state.jsonMode = true;\n      jsonValue();\n    }\n  }\n\n  var arrayComprehension = function() {\n    var CompArray = function() {\n      this.mode = \"use\";\n      this.variables = [];\n    };\n    var _carrays = [];\n    var _current;\n    function declare(v) {\n      var l = _current.variables.filter(function(elt) {\n        if (elt.value === v) {\n          elt.undef = false;\n          return v;\n        }\n      }).length;\n      return l !== 0;\n    }\n    function use(v) {\n      var l = _current.variables.filter(function(elt) {\n        if (elt.value === v && !elt.undef) {\n          if (elt.unused === true) {\n            elt.unused = false;\n          }\n          return v;\n        }\n      }).length;\n      return (l === 0);\n    }\n    return { stack: function() {\n          _current = new CompArray();\n          _carrays.push(_current);\n        },\n        unstack: function() {\n          _current.variables.filter(function(v) {\n            if (v.unused)\n              warning(\"W098\", v.token, v.raw_text || v.value);\n            if (v.undef)\n              state.funct[\"(scope)\"].block.use(v.value, v.token);\n          });\n          _carrays.splice(-1, 1);\n          _current = _carrays[_carrays.length - 1];\n        },\n        setState: function(s) {\n          if (_.contains([\"use\", \"define\", \"generate\", \"filter\"], s))\n            _current.mode = s;\n        },\n        check: function(v) {\n          if (!_current) {\n            return;\n          }\n          if (_current && _current.mode === \"use\") {\n            if (use(v)) {\n              _current.variables.push({\n                funct: state.funct,\n                token: state.tokens.curr,\n                value: v,\n                undef: true,\n                unused: false\n              });\n            }\n            return true;\n          } else if (_current && _current.mode === \"define\") {\n            if (!declare(v)) {\n              _current.variables.push({\n                funct: state.funct,\n                token: state.tokens.curr,\n                value: v,\n                undef: false,\n                unused: true\n              });\n            }\n            return true;\n          } else if (_current && _current.mode === \"generate\") {\n            state.funct[\"(scope)\"].block.use(v, state.tokens.curr);\n            return true;\n          } else if (_current && _current.mode === \"filter\") {\n            if (use(v)) {\n              state.funct[\"(scope)\"].block.use(v, state.tokens.curr);\n            }\n            return true;\n          }\n          return false;\n        }\n        };\n  };\n\n  function jsonValue() {\n    function jsonObject() {\n      var o = {}, t = state.tokens.next;\n      advance(\"{\");\n      if (state.tokens.next.id !== \"}\") {\n        for (;;) {\n          if (state.tokens.next.id === \"(end)\") {\n            error(\"E026\", state.tokens.next, t.line);\n          } else if (state.tokens.next.id === \"}\") {\n            warning(\"W094\", state.tokens.curr);\n            break;\n          } else if (state.tokens.next.id === \",\") {\n            error(\"E028\", state.tokens.next);\n          } else if (state.tokens.next.id !== \"(string)\") {\n            warning(\"W095\", state.tokens.next, state.tokens.next.value);\n          }\n          if (o[state.tokens.next.value] === true) {\n            warning(\"W075\", state.tokens.next, \"key\", state.tokens.next.value);\n          } else if ((state.tokens.next.value === \"__proto__\" &&\n            !state.option.proto) || (state.tokens.next.value === \"__iterator__\" &&\n            !state.option.iterator)) {\n            warning(\"W096\", state.tokens.next, state.tokens.next.value);\n          } else {\n            o[state.tokens.next.value] = true;\n          }\n          advance();\n          advance(\":\");\n          jsonValue();\n          if (state.tokens.next.id !== \",\") {\n            break;\n          }\n          advance(\",\");\n        }\n      }\n      advance(\"}\");\n    }\n\n    function jsonArray() {\n      var t = state.tokens.next;\n      advance(\"[\");\n      if (state.tokens.next.id !== \"]\") {\n        for (;;) {\n          if (state.tokens.next.id === \"(end)\") {\n            error(\"E027\", state.tokens.next, t.line);\n          } else if (state.tokens.next.id === \"]\") {\n            warning(\"W094\", state.tokens.curr);\n            break;\n          } else if (state.tokens.next.id === \",\") {\n            error(\"E028\", state.tokens.next);\n          }\n          jsonValue();\n          if (state.tokens.next.id !== \",\") {\n            break;\n          }\n          advance(\",\");\n        }\n      }\n      advance(\"]\");\n    }\n\n    switch (state.tokens.next.id) {\n    case \"{\":\n      jsonObject();\n      break;\n    case \"[\":\n      jsonArray();\n      break;\n    case \"true\":\n    case \"false\":\n    case \"null\":\n    case \"(number)\":\n    case \"(string)\":\n      advance();\n      break;\n    case \"-\":\n      advance(\"-\");\n      advance(\"(number)\");\n      break;\n    default:\n      error(\"E003\", state.tokens.next);\n    }\n  }\n\n  var escapeRegex = function(str) {\n    return str.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\");\n  };\n  var itself = function(s, o, g) {\n    var i, k, x, reIgnoreStr, reIgnore;\n    var optionKeys;\n    var newOptionObj = {};\n    var newIgnoredObj = {};\n\n    o = _.clone(o);\n    state.reset();\n\n    if (o && o.scope) {\n      JSHINT.scope = o.scope;\n    } else {\n      JSHINT.errors = [];\n      JSHINT.undefs = [];\n      JSHINT.internals = [];\n      JSHINT.blacklist = {};\n      JSHINT.scope = \"(main)\";\n    }\n\n    predefined = Object.create(null);\n    combine(predefined, vars.ecmaIdentifiers[3]);\n    combine(predefined, vars.reservedVars);\n\n    combine(predefined, g || {});\n\n    declared = Object.create(null);\n    var exported = Object.create(null); // Variables that live outside the current file\n\n    function each(obj, cb) {\n      if (!obj)\n        return;\n\n      if (!Array.isArray(obj) && typeof obj === \"object\")\n        obj = Object.keys(obj);\n\n      obj.forEach(cb);\n    }\n\n    if (o) {\n      each(o.predef || null, function(item) {\n        var slice, prop;\n\n        if (item[0] === \"-\") {\n          slice = item.slice(1);\n          JSHINT.blacklist[slice] = slice;\n          delete predefined[slice];\n        } else {\n          prop = Object.getOwnPropertyDescriptor(o.predef, item);\n          predefined[item] = prop ? prop.value : false;\n        }\n      });\n\n      each(o.exported || null, function(item) {\n        exported[item] = true;\n      });\n\n      delete o.predef;\n      delete o.exported;\n\n      optionKeys = Object.keys(o);\n      for (x = 0; x < optionKeys.length; x++) {\n        if (/^-W\\d{3}$/g.test(optionKeys[x])) {\n          newIgnoredObj[optionKeys[x].slice(1)] = true;\n        } else {\n          var optionKey = optionKeys[x];\n          newOptionObj[optionKey] = o[optionKey];\n          if ((optionKey === \"esversion\" && o[optionKey] === 5) ||\n              (optionKey === \"es5\" && o[optionKey])) {\n            warning(\"I003\");\n          }\n\n          if (optionKeys[x] === \"newcap\" && o[optionKey] === false)\n            newOptionObj[\"(explicitNewcap)\"] = true;\n        }\n      }\n    }\n\n    state.option = newOptionObj;\n    state.ignored = newIgnoredObj;\n\n    state.option.indent = state.option.indent || 4;\n    state.option.maxerr = state.option.maxerr || 50;\n\n    indent = 1;\n\n    var scopeManagerInst = scopeManager(state, predefined, exported, declared);\n    scopeManagerInst.on(\"warning\", function(ev) {\n      warning.apply(null, [ ev.code, ev.token].concat(ev.data));\n    });\n\n    scopeManagerInst.on(\"error\", function(ev) {\n      error.apply(null, [ ev.code, ev.token ].concat(ev.data));\n    });\n\n    state.funct = functor(\"(global)\", null, {\n      \"(global)\"    : true,\n      \"(scope)\"     : scopeManagerInst,\n      \"(comparray)\" : arrayComprehension(),\n      \"(metrics)\"   : createMetrics(state.tokens.next)\n    });\n\n    functions = [state.funct];\n    urls = [];\n    stack = null;\n    member = {};\n    membersOnly = null;\n    inblock = false;\n    lookahead = [];\n\n    if (!isString(s) && !Array.isArray(s)) {\n      errorAt(\"E004\", 0);\n      return false;\n    }\n\n    api = {\n      get isJSON() {\n        return state.jsonMode;\n      },\n\n      getOption: function(name) {\n        return state.option[name] || null;\n      },\n\n      getCache: function(name) {\n        return state.cache[name];\n      },\n\n      setCache: function(name, value) {\n        state.cache[name] = value;\n      },\n\n      warn: function(code, data) {\n        warningAt.apply(null, [ code, data.line, data.char ].concat(data.data));\n      },\n\n      on: function(names, listener) {\n        names.split(\" \").forEach(function(name) {\n          emitter.on(name, listener);\n        }.bind(this));\n      }\n    };\n\n    emitter.removeAllListeners();\n    (extraModules || []).forEach(function(func) {\n      func(api);\n    });\n\n    state.tokens.prev = state.tokens.curr = state.tokens.next = state.syntax[\"(begin)\"];\n\n    if (o && o.ignoreDelimiters) {\n\n      if (!Array.isArray(o.ignoreDelimiters)) {\n        o.ignoreDelimiters = [o.ignoreDelimiters];\n      }\n\n      o.ignoreDelimiters.forEach(function(delimiterPair) {\n        if (!delimiterPair.start || !delimiterPair.end)\n            return;\n\n        reIgnoreStr = escapeRegex(delimiterPair.start) +\n                      \"[\\\\s\\\\S]*?\" +\n                      escapeRegex(delimiterPair.end);\n\n        reIgnore = new RegExp(reIgnoreStr, \"ig\");\n\n        s = s.replace(reIgnore, function(match) {\n          return match.replace(/./g, \" \");\n        });\n      });\n    }\n\n    lex = new Lexer(s);\n\n    lex.on(\"warning\", function(ev) {\n      warningAt.apply(null, [ ev.code, ev.line, ev.character].concat(ev.data));\n    });\n\n    lex.on(\"error\", function(ev) {\n      errorAt.apply(null, [ ev.code, ev.line, ev.character ].concat(ev.data));\n    });\n\n    lex.on(\"fatal\", function(ev) {\n      quit(\"E041\", ev.line, ev.from);\n    });\n\n    lex.on(\"Identifier\", function(ev) {\n      emitter.emit(\"Identifier\", ev);\n    });\n\n    lex.on(\"String\", function(ev) {\n      emitter.emit(\"String\", ev);\n    });\n\n    lex.on(\"Number\", function(ev) {\n      emitter.emit(\"Number\", ev);\n    });\n\n    lex.start();\n    for (var name in o) {\n      if (_.has(o, name)) {\n        checkOption(name, state.tokens.curr);\n      }\n    }\n\n    assume();\n    combine(predefined, g || {});\n    comma.first = true;\n\n    try {\n      advance();\n      switch (state.tokens.next.id) {\n      case \"{\":\n      case \"[\":\n        destructuringAssignOrJsonValue();\n        break;\n      default:\n        directives();\n\n        if (state.directive[\"use strict\"]) {\n          if (state.option.strict !== \"global\") {\n            warning(\"W097\", state.tokens.prev);\n          }\n        }\n\n        statements();\n      }\n\n      if (state.tokens.next.id !== \"(end)\") {\n        quit(\"E041\", state.tokens.curr.line);\n      }\n\n      state.funct[\"(scope)\"].unstack();\n\n    } catch (err) {\n      if (err && err.name === \"JSHintError\") {\n        var nt = state.tokens.next || {};\n        JSHINT.errors.push({\n          scope     : \"(main)\",\n          raw       : err.raw,\n          code      : err.code,\n          reason    : err.message,\n          line      : err.line || nt.line,\n          character : err.character || nt.from\n        }, null);\n      } else {\n        throw err;\n      }\n    }\n\n    if (JSHINT.scope === \"(main)\") {\n      o = o || {};\n\n      for (i = 0; i < JSHINT.internals.length; i += 1) {\n        k = JSHINT.internals[i];\n        o.scope = k.elem;\n        itself(k.value, o, g);\n      }\n    }\n\n    return JSHINT.errors.length === 0;\n  };\n  itself.addModule = function(func) {\n    extraModules.push(func);\n  };\n\n  itself.addModule(style.register);\n  itself.data = function() {\n    var data = {\n      functions: [],\n      options: state.option\n    };\n\n    var fu, f, i, j, n, globals;\n\n    if (itself.errors.length) {\n      data.errors = itself.errors;\n    }\n\n    if (state.jsonMode) {\n      data.json = true;\n    }\n\n    var impliedGlobals = state.funct[\"(scope)\"].getImpliedGlobals();\n    if (impliedGlobals.length > 0) {\n      data.implieds = impliedGlobals;\n    }\n\n    if (urls.length > 0) {\n      data.urls = urls;\n    }\n\n    globals = state.funct[\"(scope)\"].getUsedOrDefinedGlobals();\n    if (globals.length > 0) {\n      data.globals = globals;\n    }\n\n    for (i = 1; i < functions.length; i += 1) {\n      f = functions[i];\n      fu = {};\n\n      for (j = 0; j < functionicity.length; j += 1) {\n        fu[functionicity[j]] = [];\n      }\n\n      for (j = 0; j < functionicity.length; j += 1) {\n        if (fu[functionicity[j]].length === 0) {\n          delete fu[functionicity[j]];\n        }\n      }\n\n      fu.name = f[\"(name)\"];\n      fu.param = f[\"(params)\"];\n      fu.line = f[\"(line)\"];\n      fu.character = f[\"(character)\"];\n      fu.last = f[\"(last)\"];\n      fu.lastcharacter = f[\"(lastcharacter)\"];\n\n      fu.metrics = {\n        complexity: f[\"(metrics)\"].ComplexityCount,\n        parameters: f[\"(metrics)\"].arity,\n        statements: f[\"(metrics)\"].statementCount\n      };\n\n      data.functions.push(fu);\n    }\n\n    var unuseds = state.funct[\"(scope)\"].getUnuseds();\n    if (unuseds.length > 0) {\n      data.unused = unuseds;\n    }\n\n    for (n in member) {\n      if (typeof member[n] === \"number\") {\n        data.member = member;\n        break;\n      }\n    }\n\n    return data;\n  };\n\n  itself.jshint = itself;\n\n  return itself;\n}());\nif (typeof exports === \"object\" && exports) {\n  exports.JSHINT = JSHINT;\n}\n\n},{\"../lodash\":\"/node_modules/jshint/lodash.js\",\"./lex.js\":\"/node_modules/jshint/src/lex.js\",\"./messages.js\":\"/node_modules/jshint/src/messages.js\",\"./options.js\":\"/node_modules/jshint/src/options.js\",\"./reg.js\":\"/node_modules/jshint/src/reg.js\",\"./scope-manager.js\":\"/node_modules/jshint/src/scope-manager.js\",\"./state.js\":\"/node_modules/jshint/src/state.js\",\"./style.js\":\"/node_modules/jshint/src/style.js\",\"./vars.js\":\"/node_modules/jshint/src/vars.js\",\"events\":\"/node_modules/browserify/node_modules/events/events.js\"}],\"/node_modules/jshint/src/lex.js\":[function(_dereq_,module,exports){\n\n\"use strict\";\n\nvar _      = _dereq_(\"../lodash\");\nvar events = _dereq_(\"events\");\nvar reg    = _dereq_(\"./reg.js\");\nvar state  = _dereq_(\"./state.js\").state;\n\nvar unicodeData = _dereq_(\"../data/ascii-identifier-data.js\");\nvar asciiIdentifierStartTable = unicodeData.asciiIdentifierStartTable;\nvar asciiIdentifierPartTable = unicodeData.asciiIdentifierPartTable;\n\nvar Token = {\n  Identifier: 1,\n  Punctuator: 2,\n  NumericLiteral: 3,\n  StringLiteral: 4,\n  Comment: 5,\n  Keyword: 6,\n  NullLiteral: 7,\n  BooleanLiteral: 8,\n  RegExp: 9,\n  TemplateHead: 10,\n  TemplateMiddle: 11,\n  TemplateTail: 12,\n  NoSubstTemplate: 13\n};\n\nvar Context = {\n  Block: 1,\n  Template: 2\n};\n\nfunction asyncTrigger() {\n  var _checks = [];\n\n  return {\n    push: function(fn) {\n      _checks.push(fn);\n    },\n\n    check: function() {\n      for (var check = 0; check < _checks.length; ++check) {\n        _checks[check]();\n      }\n\n      _checks.splice(0, _checks.length);\n    }\n  };\n}\nfunction Lexer(source) {\n  var lines = source;\n\n  if (typeof lines === \"string\") {\n    lines = lines\n      .replace(/\\r\\n/g, \"\\n\")\n      .replace(/\\r/g, \"\\n\")\n      .split(\"\\n\");\n  }\n\n  if (lines[0] && lines[0].substr(0, 2) === \"#!\") {\n    if (lines[0].indexOf(\"node\") !== -1) {\n      state.option.node = true;\n    }\n    lines[0] = \"\";\n  }\n\n  this.emitter = new events.EventEmitter();\n  this.source = source;\n  this.setLines(lines);\n  this.prereg = true;\n\n  this.line = 0;\n  this.char = 1;\n  this.from = 1;\n  this.input = \"\";\n  this.inComment = false;\n  this.context = [];\n  this.templateStarts = [];\n\n  for (var i = 0; i < state.option.indent; i += 1) {\n    state.tab += \" \";\n  }\n  this.ignoreLinterErrors = false;\n}\n\nLexer.prototype = {\n  _lines: [],\n\n  inContext: function(ctxType) {\n    return this.context.length > 0 && this.context[this.context.length - 1].type === ctxType;\n  },\n\n  pushContext: function(ctxType) {\n    this.context.push({ type: ctxType });\n  },\n\n  popContext: function() {\n    return this.context.pop();\n  },\n\n  isContext: function(context) {\n    return this.context.length > 0 && this.context[this.context.length - 1] === context;\n  },\n\n  currentContext: function() {\n    return this.context.length > 0 && this.context[this.context.length - 1];\n  },\n\n  getLines: function() {\n    this._lines = state.lines;\n    return this._lines;\n  },\n\n  setLines: function(val) {\n    this._lines = val;\n    state.lines = this._lines;\n  },\n  peek: function(i) {\n    return this.input.charAt(i || 0);\n  },\n  skip: function(i) {\n    i = i || 1;\n    this.char += i;\n    this.input = this.input.slice(i);\n  },\n  on: function(names, listener) {\n    names.split(\" \").forEach(function(name) {\n      this.emitter.on(name, listener);\n    }.bind(this));\n  },\n  trigger: function() {\n    this.emitter.emit.apply(this.emitter, Array.prototype.slice.call(arguments));\n  },\n  triggerAsync: function(type, args, checks, fn) {\n    checks.push(function() {\n      if (fn()) {\n        this.trigger(type, args);\n      }\n    }.bind(this));\n  },\n  scanPunctuator: function() {\n    var ch1 = this.peek();\n    var ch2, ch3, ch4;\n\n    switch (ch1) {\n    case \".\":\n      if ((/^[0-9]$/).test(this.peek(1))) {\n        return null;\n      }\n      if (this.peek(1) === \".\" && this.peek(2) === \".\") {\n        return {\n          type: Token.Punctuator,\n          value: \"...\"\n        };\n      }\n    case \"(\":\n    case \")\":\n    case \";\":\n    case \",\":\n    case \"[\":\n    case \"]\":\n    case \":\":\n    case \"~\":\n    case \"?\":\n      return {\n        type: Token.Punctuator,\n        value: ch1\n      };\n    case \"{\":\n      this.pushContext(Context.Block);\n      return {\n        type: Token.Punctuator,\n        value: ch1\n      };\n    case \"}\":\n      if (this.inContext(Context.Block)) {\n        this.popContext();\n      }\n      return {\n        type: Token.Punctuator,\n        value: ch1\n      };\n    case \"#\":\n      return {\n        type: Token.Punctuator,\n        value: ch1\n      };\n    case \"\":\n      return null;\n    }\n\n    ch2 = this.peek(1);\n    ch3 = this.peek(2);\n    ch4 = this.peek(3);\n\n    if (ch1 === \">\" && ch2 === \">\" && ch3 === \">\" && ch4 === \"=\") {\n      return {\n        type: Token.Punctuator,\n        value: \">>>=\"\n      };\n    }\n\n    if (ch1 === \"=\" && ch2 === \"=\" && ch3 === \"=\") {\n      return {\n        type: Token.Punctuator,\n        value: \"===\"\n      };\n    }\n\n    if (ch1 === \"!\" && ch2 === \"=\" && ch3 === \"=\") {\n      return {\n        type: Token.Punctuator,\n        value: \"!==\"\n      };\n    }\n\n    if (ch1 === \">\" && ch2 === \">\" && ch3 === \">\") {\n      return {\n        type: Token.Punctuator,\n        value: \">>>\"\n      };\n    }\n\n    if (ch1 === \"<\" && ch2 === \"<\" && ch3 === \"=\") {\n      return {\n        type: Token.Punctuator,\n        value: \"<<=\"\n      };\n    }\n\n    if (ch1 === \">\" && ch2 === \">\" && ch3 === \"=\") {\n      return {\n        type: Token.Punctuator,\n        value: \">>=\"\n      };\n    }\n    if (ch1 === \"=\" && ch2 === \">\") {\n      return {\n        type: Token.Punctuator,\n        value: ch1 + ch2\n      };\n    }\n    if (ch1 === ch2 && (\"+-<>&|\".indexOf(ch1) >= 0)) {\n      return {\n        type: Token.Punctuator,\n        value: ch1 + ch2\n      };\n    }\n\n    if (\"<>=!+-*%&|^\".indexOf(ch1) >= 0) {\n      if (ch2 === \"=\") {\n        return {\n          type: Token.Punctuator,\n          value: ch1 + ch2\n        };\n      }\n\n      return {\n        type: Token.Punctuator,\n        value: ch1\n      };\n    }\n\n    if (ch1 === \"/\") {\n      if (ch2 === \"=\") {\n        return {\n          type: Token.Punctuator,\n          value: \"/=\"\n        };\n      }\n\n      return {\n        type: Token.Punctuator,\n        value: \"/\"\n      };\n    }\n\n    return null;\n  },\n  scanComments: function() {\n    var ch1 = this.peek();\n    var ch2 = this.peek(1);\n    var rest = this.input.substr(2);\n    var startLine = this.line;\n    var startChar = this.char;\n    var self = this;\n\n    function commentToken(label, body, opt) {\n      var special = [\"jshint\", \"jslint\", \"members\", \"member\", \"globals\", \"global\", \"exported\"];\n      var isSpecial = false;\n      var value = label + body;\n      var commentType = \"plain\";\n      opt = opt || {};\n\n      if (opt.isMultiline) {\n        value += \"*/\";\n      }\n\n      body = body.replace(/\\n/g, \" \");\n\n      if (label === \"/*\" && reg.fallsThrough.test(body)) {\n        isSpecial = true;\n        commentType = \"falls through\";\n      }\n\n      special.forEach(function(str) {\n        if (isSpecial) {\n          return;\n        }\n        if (label === \"//\" && str !== \"jshint\") {\n          return;\n        }\n\n        if (body.charAt(str.length) === \" \" && body.substr(0, str.length) === str) {\n          isSpecial = true;\n          label = label + str;\n          body = body.substr(str.length);\n        }\n\n        if (!isSpecial && body.charAt(0) === \" \" && body.charAt(str.length + 1) === \" \" &&\n          body.substr(1, str.length) === str) {\n          isSpecial = true;\n          label = label + \" \" + str;\n          body = body.substr(str.length + 1);\n        }\n\n        if (!isSpecial) {\n          return;\n        }\n\n        switch (str) {\n        case \"member\":\n          commentType = \"members\";\n          break;\n        case \"global\":\n          commentType = \"globals\";\n          break;\n        default:\n          var options = body.split(\":\").map(function(v) {\n            return v.replace(/^\\s+/, \"\").replace(/\\s+$/, \"\");\n          });\n\n          if (options.length === 2) {\n            switch (options[0]) {\n            case \"ignore\":\n              switch (options[1]) {\n              case \"start\":\n                self.ignoringLinterErrors = true;\n                isSpecial = false;\n                break;\n              case \"end\":\n                self.ignoringLinterErrors = false;\n                isSpecial = false;\n                break;\n              }\n            }\n          }\n\n          commentType = str;\n        }\n      });\n\n      return {\n        type: Token.Comment,\n        commentType: commentType,\n        value: value,\n        body: body,\n        isSpecial: isSpecial,\n        isMultiline: opt.isMultiline || false,\n        isMalformed: opt.isMalformed || false\n      };\n    }\n    if (ch1 === \"*\" && ch2 === \"/\") {\n      this.trigger(\"error\", {\n        code: \"E018\",\n        line: startLine,\n        character: startChar\n      });\n\n      this.skip(2);\n      return null;\n    }\n    if (ch1 !== \"/\" || (ch2 !== \"*\" && ch2 !== \"/\")) {\n      return null;\n    }\n    if (ch2 === \"/\") {\n      this.skip(this.input.length); // Skip to the EOL.\n      return commentToken(\"//\", rest);\n    }\n\n    var body = \"\";\n    if (ch2 === \"*\") {\n      this.inComment = true;\n      this.skip(2);\n\n      while (this.peek() !== \"*\" || this.peek(1) !== \"/\") {\n        if (this.peek() === \"\") { // End of Line\n          body += \"\\n\";\n          if (!this.nextLine()) {\n            this.trigger(\"error\", {\n              code: \"E017\",\n              line: startLine,\n              character: startChar\n            });\n\n            this.inComment = false;\n            return commentToken(\"/*\", body, {\n              isMultiline: true,\n              isMalformed: true\n            });\n          }\n        } else {\n          body += this.peek();\n          this.skip();\n        }\n      }\n\n      this.skip(2);\n      this.inComment = false;\n      return commentToken(\"/*\", body, { isMultiline: true });\n    }\n  },\n  scanKeyword: function() {\n    var result = /^[a-zA-Z_$][a-zA-Z0-9_$]*/.exec(this.input);\n    var keywords = [\n      \"if\", \"in\", \"do\", \"var\", \"for\", \"new\",\n      \"try\", \"let\", \"this\", \"else\", \"case\",\n      \"void\", \"with\", \"enum\", \"while\", \"break\",\n      \"catch\", \"throw\", \"const\", \"yield\", \"class\",\n      \"super\", \"return\", \"typeof\", \"delete\",\n      \"switch\", \"export\", \"import\", \"default\",\n      \"finally\", \"extends\", \"function\", \"continue\",\n      \"debugger\", \"instanceof\"\n    ];\n\n    if (result && keywords.indexOf(result[0]) >= 0) {\n      return {\n        type: Token.Keyword,\n        value: result[0]\n      };\n    }\n\n    return null;\n  },\n  scanIdentifier: function() {\n    var id = \"\";\n    var index = 0;\n    var type, char;\n\n    function isNonAsciiIdentifierStart(code) {\n      return code > 256;\n    }\n\n    function isNonAsciiIdentifierPart(code) {\n      return code > 256;\n    }\n\n    function isHexDigit(str) {\n      return (/^[0-9a-fA-F]$/).test(str);\n    }\n\n    var readUnicodeEscapeSequence = function() {\n      index += 1;\n\n      if (this.peek(index) !== \"u\") {\n        return null;\n      }\n\n      var ch1 = this.peek(index + 1);\n      var ch2 = this.peek(index + 2);\n      var ch3 = this.peek(index + 3);\n      var ch4 = this.peek(index + 4);\n      var code;\n\n      if (isHexDigit(ch1) && isHexDigit(ch2) && isHexDigit(ch3) && isHexDigit(ch4)) {\n        code = parseInt(ch1 + ch2 + ch3 + ch4, 16);\n\n        if (asciiIdentifierPartTable[code] || isNonAsciiIdentifierPart(code)) {\n          index += 5;\n          return \"\\\\u\" + ch1 + ch2 + ch3 + ch4;\n        }\n\n        return null;\n      }\n\n      return null;\n    }.bind(this);\n\n    var getIdentifierStart = function() {\n      var chr = this.peek(index);\n      var code = chr.charCodeAt(0);\n\n      if (code === 92) {\n        return readUnicodeEscapeSequence();\n      }\n\n      if (code < 128) {\n        if (asciiIdentifierStartTable[code]) {\n          index += 1;\n          return chr;\n        }\n\n        return null;\n      }\n\n      if (isNonAsciiIdentifierStart(code)) {\n        index += 1;\n        return chr;\n      }\n\n      return null;\n    }.bind(this);\n\n    var getIdentifierPart = function() {\n      var chr = this.peek(index);\n      var code = chr.charCodeAt(0);\n\n      if (code === 92) {\n        return readUnicodeEscapeSequence();\n      }\n\n      if (code < 128) {\n        if (asciiIdentifierPartTable[code]) {\n          index += 1;\n          return chr;\n        }\n\n        return null;\n      }\n\n      if (isNonAsciiIdentifierPart(code)) {\n        index += 1;\n        return chr;\n      }\n\n      return null;\n    }.bind(this);\n\n    function removeEscapeSequences(id) {\n      return id.replace(/\\\\u([0-9a-fA-F]{4})/g, function(m0, codepoint) {\n        return String.fromCharCode(parseInt(codepoint, 16));\n      });\n    }\n\n    char = getIdentifierStart();\n    if (char === null) {\n      return null;\n    }\n\n    id = char;\n    for (;;) {\n      char = getIdentifierPart();\n\n      if (char === null) {\n        break;\n      }\n\n      id += char;\n    }\n\n    switch (id) {\n    case \"true\":\n    case \"false\":\n      type = Token.BooleanLiteral;\n      break;\n    case \"null\":\n      type = Token.NullLiteral;\n      break;\n    default:\n      type = Token.Identifier;\n    }\n\n    return {\n      type: type,\n      value: removeEscapeSequences(id),\n      text: id,\n      tokenLength: id.length\n    };\n  },\n  scanNumericLiteral: function() {\n    var index = 0;\n    var value = \"\";\n    var length = this.input.length;\n    var char = this.peek(index);\n    var bad;\n    var isAllowedDigit = isDecimalDigit;\n    var base = 10;\n    var isLegacy = false;\n\n    function isDecimalDigit(str) {\n      return (/^[0-9]$/).test(str);\n    }\n\n    function isOctalDigit(str) {\n      return (/^[0-7]$/).test(str);\n    }\n\n    function isBinaryDigit(str) {\n      return (/^[01]$/).test(str);\n    }\n\n    function isHexDigit(str) {\n      return (/^[0-9a-fA-F]$/).test(str);\n    }\n\n    function isIdentifierStart(ch) {\n      return (ch === \"$\") || (ch === \"_\") || (ch === \"\\\\\") ||\n        (ch >= \"a\" && ch <= \"z\") || (ch >= \"A\" && ch <= \"Z\");\n    }\n\n    if (char !== \".\" && !isDecimalDigit(char)) {\n      return null;\n    }\n\n    if (char !== \".\") {\n      value = this.peek(index);\n      index += 1;\n      char = this.peek(index);\n\n      if (value === \"0\") {\n        if (char === \"x\" || char === \"X\") {\n          isAllowedDigit = isHexDigit;\n          base = 16;\n\n          index += 1;\n          value += char;\n        }\n        if (char === \"o\" || char === \"O\") {\n          isAllowedDigit = isOctalDigit;\n          base = 8;\n\n          if (!state.inES6(true)) {\n            this.trigger(\"warning\", {\n              code: \"W119\",\n              line: this.line,\n              character: this.char,\n              data: [ \"Octal integer literal\", \"6\" ]\n            });\n          }\n\n          index += 1;\n          value += char;\n        }\n        if (char === \"b\" || char === \"B\") {\n          isAllowedDigit = isBinaryDigit;\n          base = 2;\n\n          if (!state.inES6(true)) {\n            this.trigger(\"warning\", {\n              code: \"W119\",\n              line: this.line,\n              character: this.char,\n              data: [ \"Binary integer literal\", \"6\" ]\n            });\n          }\n\n          index += 1;\n          value += char;\n        }\n        if (isOctalDigit(char)) {\n          isAllowedDigit = isOctalDigit;\n          base = 8;\n          isLegacy = true;\n          bad = false;\n\n          index += 1;\n          value += char;\n        }\n\n        if (!isOctalDigit(char) && isDecimalDigit(char)) {\n          index += 1;\n          value += char;\n        }\n      }\n\n      while (index < length) {\n        char = this.peek(index);\n\n        if (isLegacy && isDecimalDigit(char)) {\n          bad = true;\n        } else if (!isAllowedDigit(char)) {\n          break;\n        }\n        value += char;\n        index += 1;\n      }\n\n      if (isAllowedDigit !== isDecimalDigit) {\n        if (!isLegacy && value.length <= 2) { // 0x\n          return {\n            type: Token.NumericLiteral,\n            value: value,\n            isMalformed: true\n          };\n        }\n\n        if (index < length) {\n          char = this.peek(index);\n          if (isIdentifierStart(char)) {\n            return null;\n          }\n        }\n\n        return {\n          type: Token.NumericLiteral,\n          value: value,\n          base: base,\n          isLegacy: isLegacy,\n          isMalformed: false\n        };\n      }\n    }\n\n    if (char === \".\") {\n      value += char;\n      index += 1;\n\n      while (index < length) {\n        char = this.peek(index);\n        if (!isDecimalDigit(char)) {\n          break;\n        }\n        value += char;\n        index += 1;\n      }\n    }\n\n    if (char === \"e\" || char === \"E\") {\n      value += char;\n      index += 1;\n      char = this.peek(index);\n\n      if (char === \"+\" || char === \"-\") {\n        value += this.peek(index);\n        index += 1;\n      }\n\n      char = this.peek(index);\n      if (isDecimalDigit(char)) {\n        value += char;\n        index += 1;\n\n        while (index < length) {\n          char = this.peek(index);\n          if (!isDecimalDigit(char)) {\n            break;\n          }\n          value += char;\n          index += 1;\n        }\n      } else {\n        return null;\n      }\n    }\n\n    if (index < length) {\n      char = this.peek(index);\n      if (isIdentifierStart(char)) {\n        return null;\n      }\n    }\n\n    return {\n      type: Token.NumericLiteral,\n      value: value,\n      base: base,\n      isMalformed: !isFinite(value)\n    };\n  },\n  scanEscapeSequence: function(checks) {\n    var allowNewLine = false;\n    var jump = 1;\n    this.skip();\n    var char = this.peek();\n\n    switch (char) {\n    case \"'\":\n      this.triggerAsync(\"warning\", {\n        code: \"W114\",\n        line: this.line,\n        character: this.char,\n        data: [ \"\\\\'\" ]\n      }, checks, function() {return state.jsonMode; });\n      break;\n    case \"b\":\n      char = \"\\\\b\";\n      break;\n    case \"f\":\n      char = \"\\\\f\";\n      break;\n    case \"n\":\n      char = \"\\\\n\";\n      break;\n    case \"r\":\n      char = \"\\\\r\";\n      break;\n    case \"t\":\n      char = \"\\\\t\";\n      break;\n    case \"0\":\n      char = \"\\\\0\";\n      var n = parseInt(this.peek(1), 10);\n      this.triggerAsync(\"warning\", {\n        code: \"W115\",\n        line: this.line,\n        character: this.char\n      }, checks,\n      function() { return n >= 0 && n <= 7 && state.isStrict(); });\n      break;\n    case \"u\":\n      var hexCode = this.input.substr(1, 4);\n      var code = parseInt(hexCode, 16);\n      if (isNaN(code)) {\n        this.trigger(\"warning\", {\n          code: \"W052\",\n          line: this.line,\n          character: this.char,\n          data: [ \"u\" + hexCode ]\n        });\n      }\n      char = String.fromCharCode(code);\n      jump = 5;\n      break;\n    case \"v\":\n      this.triggerAsync(\"warning\", {\n        code: \"W114\",\n        line: this.line,\n        character: this.char,\n        data: [ \"\\\\v\" ]\n      }, checks, function() { return state.jsonMode; });\n\n      char = \"\\v\";\n      break;\n    case \"x\":\n      var  x = parseInt(this.input.substr(1, 2), 16);\n\n      this.triggerAsync(\"warning\", {\n        code: \"W114\",\n        line: this.line,\n        character: this.char,\n        data: [ \"\\\\x-\" ]\n      }, checks, function() { return state.jsonMode; });\n\n      char = String.fromCharCode(x);\n      jump = 3;\n      break;\n    case \"\\\\\":\n      char = \"\\\\\\\\\";\n      break;\n    case \"\\\"\":\n      char = \"\\\\\\\"\";\n      break;\n    case \"/\":\n      break;\n    case \"\":\n      allowNewLine = true;\n      char = \"\";\n      break;\n    }\n\n    return { char: char, jump: jump, allowNewLine: allowNewLine };\n  },\n  scanTemplateLiteral: function(checks) {\n    var tokenType;\n    var value = \"\";\n    var ch;\n    var startLine = this.line;\n    var startChar = this.char;\n    var depth = this.templateStarts.length;\n\n    if (!state.inES6(true)) {\n      return null;\n    } else if (this.peek() === \"`\") {\n      tokenType = Token.TemplateHead;\n      this.templateStarts.push({ line: this.line, char: this.char });\n      depth = this.templateStarts.length;\n      this.skip(1);\n      this.pushContext(Context.Template);\n    } else if (this.inContext(Context.Template) && this.peek() === \"}\") {\n      tokenType = Token.TemplateMiddle;\n    } else {\n      return null;\n    }\n\n    while (this.peek() !== \"`\") {\n      while ((ch = this.peek()) === \"\") {\n        value += \"\\n\";\n        if (!this.nextLine()) {\n          var startPos = this.templateStarts.pop();\n          this.trigger(\"error\", {\n            code: \"E052\",\n            line: startPos.line,\n            character: startPos.char\n          });\n          return {\n            type: tokenType,\n            value: value,\n            startLine: startLine,\n            startChar: startChar,\n            isUnclosed: true,\n            depth: depth,\n            context: this.popContext()\n          };\n        }\n      }\n\n      if (ch === '$' && this.peek(1) === '{') {\n        value += '${';\n        this.skip(2);\n        return {\n          type: tokenType,\n          value: value,\n          startLine: startLine,\n          startChar: startChar,\n          isUnclosed: false,\n          depth: depth,\n          context: this.currentContext()\n        };\n      } else if (ch === '\\\\') {\n        var escape = this.scanEscapeSequence(checks);\n        value += escape.char;\n        this.skip(escape.jump);\n      } else if (ch !== '`') {\n        value += ch;\n        this.skip(1);\n      }\n    }\n    tokenType = tokenType === Token.TemplateHead ? Token.NoSubstTemplate : Token.TemplateTail;\n    this.skip(1);\n    this.templateStarts.pop();\n\n    return {\n      type: tokenType,\n      value: value,\n      startLine: startLine,\n      startChar: startChar,\n      isUnclosed: false,\n      depth: depth,\n      context: this.popContext()\n    };\n  },\n  scanStringLiteral: function(checks) {\n    var quote = this.peek();\n    if (quote !== \"\\\"\" && quote !== \"'\") {\n      return null;\n    }\n    this.triggerAsync(\"warning\", {\n      code: \"W108\",\n      line: this.line,\n      character: this.char // +1?\n    }, checks, function() { return state.jsonMode && quote !== \"\\\"\"; });\n\n    var value = \"\";\n    var startLine = this.line;\n    var startChar = this.char;\n    var allowNewLine = false;\n\n    this.skip();\n\n    while (this.peek() !== quote) {\n      if (this.peek() === \"\") { // End Of Line\n\n        if (!allowNewLine) {\n          this.trigger(\"warning\", {\n            code: \"W112\",\n            line: this.line,\n            character: this.char\n          });\n        } else {\n          allowNewLine = false;\n\n          this.triggerAsync(\"warning\", {\n            code: \"W043\",\n            line: this.line,\n            character: this.char\n          }, checks, function() { return !state.option.multistr; });\n\n          this.triggerAsync(\"warning\", {\n            code: \"W042\",\n            line: this.line,\n            character: this.char\n          }, checks, function() { return state.jsonMode && state.option.multistr; });\n        }\n\n        if (!this.nextLine()) {\n          this.trigger(\"error\", {\n            code: \"E029\",\n            line: startLine,\n            character: startChar\n          });\n\n          return {\n            type: Token.StringLiteral,\n            value: value,\n            startLine: startLine,\n            startChar: startChar,\n            isUnclosed: true,\n            quote: quote\n          };\n        }\n\n      } else { // Any character other than End Of Line\n\n        allowNewLine = false;\n        var char = this.peek();\n        var jump = 1; // A length of a jump, after we're done\n\n        if (char < \" \") {\n          this.trigger(\"warning\", {\n            code: \"W113\",\n            line: this.line,\n            character: this.char,\n            data: [ \"<non-printable>\" ]\n          });\n        }\n        if (char === \"\\\\\") {\n          var parsed = this.scanEscapeSequence(checks);\n          char = parsed.char;\n          jump = parsed.jump;\n          allowNewLine = parsed.allowNewLine;\n        }\n\n        value += char;\n        this.skip(jump);\n      }\n    }\n\n    this.skip();\n    return {\n      type: Token.StringLiteral,\n      value: value,\n      startLine: startLine,\n      startChar: startChar,\n      isUnclosed: false,\n      quote: quote\n    };\n  },\n  scanRegExp: function() {\n    var index = 0;\n    var length = this.input.length;\n    var char = this.peek();\n    var value = char;\n    var body = \"\";\n    var flags = [];\n    var malformed = false;\n    var isCharSet = false;\n    var terminated;\n\n    var scanUnexpectedChars = function() {\n      if (char < \" \") {\n        malformed = true;\n        this.trigger(\"warning\", {\n          code: \"W048\",\n          line: this.line,\n          character: this.char\n        });\n      }\n      if (char === \"<\") {\n        malformed = true;\n        this.trigger(\"warning\", {\n          code: \"W049\",\n          line: this.line,\n          character: this.char,\n          data: [ char ]\n        });\n      }\n    }.bind(this);\n    if (!this.prereg || char !== \"/\") {\n      return null;\n    }\n\n    index += 1;\n    terminated = false;\n\n    while (index < length) {\n      char = this.peek(index);\n      value += char;\n      body += char;\n\n      if (isCharSet) {\n        if (char === \"]\") {\n          if (this.peek(index - 1) !== \"\\\\\" || this.peek(index - 2) === \"\\\\\") {\n            isCharSet = false;\n          }\n        }\n\n        if (char === \"\\\\\") {\n          index += 1;\n          char = this.peek(index);\n          body += char;\n          value += char;\n\n          scanUnexpectedChars();\n        }\n\n        index += 1;\n        continue;\n      }\n\n      if (char === \"\\\\\") {\n        index += 1;\n        char = this.peek(index);\n        body += char;\n        value += char;\n\n        scanUnexpectedChars();\n\n        if (char === \"/\") {\n          index += 1;\n          continue;\n        }\n\n        if (char === \"[\") {\n          index += 1;\n          continue;\n        }\n      }\n\n      if (char === \"[\") {\n        isCharSet = true;\n        index += 1;\n        continue;\n      }\n\n      if (char === \"/\") {\n        body = body.substr(0, body.length - 1);\n        terminated = true;\n        index += 1;\n        break;\n      }\n\n      index += 1;\n    }\n\n    if (!terminated) {\n      this.trigger(\"error\", {\n        code: \"E015\",\n        line: this.line,\n        character: this.from\n      });\n\n      return void this.trigger(\"fatal\", {\n        line: this.line,\n        from: this.from\n      });\n    }\n\n    while (index < length) {\n      char = this.peek(index);\n      if (!/[gim]/.test(char)) {\n        break;\n      }\n      flags.push(char);\n      value += char;\n      index += 1;\n    }\n\n    try {\n      new RegExp(body, flags.join(\"\"));\n    } catch (err) {\n      malformed = true;\n      this.trigger(\"error\", {\n        code: \"E016\",\n        line: this.line,\n        character: this.char,\n        data: [ err.message ] // Platform dependent!\n      });\n    }\n\n    return {\n      type: Token.RegExp,\n      value: value,\n      flags: flags,\n      isMalformed: malformed\n    };\n  },\n  scanNonBreakingSpaces: function() {\n    return state.option.nonbsp ?\n      this.input.search(/(\\u00A0)/) : -1;\n  },\n  scanUnsafeChars: function() {\n    return this.input.search(reg.unsafeChars);\n  },\n  next: function(checks) {\n    this.from = this.char;\n    var start;\n    if (/\\s/.test(this.peek())) {\n      start = this.char;\n\n      while (/\\s/.test(this.peek())) {\n        this.from += 1;\n        this.skip();\n      }\n    }\n\n    var match = this.scanComments() ||\n      this.scanStringLiteral(checks) ||\n      this.scanTemplateLiteral(checks);\n\n    if (match) {\n      return match;\n    }\n\n    match =\n      this.scanRegExp() ||\n      this.scanPunctuator() ||\n      this.scanKeyword() ||\n      this.scanIdentifier() ||\n      this.scanNumericLiteral();\n\n    if (match) {\n      this.skip(match.tokenLength || match.value.length);\n      return match;\n    }\n\n    return null;\n  },\n  nextLine: function() {\n    var char;\n\n    if (this.line >= this.getLines().length) {\n      return false;\n    }\n\n    this.input = this.getLines()[this.line];\n    this.line += 1;\n    this.char = 1;\n    this.from = 1;\n\n    var inputTrimmed = this.input.trim();\n\n    var startsWith = function() {\n      return _.some(arguments, function(prefix) {\n        return inputTrimmed.indexOf(prefix) === 0;\n      });\n    };\n\n    var endsWith = function() {\n      return _.some(arguments, function(suffix) {\n        return inputTrimmed.indexOf(suffix, inputTrimmed.length - suffix.length) !== -1;\n      });\n    };\n    if (this.ignoringLinterErrors === true) {\n      if (!startsWith(\"/*\", \"//\") && !(this.inComment && endsWith(\"*/\"))) {\n        this.input = \"\";\n      }\n    }\n\n    char = this.scanNonBreakingSpaces();\n    if (char >= 0) {\n      this.trigger(\"warning\", { code: \"W125\", line: this.line, character: char + 1 });\n    }\n\n    this.input = this.input.replace(/\\t/g, state.tab);\n    char = this.scanUnsafeChars();\n\n    if (char >= 0) {\n      this.trigger(\"warning\", { code: \"W100\", line: this.line, character: char });\n    }\n\n    if (!this.ignoringLinterErrors && state.option.maxlen &&\n      state.option.maxlen < this.input.length) {\n      var inComment = this.inComment ||\n        startsWith.call(inputTrimmed, \"//\") ||\n        startsWith.call(inputTrimmed, \"/*\");\n\n      var shouldTriggerError = !inComment || !reg.maxlenException.test(inputTrimmed);\n\n      if (shouldTriggerError) {\n        this.trigger(\"warning\", { code: \"W101\", line: this.line, character: this.input.length });\n      }\n    }\n\n    return true;\n  },\n  start: function() {\n    this.nextLine();\n  },\n  token: function() {\n    var checks = asyncTrigger();\n    var token;\n\n\n    function isReserved(token, isProperty) {\n      if (!token.reserved) {\n        return false;\n      }\n      var meta = token.meta;\n\n      if (meta && meta.isFutureReservedWord && state.inES5()) {\n        if (!meta.es5) {\n          return false;\n        }\n        if (meta.strictOnly) {\n          if (!state.option.strict && !state.isStrict()) {\n            return false;\n          }\n        }\n\n        if (isProperty) {\n          return false;\n        }\n      }\n\n      return true;\n    }\n    var create = function(type, value, isProperty, token) {\n      var obj;\n\n      if (type !== \"(endline)\" && type !== \"(end)\") {\n        this.prereg = false;\n      }\n\n      if (type === \"(punctuator)\") {\n        switch (value) {\n        case \".\":\n        case \")\":\n        case \"~\":\n        case \"#\":\n        case \"]\":\n        case \"++\":\n        case \"--\":\n          this.prereg = false;\n          break;\n        default:\n          this.prereg = true;\n        }\n\n        obj = Object.create(state.syntax[value] || state.syntax[\"(error)\"]);\n      }\n\n      if (type === \"(identifier)\") {\n        if (value === \"return\" || value === \"case\" || value === \"typeof\") {\n          this.prereg = true;\n        }\n\n        if (_.has(state.syntax, value)) {\n          obj = Object.create(state.syntax[value] || state.syntax[\"(error)\"]);\n          if (!isReserved(obj, isProperty && type === \"(identifier)\")) {\n            obj = null;\n          }\n        }\n      }\n\n      if (!obj) {\n        obj = Object.create(state.syntax[type]);\n      }\n\n      obj.identifier = (type === \"(identifier)\");\n      obj.type = obj.type || type;\n      obj.value = value;\n      obj.line = this.line;\n      obj.character = this.char;\n      obj.from = this.from;\n      if (obj.identifier && token) obj.raw_text = token.text || token.value;\n      if (token && token.startLine && token.startLine !== this.line) {\n        obj.startLine = token.startLine;\n      }\n      if (token && token.context) {\n        obj.context = token.context;\n      }\n      if (token && token.depth) {\n        obj.depth = token.depth;\n      }\n      if (token && token.isUnclosed) {\n        obj.isUnclosed = token.isUnclosed;\n      }\n\n      if (isProperty && obj.identifier) {\n        obj.isProperty = isProperty;\n      }\n\n      obj.check = checks.check;\n\n      return obj;\n    }.bind(this);\n\n    for (;;) {\n      if (!this.input.length) {\n        if (this.nextLine()) {\n          return create(\"(endline)\", \"\");\n        }\n\n        if (this.exhausted) {\n          return null;\n        }\n\n        this.exhausted = true;\n        return create(\"(end)\", \"\");\n      }\n\n      token = this.next(checks);\n\n      if (!token) {\n        if (this.input.length) {\n          this.trigger(\"error\", {\n            code: \"E024\",\n            line: this.line,\n            character: this.char,\n            data: [ this.peek() ]\n          });\n\n          this.input = \"\";\n        }\n\n        continue;\n      }\n\n      switch (token.type) {\n      case Token.StringLiteral:\n        this.triggerAsync(\"String\", {\n          line: this.line,\n          char: this.char,\n          from: this.from,\n          startLine: token.startLine,\n          startChar: token.startChar,\n          value: token.value,\n          quote: token.quote\n        }, checks, function() { return true; });\n\n        return create(\"(string)\", token.value, null, token);\n\n      case Token.TemplateHead:\n        this.trigger(\"TemplateHead\", {\n          line: this.line,\n          char: this.char,\n          from: this.from,\n          startLine: token.startLine,\n          startChar: token.startChar,\n          value: token.value\n        });\n        return create(\"(template)\", token.value, null, token);\n\n      case Token.TemplateMiddle:\n        this.trigger(\"TemplateMiddle\", {\n          line: this.line,\n          char: this.char,\n          from: this.from,\n          startLine: token.startLine,\n          startChar: token.startChar,\n          value: token.value\n        });\n        return create(\"(template middle)\", token.value, null, token);\n\n      case Token.TemplateTail:\n        this.trigger(\"TemplateTail\", {\n          line: this.line,\n          char: this.char,\n          from: this.from,\n          startLine: token.startLine,\n          startChar: token.startChar,\n          value: token.value\n        });\n        return create(\"(template tail)\", token.value, null, token);\n\n      case Token.NoSubstTemplate:\n        this.trigger(\"NoSubstTemplate\", {\n          line: this.line,\n          char: this.char,\n          from: this.from,\n          startLine: token.startLine,\n          startChar: token.startChar,\n          value: token.value\n        });\n        return create(\"(no subst template)\", token.value, null, token);\n\n      case Token.Identifier:\n        this.triggerAsync(\"Identifier\", {\n          line: this.line,\n          char: this.char,\n          from: this.form,\n          name: token.value,\n          raw_name: token.text,\n          isProperty: state.tokens.curr.id === \".\"\n        }, checks, function() { return true; });\n      case Token.Keyword:\n      case Token.NullLiteral:\n      case Token.BooleanLiteral:\n        return create(\"(identifier)\", token.value, state.tokens.curr.id === \".\", token);\n\n      case Token.NumericLiteral:\n        if (token.isMalformed) {\n          this.trigger(\"warning\", {\n            code: \"W045\",\n            line: this.line,\n            character: this.char,\n            data: [ token.value ]\n          });\n        }\n\n        this.triggerAsync(\"warning\", {\n          code: \"W114\",\n          line: this.line,\n          character: this.char,\n          data: [ \"0x-\" ]\n        }, checks, function() { return token.base === 16 && state.jsonMode; });\n\n        this.triggerAsync(\"warning\", {\n          code: \"W115\",\n          line: this.line,\n          character: this.char\n        }, checks, function() {\n          return state.isStrict() && token.base === 8 && token.isLegacy;\n        });\n\n        this.trigger(\"Number\", {\n          line: this.line,\n          char: this.char,\n          from: this.from,\n          value: token.value,\n          base: token.base,\n          isMalformed: token.malformed\n        });\n\n        return create(\"(number)\", token.value);\n\n      case Token.RegExp:\n        return create(\"(regexp)\", token.value);\n\n      case Token.Comment:\n        state.tokens.curr.comment = true;\n\n        if (token.isSpecial) {\n          return {\n            id: '(comment)',\n            value: token.value,\n            body: token.body,\n            type: token.commentType,\n            isSpecial: token.isSpecial,\n            line: this.line,\n            character: this.char,\n            from: this.from\n          };\n        }\n\n        break;\n\n      case \"\":\n        break;\n\n      default:\n        return create(\"(punctuator)\", token.value);\n      }\n    }\n  }\n};\n\nexports.Lexer = Lexer;\nexports.Context = Context;\n\n},{\"../data/ascii-identifier-data.js\":\"/node_modules/jshint/data/ascii-identifier-data.js\",\"../lodash\":\"/node_modules/jshint/lodash.js\",\"./reg.js\":\"/node_modules/jshint/src/reg.js\",\"./state.js\":\"/node_modules/jshint/src/state.js\",\"events\":\"/node_modules/browserify/node_modules/events/events.js\"}],\"/node_modules/jshint/src/messages.js\":[function(_dereq_,module,exports){\n\"use strict\";\n\nvar _ = _dereq_(\"../lodash\");\n\nvar errors = {\n  E001: \"Bad option: '{a}'.\",\n  E002: \"Bad option value.\",\n  E003: \"Expected a JSON value.\",\n  E004: \"Input is neither a string nor an array of strings.\",\n  E005: \"Input is empty.\",\n  E006: \"Unexpected early end of program.\",\n  E007: \"Missing \\\"use strict\\\" statement.\",\n  E008: \"Strict violation.\",\n  E009: \"Option 'validthis' can't be used in a global scope.\",\n  E010: \"'with' is not allowed in strict mode.\",\n  E011: \"'{a}' has already been declared.\",\n  E012: \"const '{a}' is initialized to 'undefined'.\",\n  E013: \"Attempting to override '{a}' which is a constant.\",\n  E014: \"A regular expression literal can be confused with '/='.\",\n  E015: \"Unclosed regular expression.\",\n  E016: \"Invalid regular expression.\",\n  E017: \"Unclosed comment.\",\n  E018: \"Unbegun comment.\",\n  E019: \"Unmatched '{a}'.\",\n  E020: \"Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.\",\n  E021: \"Expected '{a}' and instead saw '{b}'.\",\n  E022: \"Line breaking error '{a}'.\",\n  E023: \"Missing '{a}'.\",\n  E024: \"Unexpected '{a}'.\",\n  E025: \"Missing ':' on a case clause.\",\n  E026: \"Missing '}' to match '{' from line {a}.\",\n  E027: \"Missing ']' to match '[' from line {a}.\",\n  E028: \"Illegal comma.\",\n  E029: \"Unclosed string.\",\n  E030: \"Expected an identifier and instead saw '{a}'.\",\n  E031: \"Bad assignment.\", // FIXME: Rephrase\n  E032: \"Expected a small integer or 'false' and instead saw '{a}'.\",\n  E033: \"Expected an operator and instead saw '{a}'.\",\n  E034: \"get/set are ES5 features.\",\n  E035: \"Missing property name.\",\n  E036: \"Expected to see a statement and instead saw a block.\",\n  E037: null,\n  E038: null,\n  E039: \"Function declarations are not invocable. Wrap the whole function invocation in parens.\",\n  E040: \"Each value should have its own case label.\",\n  E041: \"Unrecoverable syntax error.\",\n  E042: \"Stopping.\",\n  E043: \"Too many errors.\",\n  E044: null,\n  E045: \"Invalid for each loop.\",\n  E046: \"A yield statement shall be within a generator function (with syntax: `function*`)\",\n  E047: null,\n  E048: \"{a} declaration not directly within block.\",\n  E049: \"A {a} cannot be named '{b}'.\",\n  E050: \"Mozilla requires the yield expression to be parenthesized here.\",\n  E051: null,\n  E052: \"Unclosed template literal.\",\n  E053: \"Export declaration must be in global scope.\",\n  E054: \"Class properties must be methods. Expected '(' but instead saw '{a}'.\",\n  E055: \"The '{a}' option cannot be set after any executable code.\",\n  E056: \"'{a}' was used before it was declared, which is illegal for '{b}' variables.\",\n  E057: \"Invalid meta property: '{a}.{b}'.\",\n  E058: \"Missing semicolon.\"\n};\n\nvar warnings = {\n  W001: \"'hasOwnProperty' is a really bad name.\",\n  W002: \"Value of '{a}' may be overwritten in IE 8 and earlier.\",\n  W003: \"'{a}' was used before it was defined.\",\n  W004: \"'{a}' is already defined.\",\n  W005: \"A dot following a number can be confused with a decimal point.\",\n  W006: \"Confusing minuses.\",\n  W007: \"Confusing plusses.\",\n  W008: \"A leading decimal point can be confused with a dot: '{a}'.\",\n  W009: \"The array literal notation [] is preferable.\",\n  W010: \"The object literal notation {} is preferable.\",\n  W011: null,\n  W012: null,\n  W013: null,\n  W014: \"Bad line breaking before '{a}'.\",\n  W015: null,\n  W016: \"Unexpected use of '{a}'.\",\n  W017: \"Bad operand.\",\n  W018: \"Confusing use of '{a}'.\",\n  W019: \"Use the isNaN function to compare with NaN.\",\n  W020: \"Read only.\",\n  W021: \"Reassignment of '{a}', which is is a {b}. \" +\n    \"Use 'var' or 'let' to declare bindings that may change.\",\n  W022: \"Do not assign to the exception parameter.\",\n  W023: \"Expected an identifier in an assignment and instead saw a function invocation.\",\n  W024: \"Expected an identifier and instead saw '{a}' (a reserved word).\",\n  W025: \"Missing name in function declaration.\",\n  W026: \"Inner functions should be listed at the top of the outer function.\",\n  W027: \"Unreachable '{a}' after '{b}'.\",\n  W028: \"Label '{a}' on {b} statement.\",\n  W030: \"Expected an assignment or function call and instead saw an expression.\",\n  W031: \"Do not use 'new' for side effects.\",\n  W032: \"Unnecessary semicolon.\",\n  W033: \"Missing semicolon.\",\n  W034: \"Unnecessary directive \\\"{a}\\\".\",\n  W035: \"Empty block.\",\n  W036: \"Unexpected /*member '{a}'.\",\n  W037: \"'{a}' is a statement label.\",\n  W038: \"'{a}' used out of scope.\",\n  W039: \"'{a}' is not allowed.\",\n  W040: \"Possible strict violation.\",\n  W041: \"Use '{a}' to compare with '{b}'.\",\n  W042: \"Avoid EOL escaping.\",\n  W043: \"Bad escaping of EOL. Use option multistr if needed.\",\n  W044: \"Bad or unnecessary escaping.\", /* TODO(caitp): remove W044 */\n  W045: \"Bad number '{a}'.\",\n  W046: \"Don't use extra leading zeros '{a}'.\",\n  W047: \"A trailing decimal point can be confused with a dot: '{a}'.\",\n  W048: \"Unexpected control character in regular expression.\",\n  W049: \"Unexpected escaped character '{a}' in regular expression.\",\n  W050: \"JavaScript URL.\",\n  W051: \"Variables should not be deleted.\",\n  W052: \"Unexpected '{a}'.\",\n  W053: \"Do not use {a} as a constructor.\",\n  W054: \"The Function constructor is a form of eval.\",\n  W055: \"A constructor name should start with an uppercase letter.\",\n  W056: \"Bad constructor.\",\n  W057: \"Weird construction. Is 'new' necessary?\",\n  W058: \"Missing '()' invoking a constructor.\",\n  W059: \"Avoid arguments.{a}.\",\n  W060: \"document.write can be a form of eval.\",\n  W061: \"eval can be harmful.\",\n  W062: \"Wrap an immediate function invocation in parens \" +\n    \"to assist the reader in understanding that the expression \" +\n    \"is the result of a function, and not the function itself.\",\n  W063: \"Math is not a function.\",\n  W064: \"Missing 'new' prefix when invoking a constructor.\",\n  W065: \"Missing radix parameter.\",\n  W066: \"Implied eval. Consider passing a function instead of a string.\",\n  W067: \"Bad invocation.\",\n  W068: \"Wrapping non-IIFE function literals in parens is unnecessary.\",\n  W069: \"['{a}'] is better written in dot notation.\",\n  W070: \"Extra comma. (it breaks older versions of IE)\",\n  W071: \"This function has too many statements. ({a})\",\n  W072: \"This function has too many parameters. ({a})\",\n  W073: \"Blocks are nested too deeply. ({a})\",\n  W074: \"This function's cyclomatic complexity is too high. ({a})\",\n  W075: \"Duplicate {a} '{b}'.\",\n  W076: \"Unexpected parameter '{a}' in get {b} function.\",\n  W077: \"Expected a single parameter in set {a} function.\",\n  W078: \"Setter is defined without getter.\",\n  W079: \"Redefinition of '{a}'.\",\n  W080: \"It's not necessary to initialize '{a}' to 'undefined'.\",\n  W081: null,\n  W082: \"Function declarations should not be placed in blocks. \" +\n    \"Use a function expression or move the statement to the top of \" +\n    \"the outer function.\",\n  W083: \"Don't make functions within a loop.\",\n  W084: \"Assignment in conditional expression\",\n  W085: \"Don't use 'with'.\",\n  W086: \"Expected a 'break' statement before '{a}'.\",\n  W087: \"Forgotten 'debugger' statement?\",\n  W088: \"Creating global 'for' variable. Should be 'for (var {a} ...'.\",\n  W089: \"The body of a for in should be wrapped in an if statement to filter \" +\n    \"unwanted properties from the prototype.\",\n  W090: \"'{a}' is not a statement label.\",\n  W091: null,\n  W093: \"Did you mean to return a conditional instead of an assignment?\",\n  W094: \"Unexpected comma.\",\n  W095: \"Expected a string and instead saw {a}.\",\n  W096: \"The '{a}' key may produce unexpected results.\",\n  W097: \"Use the function form of \\\"use strict\\\".\",\n  W098: \"'{a}' is defined but never used.\",\n  W099: null,\n  W100: \"This character may get silently deleted by one or more browsers.\",\n  W101: \"Line is too long.\",\n  W102: null,\n  W103: \"The '{a}' property is deprecated.\",\n  W104: \"'{a}' is available in ES{b} (use 'esversion: {b}') or Mozilla JS extensions (use moz).\",\n  W105: \"Unexpected {a} in '{b}'.\",\n  W106: \"Identifier '{a}' is not in camel case.\",\n  W107: \"Script URL.\",\n  W108: \"Strings must use doublequote.\",\n  W109: \"Strings must use singlequote.\",\n  W110: \"Mixed double and single quotes.\",\n  W112: \"Unclosed string.\",\n  W113: \"Control character in string: {a}.\",\n  W114: \"Avoid {a}.\",\n  W115: \"Octal literals are not allowed in strict mode.\",\n  W116: \"Expected '{a}' and instead saw '{b}'.\",\n  W117: \"'{a}' is not defined.\",\n  W118: \"'{a}' is only available in Mozilla JavaScript extensions (use moz option).\",\n  W119: \"'{a}' is only available in ES{b} (use 'esversion: {b}').\",\n  W120: \"You might be leaking a variable ({a}) here.\",\n  W121: \"Extending prototype of native object: '{a}'.\",\n  W122: \"Invalid typeof value '{a}'\",\n  W123: \"'{a}' is already defined in outer scope.\",\n  W124: \"A generator function shall contain a yield statement.\",\n  W125: \"This line contains non-breaking spaces: http://jshint.com/doc/options/#nonbsp\",\n  W126: \"Unnecessary grouping operator.\",\n  W127: \"Unexpected use of a comma operator.\",\n  W128: \"Empty array elements require elision=true.\",\n  W129: \"'{a}' is defined in a future version of JavaScript. Use a \" +\n    \"different variable name to avoid migration issues.\",\n  W130: \"Invalid element after rest element.\",\n  W131: \"Invalid parameter after rest parameter.\",\n  W132: \"`var` declarations are forbidden. Use `let` or `const` instead.\",\n  W133: \"Invalid for-{a} loop left-hand-side: {b}.\",\n  W134: \"The '{a}' option is only available when linting ECMAScript {b} code.\",\n  W135: \"{a} may not be supported by non-browser environments.\",\n  W136: \"'{a}' must be in function scope.\",\n  W137: \"Empty destructuring.\",\n  W138: \"Regular parameters should not come after default parameters.\"\n};\n\nvar info = {\n  I001: \"Comma warnings can be turned off with 'laxcomma'.\",\n  I002: null,\n  I003: \"ES5 option is now set per default\"\n};\n\nexports.errors = {};\nexports.warnings = {};\nexports.info = {};\n\n_.each(errors, function(desc, code) {\n  exports.errors[code] = { code: code, desc: desc };\n});\n\n_.each(warnings, function(desc, code) {\n  exports.warnings[code] = { code: code, desc: desc };\n});\n\n_.each(info, function(desc, code) {\n  exports.info[code] = { code: code, desc: desc };\n});\n\n},{\"../lodash\":\"/node_modules/jshint/lodash.js\"}],\"/node_modules/jshint/src/name-stack.js\":[function(_dereq_,module,exports){\n\"use strict\";\n\nfunction NameStack() {\n  this._stack = [];\n}\n\nObject.defineProperty(NameStack.prototype, \"length\", {\n  get: function() {\n    return this._stack.length;\n  }\n});\nNameStack.prototype.push = function() {\n  this._stack.push(null);\n};\nNameStack.prototype.pop = function() {\n  this._stack.pop();\n};\nNameStack.prototype.set = function(token) {\n  this._stack[this.length - 1] = token;\n};\nNameStack.prototype.infer = function() {\n  var nameToken = this._stack[this.length - 1];\n  var prefix = \"\";\n  var type;\n  if (!nameToken || nameToken.type === \"class\") {\n    nameToken = this._stack[this.length - 2];\n  }\n\n  if (!nameToken) {\n    return \"(empty)\";\n  }\n\n  type = nameToken.type;\n\n  if (type !== \"(string)\" && type !== \"(number)\" && type !== \"(identifier)\" && type !== \"default\") {\n    return \"(expression)\";\n  }\n\n  if (nameToken.accessorType) {\n    prefix = nameToken.accessorType + \" \";\n  }\n\n  return prefix + nameToken.value;\n};\n\nmodule.exports = NameStack;\n\n},{}],\"/node_modules/jshint/src/options.js\":[function(_dereq_,module,exports){\n\"use strict\";\nexports.bool = {\n  enforcing: {\n    bitwise     : true,\n    freeze      : true,\n    camelcase   : true,\n    curly       : true,\n    eqeqeq      : true,\n    futurehostile: true,\n    notypeof    : true,\n    es3         : true,\n    es5         : true,\n    forin       : true,\n    funcscope   : true,\n    immed       : true,\n    iterator    : true,\n    newcap      : true,\n    noarg       : true,\n    nocomma     : true,\n    noempty     : true,\n    nonbsp      : true,\n    nonew       : true,\n    undef       : true,\n    singleGroups: false,\n    varstmt: false,\n    enforceall : false\n  },\n  relaxing: {\n    asi         : true,\n    multistr    : true,\n    debug       : true,\n    boss        : true,\n    evil        : true,\n    globalstrict: true,\n    plusplus    : true,\n    proto       : true,\n    scripturl   : true,\n    sub         : true,\n    supernew    : true,\n    laxbreak    : true,\n    laxcomma    : true,\n    validthis   : true,\n    withstmt    : true,\n    moz         : true,\n    noyield     : true,\n    eqnull      : true,\n    lastsemic   : true,\n    loopfunc    : true,\n    expr        : true,\n    esnext      : true,\n    elision     : true,\n  },\n  environments: {\n    mootools    : true,\n    couch       : true,\n    jasmine     : true,\n    jquery      : true,\n    node        : true,\n    qunit       : true,\n    rhino       : true,\n    shelljs     : true,\n    prototypejs : true,\n    yui         : true,\n    mocha       : true,\n    module      : true,\n    wsh         : true,\n    worker      : true,\n    nonstandard : true,\n    browser     : true,\n    browserify  : true,\n    devel       : true,\n    dojo        : true,\n    typed       : true,\n    phantom     : true\n  },\n  obsolete: {\n    onecase     : true, // if one case switch statements should be allowed\n    regexp      : true, // if the . should not be allowed in regexp literals\n    regexdash   : true  // if unescaped first/last dash (-) inside brackets\n  }\n};\nexports.val = {\n  maxlen       : false,\n  indent       : false,\n  maxerr       : false,\n  predef       : false,\n  globals      : false,\n  quotmark     : false,\n\n  scope        : false,\n  maxstatements: false,\n  maxdepth     : false,\n  maxparams    : false,\n  maxcomplexity: false,\n  shadow       : false,\n  strict      : true,\n  unused       : true,\n  latedef      : false,\n\n  ignore       : false, // start/end ignoring lines of code, bypassing the lexer\n\n  ignoreDelimiters: false, // array of start/end delimiters used to ignore\n  esversion: 5\n};\nexports.inverted = {\n  bitwise : true,\n  forin   : true,\n  newcap  : true,\n  plusplus: true,\n  regexp  : true,\n  undef   : true,\n  eqeqeq  : true,\n  strict  : true\n};\n\nexports.validNames = Object.keys(exports.val)\n  .concat(Object.keys(exports.bool.relaxing))\n  .concat(Object.keys(exports.bool.enforcing))\n  .concat(Object.keys(exports.bool.obsolete))\n  .concat(Object.keys(exports.bool.environments));\nexports.renamed = {\n  eqeq   : \"eqeqeq\",\n  windows: \"wsh\",\n  sloppy : \"strict\"\n};\n\nexports.removed = {\n  nomen: true,\n  onevar: true,\n  passfail: true,\n  white: true,\n  gcl: true,\n  smarttabs: true,\n  trailing: true\n};\nexports.noenforceall = {\n  varstmt: true,\n  strict: true\n};\n\n},{}],\"/node_modules/jshint/src/reg.js\":[function(_dereq_,module,exports){\n\n\"use strict\";\nexports.unsafeString =\n  /@cc|<\\/?|script|\\]\\s*\\]|<\\s*!|&lt/i;\nexports.unsafeChars =\n  /[\\u0000-\\u001f\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/;\nexports.needEsc =\n  /[\\u0000-\\u001f&<\"\\/\\\\\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/;\n\nexports.needEscGlobal =\n  /[\\u0000-\\u001f&<\"\\/\\\\\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g;\nexports.starSlash = /\\*\\//;\nexports.identifier = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;\nexports.javascriptURL = /^(?:javascript|jscript|ecmascript|vbscript|livescript)\\s*:/i;\nexports.fallsThrough = /^\\s*falls?\\sthrough\\s*$/;\nexports.maxlenException = /^(?:(?:\\/\\/|\\/\\*|\\*) ?)?[^ ]+$/;\n\n},{}],\"/node_modules/jshint/src/scope-manager.js\":[function(_dereq_,module,exports){\n\"use strict\";\n\nvar _      = _dereq_(\"../lodash\");\nvar events = _dereq_(\"events\");\nvar marker = {};\nvar scopeManager = function(state, predefined, exported, declared) {\n\n  var _current;\n  var _scopeStack = [];\n\n  function _newScope(type) {\n    _current = {\n      \"(labels)\": Object.create(null),\n      \"(usages)\": Object.create(null),\n      \"(breakLabels)\": Object.create(null),\n      \"(parent)\": _current,\n      \"(type)\": type,\n      \"(params)\": (type === \"functionparams\" || type === \"catchparams\") ? [] : null\n    };\n    _scopeStack.push(_current);\n  }\n\n  _newScope(\"global\");\n  _current[\"(predefined)\"] = predefined;\n\n  var _currentFunctBody = _current; // this is the block after the params = function\n\n  var usedPredefinedAndGlobals = Object.create(null);\n  var impliedGlobals = Object.create(null);\n  var unuseds = [];\n  var emitter = new events.EventEmitter();\n\n  function warning(code, token) {\n    emitter.emit(\"warning\", {\n      code: code,\n      token: token,\n      data: _.slice(arguments, 2)\n    });\n  }\n\n  function error(code, token) {\n    emitter.emit(\"warning\", {\n      code: code,\n      token: token,\n      data: _.slice(arguments, 2)\n    });\n  }\n\n  function _setupUsages(labelName) {\n    if (!_current[\"(usages)\"][labelName]) {\n      _current[\"(usages)\"][labelName] = {\n        \"(modified)\": [],\n        \"(reassigned)\": [],\n        \"(tokens)\": []\n      };\n    }\n  }\n\n  var _getUnusedOption = function(unused_opt) {\n    if (unused_opt === undefined) {\n      unused_opt = state.option.unused;\n    }\n\n    if (unused_opt === true) {\n      unused_opt = \"last-param\";\n    }\n\n    return unused_opt;\n  };\n\n  var _warnUnused = function(name, tkn, type, unused_opt) {\n    var line = tkn.line;\n    var chr  = tkn.from;\n    var raw_name = tkn.raw_text || name;\n\n    unused_opt = _getUnusedOption(unused_opt);\n\n    var warnable_types = {\n      \"vars\": [\"var\"],\n      \"last-param\": [\"var\", \"param\"],\n      \"strict\": [\"var\", \"param\", \"last-param\"]\n    };\n\n    if (unused_opt) {\n      if (warnable_types[unused_opt] && warnable_types[unused_opt].indexOf(type) !== -1) {\n        warning(\"W098\", { line: line, from: chr }, raw_name);\n      }\n    }\n    if (unused_opt || type === \"var\") {\n      unuseds.push({\n        name: name,\n        line: line,\n        character: chr\n      });\n    }\n  };\n  function _checkForUnused() {\n    if (_current[\"(type)\"] === \"functionparams\") {\n      _checkParams();\n      return;\n    }\n    var curentLabels = _current[\"(labels)\"];\n    for (var labelName in curentLabels) {\n      if (curentLabels[labelName]) {\n        if (curentLabels[labelName][\"(type)\"] !== \"exception\" &&\n          curentLabels[labelName][\"(unused)\"]) {\n          _warnUnused(labelName, curentLabels[labelName][\"(token)\"], \"var\");\n        }\n      }\n    }\n  }\n  function _checkParams() {\n    var params = _current[\"(params)\"];\n\n    if (!params) {\n      return;\n    }\n\n    var param = params.pop();\n    var unused_opt;\n\n    while (param) {\n      var label = _current[\"(labels)\"][param];\n\n      unused_opt = _getUnusedOption(state.funct[\"(unusedOption)\"]);\n      if (param === \"undefined\")\n        return;\n\n      if (label[\"(unused)\"]) {\n        _warnUnused(param, label[\"(token)\"], \"param\", state.funct[\"(unusedOption)\"]);\n      } else if (unused_opt === \"last-param\") {\n        return;\n      }\n\n      param = params.pop();\n    }\n  }\n  function _getLabel(labelName) {\n    for (var i = _scopeStack.length - 1 ; i >= 0; --i) {\n      var scopeLabels = _scopeStack[i][\"(labels)\"];\n      if (scopeLabels[labelName]) {\n        return scopeLabels;\n      }\n    }\n  }\n\n  function usedSoFarInCurrentFunction(labelName) {\n    for (var i = _scopeStack.length - 1; i >= 0; i--) {\n      var current = _scopeStack[i];\n      if (current[\"(usages)\"][labelName]) {\n        return current[\"(usages)\"][labelName];\n      }\n      if (current === _currentFunctBody) {\n        break;\n      }\n    }\n    return false;\n  }\n\n  function _checkOuterShadow(labelName, token) {\n    if (state.option.shadow !== \"outer\") {\n      return;\n    }\n\n    var isGlobal = _currentFunctBody[\"(type)\"] === \"global\",\n      isNewFunction = _current[\"(type)\"] === \"functionparams\";\n\n    var outsideCurrentFunction = !isGlobal;\n    for (var i = 0; i < _scopeStack.length; i++) {\n      var stackItem = _scopeStack[i];\n\n      if (!isNewFunction && _scopeStack[i + 1] === _currentFunctBody) {\n        outsideCurrentFunction = false;\n      }\n      if (outsideCurrentFunction && stackItem[\"(labels)\"][labelName]) {\n        warning(\"W123\", token, labelName);\n      }\n      if (stackItem[\"(breakLabels)\"][labelName]) {\n        warning(\"W123\", token, labelName);\n      }\n    }\n  }\n\n  function _latedefWarning(type, labelName, token) {\n    if (state.option.latedef) {\n      if ((state.option.latedef === true && type === \"function\") ||\n        type !== \"function\") {\n        warning(\"W003\", token, labelName);\n      }\n    }\n  }\n\n  var scopeManagerInst = {\n\n    on: function(names, listener) {\n      names.split(\" \").forEach(function(name) {\n        emitter.on(name, listener);\n      });\n    },\n\n    isPredefined: function(labelName) {\n      return !this.has(labelName) && _.has(_scopeStack[0][\"(predefined)\"], labelName);\n    },\n    stack: function(type) {\n      var previousScope = _current;\n      _newScope(type);\n\n      if (!type && previousScope[\"(type)\"] === \"functionparams\") {\n\n        _current[\"(isFuncBody)\"] = true;\n        _current[\"(context)\"] = _currentFunctBody;\n        _currentFunctBody = _current;\n      }\n    },\n\n    unstack: function() {\n      var subScope = _scopeStack.length > 1 ? _scopeStack[_scopeStack.length - 2] : null;\n      var isUnstackingFunctionBody = _current === _currentFunctBody,\n        isUnstackingFunctionParams = _current[\"(type)\"] === \"functionparams\",\n        isUnstackingFunctionOuter = _current[\"(type)\"] === \"functionouter\";\n\n      var i, j;\n      var currentUsages = _current[\"(usages)\"];\n      var currentLabels = _current[\"(labels)\"];\n      var usedLabelNameList = Object.keys(currentUsages);\n\n      if (currentUsages.__proto__ && usedLabelNameList.indexOf(\"__proto__\") === -1) {\n        usedLabelNameList.push(\"__proto__\");\n      }\n\n      for (i = 0; i < usedLabelNameList.length; i++) {\n        var usedLabelName = usedLabelNameList[i];\n\n        var usage = currentUsages[usedLabelName];\n        var usedLabel = currentLabels[usedLabelName];\n        if (usedLabel) {\n          var usedLabelType = usedLabel[\"(type)\"];\n\n          if (usedLabel[\"(useOutsideOfScope)\"] && !state.option.funcscope) {\n            var usedTokens = usage[\"(tokens)\"];\n            if (usedTokens) {\n              for (j = 0; j < usedTokens.length; j++) {\n                if (usedLabel[\"(function)\"] === usedTokens[j][\"(function)\"]) {\n                  error(\"W038\", usedTokens[j], usedLabelName);\n                }\n              }\n            }\n          }\n          _current[\"(labels)\"][usedLabelName][\"(unused)\"] = false;\n          if (usedLabelType === \"const\" && usage[\"(modified)\"]) {\n            for (j = 0; j < usage[\"(modified)\"].length; j++) {\n              error(\"E013\", usage[\"(modified)\"][j], usedLabelName);\n            }\n          }\n          if ((usedLabelType === \"function\" || usedLabelType === \"class\") &&\n              usage[\"(reassigned)\"]) {\n            for (j = 0; j < usage[\"(reassigned)\"].length; j++) {\n              error(\"W021\", usage[\"(reassigned)\"][j], usedLabelName, usedLabelType);\n            }\n          }\n          continue;\n        }\n\n        if (isUnstackingFunctionOuter) {\n          state.funct[\"(isCapturing)\"] = true;\n        }\n\n        if (subScope) {\n          if (!subScope[\"(usages)\"][usedLabelName]) {\n            subScope[\"(usages)\"][usedLabelName] = usage;\n            if (isUnstackingFunctionBody) {\n              subScope[\"(usages)\"][usedLabelName][\"(onlyUsedSubFunction)\"] = true;\n            }\n          } else {\n            var subScopeUsage = subScope[\"(usages)\"][usedLabelName];\n            subScopeUsage[\"(modified)\"] = subScopeUsage[\"(modified)\"].concat(usage[\"(modified)\"]);\n            subScopeUsage[\"(tokens)\"] = subScopeUsage[\"(tokens)\"].concat(usage[\"(tokens)\"]);\n            subScopeUsage[\"(reassigned)\"] =\n              subScopeUsage[\"(reassigned)\"].concat(usage[\"(reassigned)\"]);\n            subScopeUsage[\"(onlyUsedSubFunction)\"] = false;\n          }\n        } else {\n          if (typeof _current[\"(predefined)\"][usedLabelName] === \"boolean\") {\n            delete declared[usedLabelName];\n            usedPredefinedAndGlobals[usedLabelName] = marker;\n            if (_current[\"(predefined)\"][usedLabelName] === false && usage[\"(reassigned)\"]) {\n              for (j = 0; j < usage[\"(reassigned)\"].length; j++) {\n                warning(\"W020\", usage[\"(reassigned)\"][j]);\n              }\n            }\n          }\n          else {\n            if (usage[\"(tokens)\"]) {\n              for (j = 0; j < usage[\"(tokens)\"].length; j++) {\n                var undefinedToken = usage[\"(tokens)\"][j];\n                if (!undefinedToken.forgiveUndef) {\n                  if (state.option.undef && !undefinedToken.ignoreUndef) {\n                    warning(\"W117\", undefinedToken, usedLabelName);\n                  }\n                  if (impliedGlobals[usedLabelName]) {\n                    impliedGlobals[usedLabelName].line.push(undefinedToken.line);\n                  } else {\n                    impliedGlobals[usedLabelName] = {\n                      name: usedLabelName,\n                      line: [undefinedToken.line]\n                    };\n                  }\n                }\n              }\n            }\n          }\n        }\n      }\n      if (!subScope) {\n        Object.keys(declared)\n          .forEach(function(labelNotUsed) {\n            _warnUnused(labelNotUsed, declared[labelNotUsed], \"var\");\n          });\n      }\n      if (subScope && !isUnstackingFunctionBody &&\n        !isUnstackingFunctionParams && !isUnstackingFunctionOuter) {\n        var labelNames = Object.keys(currentLabels);\n        for (i = 0; i < labelNames.length; i++) {\n\n          var defLabelName = labelNames[i];\n          if (!currentLabels[defLabelName][\"(blockscoped)\"] &&\n            currentLabels[defLabelName][\"(type)\"] !== \"exception\" &&\n            !this.funct.has(defLabelName, { excludeCurrent: true })) {\n            subScope[\"(labels)\"][defLabelName] = currentLabels[defLabelName];\n            if (_currentFunctBody[\"(type)\"] !== \"global\") {\n              subScope[\"(labels)\"][defLabelName][\"(useOutsideOfScope)\"] = true;\n            }\n            delete currentLabels[defLabelName];\n          }\n        }\n      }\n\n      _checkForUnused();\n\n      _scopeStack.pop();\n      if (isUnstackingFunctionBody) {\n        _currentFunctBody = _scopeStack[_.findLastIndex(_scopeStack, function(scope) {\n          return scope[\"(isFuncBody)\"] || scope[\"(type)\"] === \"global\";\n        })];\n      }\n\n      _current = subScope;\n    },\n    addParam: function(labelName, token, type) {\n      type = type || \"param\";\n\n      if (type === \"exception\") {\n        var previouslyDefinedLabelType = this.funct.labeltype(labelName);\n        if (previouslyDefinedLabelType && previouslyDefinedLabelType !== \"exception\") {\n          if (!state.option.node) {\n            warning(\"W002\", state.tokens.next, labelName);\n          }\n        }\n      }\n      if (_.has(_current[\"(labels)\"], labelName)) {\n        _current[\"(labels)\"][labelName].duplicated = true;\n      } else {\n        _checkOuterShadow(labelName, token, type);\n\n        _current[\"(labels)\"][labelName] = {\n          \"(type)\" : type,\n          \"(token)\": token,\n          \"(unused)\": true };\n\n        _current[\"(params)\"].push(labelName);\n      }\n\n      if (_.has(_current[\"(usages)\"], labelName)) {\n        var usage = _current[\"(usages)\"][labelName];\n        if (usage[\"(onlyUsedSubFunction)\"]) {\n          _latedefWarning(type, labelName, token);\n        } else {\n          warning(\"E056\", token, labelName, type);\n        }\n      }\n    },\n\n    validateParams: function() {\n      if (_currentFunctBody[\"(type)\"] === \"global\") {\n        return;\n      }\n\n      var isStrict = state.isStrict();\n      var currentFunctParamScope = _currentFunctBody[\"(parent)\"];\n\n      if (!currentFunctParamScope[\"(params)\"]) {\n        return;\n      }\n\n      currentFunctParamScope[\"(params)\"].forEach(function(labelName) {\n        var label = currentFunctParamScope[\"(labels)\"][labelName];\n\n        if (label && label.duplicated) {\n          if (isStrict) {\n            warning(\"E011\", label[\"(token)\"], labelName);\n          } else if (state.option.shadow !== true) {\n            warning(\"W004\", label[\"(token)\"], labelName);\n          }\n        }\n      });\n    },\n\n    getUsedOrDefinedGlobals: function() {\n      var list = Object.keys(usedPredefinedAndGlobals);\n      if (usedPredefinedAndGlobals.__proto__ === marker &&\n        list.indexOf(\"__proto__\") === -1) {\n        list.push(\"__proto__\");\n      }\n\n      return list;\n    },\n    getImpliedGlobals: function() {\n      var values = _.values(impliedGlobals);\n      var hasProto = false;\n      if (impliedGlobals.__proto__) {\n        hasProto = values.some(function(value) {\n          return value.name === \"__proto__\";\n        });\n\n        if (!hasProto) {\n          values.push(impliedGlobals.__proto__);\n        }\n      }\n\n      return values;\n    },\n    getUnuseds: function() {\n      return unuseds;\n    },\n\n    has: function(labelName) {\n      return Boolean(_getLabel(labelName));\n    },\n\n    labeltype: function(labelName) {\n      var scopeLabels = _getLabel(labelName);\n      if (scopeLabels) {\n        return scopeLabels[labelName][\"(type)\"];\n      }\n      return null;\n    },\n    addExported: function(labelName) {\n      var globalLabels = _scopeStack[0][\"(labels)\"];\n      if (_.has(declared, labelName)) {\n        delete declared[labelName];\n      } else if (_.has(globalLabels, labelName)) {\n        globalLabels[labelName][\"(unused)\"] = false;\n      } else {\n        for (var i = 1; i < _scopeStack.length; i++) {\n          var scope = _scopeStack[i];\n          if (!scope[\"(type)\"]) {\n            if (_.has(scope[\"(labels)\"], labelName) &&\n                !scope[\"(labels)\"][labelName][\"(blockscoped)\"]) {\n              scope[\"(labels)\"][labelName][\"(unused)\"] = false;\n              return;\n            }\n          } else {\n            break;\n          }\n        }\n        exported[labelName] = true;\n      }\n    },\n    setExported: function(labelName, token) {\n      this.block.use(labelName, token);\n    },\n    addlabel: function(labelName, opts) {\n\n      var type  = opts.type;\n      var token = opts.token;\n      var isblockscoped = type === \"let\" || type === \"const\" || type === \"class\";\n      var isexported    = (isblockscoped ? _current : _currentFunctBody)[\"(type)\"] === \"global\" &&\n                          _.has(exported, labelName);\n      _checkOuterShadow(labelName, token, type);\n      if (isblockscoped) {\n\n        var declaredInCurrentScope = _current[\"(labels)\"][labelName];\n        if (!declaredInCurrentScope && _current === _currentFunctBody &&\n          _current[\"(type)\"] !== \"global\") {\n          declaredInCurrentScope = !!_currentFunctBody[\"(parent)\"][\"(labels)\"][labelName];\n        }\n        if (!declaredInCurrentScope && _current[\"(usages)\"][labelName]) {\n          var usage = _current[\"(usages)\"][labelName];\n          if (usage[\"(onlyUsedSubFunction)\"]) {\n            _latedefWarning(type, labelName, token);\n          } else {\n            warning(\"E056\", token, labelName, type);\n          }\n        }\n        if (declaredInCurrentScope) {\n          warning(\"E011\", token, labelName);\n        }\n        else if (state.option.shadow === \"outer\") {\n          if (scopeManagerInst.funct.has(labelName)) {\n            warning(\"W004\", token, labelName);\n          }\n        }\n\n        scopeManagerInst.block.add(labelName, type, token, !isexported);\n\n      } else {\n\n        var declaredInCurrentFunctionScope = scopeManagerInst.funct.has(labelName);\n        if (!declaredInCurrentFunctionScope && usedSoFarInCurrentFunction(labelName)) {\n          _latedefWarning(type, labelName, token);\n        }\n        if (scopeManagerInst.funct.has(labelName, { onlyBlockscoped: true })) {\n          warning(\"E011\", token, labelName);\n        } else if (state.option.shadow !== true) {\n          if (declaredInCurrentFunctionScope && labelName !== \"__proto__\") {\n            if (_currentFunctBody[\"(type)\"] !== \"global\") {\n              warning(\"W004\", token, labelName);\n            }\n          }\n        }\n\n        scopeManagerInst.funct.add(labelName, type, token, !isexported);\n\n        if (_currentFunctBody[\"(type)\"] === \"global\") {\n          usedPredefinedAndGlobals[labelName] = marker;\n        }\n      }\n    },\n\n    funct: {\n      labeltype: function(labelName, options) {\n        var onlyBlockscoped = options && options.onlyBlockscoped;\n        var excludeParams = options && options.excludeParams;\n        var currentScopeIndex = _scopeStack.length - (options && options.excludeCurrent ? 2 : 1);\n        for (var i = currentScopeIndex; i >= 0; i--) {\n          var current = _scopeStack[i];\n          if (current[\"(labels)\"][labelName] &&\n            (!onlyBlockscoped || current[\"(labels)\"][labelName][\"(blockscoped)\"])) {\n            return current[\"(labels)\"][labelName][\"(type)\"];\n          }\n          var scopeCheck = excludeParams ? _scopeStack[ i - 1 ] : current;\n          if (scopeCheck && scopeCheck[\"(type)\"] === \"functionparams\") {\n            return null;\n          }\n        }\n        return null;\n      },\n      hasBreakLabel: function(labelName) {\n        for (var i = _scopeStack.length - 1; i >= 0; i--) {\n          var current = _scopeStack[i];\n\n          if (current[\"(breakLabels)\"][labelName]) {\n            return true;\n          }\n          if (current[\"(type)\"] === \"functionparams\") {\n            return false;\n          }\n        }\n        return false;\n      },\n      has: function(labelName, options) {\n        return Boolean(this.labeltype(labelName, options));\n      },\n      add: function(labelName, type, tok, unused) {\n        _current[\"(labels)\"][labelName] = {\n          \"(type)\" : type,\n          \"(token)\": tok,\n          \"(blockscoped)\": false,\n          \"(function)\": _currentFunctBody,\n          \"(unused)\": unused };\n      }\n    },\n\n    block: {\n      isGlobal: function() {\n        return _current[\"(type)\"] === \"global\";\n      },\n\n      use: function(labelName, token) {\n        var paramScope = _currentFunctBody[\"(parent)\"];\n        if (paramScope && paramScope[\"(labels)\"][labelName] &&\n          paramScope[\"(labels)\"][labelName][\"(type)\"] === \"param\") {\n          if (!scopeManagerInst.funct.has(labelName,\n                { excludeParams: true, onlyBlockscoped: true })) {\n            paramScope[\"(labels)\"][labelName][\"(unused)\"] = false;\n          }\n        }\n\n        if (token && (state.ignored.W117 || state.option.undef === false)) {\n          token.ignoreUndef = true;\n        }\n\n        _setupUsages(labelName);\n\n        if (token) {\n          token[\"(function)\"] = _currentFunctBody;\n          _current[\"(usages)\"][labelName][\"(tokens)\"].push(token);\n        }\n      },\n\n      reassign: function(labelName, token) {\n\n        this.modify(labelName, token);\n\n        _current[\"(usages)\"][labelName][\"(reassigned)\"].push(token);\n      },\n\n      modify: function(labelName, token) {\n\n        _setupUsages(labelName);\n\n        _current[\"(usages)\"][labelName][\"(modified)\"].push(token);\n      },\n      add: function(labelName, type, tok, unused) {\n        _current[\"(labels)\"][labelName] = {\n          \"(type)\" : type,\n          \"(token)\": tok,\n          \"(blockscoped)\": true,\n          \"(unused)\": unused };\n      },\n\n      addBreakLabel: function(labelName, opts) {\n        var token = opts.token;\n        if (scopeManagerInst.funct.hasBreakLabel(labelName)) {\n          warning(\"E011\", token, labelName);\n        }\n        else if (state.option.shadow === \"outer\") {\n          if (scopeManagerInst.funct.has(labelName)) {\n            warning(\"W004\", token, labelName);\n          } else {\n            _checkOuterShadow(labelName, token);\n          }\n        }\n        _current[\"(breakLabels)\"][labelName] = token;\n      }\n    }\n  };\n  return scopeManagerInst;\n};\n\nmodule.exports = scopeManager;\n\n},{\"../lodash\":\"/node_modules/jshint/lodash.js\",\"events\":\"/node_modules/browserify/node_modules/events/events.js\"}],\"/node_modules/jshint/src/state.js\":[function(_dereq_,module,exports){\n\"use strict\";\nvar NameStack = _dereq_(\"./name-stack.js\");\n\nvar state = {\n  syntax: {},\n  isStrict: function() {\n    return this.directive[\"use strict\"] || this.inClassBody ||\n      this.option.module || this.option.strict === \"implied\";\n  },\n\n  inMoz: function() {\n    return this.option.moz;\n  },\n  inES6: function() {\n    return this.option.moz || this.option.esversion >= 6;\n  },\n  inES5: function(strict) {\n    if (strict) {\n      return (!this.option.esversion || this.option.esversion === 5) && !this.option.moz;\n    }\n    return !this.option.esversion || this.option.esversion >= 5 || this.option.moz;\n  },\n\n\n  reset: function() {\n    this.tokens = {\n      prev: null,\n      next: null,\n      curr: null\n    };\n\n    this.option = {};\n    this.funct = null;\n    this.ignored = {};\n    this.directive = {};\n    this.jsonMode = false;\n    this.jsonWarnings = [];\n    this.lines = [];\n    this.tab = \"\";\n    this.cache = {}; // Node.JS doesn't have Map. Sniff.\n    this.ignoredLines = {};\n    this.forinifcheckneeded = false;\n    this.nameStack = new NameStack();\n    this.inClassBody = false;\n  }\n};\n\nexports.state = state;\n\n},{\"./name-stack.js\":\"/node_modules/jshint/src/name-stack.js\"}],\"/node_modules/jshint/src/style.js\":[function(_dereq_,module,exports){\n\"use strict\";\n\nexports.register = function(linter) {\n\n  linter.on(\"Identifier\", function style_scanProto(data) {\n    if (linter.getOption(\"proto\")) {\n      return;\n    }\n\n    if (data.name === \"__proto__\") {\n      linter.warn(\"W103\", {\n        line: data.line,\n        char: data.char,\n        data: [ data.name, \"6\" ]\n      });\n    }\n  });\n\n  linter.on(\"Identifier\", function style_scanIterator(data) {\n    if (linter.getOption(\"iterator\")) {\n      return;\n    }\n\n    if (data.name === \"__iterator__\") {\n      linter.warn(\"W103\", {\n        line: data.line,\n        char: data.char,\n        data: [ data.name ]\n      });\n    }\n  });\n\n  linter.on(\"Identifier\", function style_scanCamelCase(data) {\n    if (!linter.getOption(\"camelcase\")) {\n      return;\n    }\n\n    if (data.name.replace(/^_+|_+$/g, \"\").indexOf(\"_\") > -1 && !data.name.match(/^[A-Z0-9_]*$/)) {\n      linter.warn(\"W106\", {\n        line: data.line,\n        char: data.from,\n        data: [ data.name ]\n      });\n    }\n  });\n\n  linter.on(\"String\", function style_scanQuotes(data) {\n    var quotmark = linter.getOption(\"quotmark\");\n    var code;\n\n    if (!quotmark) {\n      return;\n    }\n\n    if (quotmark === \"single\" && data.quote !== \"'\") {\n      code = \"W109\";\n    }\n\n    if (quotmark === \"double\" && data.quote !== \"\\\"\") {\n      code = \"W108\";\n    }\n\n    if (quotmark === true) {\n      if (!linter.getCache(\"quotmark\")) {\n        linter.setCache(\"quotmark\", data.quote);\n      }\n\n      if (linter.getCache(\"quotmark\") !== data.quote) {\n        code = \"W110\";\n      }\n    }\n\n    if (code) {\n      linter.warn(code, {\n        line: data.line,\n        char: data.char,\n      });\n    }\n  });\n\n  linter.on(\"Number\", function style_scanNumbers(data) {\n    if (data.value.charAt(0) === \".\") {\n      linter.warn(\"W008\", {\n        line: data.line,\n        char: data.char,\n        data: [ data.value ]\n      });\n    }\n\n    if (data.value.substr(data.value.length - 1) === \".\") {\n      linter.warn(\"W047\", {\n        line: data.line,\n        char: data.char,\n        data: [ data.value ]\n      });\n    }\n\n    if (/^00+/.test(data.value)) {\n      linter.warn(\"W046\", {\n        line: data.line,\n        char: data.char,\n        data: [ data.value ]\n      });\n    }\n  });\n\n  linter.on(\"String\", function style_scanJavaScriptURLs(data) {\n    var re = /^(?:javascript|jscript|ecmascript|vbscript|livescript)\\s*:/i;\n\n    if (linter.getOption(\"scripturl\")) {\n      return;\n    }\n\n    if (re.test(data.value)) {\n      linter.warn(\"W107\", {\n        line: data.line,\n        char: data.char\n      });\n    }\n  });\n};\n\n},{}],\"/node_modules/jshint/src/vars.js\":[function(_dereq_,module,exports){\n\n\"use strict\";\n\nexports.reservedVars = {\n  arguments : false,\n  NaN       : false\n};\n\nexports.ecmaIdentifiers = {\n  3: {\n    Array              : false,\n    Boolean            : false,\n    Date               : false,\n    decodeURI          : false,\n    decodeURIComponent : false,\n    encodeURI          : false,\n    encodeURIComponent : false,\n    Error              : false,\n    \"eval\"             : false,\n    EvalError          : false,\n    Function           : false,\n    hasOwnProperty     : false,\n    isFinite           : false,\n    isNaN              : false,\n    Math               : false,\n    Number             : false,\n    Object             : false,\n    parseInt           : false,\n    parseFloat         : false,\n    RangeError         : false,\n    ReferenceError     : false,\n    RegExp             : false,\n    String             : false,\n    SyntaxError        : false,\n    TypeError          : false,\n    URIError           : false\n  },\n  5: {\n    JSON               : false\n  },\n  6: {\n    Map                : false,\n    Promise            : false,\n    Proxy              : false,\n    Reflect            : false,\n    Set                : false,\n    Symbol             : false,\n    WeakMap            : false,\n    WeakSet            : false\n  }\n};\n\nexports.browser = {\n  Audio                : false,\n  Blob                 : false,\n  addEventListener     : false,\n  applicationCache     : false,\n  atob                 : false,\n  blur                 : false,\n  btoa                 : false,\n  cancelAnimationFrame : false,\n  CanvasGradient       : false,\n  CanvasPattern        : false,\n  CanvasRenderingContext2D: false,\n  CSS                  : false,\n  clearInterval        : false,\n  clearTimeout         : false,\n  close                : false,\n  closed               : false,\n  Comment              : false,\n  CustomEvent          : false,\n  DOMParser            : false,\n  defaultStatus        : false,\n  Document             : false,\n  document             : false,\n  DocumentFragment     : false,\n  Element              : false,\n  ElementTimeControl   : false,\n  Event                : false,\n  event                : false,\n  fetch                : false,\n  FileReader           : false,\n  FormData             : false,\n  focus                : false,\n  frames               : false,\n  getComputedStyle     : false,\n  HTMLElement          : false,\n  HTMLAnchorElement    : false,\n  HTMLBaseElement      : false,\n  HTMLBlockquoteElement: false,\n  HTMLBodyElement      : false,\n  HTMLBRElement        : false,\n  HTMLButtonElement    : false,\n  HTMLCanvasElement    : false,\n  HTMLCollection       : false,\n  HTMLDirectoryElement : false,\n  HTMLDivElement       : false,\n  HTMLDListElement     : false,\n  HTMLFieldSetElement  : false,\n  HTMLFontElement      : false,\n  HTMLFormElement      : false,\n  HTMLFrameElement     : false,\n  HTMLFrameSetElement  : false,\n  HTMLHeadElement      : false,\n  HTMLHeadingElement   : false,\n  HTMLHRElement        : false,\n  HTMLHtmlElement      : false,\n  HTMLIFrameElement    : false,\n  HTMLImageElement     : false,\n  HTMLInputElement     : false,\n  HTMLIsIndexElement   : false,\n  HTMLLabelElement     : false,\n  HTMLLayerElement     : false,\n  HTMLLegendElement    : false,\n  HTMLLIElement        : false,\n  HTMLLinkElement      : false,\n  HTMLMapElement       : false,\n  HTMLMenuElement      : false,\n  HTMLMetaElement      : false,\n  HTMLModElement       : false,\n  HTMLObjectElement    : false,\n  HTMLOListElement     : false,\n  HTMLOptGroupElement  : false,\n  HTMLOptionElement    : false,\n  HTMLParagraphElement : false,\n  HTMLParamElement     : false,\n  HTMLPreElement       : false,\n  HTMLQuoteElement     : false,\n  HTMLScriptElement    : false,\n  HTMLSelectElement    : false,\n  HTMLStyleElement     : false,\n  HTMLTableCaptionElement: false,\n  HTMLTableCellElement : false,\n  HTMLTableColElement  : false,\n  HTMLTableElement     : false,\n  HTMLTableRowElement  : false,\n  HTMLTableSectionElement: false,\n  HTMLTemplateElement  : false,\n  HTMLTextAreaElement  : false,\n  HTMLTitleElement     : false,\n  HTMLUListElement     : false,\n  HTMLVideoElement     : false,\n  history              : false,\n  Image                : false,\n  Intl                 : false,\n  length               : false,\n  localStorage         : false,\n  location             : false,\n  matchMedia           : false,\n  MessageChannel       : false,\n  MessageEvent         : false,\n  MessagePort          : false,\n  MouseEvent           : false,\n  moveBy               : false,\n  moveTo               : false,\n  MutationObserver     : false,\n  name                 : false,\n  Node                 : false,\n  NodeFilter           : false,\n  NodeList             : false,\n  Notification         : false,\n  navigator            : false,\n  onbeforeunload       : true,\n  onblur               : true,\n  onerror              : true,\n  onfocus              : true,\n  onload               : true,\n  onresize             : true,\n  onunload             : true,\n  open                 : false,\n  openDatabase         : false,\n  opener               : false,\n  Option               : false,\n  parent               : false,\n  performance          : false,\n  print                : false,\n  Range                : false,\n  requestAnimationFrame : false,\n  removeEventListener  : false,\n  resizeBy             : false,\n  resizeTo             : false,\n  screen               : false,\n  scroll               : false,\n  scrollBy             : false,\n  scrollTo             : false,\n  sessionStorage       : false,\n  setInterval          : false,\n  setTimeout           : false,\n  SharedWorker         : false,\n  status               : false,\n  SVGAElement          : false,\n  SVGAltGlyphDefElement: false,\n  SVGAltGlyphElement   : false,\n  SVGAltGlyphItemElement: false,\n  SVGAngle             : false,\n  SVGAnimateColorElement: false,\n  SVGAnimateElement    : false,\n  SVGAnimateMotionElement: false,\n  SVGAnimateTransformElement: false,\n  SVGAnimatedAngle     : false,\n  SVGAnimatedBoolean   : false,\n  SVGAnimatedEnumeration: false,\n  SVGAnimatedInteger   : false,\n  SVGAnimatedLength    : false,\n  SVGAnimatedLengthList: false,\n  SVGAnimatedNumber    : false,\n  SVGAnimatedNumberList: false,\n  SVGAnimatedPathData  : false,\n  SVGAnimatedPoints    : false,\n  SVGAnimatedPreserveAspectRatio: false,\n  SVGAnimatedRect      : false,\n  SVGAnimatedString    : false,\n  SVGAnimatedTransformList: false,\n  SVGAnimationElement  : false,\n  SVGCSSRule           : false,\n  SVGCircleElement     : false,\n  SVGClipPathElement   : false,\n  SVGColor             : false,\n  SVGColorProfileElement: false,\n  SVGColorProfileRule  : false,\n  SVGComponentTransferFunctionElement: false,\n  SVGCursorElement     : false,\n  SVGDefsElement       : false,\n  SVGDescElement       : false,\n  SVGDocument          : false,\n  SVGElement           : false,\n  SVGElementInstance   : false,\n  SVGElementInstanceList: false,\n  SVGEllipseElement    : false,\n  SVGExternalResourcesRequired: false,\n  SVGFEBlendElement    : false,\n  SVGFEColorMatrixElement: false,\n  SVGFEComponentTransferElement: false,\n  SVGFECompositeElement: false,\n  SVGFEConvolveMatrixElement: false,\n  SVGFEDiffuseLightingElement: false,\n  SVGFEDisplacementMapElement: false,\n  SVGFEDistantLightElement: false,\n  SVGFEFloodElement    : false,\n  SVGFEFuncAElement    : false,\n  SVGFEFuncBElement    : false,\n  SVGFEFuncGElement    : false,\n  SVGFEFuncRElement    : false,\n  SVGFEGaussianBlurElement: false,\n  SVGFEImageElement    : false,\n  SVGFEMergeElement    : false,\n  SVGFEMergeNodeElement: false,\n  SVGFEMorphologyElement: false,\n  SVGFEOffsetElement   : false,\n  SVGFEPointLightElement: false,\n  SVGFESpecularLightingElement: false,\n  SVGFESpotLightElement: false,\n  SVGFETileElement     : false,\n  SVGFETurbulenceElement: false,\n  SVGFilterElement     : false,\n  SVGFilterPrimitiveStandardAttributes: false,\n  SVGFitToViewBox      : false,\n  SVGFontElement       : false,\n  SVGFontFaceElement   : false,\n  SVGFontFaceFormatElement: false,\n  SVGFontFaceNameElement: false,\n  SVGFontFaceSrcElement: false,\n  SVGFontFaceUriElement: false,\n  SVGForeignObjectElement: false,\n  SVGGElement          : false,\n  SVGGlyphElement      : false,\n  SVGGlyphRefElement   : false,\n  SVGGradientElement   : false,\n  SVGHKernElement      : false,\n  SVGICCColor          : false,\n  SVGImageElement      : false,\n  SVGLangSpace         : false,\n  SVGLength            : false,\n  SVGLengthList        : false,\n  SVGLineElement       : false,\n  SVGLinearGradientElement: false,\n  SVGLocatable         : false,\n  SVGMPathElement      : false,\n  SVGMarkerElement     : false,\n  SVGMaskElement       : false,\n  SVGMatrix            : false,\n  SVGMetadataElement   : false,\n  SVGMissingGlyphElement: false,\n  SVGNumber            : false,\n  SVGNumberList        : false,\n  SVGPaint             : false,\n  SVGPathElement       : false,\n  SVGPathSeg           : false,\n  SVGPathSegArcAbs     : false,\n  SVGPathSegArcRel     : false,\n  SVGPathSegClosePath  : false,\n  SVGPathSegCurvetoCubicAbs: false,\n  SVGPathSegCurvetoCubicRel: false,\n  SVGPathSegCurvetoCubicSmoothAbs: false,\n  SVGPathSegCurvetoCubicSmoothRel: false,\n  SVGPathSegCurvetoQuadraticAbs: false,\n  SVGPathSegCurvetoQuadraticRel: false,\n  SVGPathSegCurvetoQuadraticSmoothAbs: false,\n  SVGPathSegCurvetoQuadraticSmoothRel: false,\n  SVGPathSegLinetoAbs  : false,\n  SVGPathSegLinetoHorizontalAbs: false,\n  SVGPathSegLinetoHorizontalRel: false,\n  SVGPathSegLinetoRel  : false,\n  SVGPathSegLinetoVerticalAbs: false,\n  SVGPathSegLinetoVerticalRel: false,\n  SVGPathSegList       : false,\n  SVGPathSegMovetoAbs  : false,\n  SVGPathSegMovetoRel  : false,\n  SVGPatternElement    : false,\n  SVGPoint             : false,\n  SVGPointList         : false,\n  SVGPolygonElement    : false,\n  SVGPolylineElement   : false,\n  SVGPreserveAspectRatio: false,\n  SVGRadialGradientElement: false,\n  SVGRect              : false,\n  SVGRectElement       : false,\n  SVGRenderingIntent   : false,\n  SVGSVGElement        : false,\n  SVGScriptElement     : false,\n  SVGSetElement        : false,\n  SVGStopElement       : false,\n  SVGStringList        : false,\n  SVGStylable          : false,\n  SVGStyleElement      : false,\n  SVGSwitchElement     : false,\n  SVGSymbolElement     : false,\n  SVGTRefElement       : false,\n  SVGTSpanElement      : false,\n  SVGTests             : false,\n  SVGTextContentElement: false,\n  SVGTextElement       : false,\n  SVGTextPathElement   : false,\n  SVGTextPositioningElement: false,\n  SVGTitleElement      : false,\n  SVGTransform         : false,\n  SVGTransformList     : false,\n  SVGTransformable     : false,\n  SVGURIReference      : false,\n  SVGUnitTypes         : false,\n  SVGUseElement        : false,\n  SVGVKernElement      : false,\n  SVGViewElement       : false,\n  SVGViewSpec          : false,\n  SVGZoomAndPan        : false,\n  Text                 : false,\n  TextDecoder          : false,\n  TextEncoder          : false,\n  TimeEvent            : false,\n  top                  : false,\n  URL                  : false,\n  WebGLActiveInfo      : false,\n  WebGLBuffer          : false,\n  WebGLContextEvent    : false,\n  WebGLFramebuffer     : false,\n  WebGLProgram         : false,\n  WebGLRenderbuffer    : false,\n  WebGLRenderingContext: false,\n  WebGLShader          : false,\n  WebGLShaderPrecisionFormat: false,\n  WebGLTexture         : false,\n  WebGLUniformLocation : false,\n  WebSocket            : false,\n  window               : false,\n  Window               : false,\n  Worker               : false,\n  XDomainRequest       : false,\n  XMLHttpRequest       : false,\n  XMLSerializer        : false,\n  XPathEvaluator       : false,\n  XPathException       : false,\n  XPathExpression      : false,\n  XPathNamespace       : false,\n  XPathNSResolver      : false,\n  XPathResult          : false\n};\n\nexports.devel = {\n  alert  : false,\n  confirm: false,\n  console: false,\n  Debug  : false,\n  opera  : false,\n  prompt : false\n};\n\nexports.worker = {\n  importScripts  : true,\n  postMessage    : true,\n  self           : true,\n  FileReaderSync : true\n};\nexports.nonstandard = {\n  escape  : false,\n  unescape: false\n};\n\nexports.couch = {\n  \"require\" : false,\n  respond   : false,\n  getRow    : false,\n  emit      : false,\n  send      : false,\n  start     : false,\n  sum       : false,\n  log       : false,\n  exports   : false,\n  module    : false,\n  provides  : false\n};\n\nexports.node = {\n  __filename    : false,\n  __dirname     : false,\n  GLOBAL        : false,\n  global        : false,\n  module        : false,\n  require       : false,\n\n  Buffer        : true,\n  console       : true,\n  exports       : true,\n  process       : true,\n  setTimeout    : true,\n  clearTimeout  : true,\n  setInterval   : true,\n  clearInterval : true,\n  setImmediate  : true, // v0.9.1+\n  clearImmediate: true  // v0.9.1+\n};\n\nexports.browserify = {\n  __filename    : false,\n  __dirname     : false,\n  global        : false,\n  module        : false,\n  require       : false,\n  Buffer        : true,\n  exports       : true,\n  process       : true\n};\n\nexports.phantom = {\n  phantom      : true,\n  require      : true,\n  WebPage      : true,\n  console      : true, // in examples, but undocumented\n  exports      : true  // v1.7+\n};\n\nexports.qunit = {\n  asyncTest      : false,\n  deepEqual      : false,\n  equal          : false,\n  expect         : false,\n  module         : false,\n  notDeepEqual   : false,\n  notEqual       : false,\n  notPropEqual   : false,\n  notStrictEqual : false,\n  ok             : false,\n  propEqual      : false,\n  QUnit          : false,\n  raises         : false,\n  start          : false,\n  stop           : false,\n  strictEqual    : false,\n  test           : false,\n  \"throws\"       : false\n};\n\nexports.rhino = {\n  defineClass  : false,\n  deserialize  : false,\n  gc           : false,\n  help         : false,\n  importClass  : false,\n  importPackage: false,\n  \"java\"       : false,\n  load         : false,\n  loadClass    : false,\n  Packages     : false,\n  print        : false,\n  quit         : false,\n  readFile     : false,\n  readUrl      : false,\n  runCommand   : false,\n  seal         : false,\n  serialize    : false,\n  spawn        : false,\n  sync         : false,\n  toint32      : false,\n  version      : false\n};\n\nexports.shelljs = {\n  target       : false,\n  echo         : false,\n  exit         : false,\n  cd           : false,\n  pwd          : false,\n  ls           : false,\n  find         : false,\n  cp           : false,\n  rm           : false,\n  mv           : false,\n  mkdir        : false,\n  test         : false,\n  cat          : false,\n  sed          : false,\n  grep         : false,\n  which        : false,\n  dirs         : false,\n  pushd        : false,\n  popd         : false,\n  env          : false,\n  exec         : false,\n  chmod        : false,\n  config       : false,\n  error        : false,\n  tempdir      : false\n};\n\nexports.typed = {\n  ArrayBuffer         : false,\n  ArrayBufferView     : false,\n  DataView            : false,\n  Float32Array        : false,\n  Float64Array        : false,\n  Int16Array          : false,\n  Int32Array          : false,\n  Int8Array           : false,\n  Uint16Array         : false,\n  Uint32Array         : false,\n  Uint8Array          : false,\n  Uint8ClampedArray   : false\n};\n\nexports.wsh = {\n  ActiveXObject            : true,\n  Enumerator               : true,\n  GetObject                : true,\n  ScriptEngine             : true,\n  ScriptEngineBuildVersion : true,\n  ScriptEngineMajorVersion : true,\n  ScriptEngineMinorVersion : true,\n  VBArray                  : true,\n  WSH                      : true,\n  WScript                  : true,\n  XDomainRequest           : true\n};\n\nexports.dojo = {\n  dojo     : false,\n  dijit    : false,\n  dojox    : false,\n  define   : false,\n  \"require\": false\n};\n\nexports.jquery = {\n  \"$\"    : false,\n  jQuery : false\n};\n\nexports.mootools = {\n  \"$\"           : false,\n  \"$$\"          : false,\n  Asset         : false,\n  Browser       : false,\n  Chain         : false,\n  Class         : false,\n  Color         : false,\n  Cookie        : false,\n  Core          : false,\n  Document      : false,\n  DomReady      : false,\n  DOMEvent      : false,\n  DOMReady      : false,\n  Drag          : false,\n  Element       : false,\n  Elements      : false,\n  Event         : false,\n  Events        : false,\n  Fx            : false,\n  Group         : false,\n  Hash          : false,\n  HtmlTable     : false,\n  IFrame        : false,\n  IframeShim    : false,\n  InputValidator: false,\n  instanceOf    : false,\n  Keyboard      : false,\n  Locale        : false,\n  Mask          : false,\n  MooTools      : false,\n  Native        : false,\n  Options       : false,\n  OverText      : false,\n  Request       : false,\n  Scroller      : false,\n  Slick         : false,\n  Slider        : false,\n  Sortables     : false,\n  Spinner       : false,\n  Swiff         : false,\n  Tips          : false,\n  Type          : false,\n  typeOf        : false,\n  URI           : false,\n  Window        : false\n};\n\nexports.prototypejs = {\n  \"$\"               : false,\n  \"$$\"              : false,\n  \"$A\"              : false,\n  \"$F\"              : false,\n  \"$H\"              : false,\n  \"$R\"              : false,\n  \"$break\"          : false,\n  \"$continue\"       : false,\n  \"$w\"              : false,\n  Abstract          : false,\n  Ajax              : false,\n  Class             : false,\n  Enumerable        : false,\n  Element           : false,\n  Event             : false,\n  Field             : false,\n  Form              : false,\n  Hash              : false,\n  Insertion         : false,\n  ObjectRange       : false,\n  PeriodicalExecuter: false,\n  Position          : false,\n  Prototype         : false,\n  Selector          : false,\n  Template          : false,\n  Toggle            : false,\n  Try               : false,\n  Autocompleter     : false,\n  Builder           : false,\n  Control           : false,\n  Draggable         : false,\n  Draggables        : false,\n  Droppables        : false,\n  Effect            : false,\n  Sortable          : false,\n  SortableObserver  : false,\n  Sound             : false,\n  Scriptaculous     : false\n};\n\nexports.yui = {\n  YUI       : false,\n  Y         : false,\n  YUI_config: false\n};\n\nexports.mocha = {\n  mocha       : false,\n  describe    : false,\n  xdescribe   : false,\n  it          : false,\n  xit         : false,\n  context     : false,\n  xcontext    : false,\n  before      : false,\n  after       : false,\n  beforeEach  : false,\n  afterEach   : false,\n  suite         : false,\n  test          : false,\n  setup         : false,\n  teardown      : false,\n  suiteSetup    : false,\n  suiteTeardown : false\n};\n\nexports.jasmine = {\n  jasmine     : false,\n  describe    : false,\n  xdescribe   : false,\n  it          : false,\n  xit         : false,\n  beforeEach  : false,\n  afterEach   : false,\n  setFixtures : false,\n  loadFixtures: false,\n  spyOn       : false,\n  expect      : false,\n  runs        : false,\n  waitsFor    : false,\n  waits       : false,\n  beforeAll   : false,\n  afterAll    : false,\n  fail        : false,\n  fdescribe   : false,\n  fit         : false,\n  pending     : false\n};\n\n},{}]},{},[\"/node_modules/jshint/src/jshint.js\"]);\n\n});\n\ndefine(\"ace/mode/javascript_worker\",[\"require\",\"exports\",\"module\",\"ace/lib/oop\",\"ace/worker/mirror\",\"ace/mode/javascript/jshint\"], function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar Mirror = require(\"../worker/mirror\").Mirror;\nvar lint = require(\"./javascript/jshint\").JSHINT;\n\nfunction startRegex(arr) {\n    return RegExp(\"^(\" + arr.join(\"|\") + \")\");\n}\n\nvar disabledWarningsRe = startRegex([\n    \"Bad for in variable '(.+)'.\",\n    'Missing \"use strict\"'\n]);\nvar errorsRe = startRegex([\n    \"Unexpected\",\n    \"Expected \",\n    \"Confusing (plus|minus)\",\n    \"\\\\{a\\\\} unterminated regular expression\",\n    \"Unclosed \",\n    \"Unmatched \",\n    \"Unbegun comment\",\n    \"Bad invocation\",\n    \"Missing space after\",\n    \"Missing operator at\"\n]);\nvar infoRe = startRegex([\n    \"Expected an assignment\",\n    \"Bad escapement of EOL\",\n    \"Unexpected comma\",\n    \"Unexpected space\",\n    \"Missing radix parameter.\",\n    \"A leading decimal point can\",\n    \"\\\\['{a}'\\\\] is better written in dot notation.\",\n    \"'{a}' used out of scope\"\n]);\n\nvar JavaScriptWorker = exports.JavaScriptWorker = function(sender) {\n    Mirror.call(this, sender);\n    this.setTimeout(500);\n    this.setOptions();\n};\n\noop.inherits(JavaScriptWorker, Mirror);\n\n(function() {\n    this.setOptions = function(options) {\n        this.options = options || {\n            esnext: true,\n            moz: true,\n            devel: true,\n            browser: true,\n            node: true,\n            laxcomma: true,\n            laxbreak: true,\n            lastsemic: true,\n            onevar: false,\n            passfail: false,\n            maxerr: 100,\n            expr: true,\n            multistr: true,\n            globalstrict: true\n        };\n        this.doc.getValue() && this.deferredUpdate.schedule(100);\n    };\n\n    this.changeOptions = function(newOptions) {\n        oop.mixin(this.options, newOptions);\n        this.doc.getValue() && this.deferredUpdate.schedule(100);\n    };\n\n    this.isValidJS = function(str) {\n        try {\n            eval(\"throw 0;\" + str);\n        } catch(e) {\n            if (e === 0)\n                return true;\n        }\n        return false\n    };\n\n    this.onUpdate = function() {\n        var value = this.doc.getValue();\n        value = value.replace(/^#!.*\\n/, \"\\n\");\n        if (!value)\n            return this.sender.emit(\"annotate\", []);\n\n        // wick specific: add a semicolon to end of on(event) statements to squash missing \";\" error\n        var onEventFinderRegex = /^ *on *\\( *[a-zA-Z]+ *\\)/gm\n        var m;\n        do {\n            m = onEventFinderRegex.exec(value, 'g');\n            if (m) {\n                value = value.splice(m.index + m[0].length, 0, ';')\n            }\n        } while (m);\n\n        var errors = [];\n        var maxErrorLevel = this.isValidJS(value) ? \"warning\" : \"error\";\n        lint(value, this.options);\n        var results = lint.errors;\n\n        var errorAdded = false\n        for (var i = 0; i < results.length; i++) {\n            var error = results[i];\n            if (!error)\n                continue;\n            var raw = error.raw;\n            var type = \"warning\";\n\n            if (raw == \"Missing semicolon.\") {\n                var str = error.evidence.substr(error.character);\n                str = str.charAt(str.search(/\\S/));\n                if (maxErrorLevel == \"error\" && str && /[\\w\\d{(['\"]/.test(str)) {\n                    error.reason = 'Missing \";\" before statement';\n                    type = \"error\";\n                } else {\n                    type = \"info\";\n                }\n            }\n            else if (disabledWarningsRe.test(raw)) {\n                continue;\n            }\n            else if (infoRe.test(raw)) {\n                type = \"info\"\n            }\n            else if (errorsRe.test(raw)) {\n                errorAdded  = true;\n                type = maxErrorLevel;\n            }\n            else if (raw == \"'{a}' is not defined.\") {\n                type = \"warning\";\n            }\n            else if (raw == \"'{a}' is defined but never used.\") {\n                type = \"info\";\n            }\n\n            errors.push({\n                row: error.line-1,\n                column: error.character-1,\n                text: error.reason,\n                type: type,\n                raw: raw\n            });\n\n            if (errorAdded) {\n            }\n        }\n\n        this.sender.emit(\"annotate\", errors);\n    };\n\n}).call(JavaScriptWorker.prototype);\n\n});\n\ndefine(\"ace/lib/es5-shim\",[\"require\",\"exports\",\"module\"], function(require, exports, module) {\n\nfunction Empty() {}\n\nif (!Function.prototype.bind) {\n    Function.prototype.bind = function bind(that) { // .length is 1\n        var target = this;\n        if (typeof target != \"function\") {\n            throw new TypeError(\"Function.prototype.bind called on incompatible \" + target);\n        }\n        var args = slice.call(arguments, 1); // for normal call\n        var bound = function () {\n\n            if (this instanceof bound) {\n\n                var result = target.apply(\n                    this,\n                    args.concat(slice.call(arguments))\n                );\n                if (Object(result) === result) {\n                    return result;\n                }\n                return this;\n\n            } else {\n                return target.apply(\n                    that,\n                    args.concat(slice.call(arguments))\n                );\n\n            }\n\n        };\n        if(target.prototype) {\n            Empty.prototype = target.prototype;\n            bound.prototype = new Empty();\n            Empty.prototype = null;\n        }\n        return bound;\n    };\n}\nvar call = Function.prototype.call;\nvar prototypeOfArray = Array.prototype;\nvar prototypeOfObject = Object.prototype;\nvar slice = prototypeOfArray.slice;\nvar _toString = call.bind(prototypeOfObject.toString);\nvar owns = call.bind(prototypeOfObject.hasOwnProperty);\nvar defineGetter;\nvar defineSetter;\nvar lookupGetter;\nvar lookupSetter;\nvar supportsAccessors;\nif ((supportsAccessors = owns(prototypeOfObject, \"__defineGetter__\"))) {\n    defineGetter = call.bind(prototypeOfObject.__defineGetter__);\n    defineSetter = call.bind(prototypeOfObject.__defineSetter__);\n    lookupGetter = call.bind(prototypeOfObject.__lookupGetter__);\n    lookupSetter = call.bind(prototypeOfObject.__lookupSetter__);\n}\nif ([1,2].splice(0).length != 2) {\n    if(function() { // test IE < 9 to splice bug - see issue #138\n        function makeArray(l) {\n            var a = new Array(l+2);\n            a[0] = a[1] = 0;\n            return a;\n        }\n        var array = [], lengthBefore;\n        \n        array.splice.apply(array, makeArray(20));\n        array.splice.apply(array, makeArray(26));\n\n        lengthBefore = array.length; //46\n        array.splice(5, 0, \"XXX\"); // add one element\n\n        lengthBefore + 1 == array.length\n\n        if (lengthBefore + 1 == array.length) {\n            return true;// has right splice implementation without bugs\n        }\n    }()) {//IE 6/7\n        var array_splice = Array.prototype.splice;\n        Array.prototype.splice = function(start, deleteCount) {\n            if (!arguments.length) {\n                return [];\n            } else {\n                return array_splice.apply(this, [\n                    start === void 0 ? 0 : start,\n                    deleteCount === void 0 ? (this.length - start) : deleteCount\n                ].concat(slice.call(arguments, 2)))\n            }\n        };\n    } else {//IE8\n        Array.prototype.splice = function(pos, removeCount){\n            var length = this.length;\n            if (pos > 0) {\n                if (pos > length)\n                    pos = length;\n            } else if (pos == void 0) {\n                pos = 0;\n            } else if (pos < 0) {\n                pos = Math.max(length + pos, 0);\n            }\n\n            if (!(pos+removeCount < length))\n                removeCount = length - pos;\n\n            var removed = this.slice(pos, pos+removeCount);\n            var insert = slice.call(arguments, 2);\n            var add = insert.length;            \n            if (pos === length) {\n                if (add) {\n                    this.push.apply(this, insert);\n                }\n            } else {\n                var remove = Math.min(removeCount, length - pos);\n                var tailOldPos = pos + remove;\n                var tailNewPos = tailOldPos + add - remove;\n                var tailCount = length - tailOldPos;\n                var lengthAfterRemove = length - remove;\n\n                if (tailNewPos < tailOldPos) { // case A\n                    for (var i = 0; i < tailCount; ++i) {\n                        this[tailNewPos+i] = this[tailOldPos+i];\n                    }\n                } else if (tailNewPos > tailOldPos) { // case B\n                    for (i = tailCount; i--; ) {\n                        this[tailNewPos+i] = this[tailOldPos+i];\n                    }\n                } // else, add == remove (nothing to do)\n\n                if (add && pos === lengthAfterRemove) {\n                    this.length = lengthAfterRemove; // truncate array\n                    this.push.apply(this, insert);\n                } else {\n                    this.length = lengthAfterRemove + add; // reserves space\n                    for (i = 0; i < add; ++i) {\n                        this[pos+i] = insert[i];\n                    }\n                }\n            }\n            return removed;\n        };\n    }\n}\nif (!Array.isArray) {\n    Array.isArray = function isArray(obj) {\n        return _toString(obj) == \"[object Array]\";\n    };\n}\nvar boxedString = Object(\"a\"),\n    splitString = boxedString[0] != \"a\" || !(0 in boxedString);\n\nif (!Array.prototype.forEach) {\n    Array.prototype.forEach = function forEach(fun /*, thisp*/) {\n        var object = toObject(this),\n            self = splitString && _toString(this) == \"[object String]\" ?\n                this.split(\"\") :\n                object,\n            thisp = arguments[1],\n            i = -1,\n            length = self.length >>> 0;\n        if (_toString(fun) != \"[object Function]\") {\n            throw new TypeError(); // TODO message\n        }\n\n        while (++i < length) {\n            if (i in self) {\n                fun.call(thisp, self[i], i, object);\n            }\n        }\n    };\n}\nif (!Array.prototype.map) {\n    Array.prototype.map = function map(fun /*, thisp*/) {\n        var object = toObject(this),\n            self = splitString && _toString(this) == \"[object String]\" ?\n                this.split(\"\") :\n                object,\n            length = self.length >>> 0,\n            result = Array(length),\n            thisp = arguments[1];\n        if (_toString(fun) != \"[object Function]\") {\n            throw new TypeError(fun + \" is not a function\");\n        }\n\n        for (var i = 0; i < length; i++) {\n            if (i in self)\n                result[i] = fun.call(thisp, self[i], i, object);\n        }\n        return result;\n    };\n}\nif (!Array.prototype.filter) {\n    Array.prototype.filter = function filter(fun /*, thisp */) {\n        var object = toObject(this),\n            self = splitString && _toString(this) == \"[object String]\" ?\n                this.split(\"\") :\n                    object,\n            length = self.length >>> 0,\n            result = [],\n            value,\n            thisp = arguments[1];\n        if (_toString(fun) != \"[object Function]\") {\n            throw new TypeError(fun + \" is not a function\");\n        }\n\n        for (var i = 0; i < length; i++) {\n            if (i in self) {\n                value = self[i];\n                if (fun.call(thisp, value, i, object)) {\n                    result.push(value);\n                }\n            }\n        }\n        return result;\n    };\n}\nif (!Array.prototype.every) {\n    Array.prototype.every = function every(fun /*, thisp */) {\n        var object = toObject(this),\n            self = splitString && _toString(this) == \"[object String]\" ?\n                this.split(\"\") :\n                object,\n            length = self.length >>> 0,\n            thisp = arguments[1];\n        if (_toString(fun) != \"[object Function]\") {\n            throw new TypeError(fun + \" is not a function\");\n        }\n\n        for (var i = 0; i < length; i++) {\n            if (i in self && !fun.call(thisp, self[i], i, object)) {\n                return false;\n            }\n        }\n        return true;\n    };\n}\nif (!Array.prototype.some) {\n    Array.prototype.some = function some(fun /*, thisp */) {\n        var object = toObject(this),\n            self = splitString && _toString(this) == \"[object String]\" ?\n                this.split(\"\") :\n                object,\n            length = self.length >>> 0,\n            thisp = arguments[1];\n        if (_toString(fun) != \"[object Function]\") {\n            throw new TypeError(fun + \" is not a function\");\n        }\n\n        for (var i = 0; i < length; i++) {\n            if (i in self && fun.call(thisp, self[i], i, object)) {\n                return true;\n            }\n        }\n        return false;\n    };\n}\nif (!Array.prototype.reduce) {\n    Array.prototype.reduce = function reduce(fun /*, initial*/) {\n        var object = toObject(this),\n            self = splitString && _toString(this) == \"[object String]\" ?\n                this.split(\"\") :\n                object,\n            length = self.length >>> 0;\n        if (_toString(fun) != \"[object Function]\") {\n            throw new TypeError(fun + \" is not a function\");\n        }\n        if (!length && arguments.length == 1) {\n            throw new TypeError(\"reduce of empty array with no initial value\");\n        }\n\n        var i = 0;\n        var result;\n        if (arguments.length >= 2) {\n            result = arguments[1];\n        } else {\n            do {\n                if (i in self) {\n                    result = self[i++];\n                    break;\n                }\n                if (++i >= length) {\n                    throw new TypeError(\"reduce of empty array with no initial value\");\n                }\n            } while (true);\n        }\n\n        for (; i < length; i++) {\n            if (i in self) {\n                result = fun.call(void 0, result, self[i], i, object);\n            }\n        }\n\n        return result;\n    };\n}\nif (!Array.prototype.reduceRight) {\n    Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) {\n        var object = toObject(this),\n            self = splitString && _toString(this) == \"[object String]\" ?\n                this.split(\"\") :\n                object,\n            length = self.length >>> 0;\n        if (_toString(fun) != \"[object Function]\") {\n            throw new TypeError(fun + \" is not a function\");\n        }\n        if (!length && arguments.length == 1) {\n            throw new TypeError(\"reduceRight of empty array with no initial value\");\n        }\n\n        var result, i = length - 1;\n        if (arguments.length >= 2) {\n            result = arguments[1];\n        } else {\n            do {\n                if (i in self) {\n                    result = self[i--];\n                    break;\n                }\n                if (--i < 0) {\n                    throw new TypeError(\"reduceRight of empty array with no initial value\");\n                }\n            } while (true);\n        }\n\n        do {\n            if (i in this) {\n                result = fun.call(void 0, result, self[i], i, object);\n            }\n        } while (i--);\n\n        return result;\n    };\n}\nif (!Array.prototype.indexOf || ([0, 1].indexOf(1, 2) != -1)) {\n    Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) {\n        var self = splitString && _toString(this) == \"[object String]\" ?\n                this.split(\"\") :\n                toObject(this),\n            length = self.length >>> 0;\n\n        if (!length) {\n            return -1;\n        }\n\n        var i = 0;\n        if (arguments.length > 1) {\n            i = toInteger(arguments[1]);\n        }\n        i = i >= 0 ? i : Math.max(0, length + i);\n        for (; i < length; i++) {\n            if (i in self && self[i] === sought) {\n                return i;\n            }\n        }\n        return -1;\n    };\n}\nif (!Array.prototype.lastIndexOf || ([0, 1].lastIndexOf(0, -3) != -1)) {\n    Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) {\n        var self = splitString && _toString(this) == \"[object String]\" ?\n                this.split(\"\") :\n                toObject(this),\n            length = self.length >>> 0;\n\n        if (!length) {\n            return -1;\n        }\n        var i = length - 1;\n        if (arguments.length > 1) {\n            i = Math.min(i, toInteger(arguments[1]));\n        }\n        i = i >= 0 ? i : length - Math.abs(i);\n        for (; i >= 0; i--) {\n            if (i in self && sought === self[i]) {\n                return i;\n            }\n        }\n        return -1;\n    };\n}\nif (!Object.getPrototypeOf) {\n    Object.getPrototypeOf = function getPrototypeOf(object) {\n        return object.__proto__ || (\n            object.constructor ?\n            object.constructor.prototype :\n            prototypeOfObject\n        );\n    };\n}\nif (!Object.getOwnPropertyDescriptor) {\n    var ERR_NON_OBJECT = \"Object.getOwnPropertyDescriptor called on a \" +\n                         \"non-object: \";\n    Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) {\n        if ((typeof object != \"object\" && typeof object != \"function\") || object === null)\n            throw new TypeError(ERR_NON_OBJECT + object);\n        if (!owns(object, property))\n            return;\n\n        var descriptor, getter, setter;\n        descriptor =  { enumerable: true, configurable: true };\n        if (supportsAccessors) {\n            var prototype = object.__proto__;\n            object.__proto__ = prototypeOfObject;\n\n            var getter = lookupGetter(object, property);\n            var setter = lookupSetter(object, property);\n            object.__proto__ = prototype;\n\n            if (getter || setter) {\n                if (getter) descriptor.get = getter;\n                if (setter) descriptor.set = setter;\n                return descriptor;\n            }\n        }\n        descriptor.value = object[property];\n        return descriptor;\n    };\n}\nif (!Object.getOwnPropertyNames) {\n    Object.getOwnPropertyNames = function getOwnPropertyNames(object) {\n        return Object.keys(object);\n    };\n}\nif (!Object.create) {\n    var createEmpty;\n    if (Object.prototype.__proto__ === null) {\n        createEmpty = function () {\n            return { \"__proto__\": null };\n        };\n    } else {\n        createEmpty = function () {\n            var empty = {};\n            for (var i in empty)\n                empty[i] = null;\n            empty.constructor =\n            empty.hasOwnProperty =\n            empty.propertyIsEnumerable =\n            empty.isPrototypeOf =\n            empty.toLocaleString =\n            empty.toString =\n            empty.valueOf =\n            empty.__proto__ = null;\n            return empty;\n        }\n    }\n\n    Object.create = function create(prototype, properties) {\n        var object;\n        if (prototype === null) {\n            object = createEmpty();\n        } else {\n            if (typeof prototype != \"object\")\n                throw new TypeError(\"typeof prototype[\"+(typeof prototype)+\"] != 'object'\");\n            var Type = function () {};\n            Type.prototype = prototype;\n            object = new Type();\n            object.__proto__ = prototype;\n        }\n        if (properties !== void 0)\n            Object.defineProperties(object, properties);\n        return object;\n    };\n}\n\nfunction doesDefinePropertyWork(object) {\n    try {\n        Object.defineProperty(object, \"sentinel\", {});\n        return \"sentinel\" in object;\n    } catch (exception) {\n    }\n}\nif (Object.defineProperty) {\n    var definePropertyWorksOnObject = doesDefinePropertyWork({});\n    var definePropertyWorksOnDom = typeof document == \"undefined\" ||\n        doesDefinePropertyWork(document.createElement(\"div\"));\n    if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) {\n        var definePropertyFallback = Object.defineProperty;\n    }\n}\n\nif (!Object.defineProperty || definePropertyFallback) {\n    var ERR_NON_OBJECT_DESCRIPTOR = \"Property description must be an object: \";\n    var ERR_NON_OBJECT_TARGET = \"Object.defineProperty called on non-object: \"\n    var ERR_ACCESSORS_NOT_SUPPORTED = \"getters & setters can not be defined \" +\n                                      \"on this javascript engine\";\n\n    Object.defineProperty = function defineProperty(object, property, descriptor) {\n        if ((typeof object != \"object\" && typeof object != \"function\") || object === null)\n            throw new TypeError(ERR_NON_OBJECT_TARGET + object);\n        if ((typeof descriptor != \"object\" && typeof descriptor != \"function\") || descriptor === null)\n            throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);\n        if (definePropertyFallback) {\n            try {\n                return definePropertyFallback.call(Object, object, property, descriptor);\n            } catch (exception) {\n            }\n        }\n        if (owns(descriptor, \"value\")) {\n\n            if (supportsAccessors && (lookupGetter(object, property) ||\n                                      lookupSetter(object, property)))\n            {\n                var prototype = object.__proto__;\n                object.__proto__ = prototypeOfObject;\n                delete object[property];\n                object[property] = descriptor.value;\n                object.__proto__ = prototype;\n            } else {\n                object[property] = descriptor.value;\n            }\n        } else {\n            if (!supportsAccessors)\n                throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);\n            if (owns(descriptor, \"get\"))\n                defineGetter(object, property, descriptor.get);\n            if (owns(descriptor, \"set\"))\n                defineSetter(object, property, descriptor.set);\n        }\n\n        return object;\n    };\n}\nif (!Object.defineProperties) {\n    Object.defineProperties = function defineProperties(object, properties) {\n        for (var property in properties) {\n            if (owns(properties, property))\n                Object.defineProperty(object, property, properties[property]);\n        }\n        return object;\n    };\n}\nif (!Object.seal) {\n    Object.seal = function seal(object) {\n        return object;\n    };\n}\nif (!Object.freeze) {\n    Object.freeze = function freeze(object) {\n        return object;\n    };\n}\ntry {\n    Object.freeze(function () {});\n} catch (exception) {\n    Object.freeze = (function freeze(freezeObject) {\n        return function freeze(object) {\n            if (typeof object == \"function\") {\n                return object;\n            } else {\n                return freezeObject(object);\n            }\n        };\n    })(Object.freeze);\n}\nif (!Object.preventExtensions) {\n    Object.preventExtensions = function preventExtensions(object) {\n        return object;\n    };\n}\nif (!Object.isSealed) {\n    Object.isSealed = function isSealed(object) {\n        return false;\n    };\n}\nif (!Object.isFrozen) {\n    Object.isFrozen = function isFrozen(object) {\n        return false;\n    };\n}\nif (!Object.isExtensible) {\n    Object.isExtensible = function isExtensible(object) {\n        if (Object(object) === object) {\n            throw new TypeError(); // TODO message\n        }\n        var name = '';\n        while (owns(object, name)) {\n            name += '?';\n        }\n        object[name] = true;\n        var returnValue = owns(object, name);\n        delete object[name];\n        return returnValue;\n    };\n}\nif (!Object.keys) {\n    var hasDontEnumBug = true,\n        dontEnums = [\n            \"toString\",\n            \"toLocaleString\",\n            \"valueOf\",\n            \"hasOwnProperty\",\n            \"isPrototypeOf\",\n            \"propertyIsEnumerable\",\n            \"constructor\"\n        ],\n        dontEnumsLength = dontEnums.length;\n\n    for (var key in {\"toString\": null}) {\n        hasDontEnumBug = false;\n    }\n\n    Object.keys = function keys(object) {\n\n        if (\n            (typeof object != \"object\" && typeof object != \"function\") ||\n            object === null\n        ) {\n            throw new TypeError(\"Object.keys called on a non-object\");\n        }\n\n        var keys = [];\n        for (var name in object) {\n            if (owns(object, name)) {\n                keys.push(name);\n            }\n        }\n\n        if (hasDontEnumBug) {\n            for (var i = 0, ii = dontEnumsLength; i < ii; i++) {\n                var dontEnum = dontEnums[i];\n                if (owns(object, dontEnum)) {\n                    keys.push(dontEnum);\n                }\n            }\n        }\n        return keys;\n    };\n\n}\nif (!Date.now) {\n    Date.now = function now() {\n        return new Date().getTime();\n    };\n}\nvar ws = \"\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\xA0\\u1680\\u180E\\u2000\\u2001\\u2002\\u2003\" +\n    \"\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\u2028\" +\n    \"\\u2029\\uFEFF\";\nif (!String.prototype.trim || ws.trim()) {\n    ws = \"[\" + ws + \"]\";\n    var trimBeginRegexp = new RegExp(\"^\" + ws + ws + \"*\"),\n        trimEndRegexp = new RegExp(ws + ws + \"*$\");\n    String.prototype.trim = function trim() {\n        return String(this).replace(trimBeginRegexp, \"\").replace(trimEndRegexp, \"\");\n    };\n}\n\nfunction toInteger(n) {\n    n = +n;\n    if (n !== n) { // isNaN\n        n = 0;\n    } else if (n !== 0 && n !== (1/0) && n !== -(1/0)) {\n        n = (n > 0 || -1) * Math.floor(Math.abs(n));\n    }\n    return n;\n}\n\nfunction isPrimitive(input) {\n    var type = typeof input;\n    return (\n        input === null ||\n        type === \"undefined\" ||\n        type === \"boolean\" ||\n        type === \"number\" ||\n        type === \"string\"\n    );\n}\n\nfunction toPrimitive(input) {\n    var val, valueOf, toString;\n    if (isPrimitive(input)) {\n        return input;\n    }\n    valueOf = input.valueOf;\n    if (typeof valueOf === \"function\") {\n        val = valueOf.call(input);\n        if (isPrimitive(val)) {\n            return val;\n        }\n    }\n    toString = input.toString;\n    if (typeof toString === \"function\") {\n        val = toString.call(input);\n        if (isPrimitive(val)) {\n            return val;\n        }\n    }\n    throw new TypeError();\n}\nvar toObject = function (o) {\n    if (o == null) { // this matches both null and undefined\n        throw new TypeError(\"can't convert \"+o+\" to object\");\n    }\n    return Object(o);\n};\n\n});\n"
  },
  {
    "path": "lib/applyStyle.js",
    "content": "// https://github.com/zz85/timeliner/blob/master/src/utils.js\n\nfunction applyStyle(element, var_args) {\n\tfor (var i = 1; i < arguments.length; ++i) {\n\t\tvar styles = arguments[i];\n\t\tfor (var s in styles) {\n\t\t\telement.style[s] = styles[s];\n\t\t}\n\t}\n}"
  },
  {
    "path": "lib/base64-arraybuffer.js",
    "content": "/*\n * base64-arraybuffer\n * https://github.com/niklasvh/base64-arraybuffer\n *\n * Copyright (c) 2012 Niklas von Hertzen\n * Licensed under the MIT license.\n */\nvar Base64ArrayBuffer = (function () {\n  \"use strict\";\n\n  var base64ArrayBuffer = { };\n\n  var chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n  // Use a lookup table to find the index.\n  var lookup = new Uint8Array(256);\n  for (var i = 0; i < chars.length; i++) {\n    lookup[chars.charCodeAt(i)] = i;\n  }\n\n  base64ArrayBuffer.encode = function(arraybuffer) {\n    var bytes = new Uint8Array(arraybuffer),\n    i, len = bytes.length, base64 = \"\";\n\n    for (i = 0; i < len; i+=3) {\n      base64 += chars[bytes[i] >> 2];\n      base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];\n      base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];\n      base64 += chars[bytes[i + 2] & 63];\n    }\n\n    if ((len % 3) === 2) {\n      base64 = base64.substring(0, base64.length - 1) + \"=\";\n    } else if (len % 3 === 1) {\n      base64 = base64.substring(0, base64.length - 2) + \"==\";\n    }\n\n    return base64;\n  };\n\n  base64ArrayBuffer.decode =  function(base64) {\n    var bufferLength = base64.length * 0.75,\n    len = base64.length, i, p = 0,\n    encoded1, encoded2, encoded3, encoded4;\n\n    if (base64[base64.length - 1] === \"=\") {\n      bufferLength--;\n      if (base64[base64.length - 2] === \"=\") {\n        bufferLength--;\n      }\n    }\n\n    var arraybuffer = new ArrayBuffer(bufferLength),\n    bytes = new Uint8Array(arraybuffer);\n\n    for (i = 0; i < len; i+=4) {\n      encoded1 = lookup[base64.charCodeAt(i)];\n      encoded2 = lookup[base64.charCodeAt(i+1)];\n      encoded3 = lookup[base64.charCodeAt(i+2)];\n      encoded4 = lookup[base64.charCodeAt(i+3)];\n\n      bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);\n      bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);\n      bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);\n    }\n\n    return arraybuffer;\n  };\n\n  return base64ArrayBuffer;\n\n})();\n"
  },
  {
    "path": "lib/beautify.js",
    "content": "/*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */\n/*\n\n  The MIT License (MIT)\n\n  Copyright (c) 2007-2013 Einar Lielmanis and contributors.\n\n  Permission is hereby granted, free of charge, to any person\n  obtaining a copy of this software and associated documentation files\n  (the \"Software\"), to deal in the Software without restriction,\n  including without limitation the rights to use, copy, modify, merge,\n  publish, distribute, sublicense, and/or sell copies of the Software,\n  and to permit persons to whom the Software is furnished to do so,\n  subject to the following conditions:\n\n  The above copyright notice and this permission notice shall be\n  included in all copies or substantial portions of the Software.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n  SOFTWARE.\n\n JS Beautifier\n---------------\n\n\n  Written by Einar Lielmanis, <einar@jsbeautifier.org>\n      http://jsbeautifier.org/\n\n  Originally converted to javascript by Vital, <vital76@gmail.com>\n  \"End braces on own line\" added by Chris J. Shull, <chrisjshull@gmail.com>\n  Parsing improvements for brace-less statements by Liam Newman <bitwiseman@gmail.com>\n\n\n  Usage:\n    js_beautify(js_source_text);\n    js_beautify(js_source_text, options);\n\n  The options are:\n    indent_size (default 4)          - indentation size,\n    indent_char (default space)      - character to indent with,\n    preserve_newlines (default true) - whether existing line breaks should be preserved,\n    max_preserve_newlines (default unlimited) - maximum number of line breaks to be preserved in one chunk,\n\n    jslint_happy (default false) - if true, then jslint-stricter mode is enforced.\n\n            jslint_happy        !jslint_happy\n            ---------------------------------\n            function ()         function()\n\n            switch () {         switch() {\n            case 1:               case 1:\n              break;                break;\n            }                   }\n\n    space_after_anon_function (default false) - should the space before an anonymous function's parens be added, \"function()\" vs \"function ()\",\n          NOTE: This option is overriden by jslint_happy (i.e. if jslint_happy is true, space_after_anon_function is true by design)\n\n    brace_style (default \"collapse\") - \"collapse-preserve-inline\" | \"collapse\" | \"expand\" | \"end-expand\" | \"none\"\n            put braces on the same line as control statements (default), or put braces on own line (Allman / ANSI style), or just put end braces on own line, or attempt to keep them where they are.\n\n    space_before_conditional (default true) - should the space before conditional statement be added, \"if(true)\" vs \"if (true)\",\n\n    unescape_strings (default false) - should printable characters in strings encoded in \\xNN notation be unescaped, \"example\" vs \"\\x65\\x78\\x61\\x6d\\x70\\x6c\\x65\"\n\n    wrap_line_length (default unlimited) - lines should wrap at next opportunity after this number of characters.\n          NOTE: This is not a hard limit. Lines will continue until a point where a newline would\n                be preserved if it were present.\n\n    end_with_newline (default false)  - end output with a newline\n\n\n    e.g\n\n    js_beautify(js_source_text, {\n      'indent_size': 1,\n      'indent_char': '\\t'\n    });\n\n*/\n\n// Object.values polyfill found here:\n// http://tokenposts.blogspot.com.au/2012/04/javascript-objectkeys-browser.html\nif (!Object.values) {\n    Object.values = function(o) {\n        if (o !== Object(o)) {\n            throw new TypeError('Object.values called on a non-object');\n        }\n        var k = [],\n            p;\n        for (p in o) {\n            if (Object.prototype.hasOwnProperty.call(o, p)) {\n                k.push(o[p]);\n            }\n        }\n        return k;\n    };\n}\n\n(function() {\n\n    function js_beautify(js_source_text, options) {\n\n        var acorn = {};\n        (function(exports) {\n            /* jshint curly: false */\n            // This section of code is taken from acorn.\n            //\n            // Acorn was written by Marijn Haverbeke and released under an MIT\n            // license. The Unicode regexps (for identifiers and whitespace) were\n            // taken from [Esprima](http://esprima.org) by Ariya Hidayat.\n            //\n            // Git repositories for Acorn are available at\n            //\n            //     http://marijnhaverbeke.nl/git/acorn\n            //     https://github.com/marijnh/acorn.git\n\n            // ## Character categories\n\n            // Big ugly regular expressions that match characters in the\n            // whitespace, identifier, and identifier-start categories. These\n            // are only applied when a character is found to actually have a\n            // code point above 128.\n\n            var nonASCIIwhitespace = /[\\u1680\\u180e\\u2000-\\u200a\\u202f\\u205f\\u3000\\ufeff]/; // jshint ignore:line\n            var nonASCIIidentifierStartChars = \"\\xaa\\xb5\\xba\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\u02c1\\u02c6-\\u02d1\\u02e0-\\u02e4\\u02ec\\u02ee\\u0370-\\u0374\\u0376\\u0377\\u037a-\\u037d\\u0386\\u0388-\\u038a\\u038c\\u038e-\\u03a1\\u03a3-\\u03f5\\u03f7-\\u0481\\u048a-\\u0527\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05d0-\\u05ea\\u05f0-\\u05f2\\u0620-\\u064a\\u066e\\u066f\\u0671-\\u06d3\\u06d5\\u06e5\\u06e6\\u06ee\\u06ef\\u06fa-\\u06fc\\u06ff\\u0710\\u0712-\\u072f\\u074d-\\u07a5\\u07b1\\u07ca-\\u07ea\\u07f4\\u07f5\\u07fa\\u0800-\\u0815\\u081a\\u0824\\u0828\\u0840-\\u0858\\u08a0\\u08a2-\\u08ac\\u0904-\\u0939\\u093d\\u0950\\u0958-\\u0961\\u0971-\\u0977\\u0979-\\u097f\\u0985-\\u098c\\u098f\\u0990\\u0993-\\u09a8\\u09aa-\\u09b0\\u09b2\\u09b6-\\u09b9\\u09bd\\u09ce\\u09dc\\u09dd\\u09df-\\u09e1\\u09f0\\u09f1\\u0a05-\\u0a0a\\u0a0f\\u0a10\\u0a13-\\u0a28\\u0a2a-\\u0a30\\u0a32\\u0a33\\u0a35\\u0a36\\u0a38\\u0a39\\u0a59-\\u0a5c\\u0a5e\\u0a72-\\u0a74\\u0a85-\\u0a8d\\u0a8f-\\u0a91\\u0a93-\\u0aa8\\u0aaa-\\u0ab0\\u0ab2\\u0ab3\\u0ab5-\\u0ab9\\u0abd\\u0ad0\\u0ae0\\u0ae1\\u0b05-\\u0b0c\\u0b0f\\u0b10\\u0b13-\\u0b28\\u0b2a-\\u0b30\\u0b32\\u0b33\\u0b35-\\u0b39\\u0b3d\\u0b5c\\u0b5d\\u0b5f-\\u0b61\\u0b71\\u0b83\\u0b85-\\u0b8a\\u0b8e-\\u0b90\\u0b92-\\u0b95\\u0b99\\u0b9a\\u0b9c\\u0b9e\\u0b9f\\u0ba3\\u0ba4\\u0ba8-\\u0baa\\u0bae-\\u0bb9\\u0bd0\\u0c05-\\u0c0c\\u0c0e-\\u0c10\\u0c12-\\u0c28\\u0c2a-\\u0c33\\u0c35-\\u0c39\\u0c3d\\u0c58\\u0c59\\u0c60\\u0c61\\u0c85-\\u0c8c\\u0c8e-\\u0c90\\u0c92-\\u0ca8\\u0caa-\\u0cb3\\u0cb5-\\u0cb9\\u0cbd\\u0cde\\u0ce0\\u0ce1\\u0cf1\\u0cf2\\u0d05-\\u0d0c\\u0d0e-\\u0d10\\u0d12-\\u0d3a\\u0d3d\\u0d4e\\u0d60\\u0d61\\u0d7a-\\u0d7f\\u0d85-\\u0d96\\u0d9a-\\u0db1\\u0db3-\\u0dbb\\u0dbd\\u0dc0-\\u0dc6\\u0e01-\\u0e30\\u0e32\\u0e33\\u0e40-\\u0e46\\u0e81\\u0e82\\u0e84\\u0e87\\u0e88\\u0e8a\\u0e8d\\u0e94-\\u0e97\\u0e99-\\u0e9f\\u0ea1-\\u0ea3\\u0ea5\\u0ea7\\u0eaa\\u0eab\\u0ead-\\u0eb0\\u0eb2\\u0eb3\\u0ebd\\u0ec0-\\u0ec4\\u0ec6\\u0edc-\\u0edf\\u0f00\\u0f40-\\u0f47\\u0f49-\\u0f6c\\u0f88-\\u0f8c\\u1000-\\u102a\\u103f\\u1050-\\u1055\\u105a-\\u105d\\u1061\\u1065\\u1066\\u106e-\\u1070\\u1075-\\u1081\\u108e\\u10a0-\\u10c5\\u10c7\\u10cd\\u10d0-\\u10fa\\u10fc-\\u1248\\u124a-\\u124d\\u1250-\\u1256\\u1258\\u125a-\\u125d\\u1260-\\u1288\\u128a-\\u128d\\u1290-\\u12b0\\u12b2-\\u12b5\\u12b8-\\u12be\\u12c0\\u12c2-\\u12c5\\u12c8-\\u12d6\\u12d8-\\u1310\\u1312-\\u1315\\u1318-\\u135a\\u1380-\\u138f\\u13a0-\\u13f4\\u1401-\\u166c\\u166f-\\u167f\\u1681-\\u169a\\u16a0-\\u16ea\\u16ee-\\u16f0\\u1700-\\u170c\\u170e-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176c\\u176e-\\u1770\\u1780-\\u17b3\\u17d7\\u17dc\\u1820-\\u1877\\u1880-\\u18a8\\u18aa\\u18b0-\\u18f5\\u1900-\\u191c\\u1950-\\u196d\\u1970-\\u1974\\u1980-\\u19ab\\u19c1-\\u19c7\\u1a00-\\u1a16\\u1a20-\\u1a54\\u1aa7\\u1b05-\\u1b33\\u1b45-\\u1b4b\\u1b83-\\u1ba0\\u1bae\\u1baf\\u1bba-\\u1be5\\u1c00-\\u1c23\\u1c4d-\\u1c4f\\u1c5a-\\u1c7d\\u1ce9-\\u1cec\\u1cee-\\u1cf1\\u1cf5\\u1cf6\\u1d00-\\u1dbf\\u1e00-\\u1f15\\u1f18-\\u1f1d\\u1f20-\\u1f45\\u1f48-\\u1f4d\\u1f50-\\u1f57\\u1f59\\u1f5b\\u1f5d\\u1f5f-\\u1f7d\\u1f80-\\u1fb4\\u1fb6-\\u1fbc\\u1fbe\\u1fc2-\\u1fc4\\u1fc6-\\u1fcc\\u1fd0-\\u1fd3\\u1fd6-\\u1fdb\\u1fe0-\\u1fec\\u1ff2-\\u1ff4\\u1ff6-\\u1ffc\\u2071\\u207f\\u2090-\\u209c\\u2102\\u2107\\u210a-\\u2113\\u2115\\u2119-\\u211d\\u2124\\u2126\\u2128\\u212a-\\u212d\\u212f-\\u2139\\u213c-\\u213f\\u2145-\\u2149\\u214e\\u2160-\\u2188\\u2c00-\\u2c2e\\u2c30-\\u2c5e\\u2c60-\\u2ce4\\u2ceb-\\u2cee\\u2cf2\\u2cf3\\u2d00-\\u2d25\\u2d27\\u2d2d\\u2d30-\\u2d67\\u2d6f\\u2d80-\\u2d96\\u2da0-\\u2da6\\u2da8-\\u2dae\\u2db0-\\u2db6\\u2db8-\\u2dbe\\u2dc0-\\u2dc6\\u2dc8-\\u2dce\\u2dd0-\\u2dd6\\u2dd8-\\u2dde\\u2e2f\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303c\\u3041-\\u3096\\u309d-\\u309f\\u30a1-\\u30fa\\u30fc-\\u30ff\\u3105-\\u312d\\u3131-\\u318e\\u31a0-\\u31ba\\u31f0-\\u31ff\\u3400-\\u4db5\\u4e00-\\u9fcc\\ua000-\\ua48c\\ua4d0-\\ua4fd\\ua500-\\ua60c\\ua610-\\ua61f\\ua62a\\ua62b\\ua640-\\ua66e\\ua67f-\\ua697\\ua6a0-\\ua6ef\\ua717-\\ua71f\\ua722-\\ua788\\ua78b-\\ua78e\\ua790-\\ua793\\ua7a0-\\ua7aa\\ua7f8-\\ua801\\ua803-\\ua805\\ua807-\\ua80a\\ua80c-\\ua822\\ua840-\\ua873\\ua882-\\ua8b3\\ua8f2-\\ua8f7\\ua8fb\\ua90a-\\ua925\\ua930-\\ua946\\ua960-\\ua97c\\ua984-\\ua9b2\\ua9cf\\uaa00-\\uaa28\\uaa40-\\uaa42\\uaa44-\\uaa4b\\uaa60-\\uaa76\\uaa7a\\uaa80-\\uaaaf\\uaab1\\uaab5\\uaab6\\uaab9-\\uaabd\\uaac0\\uaac2\\uaadb-\\uaadd\\uaae0-\\uaaea\\uaaf2-\\uaaf4\\uab01-\\uab06\\uab09-\\uab0e\\uab11-\\uab16\\uab20-\\uab26\\uab28-\\uab2e\\uabc0-\\uabe2\\uac00-\\ud7a3\\ud7b0-\\ud7c6\\ud7cb-\\ud7fb\\uf900-\\ufa6d\\ufa70-\\ufad9\\ufb00-\\ufb06\\ufb13-\\ufb17\\ufb1d\\ufb1f-\\ufb28\\ufb2a-\\ufb36\\ufb38-\\ufb3c\\ufb3e\\ufb40\\ufb41\\ufb43\\ufb44\\ufb46-\\ufbb1\\ufbd3-\\ufd3d\\ufd50-\\ufd8f\\ufd92-\\ufdc7\\ufdf0-\\ufdfb\\ufe70-\\ufe74\\ufe76-\\ufefc\\uff21-\\uff3a\\uff41-\\uff5a\\uff66-\\uffbe\\uffc2-\\uffc7\\uffca-\\uffcf\\uffd2-\\uffd7\\uffda-\\uffdc\";\n            var nonASCIIidentifierChars = \"\\u0300-\\u036f\\u0483-\\u0487\\u0591-\\u05bd\\u05bf\\u05c1\\u05c2\\u05c4\\u05c5\\u05c7\\u0610-\\u061a\\u0620-\\u0649\\u0672-\\u06d3\\u06e7-\\u06e8\\u06fb-\\u06fc\\u0730-\\u074a\\u0800-\\u0814\\u081b-\\u0823\\u0825-\\u0827\\u0829-\\u082d\\u0840-\\u0857\\u08e4-\\u08fe\\u0900-\\u0903\\u093a-\\u093c\\u093e-\\u094f\\u0951-\\u0957\\u0962-\\u0963\\u0966-\\u096f\\u0981-\\u0983\\u09bc\\u09be-\\u09c4\\u09c7\\u09c8\\u09d7\\u09df-\\u09e0\\u0a01-\\u0a03\\u0a3c\\u0a3e-\\u0a42\\u0a47\\u0a48\\u0a4b-\\u0a4d\\u0a51\\u0a66-\\u0a71\\u0a75\\u0a81-\\u0a83\\u0abc\\u0abe-\\u0ac5\\u0ac7-\\u0ac9\\u0acb-\\u0acd\\u0ae2-\\u0ae3\\u0ae6-\\u0aef\\u0b01-\\u0b03\\u0b3c\\u0b3e-\\u0b44\\u0b47\\u0b48\\u0b4b-\\u0b4d\\u0b56\\u0b57\\u0b5f-\\u0b60\\u0b66-\\u0b6f\\u0b82\\u0bbe-\\u0bc2\\u0bc6-\\u0bc8\\u0bca-\\u0bcd\\u0bd7\\u0be6-\\u0bef\\u0c01-\\u0c03\\u0c46-\\u0c48\\u0c4a-\\u0c4d\\u0c55\\u0c56\\u0c62-\\u0c63\\u0c66-\\u0c6f\\u0c82\\u0c83\\u0cbc\\u0cbe-\\u0cc4\\u0cc6-\\u0cc8\\u0cca-\\u0ccd\\u0cd5\\u0cd6\\u0ce2-\\u0ce3\\u0ce6-\\u0cef\\u0d02\\u0d03\\u0d46-\\u0d48\\u0d57\\u0d62-\\u0d63\\u0d66-\\u0d6f\\u0d82\\u0d83\\u0dca\\u0dcf-\\u0dd4\\u0dd6\\u0dd8-\\u0ddf\\u0df2\\u0df3\\u0e34-\\u0e3a\\u0e40-\\u0e45\\u0e50-\\u0e59\\u0eb4-\\u0eb9\\u0ec8-\\u0ecd\\u0ed0-\\u0ed9\\u0f18\\u0f19\\u0f20-\\u0f29\\u0f35\\u0f37\\u0f39\\u0f41-\\u0f47\\u0f71-\\u0f84\\u0f86-\\u0f87\\u0f8d-\\u0f97\\u0f99-\\u0fbc\\u0fc6\\u1000-\\u1029\\u1040-\\u1049\\u1067-\\u106d\\u1071-\\u1074\\u1082-\\u108d\\u108f-\\u109d\\u135d-\\u135f\\u170e-\\u1710\\u1720-\\u1730\\u1740-\\u1750\\u1772\\u1773\\u1780-\\u17b2\\u17dd\\u17e0-\\u17e9\\u180b-\\u180d\\u1810-\\u1819\\u1920-\\u192b\\u1930-\\u193b\\u1951-\\u196d\\u19b0-\\u19c0\\u19c8-\\u19c9\\u19d0-\\u19d9\\u1a00-\\u1a15\\u1a20-\\u1a53\\u1a60-\\u1a7c\\u1a7f-\\u1a89\\u1a90-\\u1a99\\u1b46-\\u1b4b\\u1b50-\\u1b59\\u1b6b-\\u1b73\\u1bb0-\\u1bb9\\u1be6-\\u1bf3\\u1c00-\\u1c22\\u1c40-\\u1c49\\u1c5b-\\u1c7d\\u1cd0-\\u1cd2\\u1d00-\\u1dbe\\u1e01-\\u1f15\\u200c\\u200d\\u203f\\u2040\\u2054\\u20d0-\\u20dc\\u20e1\\u20e5-\\u20f0\\u2d81-\\u2d96\\u2de0-\\u2dff\\u3021-\\u3028\\u3099\\u309a\\ua640-\\ua66d\\ua674-\\ua67d\\ua69f\\ua6f0-\\ua6f1\\ua7f8-\\ua800\\ua806\\ua80b\\ua823-\\ua827\\ua880-\\ua881\\ua8b4-\\ua8c4\\ua8d0-\\ua8d9\\ua8f3-\\ua8f7\\ua900-\\ua909\\ua926-\\ua92d\\ua930-\\ua945\\ua980-\\ua983\\ua9b3-\\ua9c0\\uaa00-\\uaa27\\uaa40-\\uaa41\\uaa4c-\\uaa4d\\uaa50-\\uaa59\\uaa7b\\uaae0-\\uaae9\\uaaf2-\\uaaf3\\uabc0-\\uabe1\\uabec\\uabed\\uabf0-\\uabf9\\ufb20-\\ufb28\\ufe00-\\ufe0f\\ufe20-\\ufe26\\ufe33\\ufe34\\ufe4d-\\ufe4f\\uff10-\\uff19\\uff3f\";\n            var nonASCIIidentifierStart = new RegExp(\"[\" + nonASCIIidentifierStartChars + \"]\");\n            var nonASCIIidentifier = new RegExp(\"[\" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + \"]\");\n\n            // Whether a single character denotes a newline.\n\n            exports.newline = /[\\n\\r\\u2028\\u2029]/;\n\n            // Matches a whole line break (where CRLF is considered a single\n            // line break). Used to count lines.\n\n            // in javascript, these two differ\n            // in python they are the same, different methods are called on them\n            exports.lineBreak = new RegExp('\\r\\n|' + exports.newline.source);\n            exports.allLineBreaks = new RegExp(exports.lineBreak.source, 'g');\n\n\n            // Test whether a given character code starts an identifier.\n\n            exports.isIdentifierStart = function(code) {\n                // permit $ (36) and @ (64). @ is used in ES7 decorators.\n                if (code < 65) return code === 36 || code === 64;\n                // 65 through 91 are uppercase letters.\n                if (code < 91) return true;\n                // permit _ (95).\n                if (code < 97) return code === 95;\n                // 97 through 123 are lowercase letters.\n                if (code < 123) return true;\n                return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code));\n            };\n\n            // Test whether a given character is part of an identifier.\n\n            exports.isIdentifierChar = function(code) {\n                if (code < 48) return code === 36;\n                if (code < 58) return true;\n                if (code < 65) return false;\n                if (code < 91) return true;\n                if (code < 97) return code === 95;\n                if (code < 123) return true;\n                return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code));\n            };\n        })(acorn);\n        /* jshint curly: true */\n\n        function in_array(what, arr) {\n            for (var i = 0; i < arr.length; i += 1) {\n                if (arr[i] === what) {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        function trim(s) {\n            return s.replace(/^\\s+|\\s+$/g, '');\n        }\n\n        function ltrim(s) {\n            return s.replace(/^\\s+/g, '');\n        }\n\n        // function rtrim(s) {\n        //     return s.replace(/\\s+$/g, '');\n        // }\n\n        function sanitizeOperatorPosition(opPosition) {\n            opPosition = opPosition || OPERATOR_POSITION.before_newline;\n\n            var validPositionValues = Object.values(OPERATOR_POSITION);\n\n            if (!in_array(opPosition, validPositionValues)) {\n                throw new Error(\"Invalid Option Value: The option 'operator_position' must be one of the following values\\n\" +\n                    validPositionValues +\n                    \"\\nYou passed in: '\" + opPosition + \"'\");\n            }\n\n            return opPosition;\n        }\n\n        var OPERATOR_POSITION = {\n            before_newline: 'before-newline',\n            after_newline: 'after-newline',\n            preserve_newline: 'preserve-newline',\n        };\n\n        var OPERATOR_POSITION_BEFORE_OR_PRESERVE = [OPERATOR_POSITION.before_newline, OPERATOR_POSITION.preserve_newline];\n\n        var MODE = {\n            BlockStatement: 'BlockStatement', // 'BLOCK'\n            Statement: 'Statement', // 'STATEMENT'\n            ObjectLiteral: 'ObjectLiteral', // 'OBJECT',\n            ArrayLiteral: 'ArrayLiteral', //'[EXPRESSION]',\n            ForInitializer: 'ForInitializer', //'(FOR-EXPRESSION)',\n            Conditional: 'Conditional', //'(COND-EXPRESSION)',\n            Expression: 'Expression' //'(EXPRESSION)'\n        };\n\n        function Beautifier(js_source_text, options) {\n            \"use strict\";\n            var output;\n            var tokens = [],\n                token_pos;\n            var Tokenizer;\n            var current_token;\n            var last_type, last_last_text, indent_string;\n            var flags, previous_flags, flag_store;\n            var prefix;\n\n            var handlers, opt;\n            var baseIndentString = '';\n\n            handlers = {\n                'TK_START_EXPR': handle_start_expr,\n                'TK_END_EXPR': handle_end_expr,\n                'TK_START_BLOCK': handle_start_block,\n                'TK_END_BLOCK': handle_end_block,\n                'TK_WORD': handle_word,\n                'TK_RESERVED': handle_word,\n                'TK_SEMICOLON': handle_semicolon,\n                'TK_STRING': handle_string,\n                'TK_EQUALS': handle_equals,\n                'TK_OPERATOR': handle_operator,\n                'TK_COMMA': handle_comma,\n                'TK_BLOCK_COMMENT': handle_block_comment,\n                'TK_COMMENT': handle_comment,\n                'TK_DOT': handle_dot,\n                'TK_UNKNOWN': handle_unknown,\n                'TK_EOF': handle_eof\n            };\n\n            function create_flags(flags_base, mode) {\n                var next_indent_level = 0;\n                if (flags_base) {\n                    next_indent_level = flags_base.indentation_level;\n                    if (!output.just_added_newline() &&\n                        flags_base.line_indent_level > next_indent_level) {\n                        next_indent_level = flags_base.line_indent_level;\n                    }\n                }\n\n                var next_flags = {\n                    mode: mode,\n                    parent: flags_base,\n                    last_text: flags_base ? flags_base.last_text : '', // last token text\n                    last_word: flags_base ? flags_base.last_word : '', // last 'TK_WORD' passed\n                    declaration_statement: false,\n                    declaration_assignment: false,\n                    multiline_frame: false,\n                    inline_frame: false,\n                    if_block: false,\n                    else_block: false,\n                    do_block: false,\n                    do_while: false,\n                    import_block: false,\n                    in_case_statement: false, // switch(..){ INSIDE HERE }\n                    in_case: false, // we're on the exact line with \"case 0:\"\n                    case_body: false, // the indented case-action block\n                    indentation_level: next_indent_level,\n                    line_indent_level: flags_base ? flags_base.line_indent_level : next_indent_level,\n                    start_line_index: output.get_line_number(),\n                    ternary_depth: 0\n                };\n                return next_flags;\n            }\n\n            // Some interpreters have unexpected results with foo = baz || bar;\n            options = options ? options : {};\n            opt = {};\n\n            // compatibility\n            if (options.braces_on_own_line !== undefined) { //graceful handling of deprecated option\n                opt.brace_style = options.braces_on_own_line ? \"expand\" : \"collapse\";\n            }\n            opt.brace_style = options.brace_style ? options.brace_style : (opt.brace_style ? opt.brace_style : \"collapse\");\n\n            // graceful handling of deprecated option\n            if (opt.brace_style === \"expand-strict\") {\n                opt.brace_style = \"expand\";\n            }\n\n            opt.indent_size = options.indent_size ? parseInt(options.indent_size, 10) : 4;\n            opt.indent_char = options.indent_char ? options.indent_char : ' ';\n            opt.eol = options.eol ? options.eol : 'auto';\n            opt.preserve_newlines = (options.preserve_newlines === undefined) ? true : options.preserve_newlines;\n            opt.break_chained_methods = (options.break_chained_methods === undefined) ? false : options.break_chained_methods;\n            opt.max_preserve_newlines = (options.max_preserve_newlines === undefined) ? 0 : parseInt(options.max_preserve_newlines, 10);\n            opt.space_in_paren = (options.space_in_paren === undefined) ? false : options.space_in_paren;\n            opt.space_in_empty_paren = (options.space_in_empty_paren === undefined) ? false : options.space_in_empty_paren;\n            opt.jslint_happy = (options.jslint_happy === undefined) ? false : options.jslint_happy;\n            opt.space_after_anon_function = (options.space_after_anon_function === undefined) ? false : options.space_after_anon_function;\n            opt.keep_array_indentation = (options.keep_array_indentation === undefined) ? false : options.keep_array_indentation;\n            opt.space_before_conditional = (options.space_before_conditional === undefined) ? true : options.space_before_conditional;\n            opt.unescape_strings = (options.unescape_strings === undefined) ? false : options.unescape_strings;\n            opt.wrap_line_length = (options.wrap_line_length === undefined) ? 0 : parseInt(options.wrap_line_length, 10);\n            opt.e4x = (options.e4x === undefined) ? false : options.e4x;\n            opt.end_with_newline = (options.end_with_newline === undefined) ? false : options.end_with_newline;\n            opt.comma_first = (options.comma_first === undefined) ? false : options.comma_first;\n            opt.operator_position = sanitizeOperatorPosition(options.operator_position);\n\n            // For testing of beautify ignore:start directive\n            opt.test_output_raw = (options.test_output_raw === undefined) ? false : options.test_output_raw;\n\n            // force opt.space_after_anon_function to true if opt.jslint_happy\n            if (opt.jslint_happy) {\n                opt.space_after_anon_function = true;\n            }\n\n            if (options.indent_with_tabs) {\n                opt.indent_char = '\\t';\n                opt.indent_size = 1;\n            }\n\n            if (opt.eol === 'auto') {\n                opt.eol = '\\n';\n                if (js_source_text && acorn.lineBreak.test(js_source_text || '')) {\n                    opt.eol = js_source_text.match(acorn.lineBreak)[0];\n                }\n            }\n\n            opt.eol = opt.eol.replace(/\\\\r/, '\\r').replace(/\\\\n/, '\\n');\n\n            //----------------------------------\n            indent_string = '';\n            while (opt.indent_size > 0) {\n                indent_string += opt.indent_char;\n                opt.indent_size -= 1;\n            }\n\n            var preindent_index = 0;\n            if (js_source_text && js_source_text.length) {\n                while ((js_source_text.charAt(preindent_index) === ' ' ||\n                        js_source_text.charAt(preindent_index) === '\\t')) {\n                    baseIndentString += js_source_text.charAt(preindent_index);\n                    preindent_index += 1;\n                }\n                js_source_text = js_source_text.substring(preindent_index);\n            }\n\n            last_type = 'TK_START_BLOCK'; // last token type\n            last_last_text = ''; // pre-last token text\n            output = new Output(indent_string, baseIndentString);\n\n            // If testing the ignore directive, start with output disable set to true\n            output.raw = opt.test_output_raw;\n\n\n            // Stack of parsing/formatting states, including MODE.\n            // We tokenize, parse, and output in an almost purely a forward-only stream of token input\n            // and formatted output.  This makes the beautifier less accurate than full parsers\n            // but also far more tolerant of syntax errors.\n            //\n            // For example, the default mode is MODE.BlockStatement. If we see a '{' we push a new frame of type\n            // MODE.BlockStatement on the the stack, even though it could be object literal.  If we later\n            // encounter a \":\", we'll switch to to MODE.ObjectLiteral.  If we then see a \";\",\n            // most full parsers would die, but the beautifier gracefully falls back to\n            // MODE.BlockStatement and continues on.\n            flag_store = [];\n            set_mode(MODE.BlockStatement);\n\n            this.beautify = function() {\n\n                /*jshint onevar:true */\n                var local_token, sweet_code;\n                Tokenizer = new tokenizer(js_source_text, opt, indent_string);\n                tokens = Tokenizer.tokenize();\n                token_pos = 0;\n\n                function get_local_token() {\n                    local_token = get_token();\n                    return local_token;\n                }\n\n                while (get_local_token()) {\n                    for (var i = 0; i < local_token.comments_before.length; i++) {\n                        // The cleanest handling of inline comments is to treat them as though they aren't there.\n                        // Just continue formatting and the behavior should be logical.\n                        // Also ignore unknown tokens.  Again, this should result in better behavior.\n                        handle_token(local_token.comments_before[i]);\n                    }\n                    handle_token(local_token);\n\n                    last_last_text = flags.last_text;\n                    last_type = local_token.type;\n                    flags.last_text = local_token.text;\n\n                    token_pos += 1;\n                }\n\n                sweet_code = output.get_code();\n                if (opt.end_with_newline) {\n                    sweet_code += '\\n';\n                }\n\n                if (opt.eol !== '\\n') {\n                    sweet_code = sweet_code.replace(/[\\n]/g, opt.eol);\n                }\n\n                return sweet_code;\n            };\n\n            function handle_token(local_token) {\n                var newlines = local_token.newlines;\n                var keep_whitespace = opt.keep_array_indentation && is_array(flags.mode);\n\n                if (keep_whitespace) {\n                    for (var i = 0; i < newlines; i += 1) {\n                        print_newline(i > 0);\n                    }\n                } else {\n                    if (opt.max_preserve_newlines && newlines > opt.max_preserve_newlines) {\n                        newlines = opt.max_preserve_newlines;\n                    }\n\n                    if (opt.preserve_newlines) {\n                        if (local_token.newlines > 1) {\n                            print_newline();\n                            for (var j = 1; j < newlines; j += 1) {\n                                print_newline(true);\n                            }\n                        }\n                    }\n                }\n\n                current_token = local_token;\n                handlers[current_token.type]();\n            }\n\n            // we could use just string.split, but\n            // IE doesn't like returning empty strings\n            function split_linebreaks(s) {\n                //return s.split(/\\x0d\\x0a|\\x0a/);\n\n                s = s.replace(acorn.allLineBreaks, '\\n');\n                var out = [],\n                    idx = s.indexOf(\"\\n\");\n                while (idx !== -1) {\n                    out.push(s.substring(0, idx));\n                    s = s.substring(idx + 1);\n                    idx = s.indexOf(\"\\n\");\n                }\n                if (s.length) {\n                    out.push(s);\n                }\n                return out;\n            }\n\n            var newline_restricted_tokens = ['break', 'contiue', 'return', 'throw'];\n\n            function allow_wrap_or_preserved_newline(force_linewrap) {\n                force_linewrap = (force_linewrap === undefined) ? false : force_linewrap;\n\n                // Never wrap the first token on a line\n                if (output.just_added_newline()) {\n                    return;\n                }\n\n                var shouldPreserveOrForce = (opt.preserve_newlines && current_token.wanted_newline) || force_linewrap;\n                var operatorLogicApplies = in_array(flags.last_text, Tokenizer.positionable_operators) || in_array(current_token.text, Tokenizer.positionable_operators);\n\n                if (operatorLogicApplies) {\n                    var shouldPrintOperatorNewline = (\n                            in_array(flags.last_text, Tokenizer.positionable_operators) &&\n                            in_array(opt.operator_position, OPERATOR_POSITION_BEFORE_OR_PRESERVE)\n                        ) ||\n                        in_array(current_token.text, Tokenizer.positionable_operators);\n                    shouldPreserveOrForce = shouldPreserveOrForce && shouldPrintOperatorNewline;\n                }\n\n                if (shouldPreserveOrForce) {\n                    print_newline(false, true);\n                } else if (opt.wrap_line_length) {\n                    if (last_type === 'TK_RESERVED' && in_array(flags.last_text, newline_restricted_tokens)) {\n                        // These tokens should never have a newline inserted\n                        // between them and the following expression.\n                        return;\n                    }\n                    var proposed_line_length = output.current_line.get_character_count() + current_token.text.length +\n                        (output.space_before_token ? 1 : 0);\n                    if (proposed_line_length >= opt.wrap_line_length) {\n                        print_newline(false, true);\n                    }\n                }\n            }\n\n            function print_newline(force_newline, preserve_statement_flags) {\n                if (!preserve_statement_flags) {\n                    if (flags.last_text !== ';' && flags.last_text !== ',' && flags.last_text !== '=' && last_type !== 'TK_OPERATOR') {\n                        while (flags.mode === MODE.Statement && !flags.if_block && !flags.do_block) {\n                            restore_mode();\n                        }\n                    }\n                }\n\n                if (output.add_new_line(force_newline)) {\n                    flags.multiline_frame = true;\n                }\n            }\n\n            function print_token_line_indentation() {\n                if (output.just_added_newline()) {\n                    if (opt.keep_array_indentation && is_array(flags.mode) && current_token.wanted_newline) {\n                        output.current_line.push(current_token.whitespace_before);\n                        output.space_before_token = false;\n                    } else if (output.set_indent(flags.indentation_level)) {\n                        flags.line_indent_level = flags.indentation_level;\n                    }\n                }\n            }\n\n            function print_token(printable_token) {\n                if (output.raw) {\n                    output.add_raw_token(current_token);\n                    return;\n                }\n\n                if (opt.comma_first && last_type === 'TK_COMMA' &&\n                    output.just_added_newline()) {\n                    if (output.previous_line.last() === ',') {\n                        var popped = output.previous_line.pop();\n                        // if the comma was already at the start of the line,\n                        // pull back onto that line and reprint the indentation\n                        if (output.previous_line.is_empty()) {\n                            output.previous_line.push(popped);\n                            output.trim(true);\n                            output.current_line.pop();\n                            output.trim();\n                        }\n\n                        // add the comma in front of the next token\n                        print_token_line_indentation();\n                        output.add_token(',');\n                        output.space_before_token = true;\n                    }\n                }\n\n                printable_token = printable_token || current_token.text;\n                print_token_line_indentation();\n                output.add_token(printable_token);\n            }\n\n            function indent() {\n                flags.indentation_level += 1;\n            }\n\n            function deindent() {\n                if (flags.indentation_level > 0 &&\n                    ((!flags.parent) || flags.indentation_level > flags.parent.indentation_level)) {\n                    flags.indentation_level -= 1;\n\n                }\n            }\n\n            function set_mode(mode) {\n                if (flags) {\n                    flag_store.push(flags);\n                    previous_flags = flags;\n                } else {\n                    previous_flags = create_flags(null, mode);\n                }\n\n                flags = create_flags(previous_flags, mode);\n            }\n\n            function is_array(mode) {\n                return mode === MODE.ArrayLiteral;\n            }\n\n            function is_expression(mode) {\n                return in_array(mode, [MODE.Expression, MODE.ForInitializer, MODE.Conditional]);\n            }\n\n            function restore_mode() {\n                if (flag_store.length > 0) {\n                    previous_flags = flags;\n                    flags = flag_store.pop();\n                    if (previous_flags.mode === MODE.Statement) {\n                        output.remove_redundant_indentation(previous_flags);\n                    }\n                }\n            }\n\n            function start_of_object_property() {\n                return flags.parent.mode === MODE.ObjectLiteral && flags.mode === MODE.Statement && (\n                    (flags.last_text === ':' && flags.ternary_depth === 0) || (last_type === 'TK_RESERVED' && in_array(flags.last_text, ['get', 'set'])));\n            }\n\n            function start_of_statement() {\n                if (\n                    (last_type === 'TK_RESERVED' && in_array(flags.last_text, ['var', 'let', 'const']) && current_token.type === 'TK_WORD') ||\n                    (last_type === 'TK_RESERVED' && flags.last_text === 'do') ||\n                    (last_type === 'TK_RESERVED' && in_array(flags.last_text, ['return', 'throw']) && !current_token.wanted_newline) ||\n                    (last_type === 'TK_RESERVED' && flags.last_text === 'else' && !(current_token.type === 'TK_RESERVED' && current_token.text === 'if')) ||\n                    (last_type === 'TK_END_EXPR' && (previous_flags.mode === MODE.ForInitializer || previous_flags.mode === MODE.Conditional)) ||\n                    (last_type === 'TK_WORD' && flags.mode === MODE.BlockStatement &&\n                        !flags.in_case &&\n                        !(current_token.text === '--' || current_token.text === '++') &&\n                        last_last_text !== 'function' &&\n                        current_token.type !== 'TK_WORD' && current_token.type !== 'TK_RESERVED') ||\n                    (flags.mode === MODE.ObjectLiteral && (\n                        (flags.last_text === ':' && flags.ternary_depth === 0) || (last_type === 'TK_RESERVED' && in_array(flags.last_text, ['get', 'set']))))\n                ) {\n\n                    set_mode(MODE.Statement);\n                    indent();\n\n                    if (last_type === 'TK_RESERVED' && in_array(flags.last_text, ['var', 'let', 'const']) && current_token.type === 'TK_WORD') {\n                        flags.declaration_statement = true;\n                    }\n\n                    // Issue #276:\n                    // If starting a new statement with [if, for, while, do], push to a new line.\n                    // if (a) if (b) if(c) d(); else e(); else f();\n                    if (!start_of_object_property()) {\n                        allow_wrap_or_preserved_newline(\n                            current_token.type === 'TK_RESERVED' && in_array(current_token.text, ['do', 'for', 'if', 'while']));\n                    }\n\n                    return true;\n                }\n                return false;\n            }\n\n            function all_lines_start_with(lines, c) {\n                for (var i = 0; i < lines.length; i++) {\n                    var line = trim(lines[i]);\n                    if (line.charAt(0) !== c) {\n                        return false;\n                    }\n                }\n                return true;\n            }\n\n            function each_line_matches_indent(lines, indent) {\n                var i = 0,\n                    len = lines.length,\n                    line;\n                for (; i < len; i++) {\n                    line = lines[i];\n                    // allow empty lines to pass through\n                    if (line && line.indexOf(indent) !== 0) {\n                        return false;\n                    }\n                }\n                return true;\n            }\n\n            function is_special_word(word) {\n                return in_array(word, ['case', 'return', 'do', 'if', 'throw', 'else']);\n            }\n\n            function get_token(offset) {\n                var index = token_pos + (offset || 0);\n                return (index < 0 || index >= tokens.length) ? null : tokens[index];\n            }\n\n            function handle_start_expr() {\n                if (start_of_statement()) {\n                    // The conditional starts the statement if appropriate.\n                }\n\n                var next_mode = MODE.Expression;\n                if (current_token.text === '[') {\n\n                    if (last_type === 'TK_WORD' || flags.last_text === ')') {\n                        // this is array index specifier, break immediately\n                        // a[x], fn()[x]\n                        if (last_type === 'TK_RESERVED' && in_array(flags.last_text, Tokenizer.line_starters)) {\n                            output.space_before_token = true;\n                        }\n                        set_mode(next_mode);\n                        print_token();\n                        indent();\n                        if (opt.space_in_paren) {\n                            output.space_before_token = true;\n                        }\n                        return;\n                    }\n\n                    next_mode = MODE.ArrayLiteral;\n                    if (is_array(flags.mode)) {\n                        if (flags.last_text === '[' ||\n                            (flags.last_text === ',' && (last_last_text === ']' || last_last_text === '}'))) {\n                            // ], [ goes to new line\n                            // }, [ goes to new line\n                            if (!opt.keep_array_indentation) {\n                                print_newline();\n                            }\n                        }\n                    }\n\n                } else {\n                    if (last_type === 'TK_RESERVED' && flags.last_text === 'for') {\n                        next_mode = MODE.ForInitializer;\n                    } else if (last_type === 'TK_RESERVED' && in_array(flags.last_text, ['if', 'while'])) {\n                        next_mode = MODE.Conditional;\n                    } else {\n                        // next_mode = MODE.Expression;\n                    }\n                }\n\n                if (flags.last_text === ';' || last_type === 'TK_START_BLOCK') {\n                    print_newline();\n                } else if (last_type === 'TK_END_EXPR' || last_type === 'TK_START_EXPR' || last_type === 'TK_END_BLOCK' || flags.last_text === '.') {\n                    // TODO: Consider whether forcing this is required.  Review failing tests when removed.\n                    allow_wrap_or_preserved_newline(current_token.wanted_newline);\n                    // do nothing on (( and )( and ][ and ]( and .(\n                } else if (!(last_type === 'TK_RESERVED' && current_token.text === '(') && last_type !== 'TK_WORD' && last_type !== 'TK_OPERATOR') {\n                    output.space_before_token = true;\n                } else if ((last_type === 'TK_RESERVED' && (flags.last_word === 'function' || flags.last_word === 'typeof')) ||\n                    (flags.last_text === '*' && last_last_text === 'function')) {\n                    // function() vs function ()\n                    if (opt.space_after_anon_function) {\n                        output.space_before_token = true;\n                    }\n                } else if (last_type === 'TK_RESERVED' && (in_array(flags.last_text, Tokenizer.line_starters) || flags.last_text === 'catch')) {\n                    if (opt.space_before_conditional) {\n                        output.space_before_token = true;\n                    }\n                }\n\n                // Should be a space between await and an IIFE\n                if (current_token.text === '(' && last_type === 'TK_RESERVED' && flags.last_word === 'await') {\n                    output.space_before_token = true;\n                }\n\n                // Support of this kind of newline preservation.\n                // a = (b &&\n                //     (c || d));\n                if (current_token.text === '(') {\n                    if (last_type === 'TK_EQUALS' || last_type === 'TK_OPERATOR') {\n                        if (!start_of_object_property()) {\n                            allow_wrap_or_preserved_newline();\n                        }\n                    }\n                }\n\n                // Support preserving wrapped arrow function expressions\n                // a.b('c',\n                //     () => d.e\n                // )\n                if (current_token.text === '(' && last_type !== 'TK_WORD' && last_type !== 'TK_RESERVED') {\n                    allow_wrap_or_preserved_newline();\n                }\n\n                set_mode(next_mode);\n                print_token();\n                if (opt.space_in_paren) {\n                    output.space_before_token = true;\n                }\n\n                // In all cases, if we newline while inside an expression it should be indented.\n                indent();\n            }\n\n            function handle_end_expr() {\n                // statements inside expressions are not valid syntax, but...\n                // statements must all be closed when their container closes\n                while (flags.mode === MODE.Statement) {\n                    restore_mode();\n                }\n\n                if (flags.multiline_frame) {\n                    allow_wrap_or_preserved_newline(current_token.text === ']' && is_array(flags.mode) && !opt.keep_array_indentation);\n                }\n\n                if (opt.space_in_paren) {\n                    if (last_type === 'TK_START_EXPR' && !opt.space_in_empty_paren) {\n                        // () [] no inner space in empty parens like these, ever, ref #320\n                        output.trim();\n                        output.space_before_token = false;\n                    } else {\n                        output.space_before_token = true;\n                    }\n                }\n                if (current_token.text === ']' && opt.keep_array_indentation) {\n                    print_token();\n                    restore_mode();\n                } else {\n                    restore_mode();\n                    print_token();\n                }\n                output.remove_redundant_indentation(previous_flags);\n\n                // do {} while () // no statement required after\n                if (flags.do_while && previous_flags.mode === MODE.Conditional) {\n                    previous_flags.mode = MODE.Expression;\n                    flags.do_block = false;\n                    flags.do_while = false;\n\n                }\n            }\n\n            function handle_start_block() {\n                // Check if this is should be treated as a ObjectLiteral\n                var next_token = get_token(1);\n                var second_token = get_token(2);\n                if (second_token && (\n                        (in_array(second_token.text, [':', ',']) && in_array(next_token.type, ['TK_STRING', 'TK_WORD', 'TK_RESERVED'])) ||\n                        (in_array(next_token.text, ['get', 'set']) && in_array(second_token.type, ['TK_WORD', 'TK_RESERVED']))\n                    )) {\n                    // We don't support TypeScript,but we didn't break it for a very long time.\n                    // We'll try to keep not breaking it.\n                    if (!in_array(last_last_text, ['class', 'interface'])) {\n                        set_mode(MODE.ObjectLiteral);\n                    } else {\n                        set_mode(MODE.BlockStatement);\n                    }\n                } else if (last_type === 'TK_OPERATOR' && flags.last_text === '=>') {\n                    // arrow function: (param1, paramN) => { statements }\n                    set_mode(MODE.BlockStatement);\n                } else if (in_array(last_type, ['TK_EQUALS', 'TK_START_EXPR', 'TK_COMMA', 'TK_OPERATOR']) ||\n                    (last_type === 'TK_RESERVED' && in_array(flags.last_text, ['return', 'throw', 'import']))\n                ) {\n                    // Detecting shorthand function syntax is difficult by scanning forward,\n                    //     so check the surrounding context.\n                    // If the block is being returned, imported, passed as arg,\n                    //     assigned with = or assigned in a nested object, treat as an ObjectLiteral.\n                    set_mode(MODE.ObjectLiteral);\n                } else {\n                    set_mode(MODE.BlockStatement);\n                }\n\n                var empty_braces = !next_token.comments_before.length && next_token.text === '}';\n                var empty_anonymous_function = empty_braces && flags.last_word === 'function' &&\n                    last_type === 'TK_END_EXPR';\n\n\n                if (opt.brace_style === \"expand\" ||\n                    (opt.brace_style === \"none\" && current_token.wanted_newline)) {\n                    if (last_type !== 'TK_OPERATOR' &&\n                        (empty_anonymous_function ||\n                            last_type === 'TK_EQUALS' ||\n                            (last_type === 'TK_RESERVED' && is_special_word(flags.last_text) && flags.last_text !== 'else'))) {\n                        output.space_before_token = true;\n                    } else {\n                        print_newline(false, true);\n                    }\n                } else { // collapse\n                    if (opt.brace_style === 'collapse-preserve-inline') {\n                        // search forward for a newline wanted inside this block\n                        var index = 0;\n                        var check_token = null;\n                        flags.inline_frame = true;\n                        do {\n                            index += 1;\n                            check_token = get_token(index);\n                            if (check_token.wanted_newline) {\n                                flags.inline_frame = false;\n                                break;\n                            }\n                        } while (check_token.type !== 'TK_EOF' &&\n                            !(check_token.type === 'TK_END_BLOCK' && check_token.opened === current_token));\n                    }\n\n                    if (is_array(previous_flags.mode) && (last_type === 'TK_START_EXPR' || last_type === 'TK_COMMA')) {\n                        // if we're preserving inline,\n                        // allow newline between comma and next brace.\n                        if (last_type === 'TK_COMMA' || opt.space_in_paren) {\n                            output.space_before_token = true;\n                        }\n\n                        if (opt.brace_style === 'collapse-preserve-inline' &&\n                            (last_type === 'TK_COMMA' || (last_type === 'TK_START_EXPR' && flags.inline_frame))) {\n                            allow_wrap_or_preserved_newline();\n                            previous_flags.multiline_frame = previous_flags.multiline_frame || flags.multiline_frame;\n                            flags.multiline_frame = false;\n                        }\n                    } else if (last_type !== 'TK_OPERATOR' && last_type !== 'TK_START_EXPR') {\n                        if (last_type === 'TK_START_BLOCK') {\n                            print_newline();\n                        } else {\n                            output.space_before_token = true;\n                        }\n                    }\n                }\n                print_token();\n                indent();\n            }\n\n            function handle_end_block() {\n                // statements must all be closed when their container closes\n                while (flags.mode === MODE.Statement) {\n                    restore_mode();\n                }\n                var empty_braces = last_type === 'TK_START_BLOCK';\n\n                if (opt.brace_style === \"expand\") {\n                    if (!empty_braces) {\n                        print_newline();\n                    }\n                } else {\n                    // skip {}\n                    if (!empty_braces) {\n                        if (flags.inline_frame) {\n                            output.space_before_token = true;\n                        } else if (is_array(flags.mode) && opt.keep_array_indentation) {\n                            // we REALLY need a newline here, but newliner would skip that\n                            opt.keep_array_indentation = false;\n                            print_newline();\n                            opt.keep_array_indentation = true;\n\n                        } else {\n                            print_newline();\n                        }\n                    }\n                }\n                restore_mode();\n                print_token();\n            }\n\n            function handle_word() {\n                if (current_token.type === 'TK_RESERVED') {\n                    if (in_array(current_token.text, ['set', 'get']) && flags.mode !== MODE.ObjectLiteral) {\n                        current_token.type = 'TK_WORD';\n                    } else if (in_array(current_token.text, ['as', 'from']) && !flags.import_block) {\n                        current_token.type = 'TK_WORD';\n                    } else if (flags.mode === MODE.ObjectLiteral) {\n                        var next_token = get_token(1);\n                        if (next_token.text === ':') {\n                            current_token.type = 'TK_WORD';\n                        }\n                    }\n                }\n\n                if (start_of_statement()) {\n                    // The conditional starts the statement if appropriate.\n                } else if (current_token.wanted_newline && !is_expression(flags.mode) &&\n                    (last_type !== 'TK_OPERATOR' || (flags.last_text === '--' || flags.last_text === '++')) &&\n                    last_type !== 'TK_EQUALS' &&\n                    (opt.preserve_newlines || !(last_type === 'TK_RESERVED' && in_array(flags.last_text, ['var', 'let', 'const', 'set', 'get'])))) {\n\n                    print_newline();\n                }\n\n                if (flags.do_block && !flags.do_while) {\n                    if (current_token.type === 'TK_RESERVED' && current_token.text === 'while') {\n                        // do {} ## while ()\n                        output.space_before_token = true;\n                        print_token();\n                        output.space_before_token = true;\n                        flags.do_while = true;\n                        return;\n                    } else {\n                        // do {} should always have while as the next word.\n                        // if we don't see the expected while, recover\n                        print_newline();\n                        flags.do_block = false;\n                    }\n                }\n\n                // if may be followed by else, or not\n                // Bare/inline ifs are tricky\n                // Need to unwind the modes correctly: if (a) if (b) c(); else d(); else e();\n                if (flags.if_block) {\n                    if (!flags.else_block && (current_token.type === 'TK_RESERVED' && current_token.text === 'else')) {\n                        flags.else_block = true;\n                    } else {\n                        while (flags.mode === MODE.Statement) {\n                            restore_mode();\n                        }\n                        flags.if_block = false;\n                        flags.else_block = false;\n                    }\n                }\n\n                if (current_token.type === 'TK_RESERVED' && (current_token.text === 'case' || (current_token.text === 'default' && flags.in_case_statement))) {\n                    print_newline();\n                    if (flags.case_body || opt.jslint_happy) {\n                        // switch cases following one another\n                        deindent();\n                        flags.case_body = false;\n                    }\n                    print_token();\n                    flags.in_case = true;\n                    flags.in_case_statement = true;\n                    return;\n                }\n\n                if (current_token.type === 'TK_RESERVED' && current_token.text === 'function') {\n                    if (in_array(flags.last_text, ['}', ';']) || (output.just_added_newline() && !in_array(flags.last_text, ['[', '{', ':', '=', ',']))) {\n                        // make sure there is a nice clean space of at least one blank line\n                        // before a new function definition\n                        if (!output.just_added_blankline() && !current_token.comments_before.length) {\n                            print_newline();\n                            print_newline(true);\n                        }\n                    }\n                    if (last_type === 'TK_RESERVED' || last_type === 'TK_WORD') {\n                        if (last_type === 'TK_RESERVED' && in_array(flags.last_text, ['get', 'set', 'new', 'return', 'export', 'async'])) {\n                            output.space_before_token = true;\n                        } else if (last_type === 'TK_RESERVED' && flags.last_text === 'default' && last_last_text === 'export') {\n                            output.space_before_token = true;\n                        } else {\n                            print_newline();\n                        }\n                    } else if (last_type === 'TK_OPERATOR' || flags.last_text === '=') {\n                        // foo = function\n                        output.space_before_token = true;\n                    } else if (!flags.multiline_frame && (is_expression(flags.mode) || is_array(flags.mode))) {\n                        // (function\n                    } else {\n                        print_newline();\n                    }\n                }\n\n                if (last_type === 'TK_COMMA' || last_type === 'TK_START_EXPR' || last_type === 'TK_EQUALS' || last_type === 'TK_OPERATOR') {\n                    if (!start_of_object_property()) {\n                        allow_wrap_or_preserved_newline();\n                    }\n                }\n\n                if (current_token.type === 'TK_RESERVED' && in_array(current_token.text, ['function', 'get', 'set'])) {\n                    print_token();\n                    flags.last_word = current_token.text;\n                    return;\n                }\n\n                prefix = 'NONE';\n\n                if (last_type === 'TK_END_BLOCK') {\n\n                    if (!(current_token.type === 'TK_RESERVED' && in_array(current_token.text, ['else', 'catch', 'finally', 'from']))) {\n                        prefix = 'NEWLINE';\n                    } else {\n                        if (opt.brace_style === \"expand\" ||\n                            opt.brace_style === \"end-expand\" ||\n                            (opt.brace_style === \"none\" && current_token.wanted_newline)) {\n                            prefix = 'NEWLINE';\n                        } else {\n                            prefix = 'SPACE';\n                            output.space_before_token = true;\n                        }\n                    }\n                } else if (last_type === 'TK_SEMICOLON' && flags.mode === MODE.BlockStatement) {\n                    // TODO: Should this be for STATEMENT as well?\n                    prefix = 'NEWLINE';\n                } else if (last_type === 'TK_SEMICOLON' && is_expression(flags.mode)) {\n                    prefix = 'SPACE';\n                } else if (last_type === 'TK_STRING') {\n                    prefix = 'NEWLINE';\n                } else if (last_type === 'TK_RESERVED' || last_type === 'TK_WORD' ||\n                    (flags.last_text === '*' && last_last_text === 'function')) {\n                    prefix = 'SPACE';\n                } else if (last_type === 'TK_START_BLOCK') {\n                    if (flags.inline_frame) {\n                        prefix = 'SPACE';\n                    } else {\n                        prefix = 'NEWLINE';\n                    }\n                } else if (last_type === 'TK_END_EXPR') {\n                    output.space_before_token = true;\n                    prefix = 'NEWLINE';\n                }\n\n                if (current_token.type === 'TK_RESERVED' && in_array(current_token.text, Tokenizer.line_starters) && flags.last_text !== ')') {\n                    if (flags.last_text === 'else' || flags.last_text === 'export') {\n                        prefix = 'SPACE';\n                    } else {\n                        prefix = 'NEWLINE';\n                    }\n\n                }\n\n                if (current_token.type === 'TK_RESERVED' && in_array(current_token.text, ['else', 'catch', 'finally'])) {\n                    if (!(last_type === 'TK_END_BLOCK' && previous_flags.mode === MODE.BlockStatement) ||\n                        opt.brace_style === \"expand\" ||\n                        opt.brace_style === \"end-expand\" ||\n                        (opt.brace_style === \"none\" && current_token.wanted_newline)) {\n                        print_newline();\n                    } else {\n                        output.trim(true);\n                        var line = output.current_line;\n                        // If we trimmed and there's something other than a close block before us\n                        // put a newline back in.  Handles '} // comment' scenario.\n                        if (line.last() !== '}') {\n                            print_newline();\n                        }\n                        output.space_before_token = true;\n                    }\n                } else if (prefix === 'NEWLINE') {\n                    if (last_type === 'TK_RESERVED' && is_special_word(flags.last_text)) {\n                        // no newline between 'return nnn'\n                        output.space_before_token = true;\n                    } else if (last_type !== 'TK_END_EXPR') {\n                        if ((last_type !== 'TK_START_EXPR' || !(current_token.type === 'TK_RESERVED' && in_array(current_token.text, ['var', 'let', 'const']))) && flags.last_text !== ':') {\n                            // no need to force newline on 'var': for (var x = 0...)\n                            if (current_token.type === 'TK_RESERVED' && current_token.text === 'if' && flags.last_text === 'else') {\n                                // no newline for } else if {\n                                output.space_before_token = true;\n                            } else {\n                                print_newline();\n                            }\n                        }\n                    } else if (current_token.type === 'TK_RESERVED' && in_array(current_token.text, Tokenizer.line_starters) && flags.last_text !== ')') {\n                        print_newline();\n                    }\n                } else if (flags.multiline_frame && is_array(flags.mode) && flags.last_text === ',' && last_last_text === '}') {\n                    print_newline(); // }, in lists get a newline treatment\n                } else if (prefix === 'SPACE') {\n                    output.space_before_token = true;\n                }\n                print_token();\n                flags.last_word = current_token.text;\n\n                if (current_token.type === 'TK_RESERVED') {\n                    if (current_token.text === 'do') {\n                        flags.do_block = true;\n                    } else if (current_token.text === 'if') {\n                        flags.if_block = true;\n                    } else if (current_token.text === 'import') {\n                        flags.import_block = true;\n                    } else if (flags.import_block && current_token.type === 'TK_RESERVED' && current_token.text === 'from') {\n                        flags.import_block = false;\n                    }\n                }\n            }\n\n            function handle_semicolon() {\n                if (start_of_statement()) {\n                    // The conditional starts the statement if appropriate.\n                    // Semicolon can be the start (and end) of a statement\n                    output.space_before_token = false;\n                }\n                while (flags.mode === MODE.Statement && !flags.if_block && !flags.do_block) {\n                    restore_mode();\n                }\n\n                // hacky but effective for the moment\n                if (flags.import_block) {\n                    flags.import_block = false;\n                }\n                print_token();\n            }\n\n            function handle_string() {\n                if (start_of_statement()) {\n                    // The conditional starts the statement if appropriate.\n                    // One difference - strings want at least a space before\n                    output.space_before_token = true;\n                } else if (last_type === 'TK_RESERVED' || last_type === 'TK_WORD' || flags.inline_frame) {\n                    output.space_before_token = true;\n                } else if (last_type === 'TK_COMMA' || last_type === 'TK_START_EXPR' || last_type === 'TK_EQUALS' || last_type === 'TK_OPERATOR') {\n                    if (!start_of_object_property()) {\n                        allow_wrap_or_preserved_newline();\n                    }\n                } else {\n                    print_newline();\n                }\n                print_token();\n            }\n\n            function handle_equals() {\n                if (start_of_statement()) {\n                    // The conditional starts the statement if appropriate.\n                }\n\n                if (flags.declaration_statement) {\n                    // just got an '=' in a var-line, different formatting/line-breaking, etc will now be done\n                    flags.declaration_assignment = true;\n                }\n                output.space_before_token = true;\n                print_token();\n                output.space_before_token = true;\n            }\n\n            function handle_comma() {\n                print_token();\n                output.space_before_token = true;\n                if (flags.declaration_statement) {\n                    if (is_expression(flags.parent.mode)) {\n                        // do not break on comma, for(var a = 1, b = 2)\n                        flags.declaration_assignment = false;\n                    }\n\n                    if (flags.declaration_assignment) {\n                        flags.declaration_assignment = false;\n                        print_newline(false, true);\n                    } else if (opt.comma_first) {\n                        // for comma-first, we want to allow a newline before the comma\n                        // to turn into a newline after the comma, which we will fixup later\n                        allow_wrap_or_preserved_newline();\n                    }\n                } else if (flags.mode === MODE.ObjectLiteral ||\n                    (flags.mode === MODE.Statement && flags.parent.mode === MODE.ObjectLiteral)) {\n                    if (flags.mode === MODE.Statement) {\n                        restore_mode();\n                    }\n\n                    if (!flags.inline_frame) {\n                        print_newline();\n                    }\n                } else if (opt.comma_first) {\n                    // EXPR or DO_BLOCK\n                    // for comma-first, we want to allow a newline before the comma\n                    // to turn into a newline after the comma, which we will fixup later\n                    allow_wrap_or_preserved_newline();\n                }\n            }\n\n            function handle_operator() {\n                if (start_of_statement()) {\n                    // The conditional starts the statement if appropriate.\n                }\n\n                if (last_type === 'TK_RESERVED' && is_special_word(flags.last_text)) {\n                    // \"return\" had a special handling in TK_WORD. Now we need to return the favor\n                    output.space_before_token = true;\n                    print_token();\n                    return;\n                }\n\n                // hack for actionscript's import .*;\n                if (current_token.text === '*' && last_type === 'TK_DOT') {\n                    print_token();\n                    return;\n                }\n\n                if (current_token.text === '::') {\n                    // no spaces around exotic namespacing syntax operator\n                    print_token();\n                    return;\n                }\n\n                // Allow line wrapping between operators when operator_position is\n                //   set to before or preserve\n                if (last_type === 'TK_OPERATOR' && in_array(opt.operator_position, OPERATOR_POSITION_BEFORE_OR_PRESERVE)) {\n                    allow_wrap_or_preserved_newline();\n                }\n\n                if (current_token.text === ':' && flags.in_case) {\n                    flags.case_body = true;\n                    indent();\n                    print_token();\n                    print_newline();\n                    flags.in_case = false;\n                    return;\n                }\n\n                var space_before = true;\n                var space_after = true;\n                var in_ternary = false;\n                var isGeneratorAsterisk = current_token.text === '*' && last_type === 'TK_RESERVED' && flags.last_text === 'function';\n                var isUnary = in_array(current_token.text, ['-', '+']) && (\n                    in_array(last_type, ['TK_START_BLOCK', 'TK_START_EXPR', 'TK_EQUALS', 'TK_OPERATOR']) ||\n                    in_array(flags.last_text, Tokenizer.line_starters) ||\n                    flags.last_text === ','\n                );\n\n                if (current_token.text === ':') {\n                    if (flags.ternary_depth === 0) {\n                        // Colon is invalid javascript outside of ternary and object, but do our best to guess what was meant.\n                        space_before = false;\n                    } else {\n                        flags.ternary_depth -= 1;\n                        in_ternary = true;\n                    }\n                } else if (current_token.text === '?') {\n                    flags.ternary_depth += 1;\n                }\n\n                // let's handle the operator_position option prior to any conflicting logic\n                if (!isUnary && !isGeneratorAsterisk && opt.preserve_newlines && in_array(current_token.text, Tokenizer.positionable_operators)) {\n                    var isColon = current_token.text === ':';\n                    var isTernaryColon = (isColon && in_ternary);\n                    var isOtherColon = (isColon && !in_ternary);\n\n                    switch (opt.operator_position) {\n                        case OPERATOR_POSITION.before_newline:\n                            // if the current token is : and it's not a ternary statement then we set space_before to false\n                            output.space_before_token = !isOtherColon;\n\n                            print_token();\n\n                            if (!isColon || isTernaryColon) {\n                                allow_wrap_or_preserved_newline();\n                            }\n\n                            output.space_before_token = true;\n                            return;\n\n                        case OPERATOR_POSITION.after_newline:\n                            // if the current token is anything but colon, or (via deduction) it's a colon and in a ternary statement,\n                            //   then print a newline.\n\n                            output.space_before_token = true;\n\n                            if (!isColon || isTernaryColon) {\n                                if (get_token(1).wanted_newline) {\n                                    print_newline(false, true);\n                                } else {\n                                    allow_wrap_or_preserved_newline();\n                                }\n                            } else {\n                                output.space_before_token = false;\n                            }\n\n                            print_token();\n\n                            output.space_before_token = true;\n                            return;\n\n                        case OPERATOR_POSITION.preserve_newline:\n                            if (!isOtherColon) {\n                                allow_wrap_or_preserved_newline();\n                            }\n\n                            // if we just added a newline, or the current token is : and it's not a ternary statement,\n                            //   then we set space_before to false\n                            space_before = !(output.just_added_newline() || isOtherColon);\n\n                            output.space_before_token = space_before;\n                            print_token();\n                            output.space_before_token = true;\n                            return;\n                    }\n                }\n\n                if (in_array(current_token.text, ['--', '++', '!', '~']) || isUnary) {\n                    // unary operators (and binary +/- pretending to be unary) special cases\n\n                    space_before = false;\n                    space_after = false;\n\n                    // http://www.ecma-international.org/ecma-262/5.1/#sec-7.9.1\n                    // if there is a newline between -- or ++ and anything else we should preserve it.\n                    if (current_token.wanted_newline && (current_token.text === '--' || current_token.text === '++')) {\n                        print_newline(false, true);\n                    }\n\n                    if (flags.last_text === ';' && is_expression(flags.mode)) {\n                        // for (;; ++i)\n                        //        ^^^\n                        space_before = true;\n                    }\n\n                    if (last_type === 'TK_RESERVED') {\n                        space_before = true;\n                    } else if (last_type === 'TK_END_EXPR') {\n                        space_before = !(flags.last_text === ']' && (current_token.text === '--' || current_token.text === '++'));\n                    } else if (last_type === 'TK_OPERATOR') {\n                        // a++ + ++b;\n                        // a - -b\n                        space_before = in_array(current_token.text, ['--', '-', '++', '+']) && in_array(flags.last_text, ['--', '-', '++', '+']);\n                        // + and - are not unary when preceeded by -- or ++ operator\n                        // a-- + b\n                        // a * +b\n                        // a - -b\n                        if (in_array(current_token.text, ['+', '-']) && in_array(flags.last_text, ['--', '++'])) {\n                            space_after = true;\n                        }\n                    }\n\n\n                    if (((flags.mode === MODE.BlockStatement && !flags.inline_frame) || flags.mode === MODE.Statement) &&\n                        (flags.last_text === '{' || flags.last_text === ';')) {\n                        // { foo; --i }\n                        // foo(); --bar;\n                        print_newline();\n                    }\n                } else if (isGeneratorAsterisk) {\n                    space_before = false;\n                    space_after = false;\n                }\n                output.space_before_token = output.space_before_token || space_before;\n                print_token();\n                output.space_before_token = space_after;\n            }\n\n            function handle_block_comment() {\n                if (output.raw) {\n                    output.add_raw_token(current_token);\n                    if (current_token.directives && current_token.directives.preserve === 'end') {\n                        // If we're testing the raw output behavior, do not allow a directive to turn it off.\n                        output.raw = opt.test_output_raw;\n                    }\n                    return;\n                }\n\n                if (current_token.directives) {\n                    print_newline(false, true);\n                    print_token();\n                    if (current_token.directives.preserve === 'start') {\n                        output.raw = true;\n                    }\n                    print_newline(false, true);\n                    return;\n                }\n\n                // inline block\n                if (!acorn.newline.test(current_token.text) && !current_token.wanted_newline) {\n                    output.space_before_token = true;\n                    print_token();\n                    output.space_before_token = true;\n                    return;\n                }\n\n                var lines = split_linebreaks(current_token.text);\n                var j; // iterator for this case\n                var javadoc = false;\n                var starless = false;\n                var lastIndent = current_token.whitespace_before;\n                var lastIndentLength = lastIndent.length;\n\n                // block comment starts with a new line\n                print_newline(false, true);\n                if (lines.length > 1) {\n                    javadoc = all_lines_start_with(lines.slice(1), '*');\n                    starless = each_line_matches_indent(lines.slice(1), lastIndent);\n                }\n\n                // first line always indented\n                print_token(lines[0]);\n                for (j = 1; j < lines.length; j++) {\n                    print_newline(false, true);\n                    if (javadoc) {\n                        // javadoc: reformat and re-indent\n                        print_token(' ' + ltrim(lines[j]));\n                    } else if (starless && lines[j].length > lastIndentLength) {\n                        // starless: re-indent non-empty content, avoiding trim\n                        print_token(lines[j].substring(lastIndentLength));\n                    } else {\n                        // normal comments output raw\n                        output.add_token(lines[j]);\n                    }\n                }\n\n                // for comments of more than one line, make sure there's a new line after\n                print_newline(false, true);\n            }\n\n            function handle_comment() {\n                if (current_token.wanted_newline) {\n                    print_newline(false, true);\n                } else {\n                    output.trim(true);\n                }\n\n                output.space_before_token = true;\n                print_token();\n                print_newline(false, true);\n            }\n\n            function handle_dot() {\n                if (start_of_statement()) {\n                    // The conditional starts the statement if appropriate.\n                }\n\n                if (last_type === 'TK_RESERVED' && is_special_word(flags.last_text)) {\n                    output.space_before_token = true;\n                } else {\n                    // allow preserved newlines before dots in general\n                    // force newlines on dots after close paren when break_chained - for bar().baz()\n                    allow_wrap_or_preserved_newline(flags.last_text === ')' && opt.break_chained_methods);\n                }\n\n                print_token();\n            }\n\n            function handle_unknown() {\n                print_token();\n\n                if (current_token.text[current_token.text.length - 1] === '\\n') {\n                    print_newline();\n                }\n            }\n\n            function handle_eof() {\n                // Unwind any open statements\n                while (flags.mode === MODE.Statement) {\n                    restore_mode();\n                }\n            }\n        }\n\n\n        function OutputLine(parent) {\n            var _character_count = 0;\n            // use indent_count as a marker for lines that have preserved indentation\n            var _indent_count = -1;\n\n            var _items = [];\n            var _empty = true;\n\n            this.set_indent = function(level) {\n                _character_count = parent.baseIndentLength + level * parent.indent_length;\n                _indent_count = level;\n            };\n\n            this.get_character_count = function() {\n                return _character_count;\n            };\n\n            this.is_empty = function() {\n                return _empty;\n            };\n\n            this.last = function() {\n                if (!this._empty) {\n                    return _items[_items.length - 1];\n                } else {\n                    return null;\n                }\n            };\n\n            this.push = function(input) {\n                _items.push(input);\n                _character_count += input.length;\n                _empty = false;\n            };\n\n            this.pop = function() {\n                var item = null;\n                if (!_empty) {\n                    item = _items.pop();\n                    _character_count -= item.length;\n                    _empty = _items.length === 0;\n                }\n                return item;\n            };\n\n            this.remove_indent = function() {\n                if (_indent_count > 0) {\n                    _indent_count -= 1;\n                    _character_count -= parent.indent_length;\n                }\n            };\n\n            this.trim = function() {\n                while (this.last() === ' ') {\n                    _items.pop();\n                    _character_count -= 1;\n                }\n                _empty = _items.length === 0;\n            };\n\n            this.toString = function() {\n                var result = '';\n                if (!this._empty) {\n                    if (_indent_count >= 0) {\n                        result = parent.indent_cache[_indent_count];\n                    }\n                    result += _items.join('');\n                }\n                return result;\n            };\n        }\n\n        function Output(indent_string, baseIndentString) {\n            baseIndentString = baseIndentString || '';\n            this.indent_cache = [baseIndentString];\n            this.baseIndentLength = baseIndentString.length;\n            this.indent_length = indent_string.length;\n            this.raw = false;\n\n            var lines = [];\n            this.baseIndentString = baseIndentString;\n            this.indent_string = indent_string;\n            this.previous_line = null;\n            this.current_line = null;\n            this.space_before_token = false;\n\n            this.add_outputline = function() {\n                this.previous_line = this.current_line;\n                this.current_line = new OutputLine(this);\n                lines.push(this.current_line);\n            };\n\n            // initialize\n            this.add_outputline();\n\n\n            this.get_line_number = function() {\n                return lines.length;\n            };\n\n            // Using object instead of string to allow for later expansion of info about each line\n            this.add_new_line = function(force_newline) {\n                if (this.get_line_number() === 1 && this.just_added_newline()) {\n                    return false; // no newline on start of file\n                }\n\n                if (force_newline || !this.just_added_newline()) {\n                    if (!this.raw) {\n                        this.add_outputline();\n                    }\n                    return true;\n                }\n\n                return false;\n            };\n\n            this.get_code = function() {\n                var sweet_code = lines.join('\\n').replace(/[\\r\\n\\t ]+$/, '');\n                return sweet_code;\n            };\n\n            this.set_indent = function(level) {\n                // Never indent your first output indent at the start of the file\n                if (lines.length > 1) {\n                    while (level >= this.indent_cache.length) {\n                        this.indent_cache.push(this.indent_cache[this.indent_cache.length - 1] + this.indent_string);\n                    }\n\n                    this.current_line.set_indent(level);\n                    return true;\n                }\n                this.current_line.set_indent(0);\n                return false;\n            };\n\n            this.add_raw_token = function(token) {\n                for (var x = 0; x < token.newlines; x++) {\n                    this.add_outputline();\n                }\n                this.current_line.push(token.whitespace_before);\n                this.current_line.push(token.text);\n                this.space_before_token = false;\n            };\n\n            this.add_token = function(printable_token) {\n                this.add_space_before_token();\n                this.current_line.push(printable_token);\n            };\n\n            this.add_space_before_token = function() {\n                if (this.space_before_token && !this.just_added_newline()) {\n                    this.current_line.push(' ');\n                }\n                this.space_before_token = false;\n            };\n\n            this.remove_redundant_indentation = function(frame) {\n                // This implementation is effective but has some issues:\n                //     - can cause line wrap to happen too soon due to indent removal\n                //           after wrap points are calculated\n                // These issues are minor compared to ugly indentation.\n\n                if (frame.multiline_frame ||\n                    frame.mode === MODE.ForInitializer ||\n                    frame.mode === MODE.Conditional) {\n                    return;\n                }\n\n                // remove one indent from each line inside this section\n                var index = frame.start_line_index;\n\n                var output_length = lines.length;\n                while (index < output_length) {\n                    lines[index].remove_indent();\n                    index++;\n                }\n            };\n\n            this.trim = function(eat_newlines) {\n                eat_newlines = (eat_newlines === undefined) ? false : eat_newlines;\n\n                this.current_line.trim(indent_string, baseIndentString);\n\n                while (eat_newlines && lines.length > 1 &&\n                    this.current_line.is_empty()) {\n                    lines.pop();\n                    this.current_line = lines[lines.length - 1];\n                    this.current_line.trim();\n                }\n\n                this.previous_line = lines.length > 1 ? lines[lines.length - 2] : null;\n            };\n\n            this.just_added_newline = function() {\n                return this.current_line.is_empty();\n            };\n\n            this.just_added_blankline = function() {\n                if (this.just_added_newline()) {\n                    if (lines.length === 1) {\n                        return true; // start of the file and newline = blank\n                    }\n\n                    var line = lines[lines.length - 2];\n                    return line.is_empty();\n                }\n                return false;\n            };\n        }\n\n\n        var Token = function(type, text, newlines, whitespace_before, parent) {\n            this.type = type;\n            this.text = text;\n            this.comments_before = [];\n            this.newlines = newlines || 0;\n            this.wanted_newline = newlines > 0;\n            this.whitespace_before = whitespace_before || '';\n            this.parent = parent || null;\n            this.opened = null;\n            this.directives = null;\n        };\n\n        function tokenizer(input, opts) {\n\n            var whitespace = \"\\n\\r\\t \".split('');\n            var digit = /[0-9]/;\n            var digit_bin = /[01]/;\n            var digit_oct = /[01234567]/;\n            var digit_hex = /[0123456789abcdefABCDEF]/;\n\n            this.positionable_operators = '!= !== % & && * ** + - / : < << <= == === > >= >> >>> ? ^ | ||'.split(' ');\n            var punct = this.positionable_operators.concat(\n                // non-positionable operators - these do not follow operator position settings\n                '! %= &= *= **= ++ += , -- -= /= :: <<= = => >>= >>>= ^= |= ~'.split(' '));\n\n            // words which should always start on new line.\n            this.line_starters = 'continue,try,throw,return,var,let,const,if,switch,case,default,for,while,break,function,import,export'.split(',');\n            var reserved_words = this.line_starters.concat(['do', 'in', 'else', 'get', 'set', 'new', 'catch', 'finally', 'typeof', 'yield', 'async', 'await', 'from', 'as']);\n\n            //  /* ... */ comment ends with nearest */ or end of file\n            var block_comment_pattern = /([\\s\\S]*?)((?:\\*\\/)|$)/g;\n\n            // comment ends just before nearest linefeed or end of file\n            var comment_pattern = /([^\\n\\r\\u2028\\u2029]*)/g;\n\n            var directives_block_pattern = /\\/\\* beautify( \\w+[:]\\w+)+ \\*\\//g;\n            var directive_pattern = / (\\w+)[:](\\w+)/g;\n            var directives_end_ignore_pattern = /([\\s\\S]*?)((?:\\/\\*\\sbeautify\\signore:end\\s\\*\\/)|$)/g;\n\n            var template_pattern = /((<\\?php|<\\?=)[\\s\\S]*?\\?>)|(<%[\\s\\S]*?%>)/g;\n\n            var n_newlines, whitespace_before_token, in_html_comment, tokens, parser_pos;\n            var input_length;\n\n            this.tokenize = function() {\n                // cache the source's length.\n                input_length = input.length;\n                parser_pos = 0;\n                in_html_comment = false;\n                tokens = [];\n\n                var next, last;\n                var token_values;\n                var open = null;\n                var open_stack = [];\n                var comments = [];\n\n                while (!(last && last.type === 'TK_EOF')) {\n                    token_values = tokenize_next();\n                    next = new Token(token_values[1], token_values[0], n_newlines, whitespace_before_token);\n                    while (next.type === 'TK_COMMENT' || next.type === 'TK_BLOCK_COMMENT' || next.type === 'TK_UNKNOWN') {\n                        if (next.type === 'TK_BLOCK_COMMENT') {\n                            next.directives = token_values[2];\n                        }\n                        comments.push(next);\n                        token_values = tokenize_next();\n                        next = new Token(token_values[1], token_values[0], n_newlines, whitespace_before_token);\n                    }\n\n                    if (comments.length) {\n                        next.comments_before = comments;\n                        comments = [];\n                    }\n\n                    if (next.type === 'TK_START_BLOCK' || next.type === 'TK_START_EXPR') {\n                        next.parent = last;\n                        open_stack.push(open);\n                        open = next;\n                    } else if ((next.type === 'TK_END_BLOCK' || next.type === 'TK_END_EXPR') &&\n                        (open && (\n                            (next.text === ']' && open.text === '[') ||\n                            (next.text === ')' && open.text === '(') ||\n                            (next.text === '}' && open.text === '{')))) {\n                        next.parent = open.parent;\n                        next.opened = open;\n\n                        open = open_stack.pop();\n                    }\n\n                    tokens.push(next);\n                    last = next;\n                }\n\n                return tokens;\n            };\n\n            function get_directives(text) {\n                if (!text.match(directives_block_pattern)) {\n                    return null;\n                }\n\n                var directives = {};\n                directive_pattern.lastIndex = 0;\n                var directive_match = directive_pattern.exec(text);\n\n                while (directive_match) {\n                    directives[directive_match[1]] = directive_match[2];\n                    directive_match = directive_pattern.exec(text);\n                }\n\n                return directives;\n            }\n\n            function tokenize_next() {\n                var resulting_string;\n                var whitespace_on_this_line = [];\n\n                n_newlines = 0;\n                whitespace_before_token = '';\n\n                if (parser_pos >= input_length) {\n                    return ['', 'TK_EOF'];\n                }\n\n                var last_token;\n                if (tokens.length) {\n                    last_token = tokens[tokens.length - 1];\n                } else {\n                    // For the sake of tokenizing we can pretend that there was on open brace to start\n                    last_token = new Token('TK_START_BLOCK', '{');\n                }\n\n\n                var c = input.charAt(parser_pos);\n                parser_pos += 1;\n\n                while (in_array(c, whitespace)) {\n\n                    if (acorn.newline.test(c)) {\n                        if (!(c === '\\n' && input.charAt(parser_pos - 2) === '\\r')) {\n                            n_newlines += 1;\n                            whitespace_on_this_line = [];\n                        }\n                    } else {\n                        whitespace_on_this_line.push(c);\n                    }\n\n                    if (parser_pos >= input_length) {\n                        return ['', 'TK_EOF'];\n                    }\n\n                    c = input.charAt(parser_pos);\n                    parser_pos += 1;\n                }\n\n                if (whitespace_on_this_line.length) {\n                    whitespace_before_token = whitespace_on_this_line.join('');\n                }\n\n                if (digit.test(c) || (c === '.' && digit.test(input.charAt(parser_pos)))) {\n                    var allow_decimal = true;\n                    var allow_e = true;\n                    var local_digit = digit;\n\n                    if (c === '0' && parser_pos < input_length && /[XxOoBb]/.test(input.charAt(parser_pos))) {\n                        // switch to hex/oct/bin number, no decimal or e, just hex/oct/bin digits\n                        allow_decimal = false;\n                        allow_e = false;\n                        if (/[Bb]/.test(input.charAt(parser_pos))) {\n                            local_digit = digit_bin;\n                        } else if (/[Oo]/.test(input.charAt(parser_pos))) {\n                            local_digit = digit_oct;\n                        } else {\n                            local_digit = digit_hex;\n                        }\n                        c += input.charAt(parser_pos);\n                        parser_pos += 1;\n                    } else if (c === '.') {\n                        // Already have a decimal for this literal, don't allow another\n                        allow_decimal = false;\n                    } else {\n                        // we know this first loop will run.  It keeps the logic simpler.\n                        c = '';\n                        parser_pos -= 1;\n                    }\n\n                    // Add the digits\n                    while (parser_pos < input_length && local_digit.test(input.charAt(parser_pos))) {\n                        c += input.charAt(parser_pos);\n                        parser_pos += 1;\n\n                        if (allow_decimal && parser_pos < input_length && input.charAt(parser_pos) === '.') {\n                            c += input.charAt(parser_pos);\n                            parser_pos += 1;\n                            allow_decimal = false;\n                        } else if (allow_e && parser_pos < input_length && /[Ee]/.test(input.charAt(parser_pos))) {\n                            c += input.charAt(parser_pos);\n                            parser_pos += 1;\n\n                            if (parser_pos < input_length && /[+-]/.test(input.charAt(parser_pos))) {\n                                c += input.charAt(parser_pos);\n                                parser_pos += 1;\n                            }\n\n                            allow_e = false;\n                            allow_decimal = false;\n                        }\n                    }\n\n                    return [c, 'TK_WORD'];\n                }\n\n                if (acorn.isIdentifierStart(input.charCodeAt(parser_pos - 1))) {\n                    if (parser_pos < input_length) {\n                        while (acorn.isIdentifierChar(input.charCodeAt(parser_pos))) {\n                            c += input.charAt(parser_pos);\n                            parser_pos += 1;\n                            if (parser_pos === input_length) {\n                                break;\n                            }\n                        }\n                    }\n\n                    if (!(last_token.type === 'TK_DOT' ||\n                            (last_token.type === 'TK_RESERVED' && in_array(last_token.text, ['set', 'get']))) &&\n                        in_array(c, reserved_words)) {\n                        if (c === 'in') { // hack for 'in' operator\n                            return [c, 'TK_OPERATOR'];\n                        }\n                        return [c, 'TK_RESERVED'];\n                    }\n\n                    return [c, 'TK_WORD'];\n                }\n\n                if (c === '(' || c === '[') {\n                    return [c, 'TK_START_EXPR'];\n                }\n\n                if (c === ')' || c === ']') {\n                    return [c, 'TK_END_EXPR'];\n                }\n\n                if (c === '{') {\n                    return [c, 'TK_START_BLOCK'];\n                }\n\n                if (c === '}') {\n                    return [c, 'TK_END_BLOCK'];\n                }\n\n                if (c === ';') {\n                    return [c, 'TK_SEMICOLON'];\n                }\n\n                if (c === '/') {\n                    var comment = '';\n                    var comment_match;\n                    // peek for comment /* ... */\n                    if (input.charAt(parser_pos) === '*') {\n                        parser_pos += 1;\n                        block_comment_pattern.lastIndex = parser_pos;\n                        comment_match = block_comment_pattern.exec(input);\n                        comment = '/*' + comment_match[0];\n                        parser_pos += comment_match[0].length;\n                        var directives = get_directives(comment);\n                        if (directives && directives.ignore === 'start') {\n                            directives_end_ignore_pattern.lastIndex = parser_pos;\n                            comment_match = directives_end_ignore_pattern.exec(input);\n                            comment += comment_match[0];\n                            parser_pos += comment_match[0].length;\n                        }\n                        comment = comment.replace(acorn.allLineBreaks, '\\n');\n                        return [comment, 'TK_BLOCK_COMMENT', directives];\n                    }\n                    // peek for comment // ...\n                    if (input.charAt(parser_pos) === '/') {\n                        parser_pos += 1;\n                        comment_pattern.lastIndex = parser_pos;\n                        comment_match = comment_pattern.exec(input);\n                        comment = '//' + comment_match[0];\n                        parser_pos += comment_match[0].length;\n                        return [comment, 'TK_COMMENT'];\n                    }\n\n                }\n\n                var startXmlRegExp = /^<([-a-zA-Z:0-9_.]+|{.+?}|!\\[CDATA\\[[\\s\\S]*?\\]\\])(\\s+{.+?}|\\s+[-a-zA-Z:0-9_.]+|\\s+[-a-zA-Z:0-9_.]+\\s*=\\s*('[^']*'|\"[^\"]*\"|{.+?}))*\\s*(\\/?)\\s*>/;\n\n                if (c === '`' || c === \"'\" || c === '\"' || // string\n                    (\n                        (c === '/') || // regexp\n                        (opts.e4x && c === \"<\" && input.slice(parser_pos - 1).match(startXmlRegExp)) // xml\n                    ) && ( // regex and xml can only appear in specific locations during parsing\n                        (last_token.type === 'TK_RESERVED' && in_array(last_token.text, ['return', 'case', 'throw', 'else', 'do', 'typeof', 'yield'])) ||\n                        (last_token.type === 'TK_END_EXPR' && last_token.text === ')' &&\n                            last_token.parent && last_token.parent.type === 'TK_RESERVED' && in_array(last_token.parent.text, ['if', 'while', 'for'])) ||\n                        (in_array(last_token.type, ['TK_COMMENT', 'TK_START_EXPR', 'TK_START_BLOCK',\n                            'TK_END_BLOCK', 'TK_OPERATOR', 'TK_EQUALS', 'TK_EOF', 'TK_SEMICOLON', 'TK_COMMA'\n                        ]))\n                    )) {\n\n                    var sep = c,\n                        esc = false,\n                        has_char_escapes = false;\n\n                    resulting_string = c;\n\n                    if (sep === '/') {\n                        //\n                        // handle regexp\n                        //\n                        var in_char_class = false;\n                        while (parser_pos < input_length &&\n                            ((esc || in_char_class || input.charAt(parser_pos) !== sep) &&\n                                !acorn.newline.test(input.charAt(parser_pos)))) {\n                            resulting_string += input.charAt(parser_pos);\n                            if (!esc) {\n                                esc = input.charAt(parser_pos) === '\\\\';\n                                if (input.charAt(parser_pos) === '[') {\n                                    in_char_class = true;\n                                } else if (input.charAt(parser_pos) === ']') {\n                                    in_char_class = false;\n                                }\n                            } else {\n                                esc = false;\n                            }\n                            parser_pos += 1;\n                        }\n                    } else if (opts.e4x && sep === '<') {\n                        //\n                        // handle e4x xml literals\n                        //\n\n                        var xmlRegExp = /<(\\/?)([-a-zA-Z:0-9_.]+|{.+?}|!\\[CDATA\\[[\\s\\S]*?\\]\\])(\\s+{.+?}|\\s+[-a-zA-Z:0-9_.]+|\\s+[-a-zA-Z:0-9_.]+\\s*=\\s*('[^']*'|\"[^\"]*\"|{.+?}))*\\s*(\\/?)\\s*>/g;\n                        var xmlStr = input.slice(parser_pos - 1);\n                        var match = xmlRegExp.exec(xmlStr);\n                        if (match && match.index === 0) {\n                            var rootTag = match[2];\n                            var depth = 0;\n                            while (match) {\n                                var isEndTag = !!match[1];\n                                var tagName = match[2];\n                                var isSingletonTag = (!!match[match.length - 1]) || (tagName.slice(0, 8) === \"![CDATA[\");\n                                if (tagName === rootTag && !isSingletonTag) {\n                                    if (isEndTag) {\n                                        --depth;\n                                    } else {\n                                        ++depth;\n                                    }\n                                }\n                                if (depth <= 0) {\n                                    break;\n                                }\n                                match = xmlRegExp.exec(xmlStr);\n                            }\n                            var xmlLength = match ? match.index + match[0].length : xmlStr.length;\n                            xmlStr = xmlStr.slice(0, xmlLength);\n                            parser_pos += xmlLength - 1;\n                            xmlStr = xmlStr.replace(acorn.allLineBreaks, '\\n');\n                            return [xmlStr, \"TK_STRING\"];\n                        }\n                    } else {\n                        //\n                        // handle string\n                        //\n                        var parse_string = function(delimiter, allow_unescaped_newlines, start_sub) {\n                            // Template strings can travers lines without escape characters.\n                            // Other strings cannot\n                            var current_char;\n                            while (parser_pos < input_length) {\n                                current_char = input.charAt(parser_pos);\n                                if (!(esc || (current_char !== delimiter &&\n                                        (allow_unescaped_newlines || !acorn.newline.test(current_char))))) {\n                                    break;\n                                }\n\n                                // Handle \\r\\n linebreaks after escapes or in template strings\n                                if ((esc || allow_unescaped_newlines) && acorn.newline.test(current_char)) {\n                                    if (current_char === '\\r' && input.charAt(parser_pos + 1) === '\\n') {\n                                        parser_pos += 1;\n                                        current_char = input.charAt(parser_pos);\n                                    }\n                                    resulting_string += '\\n';\n                                } else {\n                                    resulting_string += current_char;\n                                }\n                                if (esc) {\n                                    if (current_char === 'x' || current_char === 'u') {\n                                        has_char_escapes = true;\n                                    }\n                                    esc = false;\n                                } else {\n                                    esc = current_char === '\\\\';\n                                }\n\n                                parser_pos += 1;\n\n                                if (start_sub && resulting_string.indexOf(start_sub, resulting_string.length - start_sub.length) !== -1) {\n                                    if (delimiter === '`') {\n                                        parse_string('}', allow_unescaped_newlines, '`');\n                                    } else {\n                                        parse_string('`', allow_unescaped_newlines, '${');\n                                    }\n                                }\n                            }\n                        };\n\n                        if (sep === '`') {\n                            parse_string('`', true, '${');\n                        } else {\n                            parse_string(sep);\n                        }\n                    }\n\n                    if (has_char_escapes && opts.unescape_strings) {\n                        resulting_string = unescape_string(resulting_string);\n                    }\n\n                    if (parser_pos < input_length && input.charAt(parser_pos) === sep) {\n                        resulting_string += sep;\n                        parser_pos += 1;\n\n                        if (sep === '/') {\n                            // regexps may have modifiers /regexp/MOD , so fetch those, too\n                            // Only [gim] are valid, but if the user puts in garbage, do what we can to take it.\n                            while (parser_pos < input_length && acorn.isIdentifierStart(input.charCodeAt(parser_pos))) {\n                                resulting_string += input.charAt(parser_pos);\n                                parser_pos += 1;\n                            }\n                        }\n                    }\n                    return [resulting_string, 'TK_STRING'];\n                }\n\n                if (c === '#') {\n\n                    if (tokens.length === 0 && input.charAt(parser_pos) === '!') {\n                        // shebang\n                        resulting_string = c;\n                        while (parser_pos < input_length && c !== '\\n') {\n                            c = input.charAt(parser_pos);\n                            resulting_string += c;\n                            parser_pos += 1;\n                        }\n                        return [trim(resulting_string) + '\\n', 'TK_UNKNOWN'];\n                    }\n\n\n\n                    // Spidermonkey-specific sharp variables for circular references\n                    // https://developer.mozilla.org/En/Sharp_variables_in_JavaScript\n                    // http://mxr.mozilla.org/mozilla-central/source/js/src/jsscan.cpp around line 1935\n                    var sharp = '#';\n                    if (parser_pos < input_length && digit.test(input.charAt(parser_pos))) {\n                        do {\n                            c = input.charAt(parser_pos);\n                            sharp += c;\n                            parser_pos += 1;\n                        } while (parser_pos < input_length && c !== '#' && c !== '=');\n                        if (c === '#') {\n                            //\n                        } else if (input.charAt(parser_pos) === '[' && input.charAt(parser_pos + 1) === ']') {\n                            sharp += '[]';\n                            parser_pos += 2;\n                        } else if (input.charAt(parser_pos) === '{' && input.charAt(parser_pos + 1) === '}') {\n                            sharp += '{}';\n                            parser_pos += 2;\n                        }\n                        return [sharp, 'TK_WORD'];\n                    }\n                }\n\n                if (c === '<' && (input.charAt(parser_pos) === '?' || input.charAt(parser_pos) === '%')) {\n                    template_pattern.lastIndex = parser_pos - 1;\n                    var template_match = template_pattern.exec(input);\n                    if (template_match) {\n                        c = template_match[0];\n                        parser_pos += c.length - 1;\n                        c = c.replace(acorn.allLineBreaks, '\\n');\n                        return [c, 'TK_STRING'];\n                    }\n                }\n\n                if (c === '<' && input.substring(parser_pos - 1, parser_pos + 3) === '<!--') {\n                    parser_pos += 3;\n                    c = '<!--';\n                    while (!acorn.newline.test(input.charAt(parser_pos)) && parser_pos < input_length) {\n                        c += input.charAt(parser_pos);\n                        parser_pos++;\n                    }\n                    in_html_comment = true;\n                    return [c, 'TK_COMMENT'];\n                }\n\n                if (c === '-' && in_html_comment && input.substring(parser_pos - 1, parser_pos + 2) === '-->') {\n                    in_html_comment = false;\n                    parser_pos += 2;\n                    return ['-->', 'TK_COMMENT'];\n                }\n\n                if (c === '.') {\n                    return [c, 'TK_DOT'];\n                }\n\n                if (in_array(c, punct)) {\n                    while (parser_pos < input_length && in_array(c + input.charAt(parser_pos), punct)) {\n                        c += input.charAt(parser_pos);\n                        parser_pos += 1;\n                        if (parser_pos >= input_length) {\n                            break;\n                        }\n                    }\n\n                    if (c === ',') {\n                        return [c, 'TK_COMMA'];\n                    } else if (c === '=') {\n                        return [c, 'TK_EQUALS'];\n                    } else {\n                        return [c, 'TK_OPERATOR'];\n                    }\n                }\n\n                return [c, 'TK_UNKNOWN'];\n            }\n\n\n            function unescape_string(s) {\n                var esc = false,\n                    out = '',\n                    pos = 0,\n                    s_hex = '',\n                    escaped = 0,\n                    c;\n\n                while (esc || pos < s.length) {\n\n                    c = s.charAt(pos);\n                    pos++;\n\n                    if (esc) {\n                        esc = false;\n                        if (c === 'x') {\n                            // simple hex-escape \\x24\n                            s_hex = s.substr(pos, 2);\n                            pos += 2;\n                        } else if (c === 'u') {\n                            // unicode-escape, \\u2134\n                            s_hex = s.substr(pos, 4);\n                            pos += 4;\n                        } else {\n                            // some common escape, e.g \\n\n                            out += '\\\\' + c;\n                            continue;\n                        }\n                        if (!s_hex.match(/^[0123456789abcdefABCDEF]+$/)) {\n                            // some weird escaping, bail out,\n                            // leaving whole string intact\n                            return s;\n                        }\n\n                        escaped = parseInt(s_hex, 16);\n\n                        if (escaped >= 0x00 && escaped < 0x20) {\n                            // leave 0x00...0x1f escaped\n                            if (c === 'x') {\n                                out += '\\\\x' + s_hex;\n                            } else {\n                                out += '\\\\u' + s_hex;\n                            }\n                            continue;\n                        } else if (escaped === 0x22 || escaped === 0x27 || escaped === 0x5c) {\n                            // single-quote, apostrophe, backslash - escape these\n                            out += '\\\\' + String.fromCharCode(escaped);\n                        } else if (c === 'x' && escaped > 0x7e && escaped <= 0xff) {\n                            // we bail out on \\x7f..\\xff,\n                            // leaving whole string escaped,\n                            // as it's probably completely binary\n                            return s;\n                        } else {\n                            out += String.fromCharCode(escaped);\n                        }\n                    } else if (c === '\\\\') {\n                        esc = true;\n                    } else {\n                        out += c;\n                    }\n                }\n                return out;\n            }\n        }\n\n        var beautifier = new Beautifier(js_source_text, options);\n        return beautifier.beautify();\n\n    }\n\n    if (typeof define === \"function\" && define.amd) {\n        // Add support for AMD ( https://github.com/amdjs/amdjs-api/wiki/AMD#defineamd-property- )\n        define([], function() {\n            return { js_beautify: js_beautify };\n        });\n    } else if (typeof exports !== \"undefined\") {\n        // Add support for CommonJS. Just put this file somewhere on your require.paths\n        // and you will be able to `var js_beautify = require(\"beautify\").js_beautify`.\n        exports.js_beautify = js_beautify;\n    } else if (typeof window !== \"undefined\") {\n        // If we're running a web page and don't have either of the above, add our one global\n        window.js_beautify = js_beautify;\n    } else if (typeof global !== \"undefined\") {\n        // If we don't even have window, try global.\n        global.js_beautify = js_beautify;\n    }\n\n}());"
  },
  {
    "path": "lib/bowser.js",
    "content": "/*!\n * Bowser - a browser detector\n * https://github.com/ded/bowser\n * MIT License | (c) Dustin Diaz 2015\n */\n\n!function (root, name, definition) {\n  if (typeof module != 'undefined' && module.exports) module.exports = definition()\n  else if (typeof define == 'function' && define.amd) define(name, definition)\n  else root[name] = definition()\n}(this, 'bowser', function () {\n  /**\n    * See useragents.js for examples of navigator.userAgent\n    */\n\n  var t = true\n\n  function detect(ua) {\n\n    function getFirstMatch(regex) {\n      var match = ua.match(regex);\n      return (match && match.length > 1 && match[1]) || '';\n    }\n\n    function getSecondMatch(regex) {\n      var match = ua.match(regex);\n      return (match && match.length > 1 && match[2]) || '';\n    }\n\n    var iosdevice = getFirstMatch(/(ipod|iphone|ipad)/i).toLowerCase()\n      , likeAndroid = /like android/i.test(ua)\n      , android = !likeAndroid && /android/i.test(ua)\n      , nexusMobile = /nexus\\s*[0-6]\\s*/i.test(ua)\n      , nexusTablet = !nexusMobile && /nexus\\s*[0-9]+/i.test(ua)\n      , chromeos = /CrOS/.test(ua)\n      , silk = /silk/i.test(ua)\n      , sailfish = /sailfish/i.test(ua)\n      , tizen = /tizen/i.test(ua)\n      , webos = /(web|hpw)os/i.test(ua)\n      , windowsphone = /windows phone/i.test(ua)\n      , samsungBrowser = /SamsungBrowser/i.test(ua)\n      , windows = !windowsphone && /windows/i.test(ua)\n      , mac = !iosdevice && !silk && /macintosh/i.test(ua)\n      , linux = !android && !sailfish && !tizen && !webos && /linux/i.test(ua)\n      , edgeVersion = getFirstMatch(/edge\\/(\\d+(\\.\\d+)?)/i)\n      , versionIdentifier = getFirstMatch(/version\\/(\\d+(\\.\\d+)?)/i)\n      , tablet = /tablet/i.test(ua)\n      , mobile = !tablet && /[^-]mobi/i.test(ua)\n      , xbox = /xbox/i.test(ua)\n      , result\n\n    if (/opera/i.test(ua)) {\n      //  an old Opera\n      result = {\n        name: 'Opera'\n      , opera: t\n      , version: versionIdentifier || getFirstMatch(/(?:opera|opr|opios)[\\s\\/](\\d+(\\.\\d+)?)/i)\n      }\n    } else if (/opr|opios/i.test(ua)) {\n      // a new Opera\n      result = {\n        name: 'Opera'\n        , opera: t\n        , version: getFirstMatch(/(?:opr|opios)[\\s\\/](\\d+(\\.\\d+)?)/i) || versionIdentifier\n      }\n    }\n    else if (/SamsungBrowser/i.test(ua)) {\n      result = {\n        name: 'Samsung Internet for Android'\n        , samsungBrowser: t\n        , version: versionIdentifier || getFirstMatch(/(?:SamsungBrowser)[\\s\\/](\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (/coast/i.test(ua)) {\n      result = {\n        name: 'Opera Coast'\n        , coast: t\n        , version: versionIdentifier || getFirstMatch(/(?:coast)[\\s\\/](\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (/yabrowser/i.test(ua)) {\n      result = {\n        name: 'Yandex Browser'\n      , yandexbrowser: t\n      , version: versionIdentifier || getFirstMatch(/(?:yabrowser)[\\s\\/](\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (/ucbrowser/i.test(ua)) {\n      result = {\n          name: 'UC Browser'\n        , ucbrowser: t\n        , version: getFirstMatch(/(?:ucbrowser)[\\s\\/](\\d+(?:\\.\\d+)+)/i)\n      }\n    }\n    else if (/mxios/i.test(ua)) {\n      result = {\n        name: 'Maxthon'\n        , maxthon: t\n        , version: getFirstMatch(/(?:mxios)[\\s\\/](\\d+(?:\\.\\d+)+)/i)\n      }\n    }\n    else if (/epiphany/i.test(ua)) {\n      result = {\n        name: 'Epiphany'\n        , epiphany: t\n        , version: getFirstMatch(/(?:epiphany)[\\s\\/](\\d+(?:\\.\\d+)+)/i)\n      }\n    }\n    else if (/puffin/i.test(ua)) {\n      result = {\n        name: 'Puffin'\n        , puffin: t\n        , version: getFirstMatch(/(?:puffin)[\\s\\/](\\d+(?:\\.\\d+)?)/i)\n      }\n    }\n    else if (/sleipnir/i.test(ua)) {\n      result = {\n        name: 'Sleipnir'\n        , sleipnir: t\n        , version: getFirstMatch(/(?:sleipnir)[\\s\\/](\\d+(?:\\.\\d+)+)/i)\n      }\n    }\n    else if (/k-meleon/i.test(ua)) {\n      result = {\n        name: 'K-Meleon'\n        , kMeleon: t\n        , version: getFirstMatch(/(?:k-meleon)[\\s\\/](\\d+(?:\\.\\d+)+)/i)\n      }\n    }\n    else if (windowsphone) {\n      result = {\n        name: 'Windows Phone'\n      , windowsphone: t\n      }\n      if (edgeVersion) {\n        result.msedge = t\n        result.version = edgeVersion\n      }\n      else {\n        result.msie = t\n        result.version = getFirstMatch(/iemobile\\/(\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (/msie|trident/i.test(ua)) {\n      result = {\n        name: 'Internet Explorer'\n      , msie: t\n      , version: getFirstMatch(/(?:msie |rv:)(\\d+(\\.\\d+)?)/i)\n      }\n    } else if (chromeos) {\n      result = {\n        name: 'Chrome'\n      , chromeos: t\n      , chromeBook: t\n      , chrome: t\n      , version: getFirstMatch(/(?:chrome|crios|crmo)\\/(\\d+(\\.\\d+)?)/i)\n      }\n    } else if (/chrome.+? edge/i.test(ua)) {\n      result = {\n        name: 'Microsoft Edge'\n      , msedge: t\n      , version: edgeVersion\n      }\n    }\n    else if (/vivaldi/i.test(ua)) {\n      result = {\n        name: 'Vivaldi'\n        , vivaldi: t\n        , version: getFirstMatch(/vivaldi\\/(\\d+(\\.\\d+)?)/i) || versionIdentifier\n      }\n    }\n    else if (sailfish) {\n      result = {\n        name: 'Sailfish'\n      , sailfish: t\n      , version: getFirstMatch(/sailfish\\s?browser\\/(\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (/seamonkey\\//i.test(ua)) {\n      result = {\n        name: 'SeaMonkey'\n      , seamonkey: t\n      , version: getFirstMatch(/seamonkey\\/(\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (/firefox|iceweasel|fxios/i.test(ua)) {\n      result = {\n        name: 'Firefox'\n      , firefox: t\n      , version: getFirstMatch(/(?:firefox|iceweasel|fxios)[ \\/](\\d+(\\.\\d+)?)/i)\n      }\n      if (/\\((mobile|tablet);[^\\)]*rv:[\\d\\.]+\\)/i.test(ua)) {\n        result.firefoxos = t\n      }\n    }\n    else if (silk) {\n      result =  {\n        name: 'Amazon Silk'\n      , silk: t\n      , version : getFirstMatch(/silk\\/(\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (/phantom/i.test(ua)) {\n      result = {\n        name: 'PhantomJS'\n      , phantom: t\n      , version: getFirstMatch(/phantomjs\\/(\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (/slimerjs/i.test(ua)) {\n      result = {\n        name: 'SlimerJS'\n        , slimer: t\n        , version: getFirstMatch(/slimerjs\\/(\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (/blackberry|\\bbb\\d+/i.test(ua) || /rim\\stablet/i.test(ua)) {\n      result = {\n        name: 'BlackBerry'\n      , blackberry: t\n      , version: versionIdentifier || getFirstMatch(/blackberry[\\d]+\\/(\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (webos) {\n      result = {\n        name: 'WebOS'\n      , webos: t\n      , version: versionIdentifier || getFirstMatch(/w(?:eb)?osbrowser\\/(\\d+(\\.\\d+)?)/i)\n      };\n      /touchpad\\//i.test(ua) && (result.touchpad = t)\n    }\n    else if (/bada/i.test(ua)) {\n      result = {\n        name: 'Bada'\n      , bada: t\n      , version: getFirstMatch(/dolfin\\/(\\d+(\\.\\d+)?)/i)\n      };\n    }\n    else if (tizen) {\n      result = {\n        name: 'Tizen'\n      , tizen: t\n      , version: getFirstMatch(/(?:tizen\\s?)?browser\\/(\\d+(\\.\\d+)?)/i) || versionIdentifier\n      };\n    }\n    else if (/qupzilla/i.test(ua)) {\n      result = {\n        name: 'QupZilla'\n        , qupzilla: t\n        , version: getFirstMatch(/(?:qupzilla)[\\s\\/](\\d+(?:\\.\\d+)+)/i) || versionIdentifier\n      }\n    }\n    else if (/chromium/i.test(ua)) {\n      result = {\n        name: 'Chromium'\n        , chromium: t\n        , version: getFirstMatch(/(?:chromium)[\\s\\/](\\d+(?:\\.\\d+)?)/i) || versionIdentifier\n      }\n    }\n    else if (/chrome|crios|crmo/i.test(ua)) {\n      result = {\n        name: 'Chrome'\n        , chrome: t\n        , version: getFirstMatch(/(?:chrome|crios|crmo)\\/(\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (android) {\n      result = {\n        name: 'Android'\n        , version: versionIdentifier\n      }\n    }\n    else if (/safari|applewebkit/i.test(ua)) {\n      result = {\n        name: 'Safari'\n      , safari: t\n      }\n      if (versionIdentifier) {\n        result.version = versionIdentifier\n      }\n    }\n    else if (iosdevice) {\n      result = {\n        name : iosdevice == 'iphone' ? 'iPhone' : iosdevice == 'ipad' ? 'iPad' : 'iPod'\n      }\n      // WTF: version is not part of user agent in web apps\n      if (versionIdentifier) {\n        result.version = versionIdentifier\n      }\n    }\n    else if(/googlebot/i.test(ua)) {\n      result = {\n        name: 'Googlebot'\n      , googlebot: t\n      , version: getFirstMatch(/googlebot\\/(\\d+(\\.\\d+))/i) || versionIdentifier\n      }\n    }\n    else {\n      result = {\n        name: getFirstMatch(/^(.*)\\/(.*) /),\n        version: getSecondMatch(/^(.*)\\/(.*) /)\n     };\n   }\n\n    // set webkit or gecko flag for browsers based on these engines\n    if (!result.msedge && /(apple)?webkit/i.test(ua)) {\n      if (/(apple)?webkit\\/537\\.36/i.test(ua)) {\n        result.name = result.name || \"Blink\"\n        result.blink = t\n      } else {\n        result.name = result.name || \"Webkit\"\n        result.webkit = t\n      }\n      if (!result.version && versionIdentifier) {\n        result.version = versionIdentifier\n      }\n    } else if (!result.opera && /gecko\\//i.test(ua)) {\n      result.name = result.name || \"Gecko\"\n      result.gecko = t\n      result.version = result.version || getFirstMatch(/gecko\\/(\\d+(\\.\\d+)?)/i)\n    }\n\n    // set OS flags for platforms that have multiple browsers\n    if (!result.windowsphone && !result.msedge && (android || result.silk)) {\n      result.android = t\n    } else if (!result.windowsphone && !result.msedge && iosdevice) {\n      result[iosdevice] = t\n      result.ios = t\n    } else if (mac) {\n      result.mac = t\n    } else if (xbox) {\n      result.xbox = t\n    } else if (windows) {\n      result.windows = t\n    } else if (linux) {\n      result.linux = t\n    }\n\n    // OS version extraction\n    var osVersion = '';\n    if (result.windowsphone) {\n      osVersion = getFirstMatch(/windows phone (?:os)?\\s?(\\d+(\\.\\d+)*)/i);\n    } else if (iosdevice) {\n      osVersion = getFirstMatch(/os (\\d+([_\\s]\\d+)*) like mac os x/i);\n      osVersion = osVersion.replace(/[_\\s]/g, '.');\n    } else if (android) {\n      osVersion = getFirstMatch(/android[ \\/-](\\d+(\\.\\d+)*)/i);\n    } else if (result.webos) {\n      osVersion = getFirstMatch(/(?:web|hpw)os\\/(\\d+(\\.\\d+)*)/i);\n    } else if (result.blackberry) {\n      osVersion = getFirstMatch(/rim\\stablet\\sos\\s(\\d+(\\.\\d+)*)/i);\n    } else if (result.bada) {\n      osVersion = getFirstMatch(/bada\\/(\\d+(\\.\\d+)*)/i);\n    } else if (result.tizen) {\n      osVersion = getFirstMatch(/tizen[\\/\\s](\\d+(\\.\\d+)*)/i);\n    }\n    if (osVersion) {\n      result.osversion = osVersion;\n    }\n\n    // device type extraction\n    var osMajorVersion = osVersion.split('.')[0];\n    if (\n         tablet\n      || nexusTablet\n      || iosdevice == 'ipad'\n      || (android && (osMajorVersion == 3 || (osMajorVersion >= 4 && !mobile)))\n      || result.silk\n    ) {\n      result.tablet = t\n    } else if (\n         mobile\n      || iosdevice == 'iphone'\n      || iosdevice == 'ipod'\n      || android\n      || nexusMobile\n      || result.blackberry\n      || result.webos\n      || result.bada\n    ) {\n      result.mobile = t\n    }\n\n    // Graded Browser Support\n    // http://developer.yahoo.com/yui/articles/gbs\n    if (result.msedge ||\n        (result.msie && result.version >= 10) ||\n        (result.yandexbrowser && result.version >= 15) ||\n\t\t    (result.vivaldi && result.version >= 1.0) ||\n        (result.chrome && result.version >= 20) ||\n        (result.samsungBrowser && result.version >= 4) ||\n        (result.firefox && result.version >= 20.0) ||\n        (result.safari && result.version >= 6) ||\n        (result.opera && result.version >= 10.0) ||\n        (result.ios && result.osversion && result.osversion.split(\".\")[0] >= 6) ||\n        (result.blackberry && result.version >= 10.1)\n        || (result.chromium && result.version >= 20)\n        ) {\n      result.a = t;\n    }\n    else if ((result.msie && result.version < 10) ||\n        (result.chrome && result.version < 20) ||\n        (result.firefox && result.version < 20.0) ||\n        (result.safari && result.version < 6) ||\n        (result.opera && result.version < 10.0) ||\n        (result.ios && result.osversion && result.osversion.split(\".\")[0] < 6)\n        || (result.chromium && result.version < 20)\n        ) {\n      result.c = t\n    } else result.x = t\n\n    return result\n  }\n\n  var bowser = detect(typeof navigator !== 'undefined' ? navigator.userAgent || '' : '')\n\n  bowser.test = function (browserList) {\n    for (var i = 0; i < browserList.length; ++i) {\n      var browserItem = browserList[i];\n      if (typeof browserItem=== 'string') {\n        if (browserItem in bowser) {\n          return true;\n        }\n      }\n    }\n    return false;\n  }\n\n  /**\n   * Get version precisions count\n   *\n   * @example\n   *   getVersionPrecision(\"1.10.3\") // 3\n   *\n   * @param  {string} version\n   * @return {number}\n   */\n  function getVersionPrecision(version) {\n    return version.split(\".\").length;\n  }\n\n  /**\n   * Array::map polyfill\n   *\n   * @param  {Array} arr\n   * @param  {Function} iterator\n   * @return {Array}\n   */\n  function map(arr, iterator) {\n    var result = [], i;\n    if (Array.prototype.map) {\n      return Array.prototype.map.call(arr, iterator);\n    }\n    for (i = 0; i < arr.length; i++) {\n      result.push(iterator(arr[i]));\n    }\n    return result;\n  }\n\n  /**\n   * Calculate browser version weight\n   *\n   * @example\n   *   compareVersions(['1.10.2.1',  '1.8.2.1.90'])    // 1\n   *   compareVersions(['1.010.2.1', '1.09.2.1.90']);  // 1\n   *   compareVersions(['1.10.2.1',  '1.10.2.1']);     // 0\n   *   compareVersions(['1.10.2.1',  '1.0800.2']);     // -1\n   *\n   * @param  {Array<String>} versions versions to compare\n   * @return {Number} comparison result\n   */\n  function compareVersions(versions) {\n    // 1) get common precision for both versions, for example for \"10.0\" and \"9\" it should be 2\n    var precision = Math.max(getVersionPrecision(versions[0]), getVersionPrecision(versions[1]));\n    var chunks = map(versions, function (version) {\n      var delta = precision - getVersionPrecision(version);\n\n      // 2) \"9\" -> \"9.0\" (for precision = 2)\n      version = version + new Array(delta + 1).join(\".0\");\n\n      // 3) \"9.0\" -> [\"000000000\"\", \"000000009\"]\n      return map(version.split(\".\"), function (chunk) {\n        return new Array(20 - chunk.length).join(\"0\") + chunk;\n      }).reverse();\n    });\n\n    // iterate in reverse order by reversed chunks array\n    while (--precision >= 0) {\n      // 4) compare: \"000000009\" > \"000000010\" = false (but \"9\" > \"10\" = true)\n      if (chunks[0][precision] > chunks[1][precision]) {\n        return 1;\n      }\n      else if (chunks[0][precision] === chunks[1][precision]) {\n        if (precision === 0) {\n          // all version chunks are same\n          return 0;\n        }\n      }\n      else {\n        return -1;\n      }\n    }\n  }\n\n  /**\n   * Check if browser is unsupported\n   *\n   * @example\n   *   bowser.isUnsupportedBrowser({\n   *     msie: \"10\",\n   *     firefox: \"23\",\n   *     chrome: \"29\",\n   *     safari: \"5.1\",\n   *     opera: \"16\",\n   *     phantom: \"534\"\n   *   });\n   *\n   * @param  {Object}  minVersions map of minimal version to browser\n   * @param  {Boolean} [strictMode = false] flag to return false if browser wasn't found in map\n   * @param  {String}  [ua] user agent string\n   * @return {Boolean}\n   */\n  function isUnsupportedBrowser(minVersions, strictMode, ua) {\n    var _bowser = bowser;\n\n    // make strictMode param optional with ua param usage\n    if (typeof strictMode === 'string') {\n      ua = strictMode;\n      strictMode = void(0);\n    }\n\n    if (strictMode === void(0)) {\n      strictMode = false;\n    }\n    if (ua) {\n      _bowser = detect(ua);\n    }\n\n    var version = \"\" + _bowser.version;\n    for (var browser in minVersions) {\n      if (minVersions.hasOwnProperty(browser)) {\n        if (_bowser[browser]) {\n          if (typeof minVersions[browser] !== 'string') {\n            throw new Error('Browser version in the minVersion map should be a string: ' + browser + ': ' + String(minVersions));\n          }\n\n          // browser version and min supported version.\n          return compareVersions([version, minVersions[browser]]) < 0;\n        }\n      }\n    }\n\n    return strictMode; // not found\n  }\n\n  /**\n   * Check if browser is supported\n   *\n   * @param  {Object} minVersions map of minimal version to browser\n   * @param  {Boolean} [strictMode = false] flag to return false if browser wasn't found in map\n   * @param  {String}  [ua] user agent string\n   * @return {Boolean}\n   */\n  function check(minVersions, strictMode, ua) {\n    return !isUnsupportedBrowser(minVersions, strictMode, ua);\n  }\n\n  bowser.isUnsupportedBrowser = isUnsupportedBrowser;\n  bowser.compareVersions = compareVersions;\n  bowser.check = check;\n\n  /*\n   * Set our detect method to the main bowser object so we can\n   * reuse it to test other user agents.\n   * This is needed to implement future tests.\n   */\n  bowser._detect = detect;\n\n  return bowser\n});\n"
  },
  {
    "path": "lib/canvasutils.js",
    "content": "http://blog.acipo.com/blob-detection-js/\n\nfunction unique(arr){\n/// Returns an object with the counts of unique elements in arr\n/// unique([1,2,1,1,1,2,3,4]) === { 1:4, 2:2, 3:1, 4:1 }\n\n    var value, counts = {};\n    var i, l = arr.length;\n    for( i=0; i<l; i+=1) {\n        value = arr[i];\n        if( counts[value] ){\n            counts[value] += 1;\n        }else{\n            counts[value] = 1;\n        }\n    }\n\n    return counts;\n}\n\nfunction FindBlobs(src) {\n\n  var xSize = src.width,\n      ySize = src.height,\n      srcPixels = src.data,\n      x, y, pos;\n\n  // This will hold the indecies of the regions we find\n  var blobMap = [];\n  var label = 1;\n\n  // The labelTable remember when blobs of differen labels merge\n  // so labelTabel[1] = 2; means that label 1 and 2 are the same blob\n  var labelTable = [0];\n\n  // Start by labeling every pixel as blob 0\n  for(y=0; y<ySize; y++){\n    blobMap.push([]);\n    for(x=0; x<xSize; x++){\n      blobMap[y].push(0);\n    }\n  }  \n\n  // Temporary variables for neighboring pixels and other stuff\n  var nn, nw, ne, ww, ee, sw, ss, se, minIndex;\n  var luma = 0;\n  var isVisible = 0;\n\n  // We're going to run this algorithm twice\n  // The first time identifies all of the blobs candidates the second pass\n  // merges any blobs that the first pass failed to merge\n  var nIter = 2;\n  while( nIter-- ){\n\n    // We leave a 1 pixel border which is ignored so we do not get array\n    // out of bounds errors\n    for( y=1; y<ySize-1; y++){\n      for( x=1; x<xSize-1; x++){\n\n        pos = (y*xSize+x)*4;\n\n        // We're only looking at the alpha channel in this case but you can\n        // use more complicated heuristics\n        isVisible = (srcPixels[pos+3] > 0);\n\n        if( isVisible ){\n\n          // Find the lowest blob index nearest this pixel\n          nw = blobMap[y-1][x-1] || 0;\n          nn = blobMap[y-1][x-0] || 0;\n          ne = blobMap[y-1][x+1] || 0;\n          ww = blobMap[y-0][x-1] || 0;\n          ee = blobMap[y-0][x+1] || 0;\n          sw = blobMap[y+1][x-1] || 0;\n          ss = blobMap[y+1][x-0] || 0;\n          se = blobMap[y+1][x+1] || 0;\n          minIndex = ww;\n          if( 0 < ww && ww < minIndex ){ minIndex = ww; }\n          if( 0 < ee && ee < minIndex ){ minIndex = ee; }\n          if( 0 < nn && nn < minIndex ){ minIndex = nn; }\n          if( 0 < ne && ne < minIndex ){ minIndex = ne; }\n          if( 0 < nw && nw < minIndex ){ minIndex = nw; }\n          if( 0 < ss && ss < minIndex ){ minIndex = ss; }\n          if( 0 < se && se < minIndex ){ minIndex = se; }\n          if( 0 < sw && sw < minIndex ){ minIndex = sw; }\n  \n          // This point starts a new blob -- increase the lable count and\n          // and an entry for it in the label table\n          if( minIndex === 0 ){\n            blobMap[y][x] = label;\n            labelTable.push(label);\n            label += 1;\n  \n          // This point is part of an old blob -- update the labels of the\n          // neighboring pixels in the label table so that we know a merge\n          // should occur and mark this pixel with the label.\n          }else{\n            if( minIndex < labelTable[nw] ){ labelTable[nw] = minIndex; }\n            if( minIndex < labelTable[nn] ){ labelTable[nn] = minIndex; }\n            if( minIndex < labelTable[ne] ){ labelTable[ne] = minIndex; }\n            if( minIndex < labelTable[ww] ){ labelTable[ww] = minIndex; }\n            if( minIndex < labelTable[ee] ){ labelTable[ee] = minIndex; }\n            if( minIndex < labelTable[sw] ){ labelTable[sw] = minIndex; }\n            if( minIndex < labelTable[ss] ){ labelTable[ss] = minIndex; }\n            if( minIndex < labelTable[se] ){ labelTable[se] = minIndex; }\n\n            blobMap[y][x] = minIndex;\n          }\n\n        // This pixel isn't visible so we won't mark it as special\n        }else{\n          blobMap[y][x] = 0;\n        }\n  \n      }\n    }\n  \n    // Compress the table of labels so that every location refers to only 1\n    // matching location\n    var i = labelTable.length;\n    while( i-- ){\n      label = labelTable[i];\n      while( label !== labelTable[label] ){\n        label = labelTable[label];\n      }\n      labelTable[i] = label;\n    }\n  \n    // Merge the blobs with multiple labels\n    for(y=0; y<ySize; y++){\n      for(x=0; x<xSize; x++){\n        label = blobMap[y][x];\n        if( label === 0 ){ continue; }\n        while( label !== labelTable[label] ){\n          label = labelTable[label];\n        }\n        blobMap[y][x] = label;\n      }\n    }\n  }\n\n  // The blobs may have unusual labels: [1,38,205,316,etc..]\n  // Let's rename them: [1,2,3,4,etc..]\n\n  var uniqueLabels = unique(labelTable);\n  var labelCount = 0;\n  for(uniqueLabel in uniqueLabels) labelCount++;\n\n  var i = 0;\n  for( label in uniqueLabels ){\n    labelTable[label] = i++;\n  }\n\n  // convert the blobs to the minimized labels\n  for(y=0; y<ySize; y++){\n    for(x=0; x<xSize; x++){\n      label = blobMap[y][x];\n      blobMap[y][x] = labelTable[label];\n    }\n  }\n\n  // Return the blob data:\n  return {blobMap:blobMap, nBlobs:labelCount};\n\n};\n\n\nfunction ColorTheBlobs(dst,blobs,colors){\n    var xSize = dst.width,\n        ySize = dst.height,\n        dstPixels = dst.data,\n        x, y, pos;\n\n    var label, color, nColors = colors.length;\n\n    for(y=0; y<ySize; y++){\n        for(x=0; x<xSize; x++){\n            pos = (y*xSize+x)*4;\n\n            label = blobs[y][x];\n\n            if( label !== 0 ){\n                color = colors[ label % nColors ];\n                dstPixels[ pos+0 ] = color[0];\n                dstPixels[ pos+1 ] = color[1];\n                dstPixels[ pos+2 ] = color[2];\n                dstPixels[ pos+3 ] = color[3];\n            }else{\n                dstPixels[ pos+3 ] = 0;\n            }\n        }\n    }\n\n}\n\nfunction GetBlobMap (img, callback) {\n  ImageToCanvas(img, function (canvas,context) {\n    var canvas = canvas;//document.getElementById('canvas-draw');\n    var contex = context;//canvas.getContext('2d');\n    var imageData = contex.getImageData(0,0,canvas.width,canvas.height);\n\n    var blobResults = FindBlobs(imageData);\n    var blobLabels = blobResults.blobMap;\n    var nBlobs = blobResults.nBlobs;\n\n    var blobCanvas = document.createElement('canvas');//document.getElementById('canvas-blob');\n    blobCanvas.width = canvas.width;\n    blobCanvas.height = canvas.height;\n    var blobContex = blobCanvas.getContext('2d');\n    var blobImageData = contex.getImageData(0,0,canvas.width,canvas.height);\n\n    // this means you can only have 255 blobs, ya dummy!\n    var colors = [];\n    for(var i = 0; i <= 255; i+=1) {\n      colors.push([i,0,0,255]);\n    }\n    ColorTheBlobs(blobImageData,blobLabels,colors);\n    \n    blobContex.putImageData(blobImageData,0,0);\n\n    var blobMap = new Image();\n    blobMap.onload = function () {\n      callback({blobMap:blobMap, nBlobs:nBlobs});\n    }\n    blobMap.src = blobCanvas.toDataURL();\n  });\n}\n\nfunction GetBlobImages (blobMap, nBlobs, image, callback) {\n\tvar imagesData = [];\n\n\tvar label;\n\tfor(label=1; label<=nBlobs; label++) {\n\t\timagesData[label] = GetBlobImage(blobMap, image, label);\n\t}\n\n\tvar images = [];\n\tvar done = false;\n\n\tfunction processBlobImage (i) {\n\t\tvar data = imagesData[i];\n\t\tif(data) {\n\t\t\tctx.putImageData(data,0,0);\n\n\t\t\tvar image = new Image();\n\t\t\timage.onload = function () {\n\t\t\t\t//callback(image);\n\t\t\t\timages.push(image);\n\t\t\t\tif(images.length >= nBlobs-1) {\n\t\t\t\t\tif(!done) callback(images);\n\t\t\t\t\tdone = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\timage.src = canvas.toDataURL();\n\t\t}\n\t}\n\n\tfor(label=1; label<=nBlobs; label++) {\n\t\tif(done) return;\n\n\t\tvar canvas = document.createElement('canvas');\n\t\tcanvas.width = image.width;\n\t\tcanvas.height = image.height;\n\t\tvar ctx = canvas.getContext('2d');\n\n\t\tprocessBlobImage(label);\n\t}\n}\n\nfunction GetBlobImage (blobMap, originalImg, label) {\n\n\tvar blobMapData = ImageToImageData(blobMap)\n\tvar originalImgData = ImageToImageData(originalImg)\n\n\tvar xSize = blobMapData.width,\n        ySize = blobMapData.height,\n        blobMapPixels = blobMapData.data,\n        x, y, pos;\n\n    var originalImgPixels = originalImgData.data;\n\n    var canvas = document.createElement('canvas');\n    var ctx = canvas.getContext('2d');\n    var newImgData = ctx.createImageData(originalImgData);\n    var newImagePixels = newImgData.data;\n\n    var blobExistsWithLabel = false;\n\n    for(y=0; y<ySize; y++){\n        for(x=0; x<xSize; x++){\n            pos = (y*xSize+x)*4;\n\n            if(blobMapPixels[ pos+0 ] === label) {\n            \tnewImagePixels[ pos+0 ] = originalImgPixels[ pos+0 ];\n            \tnewImagePixels[ pos+1 ] = originalImgPixels[ pos+1 ];\n            \tnewImagePixels[ pos+2 ] = originalImgPixels[ pos+2 ];\n            \tnewImagePixels[ pos+3 ] = originalImgPixels[ pos+3 ];\n            \tblobExistsWithLabel = true;\n            } else {\n            \tnewImagePixels[ pos+0 ] = 0;\n\t            newImagePixels[ pos+1 ] = 0;\n\t            newImagePixels[ pos+2 ] = 0;\n\t            newImagePixels[ pos+3 ] = 0;\n            }\n        }\n    }\n\n    return blobExistsWithLabel ? newImgData : null;\n}\n\nfunction FindBlobsAndGetBlobImages (imgData, callback) {\n\n\tGetBlobMap(imgData, function (blobResult) {\n        var img = new Image();\n        img.onload = function () {\n            GetBlobImages(blobResult.blobMap, blobResult.nBlobs, img, function (blobImages) {\n                callback(blobImages);\n            });\n        }\n        img.src = imgData;\n    });\n\n}\n\n// Image cropping / padding (zrispo)\n\nvar CropImage = function (src, callback, args) {\n    var canvas = document.createElement('canvas');\n    canvas.width = args.width;\n    canvas.height = args.height;\n\n    var context = canvas.getContext('2d');\n    var imageObj = new Image();\n\n    imageObj.onload = function() {\n        // draw cropped image\n        var sourceX = args.x;\n        var sourceY = args.y;\n        var sourceWidth = args.width;\n        var sourceHeight = args.height;\n        var destWidth = sourceWidth;\n        var destHeight = sourceHeight;\n        var destX = canvas.width / 2 - destWidth / 2;\n        var destY = canvas.height / 2 - destHeight / 2;\n\n        context.drawImage(imageObj, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight);\n\n        callback(canvas.toDataURL());\n    };\n\n    imageObj.src = src;\n}\n\nfunction AddPaddingToImage (img, callback) {\n    var oddWidth = img.width % 2 === 1;\n    var oddHeight = img.height % 2 === 1;\n\n    if (oddWidth && oddHeight) {\n        CropImage(img.src, callback, {\n            x: 0,\n            y: 0,\n            width: img.width+1,\n            height: img.height+1\n        });\n    } else if (oddWidth) {\n        CropImage(img.src, callback, {\n            x: 0,\n            y: 0,\n            width: img.width+1,\n            height: img.height\n        });\n    } else if (oddHeight) {\n        CropImage(img.src, callback, {\n            x: 0,\n            y: 0,\n            width: img.width,\n            height: img.height+1\n        });\n    } else {\n        callback(img.src);\n    }\n\n}\n\n// Canvas <-> Image conversion (zrispo)\n\nvar ImageToCanvas = function (src, callback, args) {\n\n  var image = new Image();\n    image.onload = function () {\n      var w = image.width;\n        var h = image.height;\n\n        if(args && args.width)  w = args.width;\n        if(args && args.height) h = args.height;\n\n        var canvas = document.createElement('canvas');\n        canvas.height = h;\n        canvas.width = w;\n        \n        var ctx = canvas.getContext('2d');\n        ctx.drawImage( image, 0, 0, w, h );\n        callback(canvas,ctx);\n    };\n    image.setAttribute('crossOrigin', 'anonymous');\n    image.src = src;\n\n}\n\nfunction ImageToImageData (img) {\n    var canvas = document.createElement('canvas');\n    canvas.width = img.width;\n    canvas.height = img.height;\n    var ctx = canvas.getContext('2d');\n    ctx.drawImage(img, 0, 0)\n    return ctx.getImageData(0,0,canvas.width,canvas.height);\n}\n\nfunction PixelsToImageData (pixelData) {\n\n}\n\n// Color picking (unknown source??)\n\nvar GetColorAtCoords = function (img, x, y, format) {\n  \n  if(x < 0 || y < 0 || x > img.width || y > img.height) {\n    console.error(\"GetColorAtCoords: coords out of bounds: (\"+x+\",\"+y+\")\")\n  }\n\n  var canvas = document.createElement('canvas');\n  canvas.width = img.width;\n  canvas.height = img.height;\n  var context = canvas.getContext('2d');\n  context.drawImage(img, 0, 0);\n  var data = context.getImageData(0, 0, canvas.width, canvas.height).data;\n\n  var i = (x + y*img.width) * 4;\n\n  var color = {};\n  color.r = data[i+0];\n  color.g = data[i+1];\n  color.b = data[i+2];\n  color.a = data[i+3];\n\n  if (!format) {\n    return color;\n  }\n\n  if (format === \"rgba\") {\n    return color;\n  } else if (format === \"hex\") {\n    // http://jsfiddle.net/Mottie/xcqpF/1/light/\n    function rgb2hex(rgb){\n      rgb = rgb.match(/^rgba?[\\s+]?\\([\\s+]?(\\d+)[\\s+]?,[\\s+]?(\\d+)[\\s+]?,[\\s+]?(\\d+)[\\s+]?/i);\n      return (rgb && rgb.length === 4) ? \"#\" +\n        (\"0\" + parseInt(rgb[1],10).toString(16)).slice(-2) +\n        (\"0\" + parseInt(rgb[2],10).toString(16)).slice(-2) +\n        (\"0\" + parseInt(rgb[3],10).toString(16)).slice(-2) : '';\n    }\n    return rgb2hex(\"rgb(\"+color.r+\",\"+color.g+\",\"+color.b+\")\").toUpperCase();\n  }\n\n}\n\n// Blank pixel remover / cropper\n\n// http://stackoverflow.com/questions/12175991/crop-image-white-space-automatically-using-jquery\n\nvar removeBlankPixels = function (img, imgWidth, imgHeight) {\n    var canvas = document.createElement('canvas');\n    var context = canvas.getContext('2d');\n\n    canvas.width = img.width;\n    canvas.height = img.height;\n    context.drawImage(img, 0, 0)\n\n    var imageData = context.getImageData(0, 0, imgWidth, imgHeight),\n        data = imageData.data,\n        getRBG = function(x, y) {\n            var offset = imgWidth * y + x;\n            return {\n                red:     data[offset * 4],\n                green:   data[offset * 4 + 1],\n                blue:    data[offset * 4 + 2],\n                opacity: data[offset * 4 + 3]\n            };\n        },\n        isWhite = function (rgb) {\n            // many images contain noise, as the white is not a pure #fff white\n            //return rgb.red > 200 && rgb.green > 200 && rgb.blue > 200;\n            return rgb.opacity === 0;\n        },\n        scanY = function (fromTop) {\n            var offset = fromTop ? 1 : -1;\n            \n            // loop through each row\n            for(var y = fromTop ? 0 : imgHeight - 1; fromTop ? (y < imgHeight) : (y > -1); y += offset) {\n                \n                // loop through each column\n                for(var x = 0; x < imgWidth; x++) {\n                    var rgb = getRBG(x, y);\n                    if (!isWhite(rgb)) {\n                        return y;                        \n                    }      \n                }\n            }\n            return null; // all image is white\n        },\n        scanX = function (fromLeft) {\n            var offset = fromLeft? 1 : -1;\n            \n            // loop through each column\n            for(var x = fromLeft ? 0 : imgWidth - 1; fromLeft ? (x < imgWidth) : (x > -1); x += offset) {\n                \n                // loop through each row\n                for(var y = 0; y < imgHeight; y++) {\n                    var rgb = getRBG(x, y);\n                    if (!isWhite(rgb)) {\n                        return x;                        \n                    }      \n                }\n            }\n            return null; // all image is white\n        };\n    \n    var cropTop = scanY(true),\n        cropBottom = scanY(false),\n        cropLeft = scanX(true),\n        cropRight = scanX(false),\n        cropWidth = cropRight - cropLeft + 1,\n        cropHeight = cropBottom - cropTop + 1;\n    \n    var croppedCanvas = document.createElement('canvas');\n    croppedCanvas.width = cropWidth;\n    croppedCanvas.height = cropHeight;\n\n    //$(\"<canvas>\").attr({ width: cropWidth, height: cropHeight });\n    \n    // finally crop the guy\n    croppedCanvas.getContext(\"2d\").drawImage(\n        canvas,\n        cropLeft, cropTop, \n        cropWidth, cropHeight,\n        0, 0, \n        cropWidth, cropHeight );\n    \n    /*$(\"body\").\n        append(\"<p>same image with white spaces cropped:</p>\").\n        append($croppedCanvas);*/\n    //console.log(cropTop, cropBottom, cropLeft, cropRight);\n\n    var dataURL = croppedCanvas.toDataURL();\n    return {dataURL:dataURL, left:cropLeft, top:cropTop};\n};\n\nfunction getColorIndicesForCoord(x, y, width) {\n  var red = y * (width * 4) + x * 4;\n  return {\n    r: red,\n    g: red+1,\n    b: red+2,\n    a: red+3,\n  }\n  //[red, red + 1, red + 2, red + 3];\n}\n\nfunction getPixelAt (x,y,width,height,imageData) {\n  if(x<0 || y<0 || x>=width || y>=height) return null;\n\n  var offset = (y*width+x)*4;\n  return {\n    r: imageData[offset],\n    g: imageData[offset+1],\n    b: imageData[offset+2],\n    a: imageData[offset+3]\n  }\n}\n\nfunction setPixelAt (x,y,width,height,imageData,color) {\n  var offset = (y*width+x)*4;\n  imageData[offset] = color.r\n  imageData[offset+1] = color.g\n  imageData[offset+2] = color.b\n  imageData[offset+3] = color.a\n}\n"
  },
  {
    "path": "lib/croquis.js",
    "content": "function Croquis(imageDataList, properties) {\n    var self = this;\n    if (properties != null)\n        for (var property in properties)\n            self[property] = properties[property];\n    var domElement = document.createElement('div');\n    domElement.style.clear = 'both';\n    domElement.style.setProperty('user-select', 'none');\n    domElement.style.setProperty('-webkit-user-select', 'none');\n    domElement.style.setProperty('-ms-user-select', 'none');\n    domElement.style.setProperty('-moz-user-select', 'none');\n    self.getDOMElement = function () {\n        return domElement;\n    };\n    self.getRelativePosition = function (absoluteX, absoluteY) {\n        var rect = domElement.getBoundingClientRect();\n        return {x: absoluteX - rect.left,y: absoluteY - rect.top};\n    };\n    var eventListeners = {\n        'ondown': [],\n        'onmove': [],\n        'onup': [],\n        'ontick': [],\n        'onchange': [],\n        'onundo': [],\n        'onredo': [],\n        'ontool': [],\n        'oncanvassize': [],\n        'onlayeradd': [],\n        'onlayerremove': [],\n        'onlayerswap': [],\n        'onlayerselect': []\n    };\n    function dispatchEvent(event, e) {\n        event = event.toLowerCase();\n        e = e || {};\n        if (eventListeners.hasOwnProperty(event)) {\n            eventListeners[event].forEach(function (listener) {\n                listener.call(self, e);\n            });\n        }\n        else throw 'don\\'t support ' + event;\n    }\n    self.addEventListener = function (event, listener) {\n        event = event.toLowerCase();\n        if (eventListeners.hasOwnProperty(event)) {\n            if (typeof listener !== 'function')\n                throw listener + ' is not a function';\n            eventListeners[event].push(listener);\n        }\n        else throw 'don\\'t support ' + event;\n    };\n    self.removeEventListener = function (event, listener) {\n        event = event.toLowerCase();\n        if (eventListeners.hasOwnProperty(event)) {\n            if (listener == null) { // remove all\n                eventListeners[event] = [];\n                return;\n            }\n            var listeners = eventListeners[event];\n            var index = listeners.indexOf(listener);\n            if (index >= 0) listeners.splice(index, 1);\n        }\n        else throw 'don\\'t support ' + event;\n    };\n    self.hasEventListener = function (event, listener) {\n        event = event.toLowerCase();\n        if (eventListeners.hasOwnProperty(event)) {\n            if (listener == null)\n                return eventListeners[event].length > 0;\n            return eventListeners[event].indexOf(listener) >= 0;\n        }\n        else return false;\n    };\n    var undoStack = [];\n    var redoStack = [];\n    var undoLimit = 10;\n    var preventPushUndo = false;\n    var pushToTransaction = false;\n    self.getUndoLimit = function () {\n        return undoLimit;\n    };\n    self.setUndoLimit = function (limit) {\n        undoLimit = limit;\n    };\n    self.lockHistory = function () {\n        preventPushUndo = true;\n    };\n    self.unlockHistory = function () {\n        preventPushUndo = false;\n    };\n    self.beginHistoryTransaction = function () {\n        undoStack.push([]);\n        pushToTransaction = true;\n    };\n    self.endHistoryTransaction = function () {\n        pushToTransaction = false;\n    };\n    self.clearHistory = function () {\n        if (preventPushUndo)\n            throw 'history is locked';\n        undoStack = [];\n        redoStack = [];\n    };\n    function pushUndo(undoFunction) {\n        dispatchEvent('onchange');\n        if (self.onChanged)\n            self.onChanged();\n        if (preventPushUndo)\n            return;\n        redoStack = [];\n        if (pushToTransaction)\n            undoStack[undoStack.length - 1].push(undoFunction);\n        else\n            undoStack.push([undoFunction]);\n        while (undoStack.length > undoLimit)\n            undoStack.shift();\n    }\n    self.undo = function () {\n        if (pushToTransaction)\n            throw 'transaction is not ended';\n        if (preventPushUndo)\n            throw 'history is locked';\n        if (isDrawing || isStabilizing)\n            throw 'still drawing';\n        if (undoStack.length == 0)\n            throw 'no more undo data';\n        var undoTransaction = undoStack.pop();\n        var redoTransaction = [];\n        while (undoTransaction.length)\n            redoTransaction.push(undoTransaction.pop()());\n        redoStack.push(redoTransaction);\n        dispatchEvent('onundo');\n    };\n    self.redo = function () {\n        if (pushToTransaction)\n            throw 'transaction is not ended';\n        if (preventPushUndo)\n            throw 'history is locked';\n        if (isDrawing || isStabilizing)\n            throw 'still drawing';\n        if (redoStack.length == 0)\n            throw 'no more redo data';\n        var redoTransaction = redoStack.pop();\n        var undoTransaction = [];\n        while (redoTransaction.length)\n            undoTransaction.push(redoTransaction.pop()());\n        undoStack.push(undoTransaction);\n        dispatchEvent('onredo');\n    };\n    function pushLayerMetadataUndo(index) {\n        index = index || layerIndex;\n        var snapshotMetadata = self.getLayerMetadata(index);\n        var swap = function () {\n            self.lockHistory();\n            var temp = self.getLayerMetadata(index);\n            self.setLayerMetadata(snapshotMetadata, index);\n            snapshotMetadata = temp;\n            self.unlockHistory();\n            return swap;\n        };\n        pushUndo(swap);\n    }\n    function pushLayerOpacityUndo(index) {\n        index = index || layerIndex;\n        var snapshotOpacity = self.getLayerOpacity(index);\n        var swap = function () {\n            self.lockHistory();\n            var temp = self.getLayerOpacity(index);\n            self.setLayerOpacity(snapshotOpacity, index);\n            snapshotOpacity = temp;\n            self.unlockHistory();\n            return swap;\n        };\n        pushUndo(swap);\n    }\n    function pushLayerVisibleUndo(index) {\n        index = index || layerIndex;\n        var snapshotVisible = self.getLayerVisible(index);\n        var swap = function () {\n            self.lockHistory();\n            var temp = self.getLayerVisible(index);\n            self.setLayerVisible(snapshotVisible, index);\n            snapshotVisible = temp;\n            self.unlockHistory();\n            return swap;\n        };\n        pushUndo(swap);\n    }\n    function pushSwapLayerUndo(layerA, layerB) {\n        var swap = function () {\n            self.lockHistory();\n            self.swapLayer(layerA, layerB);\n            self.unlockHistory();\n            return swap;\n        };\n        pushUndo(swap);\n    }\n    function pushAddLayerUndo(index) {\n        var add = function () {\n            self.lockHistory();\n            self.addLayer(index);\n            self.unlockHistory();\n            cacheLayer(index);\n            return remove;\n        };\n        var remove = function () {\n            self.lockHistory();\n            self.removeLayer(index);\n            self.unlockHistory();\n            return add;\n        };\n        pushUndo(remove);\n    }\n    function pushRemoveLayerUndo(index) {\n        var layerContext = getLayerContext(index);\n        var w = size.width;\n        var h = size.height;\n        var snapshotData = layerContext.getImageData(0, 0, w, h);\n        var snapshotMetadata = self.getLayerMetadata(index);\n        var snapshotOpacity = self.getLayerOpacity(index);\n        var snapshotVisible = self.getLayerVisible(index);\n        var add = function () {\n            self.lockHistory();\n            self.addLayer(index);\n            self.setLayerMetadata(snapshotMetadata, index);\n            self.setLayerOpacity(snapshotOpacity, index);\n            self.setLayerVisible(snapshotVisible, index);\n            var layerContext = getLayerContext(index);\n            layerContext.putImageData(snapshotData, 0, 0);\n            self.unlockHistory();\n            cacheLayer(index);\n            return remove;\n        };\n        var remove = function () {\n            self.lockHistory();\n            self.removeLayer(index);\n            self.unlockHistory();\n            return add;\n        };\n        pushUndo(add);\n    }\n    function pushDirtyRectUndo(x, y, width, height, index) {\n        index = index || layerIndex;\n        var w = size.width;\n        var h = size.height;\n        var right = x + width;\n        var bottom = y + height;\n        x = Math.min(w, Math.max(0, x));\n        y = Math.min(h, Math.max(0, y));\n        width = Math.min(w, Math.max(x, right)) - x;\n        height = Math.min(h, Math.max(y, bottom)) - y;\n        if ((x % 1) > 0)\n            ++width;\n        if ((y % 1) > 0)\n            ++height;\n        x = x | 0;\n        y = y | 0;\n        width = Math.min(w - x, Math.ceil(width));\n        height = Math.min(h - y, Math.ceil(height));\n        if ((width === 0) || (height === 0)) {\n            var doNothing = function () {\n                return doNothing;\n            };\n            pushUndo(doNothing);\n        }\n        else {\n            var layerContext = getLayerContext(index);\n            var snapshotData = layerContext.getImageData(x, y, width, height);\n            var swap = function () {\n                var layerContext = getLayerContext(index);\n                var tempData = layerContext.getImageData(x, y, width, height);\n                layerContext.putImageData(snapshotData, x, y);\n                snapshotData = tempData;\n                cacheLayer(index);\n                return swap;\n            };\n            pushUndo(swap);\n        }\n        if (renderDirtyRect)\n            drawDirtyRect(x, y, width, height);\n    }\n    function pushContextUndo(index) {\n        index = index || layerIndex;\n        pushDirtyRectUndo(0, 0, size.width, size.height, index);\n    }\n    function pushAllContextUndo() {\n        var snapshotDatas = [];\n        var i;\n        var w = size.width;\n        var h = size.height;\n        for (i = 0; i < layers.length; ++i) {\n            var layerContext = getLayerContext(i);\n            snapshotDatas.push(layerContext.getImageData(0, 0, w, h));\n        }\n        var swap = function (index) {\n            var layerContext = getLayerContext(index);\n            var tempData = layerContext.getImageData(0, 0, w, h);\n            layerContext.putImageData(snapshotDatas[index], 0, 0);\n            snapshotDatas[index] = tempData;\n            cacheLayer(index);\n        };\n        var swapAll = function () {\n            for (var i = 0; i < layers.length; ++i)\n                swap(i);\n            return swapAll;\n        };\n        pushUndo(swapAll);\n    }\n    function pushCanvasSizeUndo(width, height, offsetX, offsetY) {\n        var snapshotSize = self.getCanvasSize();\n        var snapshotDatas = [];\n        var w = snapshotSize.width;\n        var h = snapshotSize.height;\n        for (var i = 0; i < layers.length; ++i) {\n            var layerContext = getLayerContext(i);\n            snapshotDatas[i] = layerContext.getImageData(0, 0, w, h);\n        }\n        function setSize(width, height, offsetX, offsetY) {\n            self.lockHistory();\n            self.setCanvasSize(width, height, offsetX, offsetY);\n            self.unlockHistory();\n        }\n        var rollback = function () {\n            setSize(w, h);\n            for (var i = 0; i < layers.length; ++i) {\n                var layerContext = getLayerContext(i);\n                layerContext.putImageData(snapshotDatas[i], 0, 0);\n            }\n            return redo;\n        };\n        var redo = function () {\n            rollback();\n            setSize(width, height, offsetX, offsetY);\n            return rollback;\n        };\n        pushUndo(rollback);\n    }\n    var size = {width: 640, height: 480};\n    self.getCanvasSize = function () {\n        return {width: size.width, height: size.height}; //clone size\n    };\n    self.setCanvasSize = function (width, height, offsetX, offsetY) {\n        offsetX = offsetX || 0;\n        offsetY = offsetY || 0;\n        size.width = width = Math.floor(width);\n        size.height = height = Math.floor(height);\n        pushCanvasSizeUndo(width, height, offsetX, offsetY);\n        dispatchEvent('oncanvassize', {\n            width: width, height: height,\n            offsetX: offsetX, offsetY: offsetY\n        });\n        paintingCanvas.width = width;\n        paintingCanvas.height = height;\n        dirtyRectDisplay.width = width;\n        dirtyRectDisplay.height = height;\n        domElement.style.width = width + 'px';\n        domElement.style.height = height + 'px';\n        for (var i=0; i<layers.length; ++i) {\n            var canvas = getLayerCanvas(i);\n            var context = getLayerContext(i);\n            var imageData = context.getImageData(0, 0, width, height);\n            canvas.width = width;\n            canvas.height = height;\n            context.putImageData(imageData, offsetX, offsetY);\n        }\n    };\n    self.getCanvasWidth = function () {\n        return size.width;\n    };\n    self.setCanvasWidth = function (width, offsetX) {\n        self.setCanvasSize(width, size.height, offsetX, 0);\n    };\n    self.getCanvasHeight = function () {\n        return size.height;\n    };\n    self.setCanvasHeight = function (height, offsetY) {\n        self.setCanvasSize(size.width, height, 0, offsetY);\n    };\n    function getLayerCanvas(index) {\n        return layers[index].getElementsByClassName('croquis-layer-canvas')[0];\n    }\n    self.getLayerCanvas = getLayerCanvas;\n    function getLayerContext(index) {\n        return getLayerCanvas(index).getContext('2d');\n    }\n    var layers = [];\n    var layerIndex = 0;\n    var paintingCanvas = document.createElement('canvas');\n    var paintingContext = paintingCanvas.getContext('2d');\n    paintingCanvas.className = 'croquis-painting-canvas';\n    paintingCanvas.style.position = 'absolute';\n    var dirtyRectDisplay = document.createElement('canvas');\n    var dirtyRectDisplayContext = dirtyRectDisplay.getContext('2d');\n    dirtyRectDisplay.className = 'croquis-dirty-rect-display';\n    dirtyRectDisplay.style.position = 'absolute';\n    var renderDirtyRect = false;\n    function sortLayers() {\n        while (domElement.firstChild)\n            domElement.removeChild(domElement.firstChild);\n        for (var i = 0; i < layers.length; ++i) {\n            var layer = layers[i];\n            domElement.appendChild(layer);\n        }\n        domElement.appendChild(dirtyRectDisplay);\n    }\n    function drawDirtyRect(x, y, w, h) {\n        var context = dirtyRectDisplayContext;\n        context.fillStyle = '#f00';\n        context.globalCompositeOperation = 'source-over';\n        context.fillRect(x, y, w, h);\n        if ((w > 2) && (h > 2)) {\n            context.globalCompositeOperation = 'destination-out';\n            context.fillRect(x + 1, y + 1, w - 2, h - 2);\n        }\n    }\n    self.getRenderDirtyRect = function () {\n        return renderDirtyRect;\n    };\n    self.setRenderDirtyRect = function (render) {\n        renderDirtyRect = render;\n        if (render == false)\n            dirtyRectDisplayContext.clearRect(0, 0, size.width, size.height);\n    };\n    self.createLayerThumbnail = function (index, width, height) {\n        index = index || layerIndex;\n        width = width || size.width;\n        height = height || size.height;\n        var canvas = getLayerCanvas(index);\n        var thumbnail = document.createElement('canvas');\n        var thumbnailContext = thumbnail.getContext('2d');\n        thumbnail.width = width;\n        thumbnail.height = height;\n        thumbnailContext.drawImage(canvas, 0, 0, width, height);\n        return thumbnail;\n    };\n    self.createFlattenThumbnail = function (width, height) {\n        width = width || size.width;\n        height = height || size.height;\n        var thumbnail = document.createElement('canvas');\n        var thumbnailContext = thumbnail.getContext('2d');\n        thumbnail.width = width;\n        thumbnail.height = height;\n        for (var i = 0; i < layers.length; ++i) {\n            if (!self.getLayerVisible(i))\n                continue;\n            var canvas = getLayerCanvas(i);\n            thumbnailContext.globalAlpha = self.getLayerOpacity(i);\n            thumbnailContext.drawImage(canvas, 0, 0, width, height);\n        }\n        return thumbnail;\n    };\n    self.getLayers = function () {\n        return layers.concat(); //clone layers\n    };\n    self.getLayerCount = function () {\n        return layers.length;\n    };\n    self.addLayer = function (index) {\n        index = index || layers.length;\n        pushAddLayerUndo(index);\n        var layer = document.createElement('div');\n        layer.className = 'croquis-layer';\n        layer.style.visibility = 'visible';\n        layer.style.opacity = 1;\n        layer['croquis-metadata'] = {};\n        var canvas = document.createElement('canvas');\n        canvas.className = 'croquis-layer-canvas';\n        canvas.width = size.width;\n        canvas.height = size.height;\n        canvas.style.position = 'absolute';\n        layer.appendChild(canvas);\n        domElement.appendChild(layer);\n        layers.splice(index, 0, layer);\n        sortLayers();\n        self.selectLayer(layerIndex);\n        dispatchEvent('onlayeradd', {index: index});\n        if (self.onLayerAdded)\n            self.onLayerAdded(index);\n        return layer;\n    };\n    self.removeLayer = function (index) {\n        index = index || layerIndex;\n        pushRemoveLayerUndo(index);\n        domElement.removeChild(layers[index]);\n        layers.splice(index, 1);\n        if (layerIndex == layers.length)\n            self.selectLayer(layerIndex - 1);\n        sortLayers();\n        dispatchEvent('onlayerremove', {index: index});\n        if (self.onLayerRemoved)\n            self.onLayerRemoved(index);\n    };\n    self.removeAllLayer = function () {\n        while (layers.length)\n            self.removeLayer(0);\n    };\n    self.swapLayer = function (layerA, layerB) {\n        pushSwapLayerUndo(layerA, layerB);\n        var layer = layers[layerA];\n        layers[layerA] = layers[layerB];\n        layers[layerB] = layer;\n        sortLayers();\n        dispatchEvent('onlayerswap', {a: layerA, b: layerB});\n        if (self.onLayerSwapped)\n            self.onLayerSwapped(layerA, layerB);\n    };\n    self.getCurrentLayerIndex = function () {\n        return layerIndex;\n    };\n    self.selectLayer = function (index) {\n        var lastestLayerIndex = layers.length - 1;\n        if (index > lastestLayerIndex)\n            index = lastestLayerIndex;\n        layerIndex = index;\n        if (paintingCanvas.parentElement != null)\n            paintingCanvas.parentElement.removeChild(paintingCanvas);\n        layers[index].appendChild(paintingCanvas);\n        dispatchEvent('onlayerselect', {index: index});\n        if (self.onLayerSelected)\n            self.onLayerSelected(index);\n    };\n    self.clearLayer = function (index) {\n        index = index || layerIndex;\n        pushContextUndo(index);\n        var context = getLayerContext(index);\n        context.clearRect(0, 0, size.width, size.height);\n        cacheLayer(index);\n    };\n    self.fillLayer = function (fillColor, index) {\n        index = index || layerIndex;\n        pushContextUndo(index);\n        var context = getLayerContext(index);\n        context.fillStyle = fillColor;\n        context.fillRect(0, 0, size.width, size.height);\n        cacheLayer(index);\n    };\n    self.fillLayerRect = function (fillColor, x, y, width, height, index) {\n        index = index || layerIndex;\n        pushDirtyRectUndo(x, y, width, height, index);\n        var context = getLayerContext(index);\n        context.fillStyle = fillColor;\n        context.fillRect(x, y, width, height);\n        cacheLayer(index);\n    };\n    self.floodFill = function (x, y, r, g, b, a, index) {\n        index = index || layerIndex;\n        pushContextUndo(index);\n        var context = getLayerContext(index);\n        var w = size.width;\n        var h = size.height;\n        if ((x < 0) || (x >= w) || (y < 0) || (y >= h))\n            return;\n        var imageData = context.getImageData(0, 0, w, h);\n        var d = imageData.data;\n        var targetColor = getColor(x, y);\n        var replacementColor = (r << 24) | (g << 16) | (b << 8) | a;\n        if (targetColor === replacementColor)\n            return;\n        function getColor(x, y) {\n            var index = ((y * w) + x) * 4;\n            return ((d[index] << 24) | (d[index + 1] << 16) |\n                (d[index + 2] << 8) | d[index + 3]);\n        }\n        function setColor(x, y) {\n            var index = ((y * w) + x) * 4;\n            d[index] = r;\n            d[index + 1] = g;\n            d[index + 2] = b;\n            d[index + 3] = a;\n        }\n        var queue = [];\n        queue.push(x, y);\n        while (queue.length) {\n            var nx = queue.shift();\n            var ny = queue.shift();\n            if ((nx < 0) || (nx >= w) || (ny < 0) || (ny >= h) ||\n                (getColor(nx, ny) !== targetColor))\n                continue;\n            var west, east;\n            west = east = nx;\n            do {\n                var wc = getColor(--west, ny);\n            } while ((west >= 0) && (wc === targetColor));\n            do {\n                var ec = getColor(++east, ny);\n            } while ((east < w) && (ec === targetColor));\n            for (var i = west + 1; i < east; ++i) {\n                setColor(i, ny);\n                var north = ny - 1;\n                var south = ny + 1;\n                if (getColor(i, north) === targetColor)\n                    queue.push(i, north);\n                if (getColor(i, south) === targetColor)\n                    queue.push(i, south);\n            }\n        }\n        context.putImageData(imageData, 0, 0);\n        cacheLayer(index);\n    };\n    self.getLayerMetadata = function (index) {\n        index = index || layerIndex;\n        var metadata = layers[index]['croquis-metadata'];\n        var clone = {};\n        Object.keys(metadata).forEach(function (key) {\n            clone[key] = metadata[key];\n        });\n        return clone;\n    };\n    self.setLayerMetadata = function (metadata, index) {\n        index = index || layerIndex;\n        pushLayerMetadataUndo(index);\n        layers[index]['croquis-metadata'] = metadata;\n    };\n    self.getLayerOpacity = function (index) {\n        index = index || layerIndex;\n        var opacity = parseFloat(\n            layers[index].style.getPropertyValue('opacity'));\n        return window.isNaN(opacity) ? 1 : opacity;\n    };\n    self.setLayerOpacity = function (opacity, index) {\n        index = index || layerIndex;\n        pushLayerOpacityUndo(index);\n        layers[index].style.opacity = opacity;\n    };\n    self.getLayerVisible = function (index) {\n        index = index || layerIndex;\n        var visible = layers[index].style.getPropertyValue('visibility');\n        return visible != 'hidden';\n    };\n    self.setLayerVisible = function (visible, index) {\n        index = index || layerIndex;\n        pushLayerVisibleUndo(index);\n        layers[index].style.visibility = visible ? 'visible' : 'hidden';\n    };\n    function cacheLayer(index) {\n        index = index || layerIndex;\n        var w = size.width;\n        var h = size.height;\n        layers[index].cache = getLayerContext(index).getImageData(0, 0, w, h);\n    }\n    self.getLayerImageDataCache = function (index) {\n        index = index || layerIndex;\n        if (layers[index].cache == null)\n            cacheLayer(index);\n        return layers[index].cache;\n    };\n    function makeColorData(imageData1x1) {\n        var data = imageData1x1.data;\n        var r = data[0];\n        var g = data[1];\n        var b = data[2];\n        var a = data[3];\n        return {\n            r: r, g: g, b: b, a: a,\n            htmlColor: 'rgba(' + [r, g, b, a / 0xff].join(',') + ')'\n        };\n    }\n    self.pickColor = function (x, y, index) {\n        x = x | 0; // cast to int\n        y = y | 0;\n        if ((x < 0) || (x >= size.width) || (y < 0) || (y >= size.height))\n            return null;\n        index = index || layerIndex;\n        var cache = self.getLayerImageDataCache(index);\n        var position = (y * size.width + x) * 4;\n        var data = [];\n        data[0] = cache.data[position];\n        data[1] = cache.data[++position];\n        data[2] = cache.data[++position];\n        data[3] = cache.data[++position];\n        return makeColorData({data: data});\n    };\n    self.eyeDrop = function (x, y, baseColor) {\n        if (self.pickColor(x, y) == null)\n            return null;\n        baseColor = baseColor || '#fff';\n        var plane = document.createElement('canvas');\n        plane.width = 1;\n        plane.height = 1;\n        var planeContext = plane.getContext('2d');\n        planeContext.fillStyle = baseColor;\n        planeContext.fillRect(0, 0, 1, 1);\n        for (var i = 0; i < layers.length; ++i) {\n            if (!self.getLayerVisible(i))\n                continue;\n            planeContext.globalAlpha = self.getLayerOpacity(i);\n            planeContext.fillStyle = self.pickColor(x, y, i).htmlColor;\n            planeContext.fillRect(0, 0, 1, 1);\n        }\n        return makeColorData(planeContext.getImageData(0, 0, 1, 1));\n    };\n    var tool;\n    var toolStabilizeLevel = 0;\n    var toolStabilizeWeight = 0.8;\n    var stabilizer = null;\n    var stabilizerInterval = 5;\n    var tick;\n    var tickInterval = 20;\n    var paintingOpacity = 1;\n    var paintingKnockout = false;\n    self.getTool = function () {\n        return tool;\n    };\n    self.setTool = function (value) {\n        tool = value;\n        dispatchEvent('ontool', {tool: value});\n        paintingContext = paintingCanvas.getContext('2d');\n        if (tool && tool.setContext)\n            tool.setContext(paintingContext);\n    };\n    self.setTool(new Croquis.Brush());\n    self.getPaintingOpacity = function () {\n        return paintingOpacity;\n    };\n    self.setPaintingOpacity = function (opacity) {\n        paintingOpacity = opacity;\n        paintingCanvas.style.opacity = opacity;\n    };\n    self.getPaintingKnockout = function () {\n        return paintingKnockout;\n    };\n    self.setPaintingKnockout = function (knockout) {\n        if (isDrawing || isStabilizing)\n            throw 'still drawing';\n        paintingKnockout = knockout;\n        paintingCanvas.style.visibility = knockout ? 'hidden' : 'visible';\n    };\n    self.getTickInterval = function () {\n        return tickInterval;\n    };\n    self.setTickInterval = function (interval) {\n        tickInterval = interval;\n    };\n    /*\n    stabilize level is the number of coordinate tracker.\n    higher stabilize level makes lines smoother.\n    */\n    self.getToolStabilizeLevel = function () {\n        return toolStabilizeLevel;\n    };\n    self.setToolStabilizeLevel = function (level) {\n        toolStabilizeLevel = (level < 0) ? 0 : level;\n    };\n    /*\n    higher stabilize weight makes trackers follow slower.\n    */\n    self.getToolStabilizeWeight = function () {\n        return toolStabilizeWeight;\n    };\n    self.setToolStabilizeWeight = function (weight) {\n        toolStabilizeWeight = weight;\n    };\n    self.getToolStabilizeInterval = function () {\n        return stabilizerInterval;\n    };\n    self.setToolStabilizeInterval = function (interval) {\n        stabilizerInterval = interval;\n    };\n    var isDrawing = false;\n    var isStabilizing = false;\n    var beforeKnockout = document.createElement('canvas');\n    var knockoutTick;\n    var knockoutTickInterval = 20;\n    function gotoBeforeKnockout() {\n        var context = getLayerContext(layerIndex);\n        var w = size.width;\n        var h = size.height;\n        context.clearRect(0, 0, w, h);\n        context.drawImage(beforeKnockout, 0, 0, w, h);\n    }\n    function drawPaintingCanvas() { //draw painting canvas on current layer\n        var context = getLayerContext(layerIndex);\n        var w = size.width;\n        var h = size.height;\n        context.save();\n        context.globalAlpha = paintingOpacity;\n        context.globalCompositeOperation = paintingKnockout ?\n            'destination-out' : 'source-over';\n        context.drawImage(paintingCanvas, 0, 0, w, h);\n        context.restore();\n    }\n    function _move(x, y, pressure) {\n        if (tool.move)\n            tool.move(x, y, pressure);\n        dispatchEvent('onmove', {x: x, y: y, pressure: pressure});\n        if (self.onMoved)\n            self.onMoved(x, y, pressure);\n    }\n    function _up(x, y, pressure) {\n        isDrawing = false;\n        isStabilizing = false;\n        var dirtyRect;\n        if (tool.up)\n            dirtyRect = tool.up(x, y, pressure);\n        if (paintingKnockout)\n            gotoBeforeKnockout();\n        if (dirtyRect)\n            pushDirtyRectUndo(dirtyRect.x, dirtyRect.y,\n                              dirtyRect.width, dirtyRect.height);\n        else\n            pushContextUndo();\n        drawPaintingCanvas();\n        paintingContext.clearRect(0, 0, size.width, size.height);\n        dirtyRect = dirtyRect ||\n            {x: 0, y: 0, width: size.width, height: size.height};\n        dispatchEvent('onup',\n            {x: x, y: y, pressure: pressure, dirtyRect: dirtyRect});\n        if (self.onUpped)\n            self.onUpped(x, y, pressure, dirtyRect);\n        window.clearInterval(knockoutTick);\n        window.clearInterval(tick);\n        cacheLayer(self.getCurrentLayerIndex());\n    }\n    self.down = function (x, y, pressure) {\n        if (isDrawing || isStabilizing)\n            throw 'still drawing';\n        isDrawing = true;\n        if (tool == null)\n            return;\n        if (paintingKnockout) {\n            var w = size.width;\n            var h = size.height;\n            var canvas = getLayerCanvas(layerIndex);\n            var beforeKnockoutContext = beforeKnockout.getContext('2d');\n            beforeKnockout.width = w;\n            beforeKnockout.height = h;\n            beforeKnockoutContext.clearRect(0, 0, w, h);\n            beforeKnockoutContext.drawImage(canvas, 0, 0, w, h);\n        }\n        pressure = pressure || Croquis.Tablet.pressure();\n        var down = tool.down;\n        if (toolStabilizeLevel > 0) {\n            stabilizer = new Croquis.Stabilizer(down, _move, _up,\n                toolStabilizeLevel, toolStabilizeWeight,\n                x, y, pressure, stabilizerInterval);\n            isStabilizing = true;\n        }\n        else if (down != null)\n            down(x, y, pressure);\n        dispatchEvent('ondown', {x: x, y: y, pressure: pressure});\n        if (self.onDowned)\n            self.onDowned(x, y, pressure);\n        knockoutTick = window.setInterval(function () {\n            if (paintingKnockout) {\n                gotoBeforeKnockout();\n                drawPaintingCanvas();\n            }\n        }, knockoutTickInterval);\n        tick = window.setInterval(function () {\n            if (tool.tick)\n                tool.tick();\n            dispatchEvent('ontick');\n            if (self.onTicked)\n                self.onTicked();\n        }, tickInterval);\n    };\n    self.move = function (x, y, pressure) {\n        if (!isDrawing)\n            throw 'you need to call \\'down\\' first';\n        if (tool == null)\n            return;\n        pressure = pressure || Croquis.Tablet.pressure();\n        if (stabilizer != null)\n            stabilizer.move(x, y, pressure);\n        else if (!isStabilizing)\n            _move(x, y, pressure);\n    };\n    self.up = function (x, y, pressure) {\n        if (!isDrawing)\n            throw 'you need to call \\'down\\' first';\n        if (tool == null) {\n            isDrawing = false;\n            return;\n        }\n        pressure = pressure || Croquis.Tablet.pressure();\n        if (stabilizer != null)\n            stabilizer.up(x, y, pressure);\n        else\n            _up(x, y, pressure);\n        stabilizer = null;\n    };\n    // apply image data\n    ;(function (croquis, imageDataList) {\n        if (imageDataList != null) {\n            if (imageDataList.length === 0)\n                return;\n            croquis.lockHistory();\n            var first = imageDataList[0];\n            croquis.setCanvasSize(first.width, first.height);\n            for (var i = 0; i < imageDataList.length; ++i) {\n                var current = imageDataList[i];\n                if ((current.width != first.width) ||\n                    (current.height != first.height))\n                    throw 'all image data must have same size';\n                croquis.addLayer();\n                var context = croquis.getLayerCanvas(i).getContext('2d');\n                context.putImageData(current, 0, 0);\n            }\n            croquis.selectLayer(0);\n            croquis.unlockHistory();\n        }\n    }).call(null, self, imageDataList);\n}\nCroquis.createChecker = function (cellSize, colorA, colorB) {\n    cellSize = cellSize || 10;\n    colorA = colorA || '#fff';\n    colorB = colorB || '#ccc';\n    var size = cellSize + cellSize;\n    var checker = document.createElement('canvas');\n    checker.width = checker.height = size;\n    var context = checker.getContext('2d');\n    context.fillStyle = colorB;\n    context.fillRect(0, 0, size, size);\n    context.fillStyle = colorA;\n    context.fillRect(0, 0, cellSize, cellSize);\n    context.fillRect(cellSize, cellSize, size, size);\n    return checker;\n};\nCroquis.createBrushPointer = function (brushImage, brushSize, brushAngle,\n                                       threshold, antialias, color,\n                                       shadow, shadowOffsetX, shadowOffsetY) {\n    brushSize = brushSize | 0;\n    var pointer = document.createElement('canvas');\n    var pointerContext = pointer.getContext('2d');\n    var boundWidth;\n    var boundHeight;\n    if (brushSize === 0) {\n        pointer.width = boundWidth = 1;\n        pointer.height = boundHeight = 1;\n    }\n    if (brushImage == null) {\n        var halfSize = (brushSize * 0.5) | 0;\n        pointer.width = boundWidth = brushSize;\n        pointer.height = boundHeight = brushSize;\n        pointerContext.fillStyle = '#000';\n        pointerContext.beginPath();\n        pointerContext.arc(halfSize, halfSize, halfSize, 0, Math.PI * 2);\n        pointerContext.closePath();\n        pointerContext.fill();\n    }\n    else {\n        var width = brushSize;\n        var height = brushSize * (brushImage.height / brushImage.width);\n        var toRad = Math.PI / 180;\n        var ra = brushAngle * toRad;\n        var abs = Math.abs;\n        var sin = Math.sin;\n        var cos = Math.cos;\n        boundWidth = abs(height * sin(ra)) + abs(width * cos(ra));\n        boundHeight = abs(width * sin(ra)) + abs(height * cos(ra));\n        pointer.width = boundWidth;\n        pointer.height = boundHeight;\n        pointerContext.save();\n        pointerContext.translate(boundWidth * 0.5, boundHeight * 0.5);\n        pointerContext.rotate(ra);\n        pointerContext.translate(width * -0.5, height * -0.5);\n        pointerContext.drawImage(brushImage, 0, 0, width, height);\n        pointerContext.restore();\n    }\n    var result;\n    var alphaThresholdBorder = Croquis.createAlphaThresholdBorder(\n        pointer, threshold, antialias, color);\n    if (shadow) {\n        shadowOffsetX = shadowOffsetX || 1;\n        shadowOffsetY = shadowOffsetY || 1;\n        result = document.createElement('canvas');\n        result.width = boundWidth + shadowOffsetX;\n        result.height = boundHeight + shadowOffsetY;\n        var resultContext = result.getContext('2d');\n        resultContext.shadowOffsetX = shadowOffsetX;\n        resultContext.shadowOffsetY = shadowOffsetY;\n        resultContext.shadowColor = shadow;\n        resultContext.drawImage(\n            alphaThresholdBorder, 0, 0, boundWidth, boundHeight);\n    }\n    else {\n        result = alphaThresholdBorder;\n    }\n    return result;\n};\nCroquis.createAlphaThresholdBorder = function (image, threshold,\n                                               antialias, color) {\n    threshold = threshold || 0x80;\n    color = color || '#000';\n    var width = image.width;\n    var height = image.height;\n    var canvas = document.createElement('canvas');\n    var context = canvas.getContext('2d');\n    canvas.width = width;\n    canvas.height = height;\n    try {\n        context.drawImage(image, 0, 0, width, height);\n    }\n    catch (e) {\n        return canvas;\n    }\n    var imageData = context.getImageData(0, 0, width, height);\n    var d = imageData.data;\n    function getAlphaIndex(index) {\n        return d[index * 4 + 3];\n    }\n    function setRedIndex(index, red) {\n        d[index * 4] = red;\n    }\n    function getRedXY(x, y) {\n        var red = d[((y * width) + x) * 4];\n        return red || 0;\n    }\n    function getGreenXY(x, y) {\n        var green = d[((y * width) + x) * 4 + 1];\n        return green;\n    }\n    function setColorXY(x, y, red, green, alpha) {\n        var i = ((y * width) + x) * 4;\n        d[i] = red;\n        d[i + 1] = green;\n        d[i + 2] = 0;\n        d[i + 3] = alpha;\n    }\n    //threshold\n    var pixelCount = (d.length * 0.25) | 0;\n    for (var i = 0; i < pixelCount; ++i)\n        setRedIndex(i, (getAlphaIndex(i) < threshold) ? 0 : 1);\n    //outline\n    var x;\n    var y;\n    for (x = 0; x < width; ++x) {\n        for (y = 0; y < height; ++y) {\n            if (!getRedXY(x, y)) {\n                setColorXY(x, y, 0, 0, 0);\n            }\n            else {\n                var redCount = 0;\n                var left = x - 1;\n                var right = x + 1;\n                var up = y - 1;\n                var down = y + 1;\n                redCount += getRedXY(left, up);\n                redCount += getRedXY(left, y);\n                redCount += getRedXY(left, down);\n                redCount += getRedXY(right, up);\n                redCount += getRedXY(right, y);\n                redCount += getRedXY(right, down);\n                redCount += getRedXY(x, up);\n                redCount += getRedXY(x, down);\n                if (redCount != 8)\n                    setColorXY(x, y, 1, 1, 255);\n                else\n                    setColorXY(x, y, 1, 0, 0);\n            }\n        }\n    }\n    //antialias\n    if (antialias) {\n        for (x = 0; x < width; ++x) {\n            for (y = 0; y < height; ++y) {\n                if (getGreenXY(x, y)) {\n                    var alpha = 0;\n                    if (getGreenXY(x - 1, y) != getGreenXY(x + 1, y))\n                        setColorXY(x, y, 1, 1, alpha += 0x40);\n                    if (getGreenXY(x, y - 1) != getGreenXY(x, y + 1))\n                        setColorXY(x, y, 1, 1, alpha + 0x50);\n                }\n            }\n        }\n    }\n    context.putImageData(imageData, 0, 0);\n    context.globalCompositeOperation = 'source-in';\n    context.fillStyle = color;\n    context.fillRect(0, 0, width, height);\n    return canvas;\n};\nCroquis.createFloodFill = function (canvas, x, y, r, g, b, a) {\n    var result = document.createElement('canvas');\n    var w = result.width = canvas.width;\n    var h = result.height = canvas.height;\n    if ((x < 0) || (x >= w) || (y < 0) || (y >= h) || !(r || g || b || a))\n        return result;\n    var originalContext = canvas.getContext('2d');\n    var originalData = originalContext.getImageData(0, 0, w, h);\n    var od = originalData.data;\n    var resultContext = result.getContext('2d');\n    var resultData = resultContext.getImageData(0, 0, w, h);\n    var rd = resultData.data;\n    var targetColor = getColor(x, y);\n    var replacementColor = (r << 24) | (g << 16) | (b << 8) | a;\n    function getColor(x, y) {\n        var index = ((y * w) + x) * 4;\n        return (rd[index] ? replacementColor :\n            ((od[index] << 24) | (od[index + 1] << 16) |\n             (od[index + 2] << 8) | od[index + 3]));\n    }\n    var queue = [];\n    queue.push(x, y);\n    while (queue.length) {\n        var nx = queue.shift();\n        var ny = queue.shift();\n        if ((nx < 0) || (nx >= w) || (ny < 0) || (ny >= h) ||\n            (getColor(nx, ny) !== targetColor))\n            continue;\n        var west, east;\n        west = east = nx;\n        do {\n            var wc = getColor(--west, ny);\n        } while ((west >= 0) && (wc === targetColor));\n        do {\n            var ec = getColor(++east, ny);\n        } while ((east < w) && (ec === targetColor));\n        for (var i = west + 1; i < east; ++i) {\n            rd[((ny * w) + i) * 4] = 1;\n            var north = ny - 1;\n            var south = ny + 1;\n            if (getColor(i, north) === targetColor)\n                queue.push(i, north);\n            if (getColor(i, south) === targetColor)\n                queue.push(i, south);\n        }\n    }\n    for (var i = 0; i < w; ++i) {\n        for (var j = 0; j < h; ++j) {\n            var index = ((j * w) + i) * 4;\n            if (rd[index] === 0)\n                continue;\n            rd[index] = r;\n            rd[index + 1] = g;\n            rd[index + 2] = b;\n            rd[index + 3] = a;\n        }\n    }\n    resultContext.putImageData(resultData, 0, 0);\n    return result;\n};\n\nCroquis.Tablet = {};\nCroquis.Tablet.plugin = function () {\n    var plugin = document.querySelector(\n        'object[type=\\'application/x-wacomtabletplugin\\']');\n    if (!plugin) {\n        plugin = document.createElement('object');\n        plugin.type = 'application/x-wacomtabletplugin';\n        plugin.style.position = 'absolute';\n        plugin.style.top = '-1000px';\n        document.body.appendChild(plugin);\n    }\n    return plugin;\n};\nCroquis.Tablet.pen = function () {\n    var plugin = Croquis.Tablet.plugin();\n    return plugin.penAPI;\n};\nCroquis.Tablet.pressure = function () {\n    var pen = Croquis.Tablet.pen();\n    return (pen && pen.pointerType) ? pen.pressure : 1;\n};\nCroquis.Tablet.isEraser = function () {\n    var pen = Croquis.Tablet.pen();\n    return pen ? pen.isEraser : false;\n};\n\nCroquis.Stabilizer = function (down, move, up, level, weight,\n                               x, y, pressure, interval) {\n    interval = interval || 5;\n    var follow = 1 - Math.min(0.95, Math.max(0, weight));\n    var paramTable = [];\n    var current = { x: x, y: y, pressure: pressure };\n    for (var i = 0; i < level; ++i)\n        paramTable.push({ x: x, y: y, pressure: pressure });\n    var first = paramTable[0];\n    var last = paramTable[paramTable.length - 1];\n    var upCalled = false;\n    if (down != null)\n        down(x, y, pressure);\n    window.setTimeout(_move, interval);\n    this.getParamTable = function () { //for test\n        return paramTable;\n    };\n    this.move = function (x, y, pressure) {\n        current.x = x;\n        current.y = y;\n        current.pressure = pressure;\n    };\n    this.up = function (x, y, pressure) {\n        current.x = x;\n        current.y = y;\n        current.pressure = pressure;\n        upCalled = true;\n    };\n    function dlerp(a, d, t) {\n        return a + d * t;\n    }\n    function _move(justCalc) {\n        var curr;\n        var prev;\n        var dx;\n        var dy;\n        var dp;\n        var delta = 0;\n        first.x = current.x;\n        first.y = current.y;\n        first.pressure = current.pressure;\n        for (var i = 1; i < paramTable.length; ++i) {\n            curr = paramTable[i];\n            prev = paramTable[i - 1];\n            dx = prev.x - curr.x;\n            dy = prev.y - curr.y;\n            dp = prev.pressure - curr.pressure;\n            delta += Math.abs(dx);\n            delta += Math.abs(dy);\n            curr.x = dlerp(curr.x, dx, follow);\n            curr.y = dlerp(curr.y, dy, follow);\n            curr.pressure = dlerp(curr.pressure, dp, follow);\n        }\n        if (justCalc)\n            return delta;\n        if (upCalled) {\n            while(delta > 1) {\n                move(last.x, last.y, last.pressure);\n                delta = _move(true);\n            }\n            up(last.x, last.y, last.pressure);\n        }\n        else {\n            move(last.x, last.y, last.pressure);\n            window.setTimeout(_move, interval);\n        }\n    }\n};\n\nCroquis.Random = {};\nCroquis.Random.LFSR113 = function (seed) {\n    var IA = 16807;\n    var IM = 2147483647;\n    var IQ = 127773;\n    var IR = 2836;\n    var a, b, c, d, e;\n    this.get = function () {\n        var f = ((a << 6) ^ a) >> 13;\n        a = ((a & 4294967294) << 18) ^ f;\n        f  = ((b << 2) ^ b) >> 27;\n        b = ((b & 4294967288) << 2) ^ f;\n        f  = ((c << 13) ^ c) >> 21;\n        c = ((c & 4294967280) << 7) ^ f;\n        f  = ((d << 3) ^ d) >> 12;\n        d = ((d & 4294967168) << 13) ^ f;\n        return (a ^ b ^ c ^ d) * 2.3283064365386963e-10 + 0.5;\n    };\n    seed |= 0;\n    if (seed <= 0) seed = 1;\n    e = (seed / IQ) | 0;\n    seed = (((IA * (seed - ((e * IQ) | 0))) | 0) - ((IR * e) | 0)) | 0;\n    if (seed < 0) seed = (seed + IM) | 0;\n    if (seed < 2) a = (seed + 2) | 0 ; else a = seed;\n    e = (seed / IQ) | 0;\n    seed = (((IA * (seed - ((e * IQ) | 0))) | 0) - ((IR * e) | 0)) | 0;\n    if (seed < 0) seed = (seed + IM) | 0;\n    if (seed < 8) b = (seed + 8) | 0; else b = seed;\n    e = (seed / IQ) | 0;\n    seed = (((IA * (seed - ((e * IQ) | 0))) | 0) - ((IR * e) | 0)) | 0;\n    if (seed < 0) seed = (seed + IM) | 0;\n    if (seed < 16) c = (seed + 16) | 0; else c = seed;\n    e = (seed / IQ) | 0;\n    seed = (((IA * (seed - ((e * IQ) | 0))) | 0) - ((IR * e) | 0)) | 0;\n    if (seed < 0) seed = (seed + IM) | 0;\n    if (seed < 128) d = (seed + 128) | 0; else d = seed;\n    this.get();\n};\n\nCroquis.Brush = function () {\n    // math shortcut\n    var min = Math.min;\n    var max = Math.max;\n    var abs = Math.abs;\n    var sin = Math.sin;\n    var cos = Math.cos;\n    var sqrt = Math.sqrt;\n    var atan2 = Math.atan2;\n    var PI = Math.PI;\n    var ONE = PI + PI;\n    var QUARTER = PI * 0.5;\n    var random = Math.random;\n    this.setRandomFunction = function (value) {\n        random = value;\n    };\n    this.clone = function () {\n        var clone = new Brush(context);\n        clone.setColor(this.getColor());\n        clone.setFlow(this.getFlow());\n        clone.setSize(this.getSize());\n        clone.setSpacing(this.getSpacing());\n        clone.setAngle(this.getAngle());\n        clone.setRotateToDirection(this.getRotateToDirection());\n        clone.setNormalSpread(this.getNormalSpread());\n        clone.setTangentSpread(this.getTangentSpread());\n        clone.setImage(this.getImage());\n    };\n    var context = null;\n    this.getContext = function () {\n        return context;\n    };\n    this.setContext = function (value) {\n        context = value;\n    };\n    var color = '#000';\n    this.getColor = function () {\n        return color;\n    };\n    this.setColor = function (value) {\n        color = value;\n        transformedImageIsDirty = true;\n    };\n    var flow = 1;\n    this.getFlow = function() {\n        return flow;\n    };\n    this.setFlow = function(value) {\n        flow = value;\n        transformedImageIsDirty = true;\n    };\n    var size = 10;\n    this.getSize = function () {\n        return size;\n    };\n    this.setSize = function (value) {\n        size = (value < 1) ? 1 : value;\n        transformedImageIsDirty = true;\n    };\n    var spacing = 0.2;\n    this.getSpacing = function () {\n        return spacing;\n    };\n    this.setSpacing = function (value) {\n        spacing = (value < 0.01) ? 0.01 : value;\n    };\n    var toRad = PI / 180;\n    var toDeg = 1 / toRad;\n    var angle = 0; // radian unit\n    this.getAngle = function () { // returns degree unit\n        return angle * toDeg;\n    };\n    this.setAngle = function (value) {\n        angle = value * toRad;\n    };\n    var rotateToDirection = false;\n    this.getRotateToDirection = function () {\n        return rotateToDirection;\n    };\n    this.setRotateToDirection = function (value) {\n        rotateToDirection = value;\n    };\n    var normalSpread = 0;\n    this.getNormalSpread = function () {\n        return normalSpread;\n    };\n    this.setNormalSpread = function (value) {\n        normalSpread = value;\n    };\n    var tangentSpread = 0;\n    this.getTangentSpread = function () {\n        return tangentSpread;\n    };\n    this.setTangentSpread = function (value) {\n        tangentSpread = value;\n    };\n    var image = null;\n    var transformedImage = null;\n    var transformedImageIsDirty = true;\n    var imageRatio = 1;\n    this.getImage = function () {\n        return image;\n    };\n    this.setImage = function (value) {\n        if (value == null) {\n            transformedImage = image = null;\n            imageRatio = 1;\n            drawFunction = drawCircle;\n        }\n        else if (value != image) {\n            image = value;\n            imageRatio = image.height / image.width;\n            transformedImage = document.createElement('canvas');\n            drawFunction = drawImage;\n            transformedImageIsDirty = true;\n        }\n    };\n    var delta = 0;\n    var prevX = 0;\n    var prevY = 0;\n    var lastX = 0;\n    var lastY = 0;\n    var dir = 0;\n    var prevScale = 0;\n    var drawFunction = drawCircle;\n    var reserved = null;\n    var dirtyRect;\n    function spreadRandom() {\n        return random() - 0.5;\n    }\n    function drawReserved() {\n        if (reserved != null) {\n            drawTo(reserved.x, reserved.y, reserved.scale);\n            reserved = null;\n        }\n    }\n    function appendDirtyRect(x, y, width, height) {\n        if (!(width && height))\n            return;\n        var dxw = dirtyRect.x + dirtyRect.width;\n        var dyh = dirtyRect.y + dirtyRect.height;\n        var xw = x + width;\n        var yh = y + height;\n        var minX = dirtyRect.width ? min(dirtyRect.x, x) : x;\n        var minY = dirtyRect.height ? min(dirtyRect.y, y) : y;\n        dirtyRect.x = minX;\n        dirtyRect.y = minY;\n        dirtyRect.width = max(dxw, xw) - minX;\n        dirtyRect.height = max(dyh, yh) - minY;\n    }\n    function transformImage() {\n        transformedImage.width = size;\n        transformedImage.height = size * imageRatio;\n        var brushContext = transformedImage.getContext('2d');\n        brushContext.clearRect(0, 0,\n            transformedImage.width, transformedImage.height);\n        brushContext.drawImage(image, 0, 0,\n            transformedImage.width, transformedImage.height);\n        brushContext.globalCompositeOperation = 'source-in';\n        brushContext.fillStyle = color;\n        brushContext.globalAlpha = flow;\n        brushContext.fillRect(0, 0,\n            transformedImage.width, transformedImage.height);\n    }\n    function drawCircle(size) {\n        var halfSize = size * 0.5;\n        context.fillStyle = color;\n        context.globalAlpha = flow;\n        context.beginPath();\n        context.arc(halfSize, halfSize, halfSize, 0, ONE);\n        context.closePath();\n        context.fill();\n    }\n    function drawImage(size) {\n        if (transformedImageIsDirty)\n            transformImage();\n        try {\n            context.drawImage(transformedImage, 0, 0, size, size * imageRatio);\n        }\n        catch (e) {\n            drawCircle(size);\n        }\n    }\n    function drawTo(x, y, scale) {\n        var scaledSize = size * scale;\n        var nrm = dir + QUARTER;\n        var nr = normalSpread * scaledSize * spreadRandom();\n        var tr = tangentSpread * scaledSize * spreadRandom();\n        var ra = rotateToDirection ? angle + dir : angle;\n        var width = scaledSize;\n        var height = width * imageRatio;\n        var boundWidth = abs(height * sin(ra)) + abs(width * cos(ra));\n        var boundHeight = abs(width * sin(ra)) + abs(height * cos(ra));\n        x += Math.cos(nrm) * nr + Math.cos(dir) * tr;\n        y += Math.sin(nrm) * nr + Math.sin(dir) * tr;\n        context.save();\n        context.translate(x, y);\n        context.rotate(ra);\n        context.translate(-(width * 0.5), -(height * 0.5));\n        drawFunction(width);\n        context.restore();\n        appendDirtyRect(x - (boundWidth * 0.5),\n                        y - (boundHeight * 0.5),\n                        boundWidth, boundHeight);\n    }\n    this.down = function(x, y, scale) {\n        if (context == null)\n            throw 'brush needs the context';\n        dir = 0;\n        dirtyRect = {x: 0, y: 0, width: 0, height: 0};\n        if (scale > 0) {\n            if (rotateToDirection || normalSpread !== 0 || tangentSpread !== 0)\n                reserved = {x: x, y: y, scale: scale};\n            else\n                drawTo(x, y, scale);\n        }\n        delta = 0;\n        lastX = prevX = x;\n        lastY = prevY = y;\n        prevScale = scale;\n    };\n    this.move = function(x, y, scale) {\n        if (context == null)\n            throw 'brush needs the context';\n        if (scale <= 0) {\n            delta = 0;\n            prevX = x;\n            prevY = y;\n            prevScale = scale;\n            return;\n        }\n        var dx = x - prevX;\n        var dy = y - prevY;\n        var ds = scale - prevScale;\n        var d = sqrt(dx * dx + dy * dy);\n        prevX = x;\n        prevY = y;\n        delta += d;\n        var midScale = (prevScale + scale) * 0.5;\n        var drawSpacing = size * spacing * midScale;\n        var ldx = x - lastX;\n        var ldy = y - lastY;\n        var ld = sqrt(ldx * ldx + ldy * ldy);\n        dir = atan2(ldy, ldx);\n        if (ldx || ldy)\n            drawReserved();\n        if (drawSpacing < 0.5)\n            drawSpacing = 0.5;\n        if (delta < drawSpacing) {\n            prevScale = scale;\n            return;\n        }\n        var scaleSpacing = ds * (drawSpacing / delta);\n        if (ld < drawSpacing) {\n            lastX = x;\n            lastY = y;\n            drawTo(lastX, lastY, scale);\n            delta -= drawSpacing;\n        } else {\n            while(delta >= drawSpacing) {\n                ldx = x - lastX;\n                ldy = y - lastY;\n                var tx = cos(dir);\n                var ty = sin(dir);\n                lastX += tx * drawSpacing;\n                lastY += ty * drawSpacing;\n                prevScale += scaleSpacing;\n                drawTo(lastX, lastY, prevScale);\n                delta -= drawSpacing;\n            }\n        }\n        prevScale = scale;\n    };\n    this.up = function (x, y, scale) {\n        dir = atan2(y - lastY, x - lastX);\n        drawReserved();\n        return dirtyRect;\n    };\n};\n"
  },
  {
    "path": "lib/filedownloader.js",
    "content": " var FileDownloader = (function () {\n\n\tvar fileDownloader = { };\n\n\tfileDownloader.downloadFile = function (url) {\n\t\tvar fileString = \"\";\n\t\tvar rawFile = new XMLHttpRequest();\n\t\trawFile.open(\"GET\", url, false);\n\t\trawFile.onreadystatechange = function () {\n\t\t\tif(rawFile.readyState === 4) {\n\t\t\t\tif(rawFile.status === 200 || rawFile.status == 0) {\n\t\t\t\t\tfileString = rawFile.responseText;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\trawFile.send(null);\n\t\treturn fileString;\n\t}\n\n\treturn fileDownloader;\n\n})();"
  },
  {
    "path": "lib/fpscounter.js",
    "content": "// Framerate keeper \n// http://www.html5gamedevs.com/topic/1828-how-to-calculate-fps-in-plain-javascript/\nvar fps = { startTime : 0,\n\tframeNumber : 0,\n\tgetFPS : function() {\n\t\tthis.frameNumber++;\n\n\t\tvar d = new Date().getTime();\n\t\tvar currentTime = ( d - this.startTime ) / 1000;\n\t\tvar result = Math.floor( ( this.frameNumber / currentTime ) );\n\n\t\tif( currentTime > 1 ) {\n\t\t\tthis.startTime = new Date().getTime();\n\t\t\tthis.frameNumber = 0;\n\t\t}\n\n\t\treturn result;\n\t}   \n};"
  },
  {
    "path": "lib/gif.js",
    "content": "// gif.js 0.2.0 - https://github.com/jnordberg/gif.js\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.GIF=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(require,module,exports){function EventEmitter(){this._events=this._events||{};this._maxListeners=this._maxListeners||undefined}module.exports=EventEmitter;EventEmitter.EventEmitter=EventEmitter;EventEmitter.prototype._events=undefined;EventEmitter.prototype._maxListeners=undefined;EventEmitter.defaultMaxListeners=10;EventEmitter.prototype.setMaxListeners=function(n){if(!isNumber(n)||n<0||isNaN(n))throw TypeError(\"n must be a positive number\");this._maxListeners=n;return this};EventEmitter.prototype.emit=function(type){var er,handler,len,args,i,listeners;if(!this._events)this._events={};if(type===\"error\"){if(!this._events.error||isObject(this._events.error)&&!this._events.error.length){er=arguments[1];if(er instanceof Error){throw er}else{var err=new Error('Uncaught, unspecified \"error\" event. ('+er+\")\");err.context=er;throw err}}}handler=this._events[type];if(isUndefined(handler))return false;if(isFunction(handler)){switch(arguments.length){case 1:handler.call(this);break;case 2:handler.call(this,arguments[1]);break;case 3:handler.call(this,arguments[1],arguments[2]);break;default:args=Array.prototype.slice.call(arguments,1);handler.apply(this,args)}}else if(isObject(handler)){args=Array.prototype.slice.call(arguments,1);listeners=handler.slice();len=listeners.length;for(i=0;i<len;i++)listeners[i].apply(this,args)}return true};EventEmitter.prototype.addListener=function(type,listener){var m;if(!isFunction(listener))throw TypeError(\"listener must be a function\");if(!this._events)this._events={};if(this._events.newListener)this.emit(\"newListener\",type,isFunction(listener.listener)?listener.listener:listener);if(!this._events[type])this._events[type]=listener;else if(isObject(this._events[type]))this._events[type].push(listener);else this._events[type]=[this._events[type],listener];if(isObject(this._events[type])&&!this._events[type].warned){if(!isUndefined(this._maxListeners)){m=this._maxListeners}else{m=EventEmitter.defaultMaxListeners}if(m&&m>0&&this._events[type].length>m){this._events[type].warned=true;console.error(\"(node) warning: possible EventEmitter memory \"+\"leak detected. %d listeners added. \"+\"Use emitter.setMaxListeners() to increase limit.\",this._events[type].length);if(typeof console.trace===\"function\"){console.trace()}}}return this};EventEmitter.prototype.on=EventEmitter.prototype.addListener;EventEmitter.prototype.once=function(type,listener){if(!isFunction(listener))throw TypeError(\"listener must be a function\");var fired=false;function g(){this.removeListener(type,g);if(!fired){fired=true;listener.apply(this,arguments)}}g.listener=listener;this.on(type,g);return this};EventEmitter.prototype.removeListener=function(type,listener){var list,position,length,i;if(!isFunction(listener))throw TypeError(\"listener must be a function\");if(!this._events||!this._events[type])return this;list=this._events[type];length=list.length;position=-1;if(list===listener||isFunction(list.listener)&&list.listener===listener){delete this._events[type];if(this._events.removeListener)this.emit(\"removeListener\",type,listener)}else if(isObject(list)){for(i=length;i-- >0;){if(list[i]===listener||list[i].listener&&list[i].listener===listener){position=i;break}}if(position<0)return this;if(list.length===1){list.length=0;delete this._events[type]}else{list.splice(position,1)}if(this._events.removeListener)this.emit(\"removeListener\",type,listener)}return this};EventEmitter.prototype.removeAllListeners=function(type){var key,listeners;if(!this._events)return this;if(!this._events.removeListener){if(arguments.length===0)this._events={};else if(this._events[type])delete this._events[type];return this}if(arguments.length===0){for(key in this._events){if(key===\"removeListener\")continue;this.removeAllListeners(key)}this.removeAllListeners(\"removeListener\");this._events={};return this}listeners=this._events[type];if(isFunction(listeners)){this.removeListener(type,listeners)}else if(listeners){while(listeners.length)this.removeListener(type,listeners[listeners.length-1])}delete this._events[type];return this};EventEmitter.prototype.listeners=function(type){var ret;if(!this._events||!this._events[type])ret=[];else if(isFunction(this._events[type]))ret=[this._events[type]];else ret=this._events[type].slice();return ret};EventEmitter.prototype.listenerCount=function(type){if(this._events){var evlistener=this._events[type];if(isFunction(evlistener))return 1;else if(evlistener)return evlistener.length}return 0};EventEmitter.listenerCount=function(emitter,type){return emitter.listenerCount(type)};function isFunction(arg){return typeof arg===\"function\"}function isNumber(arg){return typeof arg===\"number\"}function isObject(arg){return typeof arg===\"object\"&&arg!==null}function isUndefined(arg){return arg===void 0}},{}],2:[function(require,module,exports){var UA,browser,mode,platform,ua;ua=navigator.userAgent.toLowerCase();platform=navigator.platform.toLowerCase();UA=ua.match(/(opera|ie|firefox|chrome|version)[\\s\\/:]([\\w\\d\\.]+)?.*?(safari|version[\\s\\/:]([\\w\\d\\.]+)|$)/)||[null,\"unknown\",0];mode=UA[1]===\"ie\"&&document.documentMode;browser={name:UA[1]===\"version\"?UA[3]:UA[1],version:mode||parseFloat(UA[1]===\"opera\"&&UA[4]?UA[4]:UA[2]),platform:{name:ua.match(/ip(?:ad|od|hone)/)?\"ios\":(ua.match(/(?:webos|android)/)||platform.match(/mac|win|linux/)||[\"other\"])[0]}};browser[browser.name]=true;browser[browser.name+parseInt(browser.version,10)]=true;browser.platform[browser.platform.name]=true;module.exports=browser},{}],3:[function(require,module,exports){var EventEmitter,GIF,browser,extend=function(child,parent){for(var key in parent){if(hasProp.call(parent,key))child[key]=parent[key]}function ctor(){this.constructor=child}ctor.prototype=parent.prototype;child.prototype=new ctor;child.__super__=parent.prototype;return child},hasProp={}.hasOwnProperty,indexOf=[].indexOf||function(item){for(var i=0,l=this.length;i<l;i++){if(i in this&&this[i]===item)return i}return-1},slice=[].slice;EventEmitter=require(\"events\").EventEmitter;browser=require(\"./browser.coffee\");GIF=function(superClass){var defaults,frameDefaults;extend(GIF,superClass);defaults={workerScript:\"gif.worker.js\",workers:2,repeat:0,background:\"#fff\",quality:10,width:null,height:null,transparent:null,debug:false,dither:false};frameDefaults={delay:500,copy:false};function GIF(options){var base,key,value;this.running=false;this.options={};this.frames=[];this.freeWorkers=[];this.activeWorkers=[];this.setOptions(options);for(key in defaults){value=defaults[key];if((base=this.options)[key]==null){base[key]=value}}}GIF.prototype.setOption=function(key,value){this.options[key]=value;if(this._canvas!=null&&(key===\"width\"||key===\"height\")){return this._canvas[key]=value}};GIF.prototype.setOptions=function(options){var key,results,value;results=[];for(key in options){if(!hasProp.call(options,key))continue;value=options[key];results.push(this.setOption(key,value))}return results};GIF.prototype.addFrame=function(image,options){var frame,key;if(options==null){options={}}frame={};frame.transparent=this.options.transparent;for(key in frameDefaults){frame[key]=options[key]||frameDefaults[key]}if(this.options.width==null){this.setOption(\"width\",image.width)}if(this.options.height==null){this.setOption(\"height\",image.height)}if(typeof ImageData!==\"undefined\"&&ImageData!==null&&image instanceof ImageData){frame.data=image.data}else if(typeof CanvasRenderingContext2D!==\"undefined\"&&CanvasRenderingContext2D!==null&&image instanceof CanvasRenderingContext2D||typeof WebGLRenderingContext!==\"undefined\"&&WebGLRenderingContext!==null&&image instanceof WebGLRenderingContext){if(options.copy){frame.data=this.getContextData(image)}else{frame.context=image}}else if(image.childNodes!=null){if(options.copy){frame.data=this.getImageData(image)}else{frame.image=image}}else{throw new Error(\"Invalid image\")}return this.frames.push(frame)};GIF.prototype.render=function(){var i,j,numWorkers,ref;if(this.running){throw new Error(\"Already running\")}if(this.options.width==null||this.options.height==null){throw new Error(\"Width and height must be set prior to rendering\")}this.running=true;this.nextFrame=0;this.finishedFrames=0;this.imageParts=function(){var j,ref,results;results=[];for(i=j=0,ref=this.frames.length;0<=ref?j<ref:j>ref;i=0<=ref?++j:--j){results.push(null)}return results}.call(this);numWorkers=this.spawnWorkers();if(this.options.globalPalette===true){this.renderNextFrame()}else{for(i=j=0,ref=numWorkers;0<=ref?j<ref:j>ref;i=0<=ref?++j:--j){this.renderNextFrame()}}this.emit(\"start\");return this.emit(\"progress\",0)};GIF.prototype.abort=function(){var worker;while(true){worker=this.activeWorkers.shift();if(worker==null){break}this.log(\"killing active worker\");worker.terminate()}this.running=false;return this.emit(\"abort\")};GIF.prototype.spawnWorkers=function(){var j,numWorkers,ref,results;numWorkers=Math.min(this.options.workers,this.frames.length);(function(){results=[];for(var j=ref=this.freeWorkers.length;ref<=numWorkers?j<numWorkers:j>numWorkers;ref<=numWorkers?j++:j--){results.push(j)}return results}).apply(this).forEach(function(_this){return function(i){var worker;_this.log(\"spawning worker \"+i);worker=new Worker(_this.options.workerScript);worker.onmessage=function(event){_this.activeWorkers.splice(_this.activeWorkers.indexOf(worker),1);_this.freeWorkers.push(worker);return _this.frameFinished(event.data)};return _this.freeWorkers.push(worker)}}(this));return numWorkers};GIF.prototype.frameFinished=function(frame){var i,j,ref;this.log(\"frame \"+frame.index+\" finished - \"+this.activeWorkers.length+\" active\");this.finishedFrames++;this.emit(\"progress\",this.finishedFrames/this.frames.length);this.imageParts[frame.index]=frame;if(this.options.globalPalette===true){this.options.globalPalette=frame.globalPalette;this.log(\"global palette analyzed\");if(this.frames.length>2){for(i=j=1,ref=this.freeWorkers.length;1<=ref?j<ref:j>ref;i=1<=ref?++j:--j){this.renderNextFrame()}}}if(indexOf.call(this.imageParts,null)>=0){return this.renderNextFrame()}else{return this.finishRendering()}};GIF.prototype.finishRendering=function(){var data,frame,i,image,j,k,l,len,len1,len2,len3,offset,page,ref,ref1,ref2;len=0;ref=this.imageParts;for(j=0,len1=ref.length;j<len1;j++){frame=ref[j];len+=(frame.data.length-1)*frame.pageSize+frame.cursor}len+=frame.pageSize-frame.cursor;this.log(\"rendering finished - filesize \"+Math.round(len/1e3)+\"kb\");data=new Uint8Array(len);offset=0;ref1=this.imageParts;for(k=0,len2=ref1.length;k<len2;k++){frame=ref1[k];ref2=frame.data;for(i=l=0,len3=ref2.length;l<len3;i=++l){page=ref2[i];data.set(page,offset);if(i===frame.data.length-1){offset+=frame.cursor}else{offset+=frame.pageSize}}}image=new Blob([data],{type:\"image/gif\"});return this.emit(\"finished\",image,data)};GIF.prototype.renderNextFrame=function(){var frame,task,worker;if(this.freeWorkers.length===0){throw new Error(\"No free workers\")}if(this.nextFrame>=this.frames.length){return}frame=this.frames[this.nextFrame++];worker=this.freeWorkers.shift();task=this.getTask(frame);this.log(\"starting frame \"+(task.index+1)+\" of \"+this.frames.length);this.activeWorkers.push(worker);return worker.postMessage(task)};GIF.prototype.getContextData=function(ctx){return ctx.getImageData(0,0,this.options.width,this.options.height).data};GIF.prototype.getImageData=function(image){var ctx;if(this._canvas==null){this._canvas=document.createElement(\"canvas\");this._canvas.width=this.options.width;this._canvas.height=this.options.height}ctx=this._canvas.getContext(\"2d\");ctx.setFill=this.options.background;ctx.fillRect(0,0,this.options.width,this.options.height);ctx.drawImage(image,0,0);return this.getContextData(ctx)};GIF.prototype.getTask=function(frame){var index,task;index=this.frames.indexOf(frame);task={index:index,last:index===this.frames.length-1,delay:frame.delay,transparent:frame.transparent,width:this.options.width,height:this.options.height,quality:this.options.quality,dither:this.options.dither,globalPalette:this.options.globalPalette,repeat:this.options.repeat,canTransfer:browser.name===\"chrome\"};if(frame.data!=null){task.data=frame.data}else if(frame.context!=null){task.data=this.getContextData(frame.context)}else if(frame.image!=null){task.data=this.getImageData(frame.image)}else{throw new Error(\"Invalid frame\")}return task};GIF.prototype.log=function(){var args;args=1<=arguments.length?slice.call(arguments,0):[];if(!this.options.debug){return}return console.log.apply(console,args)};return GIF}(EventEmitter);module.exports=GIF},{\"./browser.coffee\":2,events:1}]},{},[3])(3)});\n//# sourceMappingURL=gif.js.map\n"
  },
  {
    "path": "lib/gif.worker.js",
    "content": "// gif.worker.js 0.2.0 - https://github.com/jnordberg/gif.js\n(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){var NeuQuant=require(\"./TypedNeuQuant.js\");var LZWEncoder=require(\"./LZWEncoder.js\");function ByteArray(){this.page=-1;this.pages=[];this.newPage()}ByteArray.pageSize=4096;ByteArray.charMap={};for(var i=0;i<256;i++)ByteArray.charMap[i]=String.fromCharCode(i);ByteArray.prototype.newPage=function(){this.pages[++this.page]=new Uint8Array(ByteArray.pageSize);this.cursor=0};ByteArray.prototype.getData=function(){var rv=\"\";for(var p=0;p<this.pages.length;p++){for(var i=0;i<ByteArray.pageSize;i++){rv+=ByteArray.charMap[this.pages[p][i]]}}return rv};ByteArray.prototype.writeByte=function(val){if(this.cursor>=ByteArray.pageSize)this.newPage();this.pages[this.page][this.cursor++]=val};ByteArray.prototype.writeUTFBytes=function(string){for(var l=string.length,i=0;i<l;i++)this.writeByte(string.charCodeAt(i))};ByteArray.prototype.writeBytes=function(array,offset,length){for(var l=length||array.length,i=offset||0;i<l;i++)this.writeByte(array[i])};function GIFEncoder(width,height){this.width=~~width;this.height=~~height;this.transparent=null;this.transIndex=0;this.repeat=-1;this.delay=0;this.image=null;this.pixels=null;this.indexedPixels=null;this.colorDepth=null;this.colorTab=null;this.neuQuant=null;this.usedEntry=new Array;this.palSize=7;this.dispose=-1;this.firstFrame=true;this.sample=10;this.dither=false;this.globalPalette=false;this.out=new ByteArray}GIFEncoder.prototype.setDelay=function(milliseconds){this.delay=Math.round(milliseconds/10)};GIFEncoder.prototype.setFrameRate=function(fps){this.delay=Math.round(100/fps)};GIFEncoder.prototype.setDispose=function(disposalCode){if(disposalCode>=0)this.dispose=disposalCode};GIFEncoder.prototype.setRepeat=function(repeat){this.repeat=repeat};GIFEncoder.prototype.setTransparent=function(color){this.transparent=color};GIFEncoder.prototype.addFrame=function(imageData){this.image=imageData;this.colorTab=this.globalPalette&&this.globalPalette.slice?this.globalPalette:null;this.getImagePixels();this.analyzePixels();if(this.globalPalette===true)this.globalPalette=this.colorTab;if(this.firstFrame){this.writeLSD();this.writePalette();if(this.repeat>=0){this.writeNetscapeExt()}}this.writeGraphicCtrlExt();this.writeImageDesc();if(!this.firstFrame&&!this.globalPalette)this.writePalette();this.writePixels();this.firstFrame=false};GIFEncoder.prototype.finish=function(){this.out.writeByte(59)};GIFEncoder.prototype.setQuality=function(quality){if(quality<1)quality=1;this.sample=quality};GIFEncoder.prototype.setDither=function(dither){if(dither===true)dither=\"FloydSteinberg\";this.dither=dither};GIFEncoder.prototype.setGlobalPalette=function(palette){this.globalPalette=palette};GIFEncoder.prototype.getGlobalPalette=function(){return this.globalPalette&&this.globalPalette.slice&&this.globalPalette.slice(0)||this.globalPalette};GIFEncoder.prototype.writeHeader=function(){this.out.writeUTFBytes(\"GIF89a\")};GIFEncoder.prototype.analyzePixels=function(){if(!this.colorTab){this.neuQuant=new NeuQuant(this.pixels,this.sample);this.neuQuant.buildColormap();this.colorTab=this.neuQuant.getColormap()}if(this.dither){this.ditherPixels(this.dither.replace(\"-serpentine\",\"\"),this.dither.match(/-serpentine/)!==null)}else{this.indexPixels()}this.pixels=null;this.colorDepth=8;this.palSize=7;if(this.transparent!==null){this.transIndex=this.findClosest(this.transparent,true)}};GIFEncoder.prototype.indexPixels=function(imgq){var nPix=this.pixels.length/3;this.indexedPixels=new Uint8Array(nPix);var k=0;for(var j=0;j<nPix;j++){var index=this.findClosestRGB(this.pixels[k++]&255,this.pixels[k++]&255,this.pixels[k++]&255);this.usedEntry[index]=true;this.indexedPixels[j]=index}};GIFEncoder.prototype.ditherPixels=function(kernel,serpentine){var kernels={FalseFloydSteinberg:[[3/8,1,0],[3/8,0,1],[2/8,1,1]],FloydSteinberg:[[7/16,1,0],[3/16,-1,1],[5/16,0,1],[1/16,1,1]],Stucki:[[8/42,1,0],[4/42,2,0],[2/42,-2,1],[4/42,-1,1],[8/42,0,1],[4/42,1,1],[2/42,2,1],[1/42,-2,2],[2/42,-1,2],[4/42,0,2],[2/42,1,2],[1/42,2,2]],Atkinson:[[1/8,1,0],[1/8,2,0],[1/8,-1,1],[1/8,0,1],[1/8,1,1],[1/8,0,2]]};if(!kernel||!kernels[kernel]){throw\"Unknown dithering kernel: \"+kernel}var ds=kernels[kernel];var index=0,height=this.height,width=this.width,data=this.pixels;var direction=serpentine?-1:1;this.indexedPixels=new Uint8Array(this.pixels.length/3);for(var y=0;y<height;y++){if(serpentine)direction=direction*-1;for(var x=direction==1?0:width-1,xend=direction==1?width:0;x!==xend;x+=direction){index=y*width+x;var idx=index*3;var r1=data[idx];var g1=data[idx+1];var b1=data[idx+2];idx=this.findClosestRGB(r1,g1,b1);this.usedEntry[idx]=true;this.indexedPixels[index]=idx;idx*=3;var r2=this.colorTab[idx];var g2=this.colorTab[idx+1];var b2=this.colorTab[idx+2];var er=r1-r2;var eg=g1-g2;var eb=b1-b2;for(var i=direction==1?0:ds.length-1,end=direction==1?ds.length:0;i!==end;i+=direction){var x1=ds[i][1];var y1=ds[i][2];if(x1+x>=0&&x1+x<width&&y1+y>=0&&y1+y<height){var d=ds[i][0];idx=index+x1+y1*width;idx*=3;data[idx]=Math.max(0,Math.min(255,data[idx]+er*d));data[idx+1]=Math.max(0,Math.min(255,data[idx+1]+eg*d));data[idx+2]=Math.max(0,Math.min(255,data[idx+2]+eb*d))}}}}};GIFEncoder.prototype.findClosest=function(c,used){return this.findClosestRGB((c&16711680)>>16,(c&65280)>>8,c&255,used)};GIFEncoder.prototype.findClosestRGB=function(r,g,b,used){if(this.colorTab===null)return-1;if(this.neuQuant&&!used){return this.neuQuant.lookupRGB(r,g,b)}var c=b|g<<8|r<<16;var minpos=0;var dmin=256*256*256;var len=this.colorTab.length;for(var i=0,index=0;i<len;index++){var dr=r-(this.colorTab[i++]&255);var dg=g-(this.colorTab[i++]&255);var db=b-(this.colorTab[i++]&255);var d=dr*dr+dg*dg+db*db;if((!used||this.usedEntry[index])&&d<dmin){dmin=d;minpos=index}}return minpos};GIFEncoder.prototype.getImagePixels=function(){var w=this.width;var h=this.height;this.pixels=new Uint8Array(w*h*3);var data=this.image;var srcPos=0;var count=0;for(var i=0;i<h;i++){for(var j=0;j<w;j++){this.pixels[count++]=data[srcPos++];this.pixels[count++]=data[srcPos++];this.pixels[count++]=data[srcPos++];srcPos++}}};GIFEncoder.prototype.writeGraphicCtrlExt=function(){this.out.writeByte(33);this.out.writeByte(249);this.out.writeByte(4);var transp,disp;if(this.transparent===null){transp=0;disp=0}else{transp=1;disp=2}if(this.dispose>=0){disp=dispose&7}disp<<=2;this.out.writeByte(0|disp|0|transp);this.writeShort(this.delay);this.out.writeByte(this.transIndex);this.out.writeByte(0)};GIFEncoder.prototype.writeImageDesc=function(){this.out.writeByte(44);this.writeShort(0);this.writeShort(0);this.writeShort(this.width);this.writeShort(this.height);if(this.firstFrame||this.globalPalette){this.out.writeByte(0)}else{this.out.writeByte(128|0|0|0|this.palSize)}};GIFEncoder.prototype.writeLSD=function(){this.writeShort(this.width);this.writeShort(this.height);this.out.writeByte(128|112|0|this.palSize);this.out.writeByte(0);this.out.writeByte(0)};GIFEncoder.prototype.writeNetscapeExt=function(){this.out.writeByte(33);this.out.writeByte(255);this.out.writeByte(11);this.out.writeUTFBytes(\"NETSCAPE2.0\");this.out.writeByte(3);this.out.writeByte(1);this.writeShort(this.repeat);this.out.writeByte(0)};GIFEncoder.prototype.writePalette=function(){this.out.writeBytes(this.colorTab);var n=3*256-this.colorTab.length;for(var i=0;i<n;i++)this.out.writeByte(0)};GIFEncoder.prototype.writeShort=function(pValue){this.out.writeByte(pValue&255);this.out.writeByte(pValue>>8&255)};GIFEncoder.prototype.writePixels=function(){var enc=new LZWEncoder(this.width,this.height,this.indexedPixels,this.colorDepth);enc.encode(this.out)};GIFEncoder.prototype.stream=function(){return this.out};module.exports=GIFEncoder},{\"./LZWEncoder.js\":2,\"./TypedNeuQuant.js\":3}],2:[function(require,module,exports){var EOF=-1;var BITS=12;var HSIZE=5003;var masks=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535];function LZWEncoder(width,height,pixels,colorDepth){var initCodeSize=Math.max(2,colorDepth);var accum=new Uint8Array(256);var htab=new Int32Array(HSIZE);var codetab=new Int32Array(HSIZE);var cur_accum,cur_bits=0;var a_count;var free_ent=0;var maxcode;var clear_flg=false;var g_init_bits,ClearCode,EOFCode;function char_out(c,outs){accum[a_count++]=c;if(a_count>=254)flush_char(outs)}function cl_block(outs){cl_hash(HSIZE);free_ent=ClearCode+2;clear_flg=true;output(ClearCode,outs)}function cl_hash(hsize){for(var i=0;i<hsize;++i)htab[i]=-1}function compress(init_bits,outs){var fcode,c,i,ent,disp,hsize_reg,hshift;g_init_bits=init_bits;clear_flg=false;n_bits=g_init_bits;maxcode=MAXCODE(n_bits);ClearCode=1<<init_bits-1;EOFCode=ClearCode+1;free_ent=ClearCode+2;a_count=0;ent=nextPixel();hshift=0;for(fcode=HSIZE;fcode<65536;fcode*=2)++hshift;hshift=8-hshift;hsize_reg=HSIZE;cl_hash(hsize_reg);output(ClearCode,outs);outer_loop:while((c=nextPixel())!=EOF){fcode=(c<<BITS)+ent;i=c<<hshift^ent;if(htab[i]===fcode){ent=codetab[i];continue}else if(htab[i]>=0){disp=hsize_reg-i;if(i===0)disp=1;do{if((i-=disp)<0)i+=hsize_reg;if(htab[i]===fcode){ent=codetab[i];continue outer_loop}}while(htab[i]>=0)}output(ent,outs);ent=c;if(free_ent<1<<BITS){codetab[i]=free_ent++;htab[i]=fcode}else{cl_block(outs)}}output(ent,outs);output(EOFCode,outs)}function encode(outs){outs.writeByte(initCodeSize);remaining=width*height;curPixel=0;compress(initCodeSize+1,outs);outs.writeByte(0)}function flush_char(outs){if(a_count>0){outs.writeByte(a_count);outs.writeBytes(accum,0,a_count);a_count=0}}function MAXCODE(n_bits){return(1<<n_bits)-1}function nextPixel(){if(remaining===0)return EOF;--remaining;var pix=pixels[curPixel++];return pix&255}function output(code,outs){cur_accum&=masks[cur_bits];if(cur_bits>0)cur_accum|=code<<cur_bits;else cur_accum=code;cur_bits+=n_bits;while(cur_bits>=8){char_out(cur_accum&255,outs);cur_accum>>=8;cur_bits-=8}if(free_ent>maxcode||clear_flg){if(clear_flg){maxcode=MAXCODE(n_bits=g_init_bits);clear_flg=false}else{++n_bits;if(n_bits==BITS)maxcode=1<<BITS;else maxcode=MAXCODE(n_bits)}}if(code==EOFCode){while(cur_bits>0){char_out(cur_accum&255,outs);cur_accum>>=8;cur_bits-=8}flush_char(outs)}}this.encode=encode}module.exports=LZWEncoder},{}],3:[function(require,module,exports){var ncycles=100;var netsize=256;var maxnetpos=netsize-1;var netbiasshift=4;var intbiasshift=16;var intbias=1<<intbiasshift;var gammashift=10;var gamma=1<<gammashift;var betashift=10;var beta=intbias>>betashift;var betagamma=intbias<<gammashift-betashift;var initrad=netsize>>3;var radiusbiasshift=6;var radiusbias=1<<radiusbiasshift;var initradius=initrad*radiusbias;var radiusdec=30;var alphabiasshift=10;var initalpha=1<<alphabiasshift;var alphadec;var radbiasshift=8;var radbias=1<<radbiasshift;var alpharadbshift=alphabiasshift+radbiasshift;var alpharadbias=1<<alpharadbshift;var prime1=499;var prime2=491;var prime3=487;var prime4=503;var minpicturebytes=3*prime4;function NeuQuant(pixels,samplefac){var network;var netindex;var bias;var freq;var radpower;function init(){network=[];netindex=new Int32Array(256);bias=new Int32Array(netsize);freq=new Int32Array(netsize);radpower=new Int32Array(netsize>>3);var i,v;for(i=0;i<netsize;i++){v=(i<<netbiasshift+8)/netsize;network[i]=new Float64Array([v,v,v,0]);freq[i]=intbias/netsize;bias[i]=0}}function unbiasnet(){for(var i=0;i<netsize;i++){network[i][0]>>=netbiasshift;network[i][1]>>=netbiasshift;network[i][2]>>=netbiasshift;network[i][3]=i}}function altersingle(alpha,i,b,g,r){network[i][0]-=alpha*(network[i][0]-b)/initalpha;network[i][1]-=alpha*(network[i][1]-g)/initalpha;network[i][2]-=alpha*(network[i][2]-r)/initalpha}function alterneigh(radius,i,b,g,r){var lo=Math.abs(i-radius);var hi=Math.min(i+radius,netsize);var j=i+1;var k=i-1;var m=1;var p,a;while(j<hi||k>lo){a=radpower[m++];if(j<hi){p=network[j++];p[0]-=a*(p[0]-b)/alpharadbias;p[1]-=a*(p[1]-g)/alpharadbias;p[2]-=a*(p[2]-r)/alpharadbias}if(k>lo){p=network[k--];p[0]-=a*(p[0]-b)/alpharadbias;p[1]-=a*(p[1]-g)/alpharadbias;p[2]-=a*(p[2]-r)/alpharadbias}}}function contest(b,g,r){var bestd=~(1<<31);var bestbiasd=bestd;var bestpos=-1;var bestbiaspos=bestpos;var i,n,dist,biasdist,betafreq;for(i=0;i<netsize;i++){n=network[i];dist=Math.abs(n[0]-b)+Math.abs(n[1]-g)+Math.abs(n[2]-r);if(dist<bestd){bestd=dist;bestpos=i}biasdist=dist-(bias[i]>>intbiasshift-netbiasshift);if(biasdist<bestbiasd){bestbiasd=biasdist;bestbiaspos=i}betafreq=freq[i]>>betashift;freq[i]-=betafreq;bias[i]+=betafreq<<gammashift}freq[bestpos]+=beta;bias[bestpos]-=betagamma;return bestbiaspos}function inxbuild(){var i,j,p,q,smallpos,smallval,previouscol=0,startpos=0;for(i=0;i<netsize;i++){p=network[i];smallpos=i;smallval=p[1];for(j=i+1;j<netsize;j++){q=network[j];if(q[1]<smallval){smallpos=j;smallval=q[1]}}q=network[smallpos];if(i!=smallpos){j=q[0];q[0]=p[0];p[0]=j;j=q[1];q[1]=p[1];p[1]=j;j=q[2];q[2]=p[2];p[2]=j;j=q[3];q[3]=p[3];p[3]=j}if(smallval!=previouscol){netindex[previouscol]=startpos+i>>1;for(j=previouscol+1;j<smallval;j++)netindex[j]=i;previouscol=smallval;startpos=i}}netindex[previouscol]=startpos+maxnetpos>>1;for(j=previouscol+1;j<256;j++)netindex[j]=maxnetpos}function inxsearch(b,g,r){var a,p,dist;var bestd=1e3;var best=-1;var i=netindex[g];var j=i-1;while(i<netsize||j>=0){if(i<netsize){p=network[i];dist=p[1]-g;if(dist>=bestd)i=netsize;else{i++;if(dist<0)dist=-dist;a=p[0]-b;if(a<0)a=-a;dist+=a;if(dist<bestd){a=p[2]-r;if(a<0)a=-a;dist+=a;if(dist<bestd){bestd=dist;best=p[3]}}}}if(j>=0){p=network[j];dist=g-p[1];if(dist>=bestd)j=-1;else{j--;if(dist<0)dist=-dist;a=p[0]-b;if(a<0)a=-a;dist+=a;if(dist<bestd){a=p[2]-r;if(a<0)a=-a;dist+=a;if(dist<bestd){bestd=dist;best=p[3]}}}}}return best}function learn(){var i;var lengthcount=pixels.length;var alphadec=30+(samplefac-1)/3;var samplepixels=lengthcount/(3*samplefac);var delta=~~(samplepixels/ncycles);var alpha=initalpha;var radius=initradius;var rad=radius>>radiusbiasshift;if(rad<=1)rad=0;for(i=0;i<rad;i++)radpower[i]=alpha*((rad*rad-i*i)*radbias/(rad*rad));var step;if(lengthcount<minpicturebytes){samplefac=1;step=3}else if(lengthcount%prime1!==0){step=3*prime1}else if(lengthcount%prime2!==0){step=3*prime2}else if(lengthcount%prime3!==0){step=3*prime3}else{step=3*prime4}var b,g,r,j;var pix=0;i=0;while(i<samplepixels){b=(pixels[pix]&255)<<netbiasshift;g=(pixels[pix+1]&255)<<netbiasshift;r=(pixels[pix+2]&255)<<netbiasshift;j=contest(b,g,r);altersingle(alpha,j,b,g,r);if(rad!==0)alterneigh(rad,j,b,g,r);pix+=step;if(pix>=lengthcount)pix-=lengthcount;i++;if(delta===0)delta=1;if(i%delta===0){alpha-=alpha/alphadec;radius-=radius/radiusdec;rad=radius>>radiusbiasshift;if(rad<=1)rad=0;for(j=0;j<rad;j++)radpower[j]=alpha*((rad*rad-j*j)*radbias/(rad*rad))}}}function buildColormap(){init();learn();unbiasnet();inxbuild()}this.buildColormap=buildColormap;function getColormap(){var map=[];var index=[];for(var i=0;i<netsize;i++)index[network[i][3]]=i;var k=0;for(var l=0;l<netsize;l++){var j=index[l];map[k++]=network[j][0];map[k++]=network[j][1];map[k++]=network[j][2]}return map}this.getColormap=getColormap;this.lookupRGB=inxsearch}module.exports=NeuQuant},{}],4:[function(require,module,exports){var GIFEncoder,renderFrame;GIFEncoder=require(\"./GIFEncoder.js\");renderFrame=function(frame){var encoder,page,stream,transfer;encoder=new GIFEncoder(frame.width,frame.height);if(frame.index===0){encoder.writeHeader()}else{encoder.firstFrame=false}encoder.setTransparent(frame.transparent);encoder.setRepeat(frame.repeat);encoder.setDelay(frame.delay);encoder.setQuality(frame.quality);encoder.setDither(frame.dither);encoder.setGlobalPalette(frame.globalPalette);encoder.addFrame(frame.data);if(frame.last){encoder.finish()}if(frame.globalPalette===true){frame.globalPalette=encoder.getGlobalPalette()}stream=encoder.stream();frame.data=stream.pages;frame.cursor=stream.cursor;frame.pageSize=stream.constructor.pageSize;if(frame.canTransfer){transfer=function(){var i,len,ref,results;ref=frame.data;results=[];for(i=0,len=ref.length;i<len;i++){page=ref[i];results.push(page.buffer)}return results}();return self.postMessage(frame,transfer)}else{return self.postMessage(frame)}};self.onmessage=function(event){return renderFrame(event.data)}},{\"./GIFEncoder.js\":1}]},{},[4]);\n//# sourceMappingURL=gif.worker.js.map\n"
  },
  {
    "path": "lib/highlight/CHANGES.md",
    "content": "## Version 9.9.0\n\nNew languages\n\n- *LLVM* by [Michael Rodler][]\n\nImprovements:\n\n- *TypeScript* updated with annotations and param lists inside constructors, by\n  [Raphael Parree][].\n- *CoffeeScript* updated with new keywords and fixed to recognize JavaScript\n  in \\`\\`\\`, thanks to thanks to [Geoffrey Booth][].\n- Compiler directives in *Delphi* are now correctly highlighted as \"meta\".\n\n[Raphael Parree]: https://github.com/rparree\n[Michael Rodler]: https://github.com/f0rki\n[Geoffrey Booth]: https://github.com/GeoffreyBooth\n\n\n## Version 9.8.0 \"New York\"\n\nThis version is the second one that deserved a name. Because I'm in New York,\nand the release isn't missing the deadline only because it's still Tuesday on\nWest Coast.\n\nNew languages:\n\n- *Clean* by [Camil Staps][]\n- *Flix* by [Magnus Madsen][]\n\nImprovements:\n\n- [Kenton Hamaluik][] did a comprehensive update for *Haxe*.\n- New commands for *PowerShell* from [Nicolas Le Gall][].\n- [Jan T. Sott][] updated *NSIS*.\n- *Java* and *Swift* support unicode characters in identifiers thanks to\n  [Alexander Lichter][].\n\n[Camil Staps]: https://github.com/camilstaps\n[Magnus Madsen]: https://github.com/magnus-madsen\n[Kenton Hamaluik]: https://github.com/FuzzyWuzzie\n[Nicolas Le Gall]: https://github.com/darkitty\n[Jan T. Sott]: https://github.com/idleberg\n[Alexander Lichter]: https://github.com/manniL\n\n\n## Version 9.7.0\n\nA comprehensive bugfix release. This is one of the best things about\nhighlight.js: even boring things keep getting better (even if slow).\n\n- VHDL updated with PSL keywords and uses more consistent styling.\n- Nested C-style comments no longer break highlighting in many languages.\n- JavaScript updated with `=>` functions, highlighted object attributes and\n  parsing within template string substitution blocks (`${...}`).\n- Fixed another corner case with self-closing `<tag/>` in JSX.\n- Added `HEALTHCHECK` directive in Docker.\n- Delphi updated with new Free Pascal keywords.\n- Fixed digit separator parsing in C++.\n- C# updated with new keywords and fixed to allow multiple identifiers within\n  generics `<...>`.\n- Fixed another slow regex in Less.\n\n\n## Version 9.6.0\n\nNew languages:\n\n- *ABNF* and *EBNF* by [Alex McKibben][]\n- *Awk* by [Matthew Daly][]\n- *SubUnit* by [Sergey Bronnikov][]\n\nNew styles:\n\n- *Atom One* in both Dark and Light variants  by [Daniel Gamage][]\n\nPlus, a few smaller updates for *Lasso*, *Elixir*, *C++* and *SQL*.\n\n[Alex McKibben]: https://github.com/mckibbenta\n[Daniel Gamage]: https://github.com/danielgamage\n[Matthew Daly]: https://github.com/matthewbdaly\n[Sergey Bronnikov]: https://github.com/ligurio\n\n\n## Version 9.5.0\n\nNew languages:\n\n- *Excel* by [Victor Zhou][]\n- *Linden Scripting Language* by [Builder's Brewery][]\n- *TAP* (Test Anything Protocol) by [Sergey Bronnikov][]\n- *Pony* by [Joe Eli McIlvain][]\n- *Coq* by [Stephan Boyer][]\n- *dsconfig* and *LDIF* by [Jacob Childress][]\n\nNew styles:\n\n- *Ocean Dark* by [Gavin Siu][]\n\nNotable changes:\n\n- [Minh Nguyễn][] added more built-ins to Objective C.\n- [Jeremy Hull][] fixed corner cases in C++ preprocessor directives and Diff\n  comments.\n- [Victor Zhou][] added support for digit separators in C++ numbers.\n\n[Gavin Siu]: https://github.com/gavsiu\n[Builder's Brewery]: https://github.com/buildersbrewery\n[Victor Zhou]: https://github.com/OiCMudkips\n[Sergey Bronnikov]: https://github.com/ligurio\n[Joe Eli McIlvain]: https://github.com/jemc\n[Stephan Boyer]: https://github.com/boyers\n[Jacob Childress]: https://github.com/braveulysses\n[Minh Nguyễn]: https://github.com/1ec5\n[Jeremy Hull]: https://github.com/sourrust\n\n\n## Version 9.4.0\n\nNew languages:\n\n- *PureBASIC* by [Tristano Ajmone][]\n- *BNF* by [Oleg Efimov][]\n- *Ada* by [Lars Schulna][]\n\nNew styles:\n\n- *PureBASIC* by [Tristano Ajmone][]\n\nImprovements to existing languages and styles:\n\n- We now highlight function declarations in Go.\n- [Taisuke Fujimoto][] contributed very convoluted rules for raw and\n  interpolated strings in C#.\n- [Boone Severson][] updated Verilog to comply with IEEE 1800-2012\n  SystemVerilog.\n- [Victor Zhou][] improved rules for comments and strings in PowerShell files.\n- [Janis Voigtländer][] updated the definition of Elm to version 0.17 of the\n  languages. Elm is now featured on the front page of <https://highlightjs.org>.\n- Special variable `$this` is highlighted as a keyword in PHP.\n- `usize` and `isize` are now highlighted in Rust.\n- Fixed labels and directives in x86 assembler.\n\n[Tristano Ajmone]: https://github.com/tajmone\n[Taisuke Fujimoto]: https://github.com/temp-impl\n[Oleg Efimov]: https://github.com/Sannis\n[Boone Severson]: https://github.com/BooneJS\n[Victor Zhou]: https://github.com/OiCMudkips\n[Lars Schulna]: https://github.com/captain-hanuta\n[Janis Voigtländer]: https://github.com/jvoigtlaender\n\n\n## Version 9.3.0\n\nNew languages:\n\n- *Tagger Script* by [Philipp Wolfer][]\n- *MoonScript* by [Billy Quith][]\n\nNew styles:\n\n- *xt256* by [Herbert Shin][]\n\nImprovements to existing languages and styles:\n\n- More robust handling of unquoted HTML tag attributes\n- Relevance tuning for QML which was unnecessary eager at seizing other\n  languages' code\n- Improve GAMS language parsing\n- Fixed a bunch of bugs around selectors in Less\n- Kotlin's got a new definition for annotations, updated keywords and other\n  minor improvements\n- Added `move` to Rust keywords\n- Markdown now recognizes \\`\\`\\`-fenced code blocks\n- Improved detection of function declarations in C++ and C#\n\n[Philipp Wolfer]: https://github.com/phw\n[Billy Quith]: https://github.com/billyquith\n[Herbert Shin]: https://github.com/initbar\n\n\n## Version 9.2.0\n\nNew languages:\n\n- *QML* by [John Foster][]\n- *HTMLBars* by [Michael Johnston][]\n- *CSP* by [Taras][]\n- *Maxima* by [Robert Dodier][]\n\nNew styles:\n\n- *Gruvbox* by [Qeole][]\n- *Dracula* by [Denis Ciccale][]\n\nImprovements to existing languages and styles:\n\n- We now correctly handle JSX with arbitrary node tree depth.\n- Argument list for `(lambda)` in Scheme is no longer highlighted as a function\n  call.\n- Stylus syntax doesn't break on valid CSS.\n- More correct handling of comments and strings and other improvements for\n  VimScript.\n- More subtle work on the default style.\n- We now use anonymous modules for AMD.\n- `macro_rules!` is now recognized as a built-in in Rust.\n\n[John Foster]: https://github.com/jf990\n[Qeole]: https://github.com/Qeole\n[Denis Ciccale]: https://github.com/dciccale\n[Michael Johnston]: https://github.com/lastobelus\n[Taras]: https://github.com/oxdef\n[Robert Dodier]: https://github.com/robert-dodier\n\n\n## Version 9.1.0\n\nNew languages:\n\n- *Stan* by [Brendan Rocks][]\n- *BASIC* by [Raphaël Assénat][]\n- *GAUSS* by [Matt Evans][]\n- *DTS* by [Martin Braun][]\n- *Arduino* by [Stefania Mellai][]\n\nNew Styles:\n\n- *Arduino Light* by [Stefania Mellai][]\n\nImprovements to existing languages and styles:\n\n- Handle return type annotations in Python\n- Allow shebang headers in Javascript\n- Support strings in Rust meta\n- Recognize `struct` as a class-level definition in Rust\n- Recognize b-prefixed chars and strings in Rust\n- Better numbers handling in Verilog\n\n[Brendan Rocks]: http://brendanrocks.com\n[Raphaël Assénat]: https://github.com/raphnet\n[Matt Evans]: https://github.com/matthewevans\n[Martin Braun]: https://github.com/mbr0wn\n[Stefania Mellai]: https://github.com/smellai\n\n\n## Version 9.0.0\n\nThe new major version brings a reworked styling system. Highlight.js now defines\na limited set of highlightable classes giving a consistent result across all the\nstyles and languages. You can read a more detailed explanation and background in\nthe [tracking issue][#348] that started this long process back in May.\n\nThis change is backwards incompatible for those who uses highlight.js with a\ncustom stylesheet. The [new style guide][sg] explains how to write styles\nin this new world.\n\nBundled themes have also suffered a significant amount of improvements and may\nlook different in places, but all the things now consistent and make more sense.\nAmong others, the Default style has got a refresh and will probably be tweaked\nsome more in next releases. Please do give your feedback in our\n[issue tracker][issues].\n\nNew languages in this release:\n\n- *Caché Object Script* by [Nikita Savchenko][]\n- *YAML* by [Stefan Wienert][]\n- *MIPS Assembler* by [Nebuleon Fumika][]\n- *HSP* by [prince][]\n\nImprovements to existing languages and styles:\n\n- ECMAScript 6 modules import now do not require closing semicolon.\n- ECMAScript 6 classes constructors now highlighted.\n- Template string support for Typescript, as for ECMAScript 6.\n- Scala case classes params highlight fixed.\n- Built-in names introduced in Julia v0.4 added by [Kenta Sato][].\n- Refreshed Default style.\n\nOther notable changes:\n\n- [Web workers support][webworkers] added bu [Jan Kühle][].\n- We now have tests for compressed browser builds as well.\n- The building tool chain has been switched to node.js 4.x. and is now\n  shamelessly uses ES6 features all over the place, courtesy of [Jeremy Hull][].\n- License added to non-compressed browser build.\n\n[Jan Kühle]: https://github.com/frigus02\n[Stefan Wienert]: https://github.com/zealot128\n[Kenta Sato]: https://github.com/bicycle1885\n[Nikita Savchenko]: https://github.com/ZitRos\n[webworkers]: https://github.com/isagalaev/highlight.js#web-workers\n[Jeremy Hull]: https://github.com/sourrust\n[#348]: https://github.com/isagalaev/highlight.js/issues/348\n[sg]: http://highlightjs.readthedocs.org/en/latest/style-guide.html\n[issues]: https://github.com/isagalaev/highlight.js/issues\n[Nebuleon Fumika]: https://github.com/Nebuleon\n[prince]: https://github.com/prince-0203\n\n\n## Version 8.9.1\n\nSome last-minute changes reverted due to strange bug with minified browser build:\n\n- Scala case classes params highlight fixed\n- ECMAScript 6 modules import now do not require closing semicolon\n- ECMAScript 6 classes constructors now highlighted\n- Template string support for Typescript, as for ECMAScript 6\n- License added to not minified browser build\n\n\n## Version 8.9.0\n\nNew languages:\n\n- *crmsh* by [Kristoffer Gronlund][]\n- *SQF* by [Soren Enevoldsen][]\n\n[Kristoffer Gronlund]: https://github.com/krig\n[Soren Enevoldsen]: https://github.com/senevoldsen90\n\nNotable fixes and improvements to existing languages:\n\n- Added `abstract` and `namespace` keywords to TypeScript by [Daniel Rosenwasser][]\n- Added `label` support to Dockerfile by [Ladislav Prskavec][]\n- Crystal highlighting improved by [Tsuyusato Kitsune][]\n- Missing Swift keywords added by [Nate Cook][]\n- Improve detection of C block comments\n- ~~Scala case classes params highlight fixed~~\n- ~~ECMAScript 6 modules import now do not require closing semicolon~~\n- ~~ECMAScript 6 classes constructors now highlighted~~\n- ~~Template string support for Typescript, as for ECMAScript 6~~\n\nOther notable changes:\n\n- ~~License added to not minified browser build~~\n\n[Kristoffer Gronlund]: https://github.com/krig\n[Søren Enevoldsen]: https://github.com/senevoldsen90\n[Daniel Rosenwasser]: https://github.com/DanielRosenwasser\n[Ladislav Prskavec]: https://github.com/abtris\n[Tsuyusato Kitsune]: https://github.com/MakeNowJust\n[Nate Cook]: https://github.com/natecook1000\n\n\n## Version 8.8.0\n\nNew languages:\n\n- *Golo* by [Philippe Charrière][]\n- *GAMS* by [Stefan Bechert][]\n- *IRPF90* by [Anthony Scemama][]\n- *Access logs* by [Oleg Efimov][]\n- *Crystal* by [Tsuyusato Kitsune][]\n\nNotable fixes and improvements to existing languages:\n\n- JavaScript highlighting no longer fails with ES6 default parameters\n- Added keywords `async` and `await` to Python\n- PHP heredoc support improved\n- Allow preprocessor directives within C++ functions\n\nOther notable changes:\n\n- Change versions to X.Y.Z SemVer-compatible format\n- Added ability to build all targets at once\n\n[Philippe Charrière]: https://github.com/k33g\n[Stefan Bechert]: https://github.com/b-pos465\n[Anthony Scemama]: https://github.com/scemama\n[Oleg Efimov]: https://github.com/Sannis\n[Tsuyusato Kitsune]: https://github.com/MakeNowJust\n\n\n## Version 8.7\n\nNew languages:\n\n- *Zephir* by [Oleg Efimov][]\n- *Elm* by [Janis Voigtländer][]\n- *XQuery* by [Dirk Kirsten][]\n- *Mojolicious* by [Dotan Dimet][]\n- *AutoIt* by Manh Tuan from [J2TeaM][]\n- *Toml* (ini extension) by [Guillaume Gomez][]\n\nNew styles:\n\n- *Hopscotch* by [Jan T. Sott][]\n- *Grayscale* by [MY Sun][]\n\nNotable fixes and improvements to existing languages:\n\n- Fix encoding of images when copied over in certain builds\n- Fix incorrect highlighting of the word \"bug\" in comments\n- Treat decorators different from matrix multiplication in Python\n- Fix traits inheritance highlighting in Rust\n- Fix incorrect document\n- Oracle keywords added to SQL language definition by [Vadimtro][]\n- Postgres keywords added to SQL language definition by [Benjamin Auder][]\n- Fix registers in x86asm being highlighted as a hex number\n- Fix highlighting for numbers with a leading decimal point\n- Correctly highlight numbers and strings inside of C/C++ macros\n- C/C++ functions now support pointer, reference, and move returns\n\n[Oleg Efimov]: https://github.com/Sannis\n[Guillaume Gomez]: https://github.com/GuillaumeGomez\n[Janis Voigtländer]: https://github.com/jvoigtlaender\n[Jan T. Sott]: https://github.com/idleberg\n[Dirk Kirsten]: https://github.com/dirkk\n[MY Sun]: https://github.com/simonmysun\n[Vadimtro]: https://github.com/Vadimtro\n[Benjamin Auder]: https://github.com/ghost\n[Dotan Dimet]: https://github.com/dotandimet\n[J2TeaM]: https://github.com/J2TeaM\n\n\n## Version 8.6\n\nNew languages:\n\n- *C/AL* by [Kenneth Fuglsang][]\n- *DNS zone file* by [Tim Schumacher][]\n- *Ceylon* by [Lucas Werkmeister][]\n- *OpenSCAD* by [Dan Panzarella][]\n- *Inform7* by [Bruno Dias][]\n- *armasm* by [Dan Panzarella][]\n- *TP* by [Jay Strybis][]\n\nNew styles:\n\n- *Atelier Cave*, *Atelier Estuary*,\n  *Atelier Plateau* and *Atelier Savanna* by [Bram de Haan][]\n- *Github Gist* by [Louis Barranqueiro][]\n\nNotable fixes and improvements to existing languages:\n\n- Multi-line raw strings from C++11 are now supported\n- Fix class names with dashes in HAML\n- The `async` keyword from ES6/7 is now supported\n- TypeScript functions handle type and parameter complexity better\n- We unified phpdoc/javadoc/yardoc etc modes across all languages\n- CSS .class selectors relevance was dropped to prevent wrong language detection\n- Images is now included to CDN build\n- Release process is now automated\n\n[Bram de Haan]: https://github.com/atelierbram\n[Kenneth Fuglsang]: https://github.com/kfuglsang\n[Louis Barranqueiro]: https://github.com/LouisBarranqueiro\n[Tim Schumacher]: https://github.com/enko\n[Lucas Werkmeister]: https://github.com/lucaswerkmeister\n[Dan Panzarella]: https://github.com/pzl\n[Bruno Dias]: https://github.com/sequitur\n[Jay Strybis]: https://github.com/unreal\n\n\n## Version 8.5\n\nNew languages:\n\n- *pf.conf* by [Peter Piwowarski][]\n- *Julia* by [Kenta Sato][]\n- *Prolog* by [Raivo Laanemets][]\n- *Docker* by [Alexis Hénaut][]\n- *Fortran* by [Anthony Scemama][] and [Thomas Applencourt][]\n- *Kotlin* by [Sergey Mashkov][]\n\nNew styles:\n\n- *Agate* by [Taufik Nurrohman][]\n- *Darcula* by [JetBrains][]\n- *Atelier Sulphurpool* by [Bram de Haan][]\n- *Android Studio* by [Pedro Oliveira][]\n\nNotable fixes and improvements to existing languages:\n\n- ES6 features in JavaScript are better supported now by [Gu Yiling][].\n- Swift now recognizes body-less method definitions.\n- Single expression functions `def foo, do: ... ` now work in Elixir.\n- More uniform detection of built-in classes in Objective C.\n- Fixes for number literals and processor directives in Rust.\n- HTML `<script>` tag now allows any language, not just JavaScript.\n- Multi-line comments are supported now in MatLab.\n\n[Taufik Nurrohman]: https://github.com/tovic\n[Jet Brains]: https://www.jetbrains.com/\n[Peter Piwowarski]: https://github.com/oldlaptop\n[Kenta Sato]: https://github.com/bicycle1885\n[Bram de Haan]: https://github.com/atelierbram\n[Raivo Laanemets]: https://github.com/rla\n[Alexis Hénaut]: https://github.com/AlexisNo\n[Anthony Scemama]: https://github.com/scemama\n[Pedro Oliveira]: https://github.com/kanytu\n[Gu Yiling]: https://github.com/Justineo\n[Sergey Mashkov]: https://github.com/cy6erGn0m\n[Thomas Applencourt]: https://github.com/TApplencourt\n\n\n## Version 8.4\n\nWe've got the new [demo page][]! The obvious new feature is the new look, but\napart from that it's got smarter: by presenting languages in groups it avoids\nrunning 10000 highlighting attempts after first load which was slowing it down\nand giving bad overall impression. It is now also being generated from test\ncode snippets so the authors of new languages don't have to update both tests\nand the demo page with the same thing.\n\nOther notable changes:\n\n- The `template_comment` class is gone in favor of the more general `comment`.\n- Number parsing unified and improved across languages.\n- C++, Java and C# now use unified grammar to highlight titles in\n  function/method definitions.\n- The browser build is now usable as an AMD module, there's no separate build\n  target for that anymore.\n- OCaml has got a [comprehensive overhaul][ocaml] by [Mickaël Delahaye][].\n- Clojure's data structures and literals are now highlighted outside of lists\n  and we can now highlight Clojure's REPL sessions.\n\nNew languages:\n\n- *AspectJ* by [Hakan Özler][]\n- *STEP Part 21* by [Adam Joseph Cook][]\n- *SML* derived by [Edwin Dalorzo][] from OCaml definition\n- *Mercury* by [mucaho][]\n- *Smali* by [Dennis Titze][]\n- *Verilog* by [Jon Evans][]\n- *Stata* by [Brian Quistorff][]\n\n[Hakan Özler]: https://github.com/ozlerhakan\n[Adam Joseph Cook]: https://github.com/adamjcook\n[demo page]: https://highlightjs.org/static/demo/\n[Ivan Sagalaev]: https://github.com/isagalaev\n[Edwin Dalorzo]: https://github.com/edalorzo\n[mucaho]: https://github.com/mucaho\n[Dennis Titze]: https://github.com/titze\n[Jon Evans]: https://github.com/craftyjon\n[Brian Quistorff]: https://github.com/bquistorff\n[ocaml]: https://github.com/isagalaev/highlight.js/pull/608#issue-46190207\n[Mickaël Delahaye]: https://github.com/polazarus\n\n\n## Version 8.3\n\nWe streamlined our tool chain, it is now based entirely on node.js instead of\nbeing a mix of node.js, Python and Java. The build script options and arguments\nremained the same, and we've noted all the changes in the [documentation][b].\nApart from reducing complexity, the new build script is also faster from not\nhaving to start Java machine repeatedly. The credits for the work go to [Jeremy\nHull][].\n\nSome notable fixes:\n\n- PHP and JavaScript mixed in HTML now live happily with each other.\n- JavaScript regexes now understand ES6 flags \"u\" and \"y\".\n- `throw` keyword is no longer detected as a method name in Java.\n- Fixed parsing of numbers and symbols in Clojure thanks to [input from Ivan\n  Kleshnin][ik].\n\nNew languages in this release:\n\n- *Less* by [Max Mikhailov][]\n- *Stylus* by [Bryant Williams][]\n- *Tcl* by [Radek Liska][]\n- *Puppet* by [Jose Molina Colmenero][]\n- *Processing* by [Erik Paluka][]\n- *Twig* templates by [Luke Holder][]\n- *PowerShell* by [David Mohundro][], based on [the work of Nicholas Blumhardt][ps]\n- *XL* by [Christophe de Dinechin][]\n- *LiveScript* by [Taneli Vatanen][] and [Jen Evers-Corvina][]\n- *ERB* (Ruby in HTML) by [Lucas Mazza][]\n- *Roboconf* by [Vincent Zurczak][]\n\n[b]: http://highlightjs.readthedocs.org/en/latest/building-testing.html\n[Jeremy Hull]: https://github.com/sourrust\n[ik]: https://twitter.com/IvanKleshnin/status/514041599484231680\n[Max Mikhailov]: https://github.com/seven-phases-max\n[Bryant Williams]: https://github.com/scien\n[Radek Liska]: https://github.com/Nindaleth\n[Jose Molina Colmenero]: https://github.com/Moliholy\n[Erik Paluka]: https://github.com/paluka\n[Luke Holder]: https://github.com/lukeholder\n[David Mohundro]: https://github.com/drmohundro\n[ps]: https://github.com/OctopusDeploy/Library/blob/master/app/shared/presentation/highlighting/powershell.js\n[Christophe de Dinechin]: https://github.com/c3d\n[Taneli Vatanen]: https://github.com/Daiz-\n[Jen Evers-Corvina]: https://github.com/sevvie\n[Lucas Mazza]: https://github.com/lucasmazza\n[Vincent Zurczak]: https://github.com/vincent-zurczak\n\n\n## Version 8.2\n\nWe've finally got [real tests][test] and [continuous testing on Travis][ci]\nthanks to [Jeremy Hull][] and [Chris Eidhof][]. The tests designed to cover\neverything: language detection, correct parsing of individual language features\nand various special cases. This is a very important change that gives us\nconfidence in extending language definitions and refactoring library core.\n\nWe're going to redesign the old [demo/test suite][demo] into an interactive\ndemo web app. If you're confident front-end developer or designer and want to\nhelp us with it, drop a comment into [the issue][#542] on GitHub.\n\n[test]: https://github.com/isagalaev/highlight.js/tree/master/test\n[demo]: https://highlightjs.org/static/test.html\n[#542]: https://github.com/isagalaev/highlight.js/issues/542\n[ci]: https://travis-ci.org/isagalaev/highlight.js\n[Jeremy Hull]: https://github.com/sourrust\n[Chris Eidhof]: https://github.com/chriseidhof\n\nAs usually there's a handful of new languages in this release:\n\n- *Groovy* by [Guillaume Laforge][]\n- *Dart* by [Maxim Dikun][]\n- *Dust* by [Michael Allen][]\n- *Scheme* by [JP Verkamp][]\n- *G-Code* by [Adam Joseph Cook][]\n- *Q* from Kx Systems by [Sergey Vidyuk][]\n\n[Guillaume Laforge]: https://github.com/glaforge\n[Maxim Dikun]: https://github.com/dikmax\n[Michael Allen]: https://github.com/bfui\n[JP Verkamp]: https://github.com/jpverkamp\n[Adam Joseph Cook]: https://github.com/adamjcook\n[Sergey Vidyuk]: https://github.com/sv\n\nOther improvements:\n\n- [Erik Osheim][] heavily reworked Scala definitions making it richer.\n- [Lucas Mazza][] fixed Ruby hashes highlighting\n- Lisp variants (Lisp, Clojure and Scheme) are unified in regard to naming\n  the first symbol in parentheses: it's \"keyword\" in general case and also\n  \"built_in\" for built-in functions in Clojure and Scheme.\n\n[Erik Osheim]: https://github.com/non\n[Lucas Mazza]: https://github.com/lucasmazza\n\n\n## Version 8.1\n\nNew languages:\n\n- *Gherkin* by [Sam Pikesley][]\n- *Elixir* by [Josh Adams][]\n- *NSIS* by [Jan T. Sott][]\n- *VIM script* by [Jun Yang][]\n- *Protocol Buffers* by [Dan Tao][]\n- *Nix* by [Domen Kožar][]\n- *x86asm* by [innocenat][]\n- *Cap’n Proto* and *Thrift* by [Oleg Efimov][]\n- *Monkey* by [Arthur Bikmullin][]\n- *TypeScript* by [Panu Horsmalahti][]\n- *Nimrod* by [Flaviu Tamas][]\n- *Gradle* by [Damian Mee][]\n- *Haxe* by [Christopher Kaster][]\n- *Swift* by [Chris Eidhof][] and [Nate Cook][]\n\nNew styles:\n\n- *Kimbie*, light and dark variants by [Jan T. Sott][]\n- *Color brewer* by [Fabrício Tavares de Oliveira][]\n- *Codepen.io embed* by [Justin Perry][]\n- *Hybrid* by [Nic West][]\n\n[Sam Pikesley]: https://github.com/pikesley\n[Sindre Sorhus]: https://github.com/sindresorhus\n[Josh Adams]: https://github.com/knewter\n[Jan T. Sott]: https://github.com/idleberg\n[Jun Yang]: https://github.com/harttle\n[Dan Tao]: https://github.com/dtao\n[Domen Kožar]: https://github.com/iElectric\n[innocenat]: https://github.com/innocenat\n[Oleg Efimov]: https://github.com/Sannis\n[Arthur Bikmullin]: https://github.com/devolonter\n[Panu Horsmalahti]: https://github.com/panuhorsmalahti\n[Flaviu Tamas]: https://github.com/flaviut\n[Damian Mee]: https://github.com/chester1000\n[Christopher Kaster]: http://christopher.kaster.ws\n[Fabrício Tavares de Oliveira]: https://github.com/fabriciotav\n[Justin Perry]: https://github.com/ourmaninamsterdam\n[Nic West]: https://github.com/nicwest\n[Chris Eidhof]: https://github.com/chriseidhof\n[Nate Cook]: https://github.com/natecook1000\n\nOther improvements:\n\n- The README is heavily reworked and brought up to date by [Jeremy Hull][].\n- Added [`listLanguages()`][ll] method in the API.\n- Improved C/C++/C# detection.\n- Added a bunch of new language aliases, documented the existing ones. Thanks to\n  [Sindre Sorhus][] for background research.\n- Added phrasal English words to boost relevance in comments.\n- Many improvements to SQL definition made by [Heiko August][],\n  [Nikolay Lisienko][] and [Travis Odom][].\n- The shorter `lang-` prefix for language names in HTML classes supported\n  alongside `language-`. Thanks to [Jeff Escalante][].\n- Ruby's got support for interactive console sessions. Thanks to\n  [Pascal Hurni][].\n- Added built-in functions for R language. Thanks to [Artem A. Klevtsov][].\n- Rust's got definition for lifetime parameters and improved string syntax.\n  Thanks to [Roman Shmatov][].\n- Various improvements to Objective-C definition by [Matt Diephouse][].\n- Fixed highlighting of generics in Java.\n\n[ll]: http://highlightjs.readthedocs.org/en/latest/api.html#listlanguages\n[Sindre Sorhus]: https://github.com/sindresorhus\n[Heiko August]: https://github.com/auge8472\n[Nikolay Lisienko]: https://github.com/neor-ru\n[Travis Odom]: https://github.com/Burstaholic\n[Jeff Escalante]: https://github.com/jenius\n[Pascal Hurni]: https://github.com/phurni\n[Jiyin Yiyong]: https://github.com/jiyinyiyong\n[Artem A. Klevtsov]: https://github.com/unikum\n[Roman Shmatov]: https://github.com/shmatov\n[Jeremy Hull]: https://github.com/sourrust\n[Matt Diephouse]: https://github.com/mdiep\n\n\n## Version 8.0\n\nThis new major release is quite a big overhaul bringing both new features and\nsome backwards incompatible changes. However, chances are that the majority of\nusers won't be affected by the latter: the basic scenario described in the\nREADME is left intact.\n\nHere's what did change in an incompatible way:\n\n- We're now prefixing all classes located in [CSS classes reference][cr] with\n  `hljs-`, by default, because some class names would collide with other\n  people's stylesheets. If you were using an older version, you might still want\n  the previous behavior, but still want to upgrade. To suppress this new\n  behavior, you would initialize like so:\n\n  ```html\n  <script type=\"text/javascript\">\n    hljs.configure({classPrefix: ''});\n    hljs.initHighlightingOnLoad();\n  </script>\n  ```\n\n- `tabReplace` and `useBR` that were used in different places are also unified\n  into the global options object and are to be set using `configure(options)`.\n  This function is documented in our [API docs][]. Also note that these\n  parameters are gone from `highlightBlock` and `fixMarkup` which are now also\n  rely on `configure`.\n\n- We removed public-facing (though undocumented) object `hljs.LANGUAGES` which\n  was used to register languages with the library in favor of two new methods:\n  `registerLanguage` and `getLanguage`. Both are documented in our [API docs][].\n\n- Result returned from `highlight` and `highlightAuto` no longer contains two\n  separate attributes contributing to relevance score, `relevance` and\n  `keyword_count`. They are now unified in `relevance`.\n\nAnother technically compatible change that nonetheless might need attention:\n\n- The structure of the NPM package was refactored, so if you had installed it\n  locally, you'll have to update your paths. The usual `require('highlight.js')`\n  works as before. This is contributed by [Dmitry Smolin][].\n\nNew features:\n\n- Languages now can be recognized by multiple names like \"js\" for JavaScript or\n  \"html\" for, well, HTML (which earlier insisted on calling it \"xml\"). These\n  aliases can be specified in the class attribute of the code container in your\n  HTML as well as in various API calls. For now there are only a few very common\n  aliases but we'll expand it in the future. All of them are listed in the\n  [class reference][cr].\n\n- Language detection can now be restricted to a subset of languages relevant in\n  a given context — a web page or even a single highlighting call. This is\n  especially useful for node.js build that includes all the known languages.\n  Another example is a StackOverflow-style site where users specify languages\n  as tags rather than in the markdown-formatted code snippets. This is\n  documented in the [API reference][] (see methods `highlightAuto` and\n  `configure`).\n\n- Language definition syntax streamlined with [variants][] and\n  [beginKeywords][].\n\nNew languages and styles:\n\n- *Oxygene* by [Carlo Kok][]\n- *Mathematica* by [Daniel Kvasnička][]\n- *Autohotkey* by [Seongwon Lee][]\n- *Atelier* family of styles in 10 variants by [Bram de Haan][]\n- *Paraíso* styles by [Jan T. Sott][]\n\nMiscellaneous improvements:\n\n- Highlighting `=>` prompts in Clojure.\n- [Jeremy Hull][] fixed a lot of styles for consistency.\n- Finally, highlighting PHP and HTML [mixed in peculiar ways][php-html].\n- Objective C and C# now properly highlight titles in method definition.\n- Big overhaul of relevance counting for a number of languages. Please do report\n  bugs about mis-detection of non-trivial code snippets!\n\n[API reference]: http://highlightjs.readthedocs.org/en/latest/api.html\n\n[cr]: http://highlightjs.readthedocs.org/en/latest/css-classes-reference.html\n[api docs]: http://highlightjs.readthedocs.org/en/latest/api.html\n[variants]: https://groups.google.com/d/topic/highlightjs/VoGC9-1p5vk/discussion\n[beginKeywords]: https://github.com/isagalaev/highlight.js/commit/6c7fdea002eb3949577a85b3f7930137c7c3038d\n[php-html]: https://twitter.com/highlightjs/status/408890903017689088\n\n[Carlo Kok]: https://github.com/carlokok\n[Bram de Haan]: https://github.com/atelierbram\n[Daniel Kvasnička]: https://github.com/dkvasnicka\n[Dmitry Smolin]: https://github.com/dimsmol\n[Jeremy Hull]: https://github.com/sourrust\n[Seongwon Lee]: https://github.com/dlimpid\n[Jan T. Sott]: https://github.com/idleberg\n\n\n## Version 7.5\n\nA catch-up release dealing with some of the accumulated contributions. This one\nis probably will be the last before the 8.0 which will be slightly backwards\nincompatible regarding some advanced use-cases.\n\nOne outstanding change in this version is the addition of 6 languages to the\n[hosted script][d]: Markdown, ObjectiveC, CoffeeScript, Apache, Nginx and\nMakefile. It now weighs about 6K more but we're going to keep it under 30K.\n\nNew languages:\n\n- OCaml by [Mehdi Dogguy][mehdid] and [Nicolas Braud-Santoni][nbraud]\n- [LiveCode Server][lcs] by [Ralf Bitter][revig]\n- Scilab by [Sylvestre Ledru][sylvestre]\n- basic support for Makefile by [Ivan Sagalaev][isagalaev]\n\nImprovements:\n\n- Ruby's got support for characters like `?A`, `?1`, `?\\012` etc. and `%r{..}`\n  regexps.\n- Clojure now allows a function call in the beginning of s-expressions\n  `(($filter \"myCount\") (arr 1 2 3 4 5))`.\n- Haskell's got new keywords and now recognizes more things like pragmas,\n  preprocessors, modules, containers, FFIs etc. Thanks to [Zena Treep][treep]\n  for the implementation and to [Jeremy Hull][sourrust] for guiding it.\n- Miscellaneous fixes in PHP, Brainfuck, SCSS, Asciidoc, CMake, Python and F#.\n\n[mehdid]: https://github.com/mehdid\n[nbraud]: https://github.com/nbraud\n[revig]: https://github.com/revig\n[lcs]: http://livecode.com/developers/guides/server/\n[sylvestre]: https://github.com/sylvestre\n[isagalaev]: https://github.com/isagalaev\n[treep]: https://github.com/treep\n[sourrust]: https://github.com/sourrust\n[d]: http://highlightjs.org/download/\n\n\n## New core developers\n\nThe latest long period of almost complete inactivity in the project coincided\nwith growing interest to it led to a decision that now seems completely obvious:\nwe need more core developers.\n\nSo without further ado let me welcome to the core team two long-time\ncontributors: [Jeremy Hull][] and [Oleg\nEfimov][].\n\nHope now we'll be able to work through stuff faster!\n\nP.S. The historical commit is [here][1] for the record.\n\n[Jeremy Hull]: https://github.com/sourrust\n[Oleg Efimov]: https://github.com/sannis\n[1]: https://github.com/isagalaev/highlight.js/commit/f3056941bda56d2b72276b97bc0dd5f230f2473f\n\n\n## Version 7.4\n\nThis long overdue version is a snapshot of the current source tree with all the\nchanges that happened during the past year. Sorry for taking so long!\n\nAlong with the changes in code highlight.js has finally got its new home at\n<http://highlightjs.org/>, moving from its cradle on Software Maniacs which it\noutgrew a long time ago. Be sure to report any bugs about the site to\n<mailto:info@highlightjs.org>.\n\nOn to what's new…\n\nNew languages:\n\n- Handlebars templates by [Robin Ward][]\n- Oracle Rules Language by [Jason Jacobson][]\n- F# by [Joans Follesø][]\n- AsciiDoc and Haml by [Dan Allen][]\n- Lasso by [Eric Knibbe][]\n- SCSS by [Kurt Emch][]\n- VB.NET by [Poren Chiang][]\n- Mizar by [Kelley van Evert][]\n\n[Robin Ward]: https://github.com/eviltrout\n[Jason Jacobson]: https://github.com/jayce7\n[Joans Follesø]: https://github.com/follesoe\n[Dan Allen]: https://github.com/mojavelinux\n[Eric Knibbe]: https://github.com/EricFromCanada\n[Kurt Emch]: https://github.com/kemch\n[Poren Chiang]: https://github.com/rschiang\n[Kelley van Evert]: https://github.com/kelleyvanevert\n\nNew style themes:\n\n- Monokai Sublime by [noformnocontent][]\n- Railscasts by [Damien White][]\n- Obsidian by [Alexander Marenin][]\n- Docco by [Simon Madine][]\n- Mono Blue by [Ivan Sagalaev][] (uses a single color hue for everything)\n- Foundation by [Dan Allen][]\n\n[noformnocontent]: http://nn.mit-license.org/\n[Damien White]: https://github.com/visoft\n[Alexander Marenin]: https://github.com/ioncreature\n[Simon Madine]: https://github.com/thingsinjars\n[Ivan Sagalaev]: https://github.com/isagalaev\n\nOther notable changes:\n\n- Corrected many corner cases in CSS.\n- Dropped Python 2 version of the build tool.\n- Implemented building for the AMD format.\n- Updated Rust keywords (thanks to [Dmitry Medvinsky][]).\n- Literal regexes can now be used in language definitions.\n- CoffeeScript highlighting is now significantly more robust and rich due to\n  input from [Cédric Néhémie][].\n\n[Dmitry Medvinsky]: https://github.com/dmedvinsky\n[Cédric Néhémie]: https://github.com/abe33\n\n\n## Version 7.3\n\n- Since this version highlight.js no longer works in IE version 8 and older.\n  It's made it possible to reduce the library size and dramatically improve code\n  readability and made it easier to maintain. Time to go forward!\n\n- New languages: AppleScript (by [Nathan Grigg][ng] and [Dr. Drang][dd]) and\n  Brainfuck (by [Evgeny Stepanischev][bolk]).\n\n- Improvements to existing languages:\n\n    - interpreter prompt in Python (`>>>` and `...`)\n    - @-properties and classes in CoffeeScript\n    - E4X in JavaScript (by [Oleg Efimov][oe])\n    - new keywords in Perl (by [Kirk Kimmel][kk])\n    - big Ruby syntax update (by [Vasily Polovnyov][vast])\n    - small fixes in Bash\n\n- Also Oleg Efimov did a great job of moving all the docs for language and style\n  developers and contributors from the old wiki under the source code in the\n  \"docs\" directory. Now these docs are nicely presented at\n  <http://highlightjs.readthedocs.org/>.\n\n[ng]: https://github.com/nathan11g\n[dd]: https://github.com/drdrang\n[bolk]: https://github.com/bolknote\n[oe]: https://github.com/Sannis\n[kk]: https://github.com/kimmel\n[vast]: https://github.com/vast\n\n\n## Version 7.2\n\nA regular bug-fix release without any significant new features. Enjoy!\n\n\n## Version 7.1\n\nA Summer crop:\n\n- [Marc Fornos][mf] made the definition for Clojure along with the matching\n  style Rainbow (which, of course, works for other languages too).\n- CoffeeScript support continues to improve getting support for regular\n  expressions.\n- Yoshihide Jimbo ported to highlight.js [five Tomorrow styles][tm] from the\n  [project by Chris Kempson][tm0].\n- Thanks to [Casey Duncun][cd] the library can now be built in the popular\n  [AMD format][amd].\n- And last but not least, we've got a fair number of correctness and consistency\n  fixes, including a pretty significant refactoring of Ruby.\n\n[mf]: https://github.com/mfornos\n[tm]: http://jmblog.github.com/color-themes-for-highlightjs/\n[tm0]: https://github.com/ChrisKempson/Tomorrow-Theme\n[cd]: https://github.com/caseman\n[amd]: http://requirejs.org/docs/whyamd.html\n\n\n## Version 7.0\n\nThe reason for the new major version update is a global change of keyword syntax\nwhich resulted in the library getting smaller once again. For example, the\nhosted build is 2K less than at the previous version while supporting two new\nlanguages.\n\nNotable changes:\n\n- The library now works not only in a browser but also with [node.js][]. It is\n  installable with `npm install highlight.js`. [API][] docs are available on our\n  wiki.\n\n- The new unique feature (apparently) among syntax highlighters is highlighting\n  *HTTP* headers and an arbitrary language in the request body. The most useful\n  languages here are *XML* and *JSON* both of which highlight.js does support.\n  Here's [the detailed post][p] about the feature.\n\n- Two new style themes: a dark \"south\" *[Pojoaque][]* by Jason Tate and an\n  emulation of*XCode* IDE by [Angel Olloqui][ao].\n\n- Three new languages: *D* by [Aleksandar Ružičić][ar], *R* by [Joe Cheng][jc]\n  and *GLSL* by [Sergey Tikhomirov][st].\n\n- *Nginx* syntax has become a million times smaller and more universal thanks to\n  remaking it in a more generic manner that doesn't require listing all the\n  directives in the known universe.\n\n- Function titles are now highlighted in *PHP*.\n\n- *Haskell* and *VHDL* were significantly reworked to be more rich and correct\n  by their respective maintainers [Jeremy Hull][sr] and [Igor Kalnitsky][ik].\n\nAnd last but not least, many bugs have been fixed around correctness and\nlanguage detection.\n\nOverall highlight.js currently supports 51 languages and 20 style themes.\n\n[node.js]: http://nodejs.org/\n[api]: http://softwaremaniacs.org/wiki/doku.php/highlight.js:api\n[p]: http://softwaremaniacs.org/blog/2012/05/10/http-and-json-in-highlight-js/en/\n[pojoaque]: http://web-cms-designs.com/ftopict-10-pojoaque-style-for-highlight-js-code-highlighter.html\n[ao]: https://github.com/angelolloqui\n[ar]: https://github.com/raleksandar\n[jc]: https://github.com/jcheng5\n[st]: https://github.com/tikhomirov\n[sr]: https://github.com/sourrust\n[ik]: https://github.com/ikalnitsky\n\n\n## Version 6.2\n\nA lot of things happened in highlight.js since the last version! We've got nine\nnew contributors, the discussion group came alive, and the main branch on GitHub\nnow counts more than 350 followers. Here are most significant results coming\nfrom all this activity:\n\n- 5 (five!) new languages: Rust, ActionScript, CoffeeScript, MatLab and\n  experimental support for markdown. Thanks go to [Andrey Vlasovskikh][av],\n  [Alexander Myadzel][am], [Dmytrii Nagirniak][dn], [Oleg Efimov][oe], [Denis\n  Bardadym][db] and [John Crepezzi][jc].\n\n- 2 new style themes: Monokai by [Luigi Maselli][lm] and stylistic imitation of\n  another well-known highlighter Google Code Prettify by [Aahan Krish][ak].\n\n- A vast number of [correctness fixes and code refactorings][log], mostly made\n  by [Oleg Efimov][oe] and [Evgeny Stepanischev][es].\n\n[av]: https://github.com/vlasovskikh\n[am]: https://github.com/myadzel\n[dn]: https://github.com/dnagir\n[oe]: https://github.com/Sannis\n[db]: https://github.com/btd\n[jc]: https://github.com/seejohnrun\n[lm]: http://grigio.org/\n[ak]: https://github.com/geekpanth3r\n[es]: https://github.com/bolknote\n[log]: https://github.com/isagalaev/highlight.js/commits/\n\n\n## Version 6.1 — Solarized\n\n[Jeremy Hull][jh] has implemented my dream feature — a port of [Solarized][]\nstyle theme famous for being based on the intricate color theory to achieve\ncorrect contrast and color perception. It is now available for highlight.js in\nboth variants — light and dark.\n\nThis version also adds a new original style Arta. Its author pumbur maintains a\n[heavily modified fork of highlight.js][pb] on GitHub.\n\n[jh]: https://github.com/sourrust\n[solarized]: http://ethanschoonover.com/solarized\n[pb]: https://github.com/pumbur/highlight.js\n\n\n## Version 6.0\n\nNew major version of the highlighter has been built on a significantly\nrefactored syntax. Due to this it's even smaller than the previous one while\nsupporting more languages!\n\nNew languages are:\n\n- Haskell by [Jeremy Hull][sourrust]\n- Erlang in two varieties — module and REPL — made collectively by [Nikolay\n  Zakharov][desh], [Dmitry Kovega][arhibot] and [Sergey Ignatov][ignatov]\n- Objective C by [Valerii Hiora][vhbit]\n- Vala by [Antono Vasiljev][antono]\n- Go by [Stephan Kountso][steplg]\n\n[sourrust]: https://github.com/sourrust\n[desh]: http://desh.su/\n[arhibot]: https://github.com/arhibot\n[ignatov]: https://github.com/ignatov\n[vhbit]: https://github.com/vhbit\n[antono]: https://github.com/antono\n[steplg]: https://github.com/steplg\n\nAlso this version is marginally faster and fixes a number of small long-standing\nbugs.\n\nDeveloper overview of the new language syntax is available in a [blog post about\nrecent beta release][beta].\n\n[beta]: http://softwaremaniacs.org/blog/2011/04/25/highlight-js-60-beta/en/\n\nP.S. New version is not yet available on a Yandex CDN, so for now you have to\ndownload [your own copy][d].\n\n[d]: /soft/highlight/en/download/\n\n\n## Version 5.14\n\nFixed bugs in HTML/XML detection and relevance introduced in previous\nrefactoring.\n\nAlso test.html now shows the second best result of language detection by\nrelevance.\n\n\n## Version 5.13\n\nPast weekend began with a couple of simple additions for existing languages but\nended up in a big code refactoring bringing along nice improvements for language\ndevelopers.\n\n### For users\n\n- Description of C++ has got new keywords from the upcoming [C++ 0x][] standard.\n- Description of HTML has got new tags from [HTML 5][].\n- CSS-styles have been unified to use consistent padding and also have lost\n  pop-outs with names of detected languages.\n- [Igor Kalnitsky][ik] has sent two new language descriptions: CMake & VHDL.\n\nThis makes total number of languages supported by highlight.js to reach 35.\n\nBug fixes:\n\n- Custom classes on `<pre>` tags are not being overridden anymore\n- More correct highlighting of code blocks inside non-`<pre>` containers:\n  highlighter now doesn't insist on replacing them with its own container and\n  just replaces the contents.\n- Small fixes in browser compatibility and heuristics.\n\n[c++ 0x]: http://ru.wikipedia.org/wiki/C%2B%2B0x\n[html 5]: http://en.wikipedia.org/wiki/HTML5\n[ik]: http://kalnitsky.org.ua/\n\n### For developers\n\nThe most significant change is the ability to include language submodes right\nunder `contains` instead of defining explicit named submodes in the main array:\n\n    contains: [\n      'string',\n      'number',\n      {begin: '\\\\n', end: hljs.IMMEDIATE_RE}\n    ]\n\nThis is useful for auxiliary modes needed only in one place to define parsing.\nNote that such modes often don't have `className` and hence won't generate a\nseparate `<span>` in the resulting markup. This is similar in effect to\n`noMarkup: true`. All existing languages have been refactored accordingly.\n\nTest file test.html has at last become a real test. Now it not only puts the\ndetected language name under the code snippet but also tests if it matches the\nexpected one. Test summary is displayed right above all language snippets.\n\n\n## CDN\n\nFine people at [Yandex][] agreed to host highlight.js on their big fast servers.\n[Link up][l]!\n\n[yandex]: http://yandex.com/\n[l]: http://softwaremaniacs.org/soft/highlight/en/download/\n\n\n## Version 5.10 — \"Paris\".\n\nThough I'm on a vacation in Paris, I decided to release a new version with a\ncouple of small fixes:\n\n- Tomas Vitvar discovered that TAB replacement doesn't always work when used\n  with custom markup in code\n- SQL parsing is even more rigid now and doesn't step over SmallTalk in tests\n\n\n## Version 5.9\n\nA long-awaited version is finally released.\n\nNew languages:\n\n- Andrew Fedorov made a definition for Lua\n- a long-time highlight.js contributor [Peter Leonov][pl] made a definition for\n  Nginx config\n- [Vladimir Moskva][vm] made a definition for TeX\n\n[pl]: http://kung-fu-tzu.ru/\n[vm]: http://fulc.ru/\n\nFixes for existing languages:\n\n- [Loren Segal][ls] reworked the Ruby definition and added highlighting for\n  [YARD][] inline documentation\n- the definition of SQL has become more solid and now it shouldn't be overly\n  greedy when it comes to language detection\n\n[ls]: http://gnuu.org/\n[yard]: http://yardoc.org/\n\nThe highlighter has become more usable as a library allowing to do highlighting\nfrom initialization code of JS frameworks and in ajax methods (see.\nreadme.eng.txt).\n\nAlso this version drops support for the [WordPress][wp] plugin. Everyone is\nwelcome to [pick up its maintenance][p] if needed.\n\n[wp]: http://wordpress.org/\n[p]: http://bazaar.launchpad.net/~isagalaev/+junk/highlight/annotate/342/src/wp_highlight.js.php\n\n\n## Version 5.8\n\n- Jan Berkel has contributed a definition for Scala. +1 to hotness!\n- All CSS-styles are rewritten to work only inside `<pre>` tags to avoid\n  conflicts with host site styles.\n\n\n## Version 5.7.\n\nFixed escaping of quotes in VBScript strings.\n\n\n## Version 5.5\n\nThis version brings a small change: now .ini-files allow digits, underscores and\nsquare brackets in key names.\n\n\n## Version 5.4\n\nFixed small but upsetting bug in the packer which caused incorrect highlighting\nof explicitly specified languages. Thanks to Andrew Fedorov for precise\ndiagnostics!\n\n\n## Version 5.3\n\nThe version to fulfil old promises.\n\nThe most significant change is that highlight.js now preserves custom user\nmarkup in code along with its own highlighting markup. This means that now it's\npossible to use, say, links in code. Thanks to [Vladimir Dolzhenko][vd] for the\n[initial proposal][1] and for making a proof-of-concept patch.\n\nAlso in this version:\n\n- [Vasily Polovnyov][vp] has sent a GitHub-like style and has implemented\n  support for CSS @-rules and Ruby symbols.\n- Yura Zaripov has sent two styles: Brown Paper and School Book.\n- Oleg Volchkov has sent a definition for [Parser 3][p3].\n\n[1]: http://softwaremaniacs.org/forum/highlightjs/6612/\n[p3]: http://www.parser.ru/\n[vp]: http://vasily.polovnyov.ru/\n[vd]: http://dolzhenko.blogspot.com/\n\n\n## Version 5.2\n\n- at last it's possible to replace indentation TABs with something sensible\n  (e.g. 2 or 4 spaces)\n- new keywords and built-ins for 1C by Sergey Baranov\n- a couple of small fixes to Apache highlighting\n\n\n## Version 5.1\n\nThis is one of those nice version consisting entirely of new and shiny\ncontributions!\n\n- [Vladimir Ermakov][vooon] created highlighting for AVR Assembler\n- [Ruslan Keba][rukeba] created highlighting for Apache config file. Also his\n  original visual style for it is now available for all highlight.js languages\n  under the name \"Magula\".\n- [Shuen-Huei Guan][drake] (aka Drake) sent new keywords for RenderMan\n  languages. Also thanks go to [Konstantin Evdokimenko][ke] for his advice on\n  the matter.\n\n[vooon]: http://vehq.ru/about/\n[rukeba]: http://rukeba.com/\n[drake]: http://drakeguan.org/\n[ke]: http://k-evdokimenko.moikrug.ru/\n\n\n## Version 5.0\n\nThe main change in the new major version of highlight.js is a mechanism for\npacking several languages along with the library itself into a single compressed\nfile. Now sites using several languages will load considerably faster because\nthe library won't dynamically include additional files while loading.\n\nAlso this version fixes a long-standing bug with Javascript highlighting that\ncouldn't distinguish between regular expressions and division operations.\n\nAnd as usually there were a couple of minor correctness fixes.\n\nGreat thanks to all contributors! Keep using highlight.js.\n\n\n## Version 4.3\n\nThis version comes with two contributions from [Jason Diamond][jd]:\n\n- language definition for C# (yes! it was a long-missed thing!)\n- Visual Studio-like highlighting style\n\nPlus there are a couple of minor bug fixes for parsing HTML and XML attributes.\n\n[jd]: http://jason.diamond.name/weblog/\n\n\n## Version 4.2\n\nThe biggest news is highlighting for Lisp, courtesy of Vasily Polovnyov. It's\nsomewhat experimental meaning that for highlighting \"keywords\" it doesn't use\nany pre-defined set of a Lisp dialect. Instead it tries to highlight first word\nin parentheses wherever it makes sense. I'd like to ask people programming in\nLisp to confirm if it's a good idea and send feedback to [the forum][f].\n\nOther changes:\n\n- Smalltalk was excluded from DEFAULT_LANGUAGES to save traffic\n- [Vladimir Epifanov][voldmar] has implemented javascript style switcher for\n  test.html\n- comments now allowed inside Ruby function definition\n- [MEL][] language from [Shuen-Huei Guan][drake]\n- whitespace now allowed between `<pre>` and `<code>`\n- better auto-detection of C++ and PHP\n- HTML allows embedded VBScript (`<% .. %>`)\n\n[f]: http://softwaremaniacs.org/forum/highlightjs/\n[voldmar]: http://voldmar.ya.ru/\n[mel]: http://en.wikipedia.org/wiki/Maya_Embedded_Language\n[drake]: http://drakeguan.org/\n\n\n## Version 4.1\n\nLanguages:\n\n- Bash from Vah\n- DOS bat-files from Alexander Makarov (Sam)\n- Diff files from Vasily Polovnyov\n- Ini files from myself though initial idea was from Sam\n\nStyles:\n\n- Zenburn from Vladimir Epifanov, this is an imitation of a\n  [well-known theme for Vim][zenburn].\n- Ascetic from myself, as a realization of ideals of non-flashy highlighting:\n  just one color in only three gradations :-)\n\nIn other news. [One small bug][bug] was fixed, built-in keywords were added for\nPython and C++ which improved auto-detection for the latter (it was shame that\n[my wife's blog][alenacpp] had issues with it from time to time). And lastly\nthanks go to Sam for getting rid of my stylistic comments in code that were\ngetting in the way of [JSMin][].\n\n[zenburn]: http://en.wikipedia.org/wiki/Zenburn\n[alenacpp]: http://alenacpp.blogspot.com/\n[bug]: http://softwaremaniacs.org/forum/viewtopic.php?id=1823\n[jsmin]: http://code.google.com/p/jsmin-php/\n\n\n## Version 4.0\n\nNew major version is a result of vast refactoring and of many contributions.\n\nVisible new features:\n\n- Highlighting of embedded languages. Currently is implemented highlighting of\n  Javascript and CSS inside HTML.\n- Bundled 5 ready-made style themes!\n\nInvisible new features:\n\n- Highlight.js no longer pollutes global namespace. Only one object and one\n  function for backward compatibility.\n- Performance is further increased by about 15%.\n\nChanging of a major version number caused by a new format of language definition\nfiles. If you use some third-party language files they should be updated.\n\n\n## Version 3.5\n\nA very nice version in my opinion fixing a number of small bugs and slightly\nincreased speed in a couple of corner cases. Thanks to everybody who reports\nbugs in he [forum][f] and by email!\n\nThere is also a new language — XML. A custom XML formerly was detected as HTML\nand didn't highlight custom tags. In this version I tried to make custom XML to\nbe detected and highlighted by its own rules. Which by the way include such\nthings as CDATA sections and processing instructions (`<? ... ?>`).\n\n[f]: http://softwaremaniacs.org/forum/viewforum.php?id=6\n\n\n## Version 3.3\n\n[Vladimir Gubarkov][xonix] has provided an interesting and useful addition.\nFile export.html contains a little program that shows and allows to copy and\npaste an HTML code generated by the highlighter for any code snippet. This can\nbe useful in situations when one can't use the script itself on a site.\n\n\n[xonix]: http://xonixx.blogspot.com/\n\n\n## Version 3.2 consists completely of contributions:\n\n- Vladimir Gubarkov has described SmallTalk\n- Yuri Ivanov has described 1C\n- Peter Leonov has packaged the highlighter as a Firefox extension\n- Vladimir Ermakov has compiled a mod for phpBB\n\nMany thanks to you all!\n\n\n## Version 3.1\n\nThree new languages are available: Django templates, SQL and Axapta. The latter\ntwo are sent by [Dmitri Roudakov][1]. However I've almost entirely rewrote an\nSQL definition but I'd never started it be it from the ground up :-)\n\nThe engine itself has got a long awaited feature of grouping keywords\n(\"keyword\", \"built-in function\", \"literal\"). No more hacks!\n\n[1]: http://roudakov.ru/\n\n\n## Version 3.0\n\nIt is major mainly because now highlight.js has grown large and has become\nmodular. Now when you pass it a list of languages to highlight it will\ndynamically load into a browser only those languages.\n\nAlso:\n\n- Konstantin Evdokimenko of [RibKit][] project has created a highlighting for\n  RenderMan Shading Language and RenderMan Interface Bytestream. Yay for more\n  languages!\n- Heuristics for C++ and HTML got better.\n- I've implemented (at last) a correct handling of backslash escapes in C-like\n  languages.\n\nThere is also a small backwards incompatible change in the new version. The\nfunction initHighlighting that was used to initialize highlighting instead of\ninitHighlightingOnLoad a long time ago no longer works. If you by chance still\nuse it — replace it with the new one.\n\n[RibKit]: http://ribkit.sourceforge.net/\n\n\n## Version 2.9\n\nHighlight.js is a parser, not just a couple of regular expressions. That said\nI'm glad to announce that in the new version 2.9 has support for:\n\n- in-string substitutions for Ruby -- `#{...}`\n- strings from from numeric symbol codes (like #XX) for Delphi\n\n\n## Version 2.8\n\nA maintenance release with more tuned heuristics. Fully backwards compatible.\n\n\n## Version 2.7\n\n- Nikita Ledyaev presents highlighting for VBScript, yay!\n- A couple of bugs with escaping in strings were fixed thanks to Mickle\n- Ongoing tuning of heuristics\n\nFixed bugs were rather unpleasant so I encourage everyone to upgrade!\n\n\n## Version 2.4\n\n- Peter Leonov provides another improved highlighting for Perl\n- Javascript gets a new kind of keywords — \"literals\". These are the words\n  \"true\", \"false\" and \"null\"\n\nAlso highlight.js homepage now lists sites that use the library. Feel free to\nadd your site by [dropping me a message][mail] until I find the time to build a\nsubmit form.\n\n[mail]: mailto:Maniac@SoftwareManiacs.Org\n\n\n## Version 2.3\n\nThis version fixes IE breakage in previous version. My apologies to all who have\nalready downloaded that one!\n\n\n## Version 2.2\n\n- added highlighting for Javascript\n- at last fixed parsing of Delphi's escaped apostrophes in strings\n- in Ruby fixed highlighting of keywords 'def' and 'class', same for 'sub' in\n  Perl\n\n\n## Version 2.0\n\n- Ruby support by [Anton Kovalyov][ak]\n- speed increased by orders of magnitude due to new way of parsing\n- this same way allows now correct highlighting of keywords in some tricky\n  places (like keyword \"End\" at the end of Delphi classes)\n\n[ak]: http://anton.kovalyov.net/\n\n\n## Version 1.0\n\nVersion 1.0 of javascript syntax highlighter is released!\n\nIt's the first version available with English description. Feel free to post\nyour comments and question to [highlight.js forum][forum]. And don't be afraid\nif you find there some fancy Cyrillic letters -- it's for Russian users too :-)\n\n[forum]: http://softwaremaniacs.org/forum/viewforum.php?id=6\n"
  },
  {
    "path": "lib/highlight/LICENSE",
    "content": "Copyright (c) 2006, Ivan Sagalaev\nAll rights reserved.\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    * Neither the name of highlight.js nor the names of its contributors \n      may be used to endorse or promote products derived from this software \n      without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "lib/highlight/README.md",
    "content": "# Highlight.js\n\n[![Build Status](https://travis-ci.org/isagalaev/highlight.js.svg?branch=master)](https://travis-ci.org/isagalaev/highlight.js)\n\nHighlight.js is a syntax highlighter written in JavaScript. It works in\nthe browser as well as on the server. It works with pretty much any\nmarkup, doesn’t depend on any framework and has automatic language\ndetection.\n\n## Getting Started\n\nThe bare minimum for using highlight.js on a web page is linking to the\nlibrary along with one of the styles and calling\n[`initHighlightingOnLoad`][1]:\n\n```html\n<link rel=\"stylesheet\" href=\"/path/to/styles/default.css\">\n<script src=\"/path/to/highlight.pack.js\"></script>\n<script>hljs.initHighlightingOnLoad();</script>\n```\n\nThis will find and highlight code inside of `<pre><code>` tags; it tries\nto detect the language automatically. If automatic detection doesn’t\nwork for you, you can specify the language in the `class` attribute:\n\n```html\n<pre><code class=\"html\">...</code></pre>\n```\n\nThe list of supported language classes is available in the [class\nreference][2].  Classes can also be prefixed with either `language-` or\n`lang-`.\n\nTo disable highlighting altogether use the `nohighlight` class:\n\n```html\n<pre><code class=\"nohighlight\">...</code></pre>\n```\n\n## Custom Initialization\n\nWhen you need a bit more control over the initialization of\nhighlight.js, you can use the [`highlightBlock`][3] and [`configure`][4]\nfunctions. This allows you to control *what* to highlight and *when*.\n\nHere’s an equivalent way to calling [`initHighlightingOnLoad`][1] using\njQuery:\n\n```javascript\n$(document).ready(function() {\n  $('pre code').each(function(i, block) {\n    hljs.highlightBlock(block);\n  });\n});\n```\n\nYou can use any tags instead of `<pre><code>` to mark up your code. If\nyou don't use a container that preserve line breaks you will need to\nconfigure highlight.js to use the `<br>` tag:\n\n```javascript\nhljs.configure({useBR: true});\n\n$('div.code').each(function(i, block) {\n  hljs.highlightBlock(block);\n});\n```\n\nFor other options refer to the documentation for [`configure`][4].\n\n\n## Web Workers\n\nYou can run highlighting inside a web worker to avoid freezing the browser\nwindow while dealing with very big chunks of code.\n\nIn your main script:\n\n```javascript\naddEventListener('load', function() {\n  var code = document.querySelector('#code');\n  var worker = new Worker('worker.js');\n  worker.onmessage = function(event) { code.innerHTML = event.data; }\n  worker.postMessage(code.textContent);\n})\n```\n\nIn worker.js:\n\n```javascript\nonmessage = function(event) {\n  importScripts('<path>/highlight.pack.js');\n  var result = self.hljs.highlightAuto(event.data);\n  postMessage(result.value);\n}\n```\n\n\n## Getting the Library\n\nYou can get highlight.js as a hosted, or custom-build, browser script or\nas a server module. Right out of the box the browser script supports\nboth AMD and CommonJS, so if you wish you can use RequireJS or\nBrowserify without having to build from source. The server module also\nworks perfectly fine with Browserify, but there is the option to use a\nbuild specific to browsers rather than something meant for a server.\nHead over to the [download page][5] for all the options.\n\n**Don't link to GitHub directly.** The library is not supposed to work straight\nfrom the source, it requires building. If none of the pre-packaged options\nwork for you refer to the [building documentation][6].\n\n**The CDN-hosted package doesn't have all the languages.** Otherwise it'd be\ntoo big. If you don't see the language you need in the [\"Common\" section][5],\nit can be added manually:\n\n```html\n<script src=\"//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.4.0/languages/go.min.js\"></script>\n```\n\n**On Almond.** You need to use the optimizer to give the module a name. For\nexample:\n\n```\nr.js -o name=hljs paths.hljs=/path/to/highlight out=highlight.js\n```\n\n\n## License\n\nHighlight.js is released under the BSD License. See [LICENSE][7] file\nfor details.\n\n## Links\n\nThe official site for the library is at <https://highlightjs.org/>.\n\nFurther in-depth documentation for the API and other topics is at\n<http://highlightjs.readthedocs.io/>.\n\nAuthors and contributors are listed in the [AUTHORS.en.txt][8] file.\n\n[1]: http://highlightjs.readthedocs.io/en/latest/api.html#inithighlightingonload\n[2]: http://highlightjs.readthedocs.io/en/latest/css-classes-reference.html\n[3]: http://highlightjs.readthedocs.io/en/latest/api.html#highlightblock-block\n[4]: http://highlightjs.readthedocs.io/en/latest/api.html#configure-options\n[5]: https://highlightjs.org/download/\n[6]: http://highlightjs.readthedocs.io/en/latest/building-testing.html\n[7]: https://github.com/isagalaev/highlight.js/blob/master/LICENSE\n[8]: https://github.com/isagalaev/highlight.js/blob/master/AUTHORS.en.txt\n"
  },
  {
    "path": "lib/highlight/README.ru.md",
    "content": "# Highlight.js\n\nHighlight.js — это инструмент для подсветки синтаксиса, написанный на JavaScript. Он работает\nи в браузере, и на сервере. Он работает с практически любой HTML разметкой, не\nзависит от каких-либо фреймворков и умеет автоматически определять язык.\n\n\n## Начало работы\n\nМинимум, что нужно сделать для использования highlight.js на веб-странице — это\nподключить библиотеку, CSS-стили и вызывать [`initHighlightingOnLoad`][1]:\n\n```html\n<link rel=\"stylesheet\" href=\"/path/to/styles/default.css\">\n<script src=\"/path/to/highlight.pack.js\"></script>\n<script>hljs.initHighlightingOnLoad();</script>\n```\n\nБиблиотека найдёт и раскрасит код внутри тегов `<pre><code>`, попытавшись\nавтоматически определить язык. Когда автоопределение не срабатывает, можно явно\nуказать язык в атрибуте class:\n\n```html\n<pre><code class=\"html\">...</code></pre>\n```\n\nСписок поддерживаемых классов языков доступен в [справочнике по классам][2].\nКласс также можно предварить префиксами `language-` или `lang-`.\n\nЧтобы отключить подсветку для какого-то блока, используйте класс `nohighlight`:\n\n```html\n<pre><code class=\"nohighlight\">...</code></pre>\n```\n\n## Инициализация вручную\n\nЧтобы иметь чуть больше контроля за инициализацией подсветки, вы можете\nиспользовать функции [`highlightBlock`][3] и [`configure`][4]. Таким образом\nможно управлять тем, *что* и *когда* подсвечивать.\n\nВот пример инициализации, эквивалентной вызову [`initHighlightingOnLoad`][1], но\nс использованием jQuery:\n\n```javascript\n$(document).ready(function() {\n  $('pre code').each(function(i, block) {\n    hljs.highlightBlock(block);\n  });\n});\n```\n\nВы можете использовать любые теги разметки вместо `<pre><code>`. Если\nиспользуете контейнер, не сохраняющий переводы строк, вам нужно сказать\nhighlight.js использовать для них тег `<br>`:\n\n```javascript\nhljs.configure({useBR: true});\n\n$('div.code').each(function(i, block) {\n  hljs.highlightBlock(block);\n});\n```\n\nДругие опции можно найти в документации функции [`configure`][4].\n\n\n## Web Workers\n\nПодсветку можно запустить внутри web worker'а, чтобы окно\nбраузера не подтормаживало при работе с большими кусками кода.\n\nВ основном скрипте:\n\n```javascript\naddEventListener('load', function() {\n  var code = document.querySelector('#code');\n  var worker = new Worker('worker.js');\n  worker.onmessage = function(event) { code.innerHTML = event.data; }\n  worker.postMessage(code.textContent);\n})\n```\n\nВ worker.js:\n\n```javascript\nonmessage = function(event) {\n  importScripts('<path>/highlight.pack.js');\n  var result = self.hljs.highlightAuto(event.data);\n  postMessage(result.value);\n}\n```\n\n\n## Установка библиотеки\n\nHighlight.js можно использовать в браузере прямо с CDN хостинга или скачать\nиндивидуальную сборку, а также установив модуль на сервере. На\n[странице загрузки][5] подробно описаны все варианты.\n\n**Не подключайте GitHub напрямую.** Библиотека не предназначена для\nиспользования в виде исходного кода, а требует отдельной сборки. Если вам не\nподходит ни один из готовых вариантов, читайте [документацию по сборке][6].\n\n**Файл на CDN содержит не все языки.** Иначе он будет слишком большого размера.\nЕсли нужного вам языка нет в [категории \"Common\"][5], можно дообавить его\nвручную:\n\n```html\n<script src=\"//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.4.0/languages/go.min.js\"></script>\n```\n\n**Про Almond.** Нужно задать имя модуля в оптимизаторе, например:\n\n```\nr.js -o name=hljs paths.hljs=/path/to/highlight out=highlight.js\n```\n\n\n## Лицензия\n\nHighlight.js распространяется под лицензией BSD. Подробнее читайте файл\n[LICENSE][7].\n\n\n## Ссылки\n\nОфициальный сайт билиотеки расположен по адресу <https://highlightjs.org/>.\n\nБолее подробная документация по API и другим темам расположена на\n<http://highlightjs.readthedocs.io/>.\n\nАвторы и контрибьюторы перечислены в файле [AUTHORS.ru.txt][8] file.\n\n[1]: http://highlightjs.readthedocs.io/en/latest/api.html#inithighlightingonload\n[2]: http://highlightjs.readthedocs.io/en/latest/css-classes-reference.html\n[3]: http://highlightjs.readthedocs.io/en/latest/api.html#highlightblock-block\n[4]: http://highlightjs.readthedocs.io/en/latest/api.html#configure-options\n[5]: https://highlightjs.org/download/\n[6]: http://highlightjs.readthedocs.io/en/latest/building-testing.html\n[7]: https://github.com/isagalaev/highlight.js/blob/master/LICENSE\n[8]: https://github.com/isagalaev/highlight.js/blob/master/AUTHORS.ru.txt\n"
  },
  {
    "path": "lib/highlight/highlight.pack.js",
    "content": "/*! highlight.js v9.9.0 | BSD3 License | git.io/hljslicense */\n!function(e){var n=\"object\"==typeof window&&window||\"object\"==typeof self&&self;\"undefined\"!=typeof exports?e(exports):n&&(n.hljs=e({}),\"function\"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(e){function n(e){return e.replace(/[&<>]/gm,function(e){return I[e]})}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0===t.index}function i(e){return k.test(e)}function a(e){var n,t,r,a,o=e.className+\" \";if(o+=e.parentNode?e.parentNode.className:\"\",t=B.exec(o))return R(t[1])?t[1]:\"no-highlight\";for(o=o.split(/\\s+/),n=0,r=o.length;r>n;n++)if(a=o[n],i(a)||R(a))return a}function o(e,n){var t,r={};for(t in e)r[t]=e[t];if(n)for(t in n)r[t]=n[t];return r}function u(e){var n=[];return function r(e,i){for(var a=e.firstChild;a;a=a.nextSibling)3===a.nodeType?i+=a.nodeValue.length:1===a.nodeType&&(n.push({event:\"start\",offset:i,node:a}),i=r(a,i),t(a).match(/br|hr|img|input/)||n.push({event:\"stop\",offset:i,node:a}));return i}(e,0),n}function c(e,r,i){function a(){return e.length&&r.length?e[0].offset!==r[0].offset?e[0].offset<r[0].offset?e:r:\"start\"===r[0].event?e:r:e.length?e:r}function o(e){function r(e){return\" \"+e.nodeName+'=\"'+n(e.value)+'\"'}l+=\"<\"+t(e)+w.map.call(e.attributes,r).join(\"\")+\">\"}function u(e){l+=\"</\"+t(e)+\">\"}function c(e){(\"start\"===e.event?o:u)(e.node)}for(var s=0,l=\"\",f=[];e.length||r.length;){var g=a();if(l+=n(i.substring(s,g[0].offset)),s=g[0].offset,g===e){f.reverse().forEach(u);do c(g.splice(0,1)[0]),g=a();while(g===e&&g.length&&g[0].offset===s);f.reverse().forEach(o)}else\"start\"===g[0].event?f.push(g[0].node):f.pop(),c(g.splice(0,1)[0])}return l+n(i.substr(s))}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),\"m\"+(e.cI?\"i\":\"\")+(r?\"g\":\"\"))}function r(i,a){if(!i.compiled){if(i.compiled=!0,i.k=i.k||i.bK,i.k){var u={},c=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(\" \").forEach(function(e){var t=e.split(\"|\");u[t[0]]=[n,t[1]?Number(t[1]):1]})};\"string\"==typeof i.k?c(\"keyword\",i.k):E(i.k).forEach(function(e){c(e,i.k[e])}),i.k=u}i.lR=t(i.l||/\\w+/,!0),a&&(i.bK&&(i.b=\"\\\\b(\"+i.bK.split(\" \").join(\"|\")+\")\\\\b\"),i.b||(i.b=/\\B|\\b/),i.bR=t(i.b),i.e||i.eW||(i.e=/\\B|\\b/),i.e&&(i.eR=t(i.e)),i.tE=n(i.e)||\"\",i.eW&&a.tE&&(i.tE+=(i.e?\"|\":\"\")+a.tE)),i.i&&(i.iR=t(i.i)),null==i.r&&(i.r=1),i.c||(i.c=[]);var s=[];i.c.forEach(function(e){e.v?e.v.forEach(function(n){s.push(o(e,n))}):s.push(\"self\"===e?i:e)}),i.c=s,i.c.forEach(function(e){r(e,i)}),i.starts&&r(i.starts,a);var l=i.c.map(function(e){return e.bK?\"\\\\.?(\"+e.b+\")\\\\.?\":e.b}).concat([i.tE,i.i]).map(n).filter(Boolean);i.t=l.length?t(l.join(\"|\"),!0):{exec:function(){return null}}}}r(e)}function l(e,t,i,a){function o(e,n){var t,i;for(t=0,i=n.c.length;i>t;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function c(e,n){return!i&&r(n.iR,e)}function g(e,n){var t=N.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function h(e,n,t,r){var i=r?\"\":y.classPrefix,a='<span class=\"'+i,o=t?\"\":C;return a+=e+'\">',a+n+o}function p(){var e,t,r,i;if(!E.k)return n(B);for(i=\"\",t=0,E.lR.lastIndex=0,r=E.lR.exec(B);r;)i+=n(B.substring(t,r.index)),e=g(E,r),e?(M+=e[1],i+=h(e[0],n(r[0]))):i+=n(r[0]),t=E.lR.lastIndex,r=E.lR.exec(B);return i+n(B.substr(t))}function d(){var e=\"string\"==typeof E.sL;if(e&&!x[E.sL])return n(B);var t=e?l(E.sL,B,!0,L[E.sL]):f(B,E.sL.length?E.sL:void 0);return E.r>0&&(M+=t.r),e&&(L[E.sL]=t.top),h(t.language,t.value,!1,!0)}function b(){k+=null!=E.sL?d():p(),B=\"\"}function v(e){k+=e.cN?h(e.cN,\"\",!0):\"\",E=Object.create(e,{parent:{value:E}})}function m(e,n){if(B+=e,null==n)return b(),0;var t=o(n,E);if(t)return t.skip?B+=n:(t.eB&&(B+=n),b(),t.rB||t.eB||(B=n)),v(t,n),t.rB?0:n.length;var r=u(E,n);if(r){var i=E;i.skip?B+=n:(i.rE||i.eE||(B+=n),b(),i.eE&&(B=n));do E.cN&&(k+=C),E.skip||(M+=E.r),E=E.parent;while(E!==r.parent);return r.starts&&v(r.starts,\"\"),i.rE?0:n.length}if(c(n,E))throw new Error('Illegal lexeme \"'+n+'\" for mode \"'+(E.cN||\"<unnamed>\")+'\"');return B+=n,n.length||1}var N=R(e);if(!N)throw new Error('Unknown language: \"'+e+'\"');s(N);var w,E=a||N,L={},k=\"\";for(w=E;w!==N;w=w.parent)w.cN&&(k=h(w.cN,\"\",!0)+k);var B=\"\",M=0;try{for(var I,j,O=0;;){if(E.t.lastIndex=O,I=E.t.exec(t),!I)break;j=m(t.substring(O,I.index),I[0]),O=I.index+j}for(m(t.substr(O)),w=E;w.parent;w=w.parent)w.cN&&(k+=C);return{r:M,value:k,language:e,top:E}}catch(T){if(T.message&&-1!==T.message.indexOf(\"Illegal\"))return{r:0,value:n(t)};throw T}}function f(e,t){t=t||y.languages||E(x);var r={r:0,value:n(e)},i=r;return t.filter(R).forEach(function(n){var t=l(n,e,!1);t.language=n,t.r>i.r&&(i=t),t.r>r.r&&(i=r,r=t)}),i.language&&(r.second_best=i),r}function g(e){return y.tabReplace||y.useBR?e.replace(M,function(e,n){return y.useBR&&\"\\n\"===e?\"<br>\":y.tabReplace?n.replace(/\\t/g,y.tabReplace):void 0}):e}function h(e,n,t){var r=n?L[n]:t,i=[e.trim()];return e.match(/\\bhljs\\b/)||i.push(\"hljs\"),-1===e.indexOf(r)&&i.push(r),i.join(\" \").trim()}function p(e){var n,t,r,o,s,p=a(e);i(p)||(y.useBR?(n=document.createElementNS(\"http://www.w3.org/1999/xhtml\",\"div\"),n.innerHTML=e.innerHTML.replace(/\\n/g,\"\").replace(/<br[ \\/]*>/g,\"\\n\")):n=e,s=n.textContent,r=p?l(p,s,!0):f(s),t=u(n),t.length&&(o=document.createElementNS(\"http://www.w3.org/1999/xhtml\",\"div\"),o.innerHTML=r.value,r.value=c(t,u(o),s)),r.value=g(r.value),e.innerHTML=r.value,e.className=h(e.className,p,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function d(e){y=o(y,e)}function b(){if(!b.called){b.called=!0;var e=document.querySelectorAll(\"pre code\");w.forEach.call(e,p)}}function v(){addEventListener(\"DOMContentLoaded\",b,!1),addEventListener(\"load\",b,!1)}function m(n,t){var r=x[n]=t(e);r.aliases&&r.aliases.forEach(function(e){L[e]=n})}function N(){return E(x)}function R(e){return e=(e||\"\").toLowerCase(),x[e]||x[L[e]]}var w=[],E=Object.keys,x={},L={},k=/^(no-?highlight|plain|text)$/i,B=/\\blang(?:uage)?-([\\w-]+)\\b/i,M=/((^(<[^>]+>|\\t|)+|(?:\\n)))/gm,C=\"</span>\",y={classPrefix:\"hljs-\",tabReplace:null,useBR:!1,languages:void 0},I={\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\"};return e.highlight=l,e.highlightAuto=f,e.fixMarkup=g,e.highlightBlock=p,e.configure=d,e.initHighlighting=b,e.initHighlightingOnLoad=v,e.registerLanguage=m,e.listLanguages=N,e.getLanguage=R,e.inherit=o,e.IR=\"[a-zA-Z]\\\\w*\",e.UIR=\"[a-zA-Z_]\\\\w*\",e.NR=\"\\\\b\\\\d+(\\\\.\\\\d+)?\",e.CNR=\"(-?)(\\\\b0[xX][a-fA-F0-9]+|(\\\\b\\\\d+(\\\\.\\\\d*)?|\\\\.\\\\d+)([eE][-+]?\\\\d+)?)\",e.BNR=\"\\\\b(0b[01]+)\",e.RSR=\"!|!=|!==|%|%=|&|&&|&=|\\\\*|\\\\*=|\\\\+|\\\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\\\?|\\\\[|\\\\{|\\\\(|\\\\^|\\\\^=|\\\\||\\\\|=|\\\\|\\\\||~\",e.BE={b:\"\\\\\\\\[\\\\s\\\\S]\",r:0},e.ASM={cN:\"string\",b:\"'\",e:\"'\",i:\"\\\\n\",c:[e.BE]},e.QSM={cN:\"string\",b:'\"',e:'\"',i:\"\\\\n\",c:[e.BE]},e.PWM={b:/\\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|like)\\b/},e.C=function(n,t,r){var i=e.inherit({cN:\"comment\",b:n,e:t,c:[]},r||{});return i.c.push(e.PWM),i.c.push({cN:\"doctag\",b:\"(?:TODO|FIXME|NOTE|BUG|XXX):\",r:0}),i},e.CLCM=e.C(\"//\",\"$\"),e.CBCM=e.C(\"/\\\\*\",\"\\\\*/\"),e.HCM=e.C(\"#\",\"$\"),e.NM={cN:\"number\",b:e.NR,r:0},e.CNM={cN:\"number\",b:e.CNR,r:0},e.BNM={cN:\"number\",b:e.BNR,r:0},e.CSSNM={cN:\"number\",b:e.NR+\"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?\",r:0},e.RM={cN:\"regexp\",b:/\\//,e:/\\/[gimuy]*/,i:/\\n/,c:[e.BE,{b:/\\[/,e:/\\]/,r:0,c:[e.BE]}]},e.TM={cN:\"title\",b:e.IR,r:0},e.UTM={cN:\"title\",b:e.UIR,r:0},e.METHOD_GUARD={b:\"\\\\.\\\\s*\"+e.UIR,r:0},e});hljs.registerLanguage(\"javascript\",function(e){var r=\"[A-Za-z$_][0-9A-Za-z$_]*\",t={keyword:\"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as\",literal:\"true false null undefined NaN Infinity\",built_in:\"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise\"},a={cN:\"number\",v:[{b:\"\\\\b(0[bB][01]+)\"},{b:\"\\\\b(0[oO][0-7]+)\"},{b:e.CNR}],r:0},n={cN:\"subst\",b:\"\\\\$\\\\{\",e:\"\\\\}\",k:t,c:[]},c={cN:\"string\",b:\"`\",e:\"`\",c:[e.BE,n]};n.c=[e.ASM,e.QSM,c,a,e.RM];var s=n.c.concat([e.CBCM,e.CLCM]);return{aliases:[\"js\",\"jsx\"],k:t,c:[{cN:\"meta\",r:10,b:/^\\s*['\"]use (strict|asm)['\"]/},{cN:\"meta\",b:/^#!/,e:/$/},e.ASM,e.QSM,c,e.CLCM,e.CBCM,a,{b:/[{,]\\s*/,r:0,c:[{b:r+\"\\\\s*:\",rB:!0,r:0,c:[{cN:\"attr\",b:r,r:0}]}]},{b:\"(\"+e.RSR+\"|\\\\b(case|return|throw)\\\\b)\\\\s*\",k:\"return throw case\",c:[e.CLCM,e.CBCM,e.RM,{cN:\"function\",b:\"(\\\\(.*?\\\\)|\"+r+\")\\\\s*=>\",rB:!0,e:\"\\\\s*=>\",c:[{cN:\"params\",v:[{b:r},{b:/\\(\\s*\\)/},{b:/\\(/,e:/\\)/,eB:!0,eE:!0,k:t,c:s}]}]},{b:/</,e:/(\\/\\w+|\\w+\\/)>/,sL:\"xml\",c:[{b:/<\\w+\\s*\\/>/,skip:!0},{b:/<\\w+/,e:/(\\/\\w+|\\w+\\/)>/,skip:!0,c:[{b:/<\\w+\\s*\\/>/,skip:!0},\"self\"]}]}],r:0},{cN:\"function\",bK:\"function\",e:/\\{/,eE:!0,c:[e.inherit(e.TM,{b:r}),{cN:\"params\",b:/\\(/,e:/\\)/,eB:!0,eE:!0,c:s}],i:/\\[|%/},{b:/\\$[(.]/},e.METHOD_GUARD,{cN:\"class\",bK:\"class\",e:/[{;=]/,eE:!0,i:/[:\"\\[\\]]/,c:[{bK:\"extends\"},e.UTM]},{bK:\"constructor\",e:/\\{/,eE:!0}],i:/#(?!!)/}});"
  },
  {
    "path": "lib/highlight/styles/agate.css",
    "content": "/*!\n * Agate by Taufik Nurrohman <https://github.com/tovic>\n * ----------------------------------------------------\n *\n * #ade5fc\n * #a2fca2\n * #c6b4f0\n * #d36363\n * #fcc28c\n * #fc9b9b\n * #ffa\n * #fff\n * #333\n * #62c8f3\n * #888\n *\n */\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #333;\n  color: white;\n}\n\n.hljs-name,\n.hljs-strong {\n  font-weight: bold;\n}\n\n.hljs-code,\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-tag {\n  color: #62c8f3;\n}\n\n.hljs-variable,\n.hljs-template-variable,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #ade5fc;\n}\n\n.hljs-string,\n.hljs-bullet {\n  color: #a2fca2;\n}\n\n.hljs-type,\n.hljs-title,\n.hljs-section,\n.hljs-attribute,\n.hljs-quote,\n.hljs-built_in,\n.hljs-builtin-name {\n  color: #ffa;\n}\n\n.hljs-number,\n.hljs-symbol,\n.hljs-bullet {\n  color: #d36363;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-literal {\n  color: #fcc28c;\n}\n\n.hljs-comment,\n.hljs-deletion,\n.hljs-code {\n  color: #888;\n}\n\n.hljs-regexp,\n.hljs-link {\n  color: #c6b4f0;\n}\n\n.hljs-meta {\n  color: #fc9b9b;\n}\n\n.hljs-deletion {\n  background-color: #fc9b9b;\n  color: #333;\n}\n\n.hljs-addition {\n  background-color: #a2fca2;\n  color: #333;\n}\n\n.hljs a {\n  color: inherit;\n}\n\n.hljs a:focus,\n.hljs a:hover {\n  color: inherit;\n  text-decoration: underline;\n}\n"
  },
  {
    "path": "lib/highlight/styles/androidstudio.css",
    "content": "/*\nDate: 24 Fev 2015\nAuthor: Pedro Oliveira <kanytu@gmail . com>\n*/\n\n.hljs {\n  color: #a9b7c6;\n  background: #282b2e;\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n}\n\n.hljs-number,\n.hljs-literal,\n.hljs-symbol,\n.hljs-bullet {\n  color: #6897BB;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-deletion {\n  color: #cc7832;\n}\n\n.hljs-variable,\n.hljs-template-variable,\n.hljs-link {\n  color: #629755;\n}\n\n.hljs-comment,\n.hljs-quote {\n  color: #808080;\n}\n\n.hljs-meta {\n  color: #bbb529;\n}\n\n.hljs-string,\n.hljs-attribute,\n.hljs-addition {\n  color: #6A8759;\n}\n\n.hljs-section,\n.hljs-title,\n.hljs-type {\n  color: #ffc66d;\n}\n\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #e8bf6a;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/arduino-light.css",
    "content": "/*\n\nArduino® Light Theme - Stefania Mellai <s.mellai@arduino.cc>\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #FFFFFF;\n}\n\n.hljs,\n.hljs-subst {\n  color: #434f54;\n}\n\n.hljs-keyword,\n.hljs-attribute,\n.hljs-selector-tag,\n.hljs-doctag,\n.hljs-name {\n  color: #00979D;\n}\n\n.hljs-built_in,\n.hljs-literal,\n.hljs-bullet,\n.hljs-code,\n.hljs-addition {\n  color: #D35400;\n}\n\n.hljs-regexp,\n.hljs-symbol,\n.hljs-variable,\n.hljs-template-variable,\n.hljs-link,\n.hljs-selector-attr,\n.hljs-selector-pseudo {\n  color: #00979D;\n}\n\n.hljs-type,\n.hljs-string,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-quote,\n.hljs-template-tag,\n.hljs-deletion {\n  color: #005C5F;\n}\n\n.hljs-title,\n.hljs-section {\n  color: #880000;\n  font-weight: bold;\n}\n\n.hljs-comment {\n  color: rgba(149,165,166,.8);\n}\n\n.hljs-meta-keyword {\n  color: #728E00;\n}\n\n.hljs-meta {\n  color: #728E00;\n  color: #434f54;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n\n.hljs-function {\n  color: #728E00;\n}\n\n.hljs-number {\n  color: #8A7B52;  \n}\n"
  },
  {
    "path": "lib/highlight/styles/arta.css",
    "content": "/*\nDate: 17.V.2011\nAuthor: pumbur <pumbur@pumbur.net>\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #222;\n}\n\n.hljs,\n.hljs-subst {\n  color: #aaa;\n}\n\n.hljs-section {\n  color: #fff;\n}\n\n.hljs-comment,\n.hljs-quote,\n.hljs-meta {\n  color: #444;\n}\n\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-regexp {\n  color: #ffcc33;\n}\n\n.hljs-number,\n.hljs-addition {\n  color: #00cc66;\n}\n\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-link {\n  color: #32aaee;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #6644aa;\n}\n\n.hljs-title,\n.hljs-variable,\n.hljs-deletion,\n.hljs-template-tag {\n  color: #bb1166;\n}\n\n.hljs-section,\n.hljs-doctag,\n.hljs-strong {\n  font-weight: bold;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n"
  },
  {
    "path": "lib/highlight/styles/ascetic.css",
    "content": "/*\n\nOriginal style from softwaremaniacs.org (c) Ivan Sagalaev <Maniac@SoftwareManiacs.Org>\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: white;\n  color: black;\n}\n\n.hljs-string,\n.hljs-variable,\n.hljs-template-variable,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-section,\n.hljs-addition,\n.hljs-attribute,\n.hljs-link {\n  color: #888;\n}\n\n.hljs-comment,\n.hljs-quote,\n.hljs-meta,\n.hljs-deletion {\n  color: #ccc;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-section,\n.hljs-name,\n.hljs-type,\n.hljs-strong {\n  font-weight: bold;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atelier-cave-dark.css",
    "content": "/* Base16 Atelier Cave Dark - Theme */\n/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave) */\n/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */\n\n/* Atelier-Cave Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #7e7887;\n}\n\n/* Atelier-Cave Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-regexp,\n.hljs-link,\n.hljs-tag,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #be4678;\n}\n\n/* Atelier-Cave Orange */\n.hljs-number,\n.hljs-meta,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params {\n  color: #aa573c;\n}\n\n/* Atelier-Cave Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet {\n  color: #2a9292;\n}\n\n/* Atelier-Cave Blue */\n.hljs-title,\n.hljs-section {\n  color: #576ddb;\n}\n\n/* Atelier-Cave Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #955ae7;\n}\n\n.hljs-deletion,\n.hljs-addition {\n  color: #19171c;\n  display: inline-block;\n  width: 100%;\n}\n\n.hljs-deletion {\n  background-color: #be4678;\n}\n\n.hljs-addition {\n  background-color: #2a9292;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #19171c;\n  color: #8b8792;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atelier-cave-light.css",
    "content": "/* Base16 Atelier Cave Light - Theme */\n/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave) */\n/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */\n\n/* Atelier-Cave Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #655f6d;\n}\n\n/* Atelier-Cave Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-tag,\n.hljs-name,\n.hljs-regexp,\n.hljs-link,\n.hljs-name,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #be4678;\n}\n\n/* Atelier-Cave Orange */\n.hljs-number,\n.hljs-meta,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params {\n  color: #aa573c;\n}\n\n/* Atelier-Cave Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet {\n  color: #2a9292;\n}\n\n/* Atelier-Cave Blue */\n.hljs-title,\n.hljs-section {\n  color: #576ddb;\n}\n\n/* Atelier-Cave Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #955ae7;\n}\n\n.hljs-deletion,\n.hljs-addition {\n  color: #19171c;\n  display: inline-block;\n  width: 100%;\n}\n\n.hljs-deletion {\n  background-color: #be4678;\n}\n\n.hljs-addition {\n  background-color: #2a9292;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #efecf4;\n  color: #585260;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atelier-dune-dark.css",
    "content": "/* Base16 Atelier Dune Dark - Theme */\n/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/dune) */\n/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */\n\n/* Atelier-Dune Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #999580;\n}\n\n/* Atelier-Dune Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-tag,\n.hljs-name,\n.hljs-regexp,\n.hljs-link,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #d73737;\n}\n\n/* Atelier-Dune Orange */\n.hljs-number,\n.hljs-meta,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params {\n  color: #b65611;\n}\n\n/* Atelier-Dune Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet {\n  color: #60ac39;\n}\n\n/* Atelier-Dune Blue */\n.hljs-title,\n.hljs-section {\n  color: #6684e1;\n}\n\n/* Atelier-Dune Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #b854d4;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #20201d;\n  color: #a6a28c;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atelier-dune-light.css",
    "content": "/* Base16 Atelier Dune Light - Theme */\n/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/dune) */\n/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */\n\n/* Atelier-Dune Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #7d7a68;\n}\n\n/* Atelier-Dune Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-tag,\n.hljs-name,\n.hljs-regexp,\n.hljs-link,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #d73737;\n}\n\n/* Atelier-Dune Orange */\n.hljs-number,\n.hljs-meta,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params {\n  color: #b65611;\n}\n\n/* Atelier-Dune Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet {\n  color: #60ac39;\n}\n\n/* Atelier-Dune Blue */\n.hljs-title,\n.hljs-section {\n  color: #6684e1;\n}\n\n/* Atelier-Dune Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #b854d4;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #fefbec;\n  color: #6e6b5e;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atelier-estuary-dark.css",
    "content": "/* Base16 Atelier Estuary Dark - Theme */\n/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/estuary) */\n/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */\n\n/* Atelier-Estuary Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #878573;\n}\n\n/* Atelier-Estuary Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-tag,\n.hljs-name,\n.hljs-regexp,\n.hljs-link,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #ba6236;\n}\n\n/* Atelier-Estuary Orange */\n.hljs-number,\n.hljs-meta,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params {\n  color: #ae7313;\n}\n\n/* Atelier-Estuary Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet {\n  color: #7d9726;\n}\n\n/* Atelier-Estuary Blue */\n.hljs-title,\n.hljs-section {\n  color: #36a166;\n}\n\n/* Atelier-Estuary Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #5f9182;\n}\n\n.hljs-deletion,\n.hljs-addition {\n  color: #22221b;\n  display: inline-block;\n  width: 100%;\n}\n\n.hljs-deletion {\n  background-color: #ba6236;\n}\n\n.hljs-addition {\n  background-color: #7d9726;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #22221b;\n  color: #929181;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atelier-estuary-light.css",
    "content": "/* Base16 Atelier Estuary Light - Theme */\n/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/estuary) */\n/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */\n\n/* Atelier-Estuary Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #6c6b5a;\n}\n\n/* Atelier-Estuary Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-tag,\n.hljs-name,\n.hljs-regexp,\n.hljs-link,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #ba6236;\n}\n\n/* Atelier-Estuary Orange */\n.hljs-number,\n.hljs-meta,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params {\n  color: #ae7313;\n}\n\n/* Atelier-Estuary Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet {\n  color: #7d9726;\n}\n\n/* Atelier-Estuary Blue */\n.hljs-title,\n.hljs-section {\n  color: #36a166;\n}\n\n/* Atelier-Estuary Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #5f9182;\n}\n\n.hljs-deletion,\n.hljs-addition {\n  color: #22221b;\n  display: inline-block;\n  width: 100%;\n}\n\n.hljs-deletion {\n  background-color: #ba6236;\n}\n\n.hljs-addition {\n  background-color: #7d9726;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #f4f3ec;\n  color: #5f5e4e;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atelier-forest-dark.css",
    "content": "/* Base16 Atelier Forest Dark - Theme */\n/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/forest) */\n/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */\n\n/* Atelier-Forest Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #9c9491;\n}\n\n/* Atelier-Forest Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-tag,\n.hljs-name,\n.hljs-regexp,\n.hljs-link,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #f22c40;\n}\n\n/* Atelier-Forest Orange */\n.hljs-number,\n.hljs-meta,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params {\n  color: #df5320;\n}\n\n/* Atelier-Forest Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet {\n  color: #7b9726;\n}\n\n/* Atelier-Forest Blue */\n.hljs-title,\n.hljs-section {\n  color: #407ee7;\n}\n\n/* Atelier-Forest Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #6666ea;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #1b1918;\n  color: #a8a19f;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atelier-forest-light.css",
    "content": "/* Base16 Atelier Forest Light - Theme */\n/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/forest) */\n/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */\n\n/* Atelier-Forest Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #766e6b;\n}\n\n/* Atelier-Forest Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-tag,\n.hljs-name,\n.hljs-regexp,\n.hljs-link,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #f22c40;\n}\n\n/* Atelier-Forest Orange */\n.hljs-number,\n.hljs-meta,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params {\n  color: #df5320;\n}\n\n/* Atelier-Forest Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet {\n  color: #7b9726;\n}\n\n/* Atelier-Forest Blue */\n.hljs-title,\n.hljs-section {\n  color: #407ee7;\n}\n\n/* Atelier-Forest Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #6666ea;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #f1efee;\n  color: #68615e;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atelier-heath-dark.css",
    "content": "/* Base16 Atelier Heath Dark - Theme */\n/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/heath) */\n/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */\n\n/* Atelier-Heath Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #9e8f9e;\n}\n\n/* Atelier-Heath Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-tag,\n.hljs-name,\n.hljs-regexp,\n.hljs-link,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #ca402b;\n}\n\n/* Atelier-Heath Orange */\n.hljs-number,\n.hljs-meta,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params {\n  color: #a65926;\n}\n\n/* Atelier-Heath Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet {\n  color: #918b3b;\n}\n\n/* Atelier-Heath Blue */\n.hljs-title,\n.hljs-section {\n  color: #516aec;\n}\n\n/* Atelier-Heath Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #7b59c0;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #1b181b;\n  color: #ab9bab;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atelier-heath-light.css",
    "content": "/* Base16 Atelier Heath Light - Theme */\n/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/heath) */\n/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */\n\n/* Atelier-Heath Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #776977;\n}\n\n/* Atelier-Heath Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-tag,\n.hljs-name,\n.hljs-regexp,\n.hljs-link,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #ca402b;\n}\n\n/* Atelier-Heath Orange */\n.hljs-number,\n.hljs-meta,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params {\n  color: #a65926;\n}\n\n/* Atelier-Heath Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet {\n  color: #918b3b;\n}\n\n/* Atelier-Heath Blue */\n.hljs-title,\n.hljs-section {\n  color: #516aec;\n}\n\n/* Atelier-Heath Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #7b59c0;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #f7f3f7;\n  color: #695d69;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atelier-lakeside-dark.css",
    "content": "/* Base16 Atelier Lakeside Dark - Theme */\n/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/lakeside) */\n/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */\n\n/* Atelier-Lakeside Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #7195a8;\n}\n\n/* Atelier-Lakeside Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-tag,\n.hljs-name,\n.hljs-regexp,\n.hljs-link,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #d22d72;\n}\n\n/* Atelier-Lakeside Orange */\n.hljs-number,\n.hljs-meta,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params {\n  color: #935c25;\n}\n\n/* Atelier-Lakeside Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet {\n  color: #568c3b;\n}\n\n/* Atelier-Lakeside Blue */\n.hljs-title,\n.hljs-section {\n  color: #257fad;\n}\n\n/* Atelier-Lakeside Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #6b6bb8;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #161b1d;\n  color: #7ea2b4;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atelier-lakeside-light.css",
    "content": "/* Base16 Atelier Lakeside Light - Theme */\n/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/lakeside) */\n/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */\n\n/* Atelier-Lakeside Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #5a7b8c;\n}\n\n/* Atelier-Lakeside Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-tag,\n.hljs-name,\n.hljs-regexp,\n.hljs-link,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #d22d72;\n}\n\n/* Atelier-Lakeside Orange */\n.hljs-number,\n.hljs-meta,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params {\n  color: #935c25;\n}\n\n/* Atelier-Lakeside Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet {\n  color: #568c3b;\n}\n\n/* Atelier-Lakeside Blue */\n.hljs-title,\n.hljs-section {\n  color: #257fad;\n}\n\n/* Atelier-Lakeside Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #6b6bb8;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #ebf8ff;\n  color: #516d7b;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atelier-plateau-dark.css",
    "content": "/* Base16 Atelier Plateau Dark - Theme */\n/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/plateau) */\n/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */\n\n/* Atelier-Plateau Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #7e7777;\n}\n\n/* Atelier-Plateau Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-tag,\n.hljs-name,\n.hljs-regexp,\n.hljs-link,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #ca4949;\n}\n\n/* Atelier-Plateau Orange */\n.hljs-number,\n.hljs-meta,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params {\n  color: #b45a3c;\n}\n\n/* Atelier-Plateau Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet {\n  color: #4b8b8b;\n}\n\n/* Atelier-Plateau Blue */\n.hljs-title,\n.hljs-section {\n  color: #7272ca;\n}\n\n/* Atelier-Plateau Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #8464c4;\n}\n\n.hljs-deletion,\n.hljs-addition {\n  color: #1b1818;\n  display: inline-block;\n  width: 100%;\n}\n\n.hljs-deletion {\n  background-color: #ca4949;\n}\n\n.hljs-addition {\n  background-color: #4b8b8b;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #1b1818;\n  color: #8a8585;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atelier-plateau-light.css",
    "content": "/* Base16 Atelier Plateau Light - Theme */\n/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/plateau) */\n/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */\n\n/* Atelier-Plateau Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #655d5d;\n}\n\n/* Atelier-Plateau Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-tag,\n.hljs-name,\n.hljs-regexp,\n.hljs-link,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #ca4949;\n}\n\n/* Atelier-Plateau Orange */\n.hljs-number,\n.hljs-meta,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params {\n  color: #b45a3c;\n}\n\n/* Atelier-Plateau Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet {\n  color: #4b8b8b;\n}\n\n/* Atelier-Plateau Blue */\n.hljs-title,\n.hljs-section {\n  color: #7272ca;\n}\n\n/* Atelier-Plateau Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #8464c4;\n}\n\n.hljs-deletion,\n.hljs-addition {\n  color: #1b1818;\n  display: inline-block;\n  width: 100%;\n}\n\n.hljs-deletion {\n  background-color: #ca4949;\n}\n\n.hljs-addition {\n  background-color: #4b8b8b;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #f4ecec;\n  color: #585050;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atelier-savanna-dark.css",
    "content": "/* Base16 Atelier Savanna Dark - Theme */\n/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/savanna) */\n/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */\n\n/* Atelier-Savanna Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #78877d;\n}\n\n/* Atelier-Savanna Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-tag,\n.hljs-name,\n.hljs-regexp,\n.hljs-link,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #b16139;\n}\n\n/* Atelier-Savanna Orange */\n.hljs-number,\n.hljs-meta,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params {\n  color: #9f713c;\n}\n\n/* Atelier-Savanna Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet {\n  color: #489963;\n}\n\n/* Atelier-Savanna Blue */\n.hljs-title,\n.hljs-section {\n  color: #478c90;\n}\n\n/* Atelier-Savanna Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #55859b;\n}\n\n.hljs-deletion,\n.hljs-addition {\n  color: #171c19;\n  display: inline-block;\n  width: 100%;\n}\n\n.hljs-deletion {\n  background-color: #b16139;\n}\n\n.hljs-addition {\n  background-color: #489963;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #171c19;\n  color: #87928a;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atelier-savanna-light.css",
    "content": "/* Base16 Atelier Savanna Light - Theme */\n/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/savanna) */\n/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */\n\n/* Atelier-Savanna Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #5f6d64;\n}\n\n/* Atelier-Savanna Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-tag,\n.hljs-name,\n.hljs-regexp,\n.hljs-link,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #b16139;\n}\n\n/* Atelier-Savanna Orange */\n.hljs-number,\n.hljs-meta,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params {\n  color: #9f713c;\n}\n\n/* Atelier-Savanna Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet {\n  color: #489963;\n}\n\n/* Atelier-Savanna Blue */\n.hljs-title,\n.hljs-section {\n  color: #478c90;\n}\n\n/* Atelier-Savanna Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #55859b;\n}\n\n.hljs-deletion,\n.hljs-addition {\n  color: #171c19;\n  display: inline-block;\n  width: 100%;\n}\n\n.hljs-deletion {\n  background-color: #b16139;\n}\n\n.hljs-addition {\n  background-color: #489963;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #ecf4ee;\n  color: #526057;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atelier-seaside-dark.css",
    "content": "/* Base16 Atelier Seaside Dark - Theme */\n/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/seaside) */\n/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */\n\n/* Atelier-Seaside Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #809980;\n}\n\n/* Atelier-Seaside Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-tag,\n.hljs-name,\n.hljs-regexp,\n.hljs-link,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #e6193c;\n}\n\n/* Atelier-Seaside Orange */\n.hljs-number,\n.hljs-meta,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params {\n  color: #87711d;\n}\n\n/* Atelier-Seaside Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet {\n  color: #29a329;\n}\n\n/* Atelier-Seaside Blue */\n.hljs-title,\n.hljs-section {\n  color: #3d62f5;\n}\n\n/* Atelier-Seaside Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #ad2bee;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #131513;\n  color: #8ca68c;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atelier-seaside-light.css",
    "content": "/* Base16 Atelier Seaside Light - Theme */\n/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/seaside) */\n/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */\n\n/* Atelier-Seaside Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #687d68;\n}\n\n/* Atelier-Seaside Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-tag,\n.hljs-name,\n.hljs-regexp,\n.hljs-link,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #e6193c;\n}\n\n/* Atelier-Seaside Orange */\n.hljs-number,\n.hljs-meta,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params {\n  color: #87711d;\n}\n\n/* Atelier-Seaside Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet {\n  color: #29a329;\n}\n\n/* Atelier-Seaside Blue */\n.hljs-title,\n.hljs-section {\n  color: #3d62f5;\n}\n\n/* Atelier-Seaside Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #ad2bee;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #f4fbf4;\n  color: #5e6e5e;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atelier-sulphurpool-dark.css",
    "content": "/* Base16 Atelier Sulphurpool Dark - Theme */\n/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/sulphurpool) */\n/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */\n\n/* Atelier-Sulphurpool Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #898ea4;\n}\n\n/* Atelier-Sulphurpool Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-tag,\n.hljs-name,\n.hljs-regexp,\n.hljs-link,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #c94922;\n}\n\n/* Atelier-Sulphurpool Orange */\n.hljs-number,\n.hljs-meta,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params {\n  color: #c76b29;\n}\n\n/* Atelier-Sulphurpool Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet {\n  color: #ac9739;\n}\n\n/* Atelier-Sulphurpool Blue */\n.hljs-title,\n.hljs-section {\n  color: #3d8fd1;\n}\n\n/* Atelier-Sulphurpool Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #6679cc;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #202746;\n  color: #979db4;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atelier-sulphurpool-light.css",
    "content": "/* Base16 Atelier Sulphurpool Light - Theme */\n/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/sulphurpool) */\n/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */\n\n/* Atelier-Sulphurpool Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #6b7394;\n}\n\n/* Atelier-Sulphurpool Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-tag,\n.hljs-name,\n.hljs-regexp,\n.hljs-link,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #c94922;\n}\n\n/* Atelier-Sulphurpool Orange */\n.hljs-number,\n.hljs-meta,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params {\n  color: #c76b29;\n}\n\n/* Atelier-Sulphurpool Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet {\n  color: #ac9739;\n}\n\n/* Atelier-Sulphurpool Blue */\n.hljs-title,\n.hljs-section {\n  color: #3d8fd1;\n}\n\n/* Atelier-Sulphurpool Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #6679cc;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #f5f7ff;\n  color: #5e6687;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atom-one-dark.css",
    "content": "/*\n\nAtom One Dark by Daniel Gamage\nOriginal One Dark Syntax theme from https://github.com/atom/one-dark-syntax\n\nbase:    #282c34\nmono-1:  #abb2bf\nmono-2:  #818896\nmono-3:  #5c6370\nhue-1:   #56b6c2\nhue-2:   #61aeee\nhue-3:   #c678dd\nhue-4:   #98c379\nhue-5:   #e06c75\nhue-5-2: #be5046\nhue-6:   #d19a66\nhue-6-2: #e6c07b\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  color: #abb2bf;\n  background: #282c34;\n}\n\n.hljs-comment,\n.hljs-quote {\n  color: #5c6370;\n  font-style: italic;\n}\n\n.hljs-doctag,\n.hljs-keyword,\n.hljs-formula {\n  color: #c678dd;\n}\n\n.hljs-section,\n.hljs-name,\n.hljs-selector-tag,\n.hljs-deletion,\n.hljs-subst {\n  color: #e06c75;\n}\n\n.hljs-literal {\n  color: #56b6c2;\n}\n\n.hljs-string,\n.hljs-regexp,\n.hljs-addition,\n.hljs-attribute,\n.hljs-meta-string {\n  color: #98c379;\n}\n\n.hljs-built_in,\n.hljs-class .hljs-title {\n  color: #e6c07b;\n}\n\n.hljs-attr,\n.hljs-variable,\n.hljs-template-variable,\n.hljs-type,\n.hljs-selector-class,\n.hljs-selector-attr,\n.hljs-selector-pseudo,\n.hljs-number {\n  color: #d19a66;\n}\n\n.hljs-symbol,\n.hljs-bullet,\n.hljs-link,\n.hljs-meta,\n.hljs-selector-id,\n.hljs-title {\n  color: #61aeee;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n\n.hljs-link {\n  text-decoration: underline;\n}\n"
  },
  {
    "path": "lib/highlight/styles/atom-one-light.css",
    "content": "/*\n\nAtom One Light by Daniel Gamage\nOriginal One Light Syntax theme from https://github.com/atom/one-light-syntax\n\nbase:    #fafafa\nmono-1:  #383a42\nmono-2:  #686b77\nmono-3:  #a0a1a7\nhue-1:   #0184bb\nhue-2:   #4078f2\nhue-3:   #a626a4\nhue-4:   #50a14f\nhue-5:   #e45649\nhue-5-2: #c91243\nhue-6:   #986801\nhue-6-2: #c18401\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  color: #383a42;\n  background: #fafafa;\n}\n\n.hljs-comment,\n.hljs-quote {\n  color: #a0a1a7;\n  font-style: italic;\n}\n\n.hljs-doctag,\n.hljs-keyword,\n.hljs-formula {\n  color: #a626a4;\n}\n\n.hljs-section,\n.hljs-name,\n.hljs-selector-tag,\n.hljs-deletion,\n.hljs-subst {\n  color: #e45649;\n}\n\n.hljs-literal {\n  color: #0184bb;\n}\n\n.hljs-string,\n.hljs-regexp,\n.hljs-addition,\n.hljs-attribute,\n.hljs-meta-string {\n  color: #50a14f;\n}\n\n.hljs-built_in,\n.hljs-class .hljs-title {\n  color: #c18401;\n}\n\n.hljs-attr,\n.hljs-variable,\n.hljs-template-variable,\n.hljs-type,\n.hljs-selector-class,\n.hljs-selector-attr,\n.hljs-selector-pseudo,\n.hljs-number {\n  color: #986801;\n}\n\n.hljs-symbol,\n.hljs-bullet,\n.hljs-link,\n.hljs-meta,\n.hljs-selector-id,\n.hljs-title {\n  color: #4078f2;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n\n.hljs-link {\n  text-decoration: underline;\n}\n"
  },
  {
    "path": "lib/highlight/styles/brown-paper.css",
    "content": "/*\n\nBrown Paper style from goldblog.com.ua (c) Zaripov Yura <yur4ik7@ukr.net>\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background:#b7a68e url(./brown-papersq.png);\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-literal {\n  color:#005599;\n  font-weight:bold;\n}\n\n.hljs,\n.hljs-subst {\n  color: #363c69;\n}\n\n.hljs-string,\n.hljs-title,\n.hljs-section,\n.hljs-type,\n.hljs-attribute,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-built_in,\n.hljs-addition,\n.hljs-variable,\n.hljs-template-tag,\n.hljs-template-variable,\n.hljs-link,\n.hljs-name {\n  color: #2c009f;\n}\n\n.hljs-comment,\n.hljs-quote,\n.hljs-meta,\n.hljs-deletion {\n  color: #802022;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-literal,\n.hljs-doctag,\n.hljs-title,\n.hljs-section,\n.hljs-type,\n.hljs-name,\n.hljs-strong {\n  font-weight: bold;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n"
  },
  {
    "path": "lib/highlight/styles/codepen-embed.css",
    "content": "/*\n  codepen.io Embed Theme\n  Author: Justin Perry <http://github.com/ourmaninamsterdam>\n  Original theme - https://github.com/chriskempson/tomorrow-theme\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #222;\n  color: #fff;\n}\n\n.hljs-comment,\n.hljs-quote {\n  color: #777;\n}\n\n.hljs-variable,\n.hljs-template-variable,\n.hljs-tag,\n.hljs-regexp,\n.hljs-meta,\n.hljs-number,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-params,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-link,\n.hljs-deletion {\n  color: #ab875d;\n}\n\n.hljs-section,\n.hljs-title,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-type,\n.hljs-attribute {\n  color: #9b869b;\n}\n\n.hljs-string,\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-addition {\n  color: #8f9c6c;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/color-brewer.css",
    "content": "/*\n\nColorbrewer theme\nOriginal: https://github.com/mbostock/colorbrewer-theme (c) Mike Bostock <mike@ocks.org>\nPorted by Fabrício Tavares de Oliveira\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #fff;\n}\n\n.hljs,\n.hljs-subst {\n  color: #000;\n}\n\n.hljs-string,\n.hljs-meta,\n.hljs-symbol,\n.hljs-template-tag,\n.hljs-template-variable,\n.hljs-addition {\n  color: #756bb1;\n}\n\n.hljs-comment,\n.hljs-quote {\n  color: #636363;\n}\n\n.hljs-number,\n.hljs-regexp,\n.hljs-literal,\n.hljs-bullet,\n.hljs-link {\n  color: #31a354;\n}\n\n.hljs-deletion,\n.hljs-variable {\n  color: #88f;\n}\n\n\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-title,\n.hljs-section,\n.hljs-built_in,\n.hljs-doctag,\n.hljs-type,\n.hljs-tag,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-strong {\n  color: #3182bd;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-attribute {\n  color: #e6550d;\n}\n"
  },
  {
    "path": "lib/highlight/styles/darcula.css",
    "content": "/*\n\nDarcula color scheme from the JetBrains family of IDEs\n\n*/\n\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #2b2b2b;\n}\n\n.hljs {\n  color: #bababa;\n}\n\n.hljs-strong,\n.hljs-emphasis {\n  color: #a8a8a2;\n}\n\n.hljs-bullet,\n.hljs-quote,\n.hljs-link,\n.hljs-number,\n.hljs-regexp,\n.hljs-literal {\n  color: #6896ba;\n}\n\n.hljs-code,\n.hljs-selector-class {\n  color: #a6e22e;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-section,\n.hljs-attribute,\n.hljs-name,\n.hljs-variable {\n  color: #cb7832;\n}\n\n.hljs-params {\n  color: #b9b9b9;\n}\n\n.hljs-string {\n  color: #6a8759;\n}\n\n.hljs-subst,\n.hljs-type,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-symbol,\n.hljs-selector-id,\n.hljs-selector-attr,\n.hljs-selector-pseudo,\n.hljs-template-tag,\n.hljs-template-variable,\n.hljs-addition {\n  color: #e0c46c;\n}\n\n.hljs-comment,\n.hljs-deletion,\n.hljs-meta {\n  color: #7f7f7f;\n}\n"
  },
  {
    "path": "lib/highlight/styles/dark.css",
    "content": "/*\n\nDark style from softwaremaniacs.org (c) Ivan Sagalaev <Maniac@SoftwareManiacs.Org>\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #444;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-literal,\n.hljs-section,\n.hljs-link {\n  color: white;\n}\n\n.hljs,\n.hljs-subst {\n  color: #ddd;\n}\n\n.hljs-string,\n.hljs-title,\n.hljs-name,\n.hljs-type,\n.hljs-attribute,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-built_in,\n.hljs-addition,\n.hljs-variable,\n.hljs-template-tag,\n.hljs-template-variable {\n  color: #d88;\n}\n\n.hljs-comment,\n.hljs-quote,\n.hljs-deletion,\n.hljs-meta {\n  color: #777;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-literal,\n.hljs-title,\n.hljs-section,\n.hljs-doctag,\n.hljs-type,\n.hljs-name,\n.hljs-strong {\n  font-weight: bold;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n"
  },
  {
    "path": "lib/highlight/styles/darkula.css",
    "content": "/*\n  Deprecated due to a typo in the name and left here for compatibility purpose only.\n  Please use darcula.css instead.\n*/\n\n@import url('darcula.css');\n"
  },
  {
    "path": "lib/highlight/styles/default.css",
    "content": "/*\n\nOriginal highlight.js style (c) Ivan Sagalaev <maniac@softwaremaniacs.org>\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #F0F0F0;\n}\n\n\n/* Base color: saturation 0; */\n\n.hljs,\n.hljs-subst {\n  color: #444;\n}\n\n.hljs-comment {\n  color: #888888;\n}\n\n.hljs-keyword,\n.hljs-attribute,\n.hljs-selector-tag,\n.hljs-meta-keyword,\n.hljs-doctag,\n.hljs-name {\n  font-weight: bold;\n}\n\n\n/* User color: hue: 0 */\n\n.hljs-type,\n.hljs-string,\n.hljs-number,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-quote,\n.hljs-template-tag,\n.hljs-deletion {\n  color: #880000;\n}\n\n.hljs-title,\n.hljs-section {\n  color: #880000;\n  font-weight: bold;\n}\n\n.hljs-regexp,\n.hljs-symbol,\n.hljs-variable,\n.hljs-template-variable,\n.hljs-link,\n.hljs-selector-attr,\n.hljs-selector-pseudo {\n  color: #BC6060;\n}\n\n\n/* Language color: hue: 90; */\n\n.hljs-literal {\n  color: #78A960;\n}\n\n.hljs-built_in,\n.hljs-bullet,\n.hljs-code,\n.hljs-addition {\n  color: #397300;\n}\n\n\n/* Meta color: hue: 200 */\n\n.hljs-meta {\n  color: #1f7199;\n}\n\n.hljs-meta-string {\n  color: #4d99bf;\n}\n\n\n/* Misc effects */\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/docco.css",
    "content": "/*\nDocco style used in http://jashkenas.github.com/docco/ converted by Simon Madine (@thingsinjars)\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  color: #000;\n  background: #f8f8ff;\n}\n\n.hljs-comment,\n.hljs-quote {\n  color: #408080;\n  font-style: italic;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-literal,\n.hljs-subst {\n  color: #954121;\n}\n\n.hljs-number {\n  color: #40a070;\n}\n\n.hljs-string,\n.hljs-doctag {\n  color: #219161;\n}\n\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-section,\n.hljs-type {\n  color: #19469d;\n}\n\n.hljs-params {\n  color: #00f;\n}\n\n.hljs-title {\n  color: #458;\n  font-weight: bold;\n}\n\n.hljs-tag,\n.hljs-name,\n.hljs-attribute {\n  color: #000080;\n  font-weight: normal;\n}\n\n.hljs-variable,\n.hljs-template-variable {\n  color: #008080;\n}\n\n.hljs-regexp,\n.hljs-link {\n  color: #b68;\n}\n\n.hljs-symbol,\n.hljs-bullet {\n  color: #990073;\n}\n\n.hljs-built_in,\n.hljs-builtin-name {\n  color: #0086b3;\n}\n\n.hljs-meta {\n  color: #999;\n  font-weight: bold;\n}\n\n.hljs-deletion {\n  background: #fdd;\n}\n\n.hljs-addition {\n  background: #dfd;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/dracula.css",
    "content": "/*\n\nDracula Theme v1.2.0\n\nhttps://github.com/zenorocha/dracula-theme\n\nCopyright 2015, All rights reserved\n\nCode licensed under the MIT license\nhttp://zenorocha.mit-license.org\n\n@author Éverton Ribeiro <nuxlli@gmail.com>\n@author Zeno Rocha <hi@zenorocha.com>\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #282a36;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-literal,\n.hljs-section,\n.hljs-link {\n  color: #8be9fd;\n}\n\n.hljs-function .hljs-keyword {\n  color: #ff79c6;\n}\n\n.hljs,\n.hljs-subst {\n  color: #f8f8f2;\n}\n\n.hljs-string,\n.hljs-title,\n.hljs-name,\n.hljs-type,\n.hljs-attribute,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-addition,\n.hljs-variable,\n.hljs-template-tag,\n.hljs-template-variable {\n  color: #f1fa8c;\n}\n\n.hljs-comment,\n.hljs-quote,\n.hljs-deletion,\n.hljs-meta {\n  color: #6272a4;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-literal,\n.hljs-title,\n.hljs-section,\n.hljs-doctag,\n.hljs-type,\n.hljs-name,\n.hljs-strong {\n  font-weight: bold;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n"
  },
  {
    "path": "lib/highlight/styles/far.css",
    "content": "/*\n\nFAR Style (c) MajestiC <majestic2k@gmail.com>\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #000080;\n}\n\n.hljs,\n.hljs-subst {\n  color: #0ff;\n}\n\n.hljs-string,\n.hljs-attribute,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-template-tag,\n.hljs-template-variable,\n.hljs-addition {\n  color: #ff0;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-section,\n.hljs-type,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-variable {\n  color: #fff;\n}\n\n.hljs-comment,\n.hljs-quote,\n.hljs-doctag,\n.hljs-deletion {\n  color: #888;\n}\n\n.hljs-number,\n.hljs-regexp,\n.hljs-literal,\n.hljs-link {\n  color: #0f0;\n}\n\n.hljs-meta {\n  color: #008080;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-title,\n.hljs-section,\n.hljs-name,\n.hljs-strong {\n  font-weight: bold;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n"
  },
  {
    "path": "lib/highlight/styles/foundation.css",
    "content": "/*\nDescription: Foundation 4 docs style for highlight.js\nAuthor: Dan Allen <dan.j.allen@gmail.com>\nWebsite: http://foundation.zurb.com/docs/\nVersion: 1.0\nDate: 2013-04-02\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #eee; color: black;\n}\n\n.hljs-link,\n.hljs-emphasis,\n.hljs-attribute,\n.hljs-addition {\n  color: #070;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong,\n.hljs-string,\n.hljs-deletion {\n  color: #d14;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n\n.hljs-quote,\n.hljs-comment {\n  color: #998;\n  font-style: italic;\n}\n\n.hljs-section,\n.hljs-title {\n  color: #900;\n}\n\n.hljs-class .hljs-title,\n.hljs-type {\n  color: #458;\n}\n\n.hljs-variable,\n.hljs-template-variable {\n  color: #336699;\n}\n\n.hljs-bullet {\n  color: #997700;\n}\n\n.hljs-meta {\n  color: #3344bb;\n}\n\n.hljs-code,\n.hljs-number,\n.hljs-literal,\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #099;\n}\n\n.hljs-regexp {\n  background-color: #fff0ff;\n  color: #880088;\n}\n\n.hljs-symbol {\n  color: #990073;\n}\n\n.hljs-tag,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #007700;\n}\n"
  },
  {
    "path": "lib/highlight/styles/github-gist.css",
    "content": "/**\n * GitHub Gist Theme\n * Author : Louis Barranqueiro - https://github.com/LouisBarranqueiro\n */\n\n.hljs {\n  display: block;\n  background: white;\n  padding: 0.5em;\n  color: #333333;\n  overflow-x: auto;\n}\n\n.hljs-comment,\n.hljs-meta {\n  color: #969896;\n}\n\n.hljs-string,\n.hljs-variable,\n.hljs-template-variable,\n.hljs-strong,\n.hljs-emphasis,\n.hljs-quote {\n  color: #df5000;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-type {\n  color: #a71d5d;\n}\n\n.hljs-literal,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-attribute {\n  color: #0086b3;\n}\n\n.hljs-section,\n.hljs-name {\n  color: #63a35c;\n}\n\n.hljs-tag {\n  color: #333333;\n}\n\n.hljs-title,\n.hljs-attr,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-selector-attr,\n.hljs-selector-pseudo {\n  color: #795da3;\n}\n\n.hljs-addition {\n  color: #55a532;\n  background-color: #eaffea;\n}\n\n.hljs-deletion {\n  color: #bd2c00;\n  background-color: #ffecec;\n}\n\n.hljs-link {\n  text-decoration: underline;\n}\n"
  },
  {
    "path": "lib/highlight/styles/github.css",
    "content": "/*\n\ngithub.com style (c) Vasily Polovnyov <vast@whiteants.net>\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  color: #333;\n  background: #f8f8f8;\n}\n\n.hljs-comment,\n.hljs-quote {\n  color: #998;\n  font-style: italic;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-subst {\n  color: #333;\n  font-weight: bold;\n}\n\n.hljs-number,\n.hljs-literal,\n.hljs-variable,\n.hljs-template-variable,\n.hljs-tag .hljs-attr {\n  color: #008080;\n}\n\n.hljs-string,\n.hljs-doctag {\n  color: #d14;\n}\n\n.hljs-title,\n.hljs-section,\n.hljs-selector-id {\n  color: #900;\n  font-weight: bold;\n}\n\n.hljs-subst {\n  font-weight: normal;\n}\n\n.hljs-type,\n.hljs-class .hljs-title {\n  color: #458;\n  font-weight: bold;\n}\n\n.hljs-tag,\n.hljs-name,\n.hljs-attribute {\n  color: #000080;\n  font-weight: normal;\n}\n\n.hljs-regexp,\n.hljs-link {\n  color: #009926;\n}\n\n.hljs-symbol,\n.hljs-bullet {\n  color: #990073;\n}\n\n.hljs-built_in,\n.hljs-builtin-name {\n  color: #0086b3;\n}\n\n.hljs-meta {\n  color: #999;\n  font-weight: bold;\n}\n\n.hljs-deletion {\n  background: #fdd;\n}\n\n.hljs-addition {\n  background: #dfd;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/googlecode.css",
    "content": "/*\n\nGoogle Code style (c) Aahan Krish <geekpanth3r@gmail.com>\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: white;\n  color: black;\n}\n\n.hljs-comment,\n.hljs-quote {\n  color: #800;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-section,\n.hljs-title,\n.hljs-name {\n  color: #008;\n}\n\n.hljs-variable,\n.hljs-template-variable {\n  color: #660;\n}\n\n.hljs-string,\n.hljs-selector-attr,\n.hljs-selector-pseudo,\n.hljs-regexp {\n  color: #080;\n}\n\n.hljs-literal,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-meta,\n.hljs-number,\n.hljs-link {\n  color: #066;\n}\n\n.hljs-title,\n.hljs-doctag,\n.hljs-type,\n.hljs-attr,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-params {\n  color: #606;\n}\n\n.hljs-attribute,\n.hljs-subst {\n  color: #000;\n}\n\n.hljs-formula {\n  background-color: #eee;\n  font-style: italic;\n}\n\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #9B703F\n}\n\n.hljs-addition {\n  background-color: #baeeba;\n}\n\n.hljs-deletion {\n  background-color: #ffc8bd;\n}\n\n.hljs-doctag,\n.hljs-strong {\n  font-weight: bold;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n"
  },
  {
    "path": "lib/highlight/styles/grayscale.css",
    "content": "/*\n\ngrayscale style (c) MY Sun <simonmysun@gmail.com>\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  color: #333;\n  background: #fff;\n}\n\n.hljs-comment,\n.hljs-quote {\n  color: #777;\n  font-style: italic;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-subst {\n  color: #333;\n  font-weight: bold;\n}\n\n.hljs-number,\n.hljs-literal {\n  color: #777;\n}\n\n.hljs-string,\n.hljs-doctag,\n.hljs-formula {\n  color: #333;\n  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAJ0lEQVQIW2O8e/fufwYGBgZBQUEQxcCIIfDu3Tuwivfv30NUoAsAALHpFMMLqZlPAAAAAElFTkSuQmCC) repeat;\n}\n\n.hljs-title,\n.hljs-section,\n.hljs-selector-id {\n  color: #000;\n  font-weight: bold;\n}\n\n.hljs-subst {\n  font-weight: normal;\n}\n\n.hljs-class .hljs-title,\n.hljs-type,\n.hljs-name {\n  color: #333;\n  font-weight: bold;\n}\n\n.hljs-tag {\n  color: #333;\n}\n\n.hljs-regexp {\n    color: #333;\n    background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAICAYAAADA+m62AAAAPUlEQVQYV2NkQAN37979r6yszIgujiIAU4RNMVwhuiQ6H6wQl3XI4oy4FMHcCJPHcDS6J2A2EqUQpJhohQDexSef15DBCwAAAABJRU5ErkJggg==) repeat;\n}\n\n.hljs-symbol,\n.hljs-bullet,\n.hljs-link {\n  color: #000;\n  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAKElEQVQIW2NkQAO7d+/+z4gsBhJwdXVlhAvCBECKwIIwAbhKZBUwBQA6hBpm5efZsgAAAABJRU5ErkJggg==) repeat;\n}\n\n.hljs-built_in,\n.hljs-builtin-name {\n  color: #000;\n  text-decoration: underline;\n}\n\n.hljs-meta {\n  color: #999;\n  font-weight: bold;\n}\n\n.hljs-deletion {\n  color: #fff;\n  background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAADCAYAAABS3WWCAAAAE0lEQVQIW2MMDQ39zzhz5kwIAQAyxweWgUHd1AAAAABJRU5ErkJggg==) repeat;\n}\n\n.hljs-addition {\n  color: #000;\n  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAALUlEQVQYV2N89+7dfwYk8P79ewZBQUFkIQZGOiu6e/cuiptQHAPl0NtNxAQBAM97Oejj3Dg7AAAAAElFTkSuQmCC) repeat;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/gruvbox-dark.css",
    "content": "/*\n\nGruvbox style (dark) (c) Pavel Pertsev (original style at https://github.com/morhetz/gruvbox)\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #282828;\n}\n\n.hljs,\n.hljs-subst {\n  color: #ebdbb2;\n}\n\n/* Gruvbox Red */\n.hljs-deletion,\n.hljs-formula,\n.hljs-keyword,\n.hljs-link,\n.hljs-selector-tag {\n  color: #fb4934;\n}\n\n/* Gruvbox Blue */\n.hljs-built_in,\n.hljs-emphasis,\n.hljs-name,\n.hljs-quote,\n.hljs-strong,\n.hljs-title,\n.hljs-variable {\n  color: #83a598;\n}\n\n/* Gruvbox Yellow */\n.hljs-attr,\n.hljs-params,\n.hljs-template-tag,\n.hljs-type {\n  color: #fabd2f;\n}\n\n/* Gruvbox Purple */\n.hljs-builtin-name,\n.hljs-doctag,\n.hljs-literal,\n.hljs-number {\n  color: #8f3f71;\n}\n\n/* Gruvbox Orange */\n.hljs-code,\n.hljs-meta,\n.hljs-regexp,\n.hljs-selector-id,\n.hljs-template-variable {\n  color: #fe8019;\n}\n\n/* Gruvbox Green */\n.hljs-addition,\n.hljs-meta-string,\n.hljs-section,\n.hljs-selector-attr,\n.hljs-selector-class,\n.hljs-string,\n.hljs-symbol {\n  color: #b8bb26;\n}\n\n/* Gruvbox Aqua */\n.hljs-attribute,\n.hljs-bullet,\n.hljs-class,\n.hljs-function,\n.hljs-function .hljs-keyword,\n.hljs-meta-keyword,\n.hljs-selector-pseudo,\n.hljs-tag {\n  color: #8ec07c;\n}\n\n/* Gruvbox Gray */\n.hljs-comment {\n  color: #928374;\n}\n\n/* Gruvbox Purple */\n.hljs-link_label,\n.hljs-literal,\n.hljs-number {\n  color: #d3869b;\n}\n\n.hljs-comment,\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-section,\n.hljs-strong,\n.hljs-tag {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/gruvbox-light.css",
    "content": "/*\n\nGruvbox style (light) (c) Pavel Pertsev (original style at https://github.com/morhetz/gruvbox)\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #fbf1c7;\n}\n\n.hljs,\n.hljs-subst {\n  color: #3c3836;\n}\n\n/* Gruvbox Red */\n.hljs-deletion,\n.hljs-formula,\n.hljs-keyword,\n.hljs-link,\n.hljs-selector-tag {\n  color: #9d0006;\n}\n\n/* Gruvbox Blue */\n.hljs-built_in,\n.hljs-emphasis,\n.hljs-name,\n.hljs-quote,\n.hljs-strong,\n.hljs-title,\n.hljs-variable {\n  color: #076678;\n}\n\n/* Gruvbox Yellow */\n.hljs-attr,\n.hljs-params,\n.hljs-template-tag,\n.hljs-type {\n  color: #b57614;\n}\n\n/* Gruvbox Purple */\n.hljs-builtin-name,\n.hljs-doctag,\n.hljs-literal,\n.hljs-number {\n  color: #8f3f71;\n}\n\n/* Gruvbox Orange */\n.hljs-code,\n.hljs-meta,\n.hljs-regexp,\n.hljs-selector-id,\n.hljs-template-variable {\n  color: #af3a03;\n}\n\n/* Gruvbox Green */\n.hljs-addition,\n.hljs-meta-string,\n.hljs-section,\n.hljs-selector-attr,\n.hljs-selector-class,\n.hljs-string,\n.hljs-symbol {\n  color: #79740e;\n}\n\n/* Gruvbox Aqua */\n.hljs-attribute,\n.hljs-bullet,\n.hljs-class,\n.hljs-function,\n.hljs-function .hljs-keyword,\n.hljs-meta-keyword,\n.hljs-selector-pseudo,\n.hljs-tag {\n  color: #427b58;\n}\n\n/* Gruvbox Gray */\n.hljs-comment {\n  color: #928374;\n}\n\n/* Gruvbox Purple */\n.hljs-link_label,\n.hljs-literal,\n.hljs-number {\n  color: #8f3f71;\n}\n\n.hljs-comment,\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-section,\n.hljs-strong,\n.hljs-tag {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/hopscotch.css",
    "content": "/*\n * Hopscotch\n * by Jan T. Sott\n * https://github.com/idleberg/Hopscotch\n *\n * This work is licensed under the Creative Commons CC0 1.0 Universal License\n */\n\n/* Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #989498;\n}\n\n/* Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute,\n.hljs-tag,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-regexp,\n.hljs-link,\n.hljs-deletion {\n  color: #dd464c;\n}\n\n/* Orange */\n.hljs-number,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params {\n  color: #fd8b19;\n}\n\n/* Yellow */\n.hljs-class .hljs-title {\n  color: #fdcc59;\n}\n\n/* Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-addition {\n  color: #8fc13e;\n}\n\n/* Aqua */\n.hljs-meta {\n  color: #149b93;\n}\n\n/* Blue */\n.hljs-function,\n.hljs-section,\n.hljs-title {\n  color: #1290bf;\n}\n\n/* Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #c85e7c;\n}\n\n.hljs {\n  display: block;\n  background: #322931;\n  color: #b9b5b8;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/hybrid.css",
    "content": "/*\n\nvim-hybrid theme by w0ng (https://github.com/w0ng/vim-hybrid)\n\n*/\n\n/*background color*/\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #1d1f21;\n}\n\n/*selection color*/\n.hljs::selection,\n.hljs span::selection {\n  background: #373b41;\n}\n\n.hljs::-moz-selection,\n.hljs span::-moz-selection {\n  background: #373b41;\n}\n\n/*foreground color*/\n.hljs {\n  color: #c5c8c6;\n}\n\n/*color: fg_yellow*/\n.hljs-title,\n.hljs-name {\n  color: #f0c674;\n}\n\n/*color: fg_comment*/\n.hljs-comment,\n.hljs-meta,\n.hljs-meta .hljs-keyword {\n  color: #707880;\n}\n\n/*color: fg_red*/\n.hljs-number,\n.hljs-symbol,\n.hljs-literal,\n.hljs-deletion,\n.hljs-link {\n color: #cc6666\n}\n\n/*color: fg_green*/\n.hljs-string,\n.hljs-doctag,\n.hljs-addition,\n.hljs-regexp,\n.hljs-selector-attr,\n.hljs-selector-pseudo {\n  color: #b5bd68;\n}\n\n/*color: fg_purple*/\n.hljs-attribute,\n.hljs-code,\n.hljs-selector-id {\n color: #b294bb;\n}\n\n/*color: fg_blue*/\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-bullet,\n.hljs-tag {\n color: #81a2be;\n}\n\n/*color: fg_aqua*/\n.hljs-subst,\n.hljs-variable,\n.hljs-template-tag,\n.hljs-template-variable {\n  color: #8abeb7;\n}\n\n/*color: fg_orange*/\n.hljs-type,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-quote,\n.hljs-section,\n.hljs-selector-class {\n  color: #de935f;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/idea.css",
    "content": "/*\n\nIntellij Idea-like styling (c) Vasily Polovnyov <vast@whiteants.net>\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  color: #000;\n  background: #fff;\n}\n\n.hljs-subst,\n.hljs-title {\n  font-weight: normal;\n  color: #000;\n}\n\n.hljs-comment,\n.hljs-quote {\n  color: #808080;\n  font-style: italic;\n}\n\n.hljs-meta {\n  color: #808000;\n}\n\n.hljs-tag {\n  background: #efefef;\n}\n\n.hljs-section,\n.hljs-name,\n.hljs-literal,\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-type,\n.hljs-selector-id,\n.hljs-selector-class {\n  font-weight: bold;\n  color: #000080;\n}\n\n.hljs-attribute,\n.hljs-number,\n.hljs-regexp,\n.hljs-link {\n  font-weight: bold;\n  color: #0000ff;\n}\n\n.hljs-number,\n.hljs-regexp,\n.hljs-link {\n  font-weight: normal;\n}\n\n.hljs-string {\n  color: #008000;\n  font-weight: bold;\n}\n\n.hljs-symbol,\n.hljs-bullet,\n.hljs-formula {\n  color: #000;\n  background: #d0eded;\n  font-style: italic;\n}\n\n.hljs-doctag {\n  text-decoration: underline;\n}\n\n.hljs-variable,\n.hljs-template-variable {\n  color: #660e7a;\n}\n\n.hljs-addition {\n  background: #baeeba;\n}\n\n.hljs-deletion {\n  background: #ffc8bd;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/ir-black.css",
    "content": "/*\n  IR_Black style (c) Vasily Mikhailitchenko <vaskas@programica.ru>\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #000;\n  color: #f8f8f8;\n}\n\n.hljs-comment,\n.hljs-quote,\n.hljs-meta {\n  color: #7c7c7c;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-tag,\n.hljs-name {\n  color: #96cbfe;\n}\n\n.hljs-attribute,\n.hljs-selector-id {\n  color: #ffffb6;\n}\n\n.hljs-string,\n.hljs-selector-attr,\n.hljs-selector-pseudo,\n.hljs-addition {\n  color: #a8ff60;\n}\n\n.hljs-subst {\n  color: #daefa3;\n}\n\n.hljs-regexp,\n.hljs-link {\n  color: #e9c062;\n}\n\n.hljs-title,\n.hljs-section,\n.hljs-type,\n.hljs-doctag {\n  color: #ffffb6;\n}\n\n.hljs-symbol,\n.hljs-bullet,\n.hljs-variable,\n.hljs-template-variable,\n.hljs-literal {\n  color: #c6c5fe;\n}\n\n.hljs-number,\n.hljs-deletion {\n  color:#ff73fd;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/kimbie.dark.css",
    "content": "/*\n    Name:     Kimbie (dark)\n    Author:   Jan T. Sott\n    License:  Creative Commons Attribution-ShareAlike 4.0 Unported License\n    URL:      https://github.com/idleberg/Kimbie-highlight.js\n*/\n\n/* Kimbie Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #d6baad;\n}\n\n/* Kimbie Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-tag,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-regexp,\n.hljs-meta {\n  color: #dc3958;\n}\n\n/* Kimbie Orange */\n.hljs-number,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params,\n.hljs-deletion,\n.hljs-link {\n  color: #f79a32;\n}\n\n/* Kimbie Yellow */\n.hljs-title,\n.hljs-section,\n.hljs-attribute {\n  color: #f06431;\n}\n\n/* Kimbie Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-addition {\n  color: #889b4a;\n}\n\n/* Kimbie Purple */\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-function {\n  color: #98676a;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #221a0f;\n  color: #d3af86;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/kimbie.light.css",
    "content": "/*\n    Name:     Kimbie (light)\n    Author:   Jan T. Sott\n    License:  Creative Commons Attribution-ShareAlike 4.0 Unported License\n    URL:      https://github.com/idleberg/Kimbie-highlight.js\n*/\n\n/* Kimbie Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #a57a4c;\n}\n\n/* Kimbie Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-tag,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-regexp,\n.hljs-meta {\n  color: #dc3958;\n}\n\n/* Kimbie Orange */\n.hljs-number,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params,\n.hljs-deletion,\n.hljs-link {\n  color: #f79a32;\n}\n\n/* Kimbie Yellow */\n.hljs-title,\n.hljs-section,\n.hljs-attribute {\n  color: #f06431;\n}\n\n/* Kimbie Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-addition {\n  color: #889b4a;\n}\n\n/* Kimbie Purple */\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-function {\n  color: #98676a;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #fbebd4;\n  color: #84613d;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/magula.css",
    "content": "/*\nDescription: Magula style for highligh.js\nAuthor: Ruslan Keba <rukeba@gmail.com>\nWebsite: http://rukeba.com/\nVersion: 1.0\nDate: 2009-01-03\nMusic: Aphex Twin / Xtal\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background-color: #f4f4f4;\n}\n\n.hljs,\n.hljs-subst {\n  color: black;\n}\n\n.hljs-string,\n.hljs-title,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-attribute,\n.hljs-addition,\n.hljs-variable,\n.hljs-template-tag,\n.hljs-template-variable {\n  color: #050;\n}\n\n.hljs-comment,\n.hljs-quote {\n  color: #777;\n}\n\n.hljs-number,\n.hljs-regexp,\n.hljs-literal,\n.hljs-type,\n.hljs-link {\n  color: #800;\n}\n\n.hljs-deletion,\n.hljs-meta {\n  color: #00e;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-doctag,\n.hljs-title,\n.hljs-section,\n.hljs-built_in,\n.hljs-tag,\n.hljs-name {\n  font-weight: bold;\n  color: navy;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/mono-blue.css",
    "content": "/*\n  Five-color theme from a single blue hue.\n*/\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #eaeef3;\n}\n\n.hljs {\n  color: #00193a;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-title,\n.hljs-section,\n.hljs-doctag,\n.hljs-name,\n.hljs-strong {\n  font-weight: bold;\n}\n\n.hljs-comment {\n  color: #738191;\n}\n\n.hljs-string,\n.hljs-title,\n.hljs-section,\n.hljs-built_in,\n.hljs-literal,\n.hljs-type,\n.hljs-addition,\n.hljs-tag,\n.hljs-quote,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #0048ab;\n}\n\n.hljs-meta,\n.hljs-subst,\n.hljs-symbol,\n.hljs-regexp,\n.hljs-attribute,\n.hljs-deletion,\n.hljs-variable,\n.hljs-template-variable,\n.hljs-link,\n.hljs-bullet {\n  color: #4c81c9;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n"
  },
  {
    "path": "lib/highlight/styles/monokai-sublime.css",
    "content": "/*\n\nMonokai Sublime style. Derived from Monokai by noformnocontent http://nn.mit-license.org/\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #23241f;\n}\n\n.hljs,\n.hljs-tag,\n.hljs-subst {\n  color: #f8f8f2;\n}\n\n.hljs-strong,\n.hljs-emphasis {\n  color: #a8a8a2;\n}\n\n.hljs-bullet,\n.hljs-quote,\n.hljs-number,\n.hljs-regexp,\n.hljs-literal,\n.hljs-link {\n  color: #ae81ff;\n}\n\n.hljs-code,\n.hljs-title,\n.hljs-section,\n.hljs-selector-class {\n  color: #a6e22e;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-name,\n.hljs-attr {\n  color: #f92672;\n}\n\n.hljs-symbol,\n.hljs-attribute {\n  color: #66d9ef;\n}\n\n.hljs-params,\n.hljs-class .hljs-title {\n  color: #f8f8f2;\n}\n\n.hljs-string,\n.hljs-type,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-selector-id,\n.hljs-selector-attr,\n.hljs-selector-pseudo,\n.hljs-addition,\n.hljs-variable,\n.hljs-template-variable {\n  color: #e6db74;\n}\n\n.hljs-comment,\n.hljs-deletion,\n.hljs-meta {\n  color: #75715e;\n}\n"
  },
  {
    "path": "lib/highlight/styles/monokai.css",
    "content": "/*\nMonokai style - ported by Luigi Maselli - http://grigio.org\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #272822; color: #ddd;\n}\n\n.hljs-tag,\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-literal,\n.hljs-strong,\n.hljs-name {\n  color: #f92672;\n}\n\n.hljs-code {\n  color: #66d9ef;\n}\n\n.hljs-class .hljs-title {\n  color: white;\n}\n\n.hljs-attribute,\n.hljs-symbol,\n.hljs-regexp,\n.hljs-link {\n  color: #bf79db;\n}\n\n.hljs-string,\n.hljs-bullet,\n.hljs-subst,\n.hljs-title,\n.hljs-section,\n.hljs-emphasis,\n.hljs-type,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-selector-attr,\n.hljs-selector-pseudo,\n.hljs-addition,\n.hljs-variable,\n.hljs-template-tag,\n.hljs-template-variable {\n  color: #a6e22e;\n}\n\n.hljs-comment,\n.hljs-quote,\n.hljs-deletion,\n.hljs-meta {\n  color: #75715e;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-literal,\n.hljs-doctag,\n.hljs-title,\n.hljs-section,\n.hljs-type,\n.hljs-selector-id {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/obsidian.css",
    "content": "/**\n * Obsidian style\n * ported by Alexander Marenin (http://github.com/ioncreature)\n */\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #282b2e;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-literal,\n.hljs-selector-id {\n  color: #93c763;\n}\n\n.hljs-number {\n  color: #ffcd22;\n}\n\n.hljs {\n  color: #e0e2e4;\n}\n\n.hljs-attribute {\n  color: #668bb0;\n}\n\n.hljs-code,\n.hljs-class .hljs-title,\n.hljs-section {\n  color: white;\n}\n\n.hljs-regexp,\n.hljs-link {\n  color: #d39745;\n}\n\n.hljs-meta {\n  color: #557182;\n}\n\n.hljs-tag,\n.hljs-name,\n.hljs-bullet,\n.hljs-subst,\n.hljs-emphasis,\n.hljs-type,\n.hljs-built_in,\n.hljs-selector-attr,\n.hljs-selector-pseudo,\n.hljs-addition,\n.hljs-variable,\n.hljs-template-tag,\n.hljs-template-variable {\n  color: #8cbbad;\n}\n\n.hljs-string,\n.hljs-symbol {\n  color: #ec7600;\n}\n\n.hljs-comment,\n.hljs-quote,\n.hljs-deletion {\n  color: #818e96;\n}\n\n.hljs-selector-class {\n  color: #A082BD\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-literal,\n.hljs-doctag,\n.hljs-title,\n.hljs-section,\n.hljs-type,\n.hljs-name,\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/ocean.css",
    "content": "/* Ocean Dark Theme */\n/* https://github.com/gavsiu */\n/* Original theme - https://github.com/chriskempson/base16 */\n\n/* Ocean Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #65737e;\n}\n\n/* Ocean Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-tag,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-regexp,\n.hljs-deletion {\n  color: #bf616a;\n}\n\n/* Ocean Orange */\n.hljs-number,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params,\n.hljs-meta,\n.hljs-link {\n  color: #d08770;\n}\n\n/* Ocean Yellow */\n.hljs-attribute {\n  color: #ebcb8b;\n}\n\n/* Ocean Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-addition {\n  color: #a3be8c;\n}\n\n/* Ocean Blue */\n.hljs-title,\n.hljs-section {\n  color: #8fa1b3;\n}\n\n/* Ocean Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #b48ead;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #2b303b;\n  color: #c0c5ce;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/paraiso-dark.css",
    "content": "/*\n    Paraíso (dark)\n    Created by Jan T. Sott (http://github.com/idleberg)\n    Inspired by the art of Rubens LP (http://www.rubenslp.com.br)\n*/\n\n/* Paraíso Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #8d8687;\n}\n\n/* Paraíso Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-tag,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-regexp,\n.hljs-link,\n.hljs-meta {\n  color: #ef6155;\n}\n\n/* Paraíso Orange */\n.hljs-number,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params,\n.hljs-deletion {\n  color: #f99b15;\n}\n\n/* Paraíso Yellow */\n.hljs-title,\n.hljs-section,\n.hljs-attribute {\n  color: #fec418;\n}\n\n/* Paraíso Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-addition {\n  color: #48b685;\n}\n\n/* Paraíso Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #815ba4;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #2f1e2e;\n  color: #a39e9b;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/paraiso-light.css",
    "content": "/*\n    Paraíso (light)\n    Created by Jan T. Sott (http://github.com/idleberg)\n    Inspired by the art of Rubens LP (http://www.rubenslp.com.br)\n*/\n\n/* Paraíso Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #776e71;\n}\n\n/* Paraíso Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-tag,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-regexp,\n.hljs-link,\n.hljs-meta {\n  color: #ef6155;\n}\n\n/* Paraíso Orange */\n.hljs-number,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params,\n.hljs-deletion {\n  color: #f99b15;\n}\n\n/* Paraíso Yellow */\n.hljs-title,\n.hljs-section,\n.hljs-attribute {\n  color: #fec418;\n}\n\n/* Paraíso Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-addition {\n  color: #48b685;\n}\n\n/* Paraíso Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #815ba4;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #e7e9db;\n  color: #4f424c;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/pojoaque.css",
    "content": "/*\n\nPojoaque Style by Jason Tate\nhttp://web-cms-designs.com/ftopict-10-pojoaque-style-for-highlight-js-code-highlighter.html\nBased on Solarized Style from http://ethanschoonover.com/solarized\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  color: #dccf8f;\n  background: url(./pojoaque.jpg) repeat scroll left top #181914;\n}\n\n.hljs-comment,\n.hljs-quote {\n  color: #586e75;\n  font-style: italic;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-literal,\n.hljs-addition {\n  color: #b64926;\n}\n\n.hljs-number,\n.hljs-string,\n.hljs-doctag,\n.hljs-regexp {\n  color: #468966;\n}\n\n.hljs-title,\n.hljs-section,\n.hljs-built_in,\n.hljs-name {\n  color: #ffb03b;\n}\n\n.hljs-variable,\n.hljs-template-variable,\n.hljs-class .hljs-title,\n.hljs-type,\n.hljs-tag {\n  color: #b58900;\n}\n\n.hljs-attribute {\n  color: #b89859;\n}\n\n.hljs-symbol,\n.hljs-bullet,\n.hljs-link,\n.hljs-subst,\n.hljs-meta {\n  color: #cb4b16;\n}\n\n.hljs-deletion {\n  color: #dc322f;\n}\n\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #d3a60c;\n}\n\n.hljs-formula {\n  background: #073642;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/purebasic.css",
    "content": "/*\n\nPureBASIC native IDE style ( version 1.0 - April 2016 )\n\nby Tristano Ajmone <tajmone@gmail.com>\n\nPublic Domain\n\nNOTE_1:\tPureBASIC code syntax highlighting only applies the following classes:\n\t\t\t.hljs-comment\n\t\t\t.hljs-function\n\t\t\t.hljs-keywords\n\t\t\t.hljs-string\n\t\t\t.hljs-symbol\n\n\t\tOther classes are added here for the benefit of styling other languages with the look and feel of PureBASIC native IDE style.\n\t\tIf you need to customize a stylesheet for PureBASIC only, remove all non-relevant classes -- PureBASIC-related classes are followed by\n\t\ta \"--- used for PureBASIC ... ---\" comment on same line.\n\nNOTE_2:\tColor names provided in comments were derived using \"Name that Color\" online tool:\n\t\t\thttp://chir.ag/projects/name-that-color\n*/\n\n.hljs { /* Common set of rules required by highlight.js (don'r remove!) */\n\tdisplay: block;\n\toverflow-x: auto;\n\tpadding: 0.5em;\n\tbackground: #FFFFDF; /* Half and Half (approx.) */\n/* --- Uncomment to add PureBASIC native IDE styled font!\n\tfont-family: Consolas;\n*/\n}\n\n.hljs, /* --- used for PureBASIC base color --- */\n.hljs-type,  /* --- used for PureBASIC Procedures return type --- */\n.hljs-function, /* --- used for wrapping PureBASIC Procedures definitions --- */\n.hljs-name,\n.hljs-number,\n.hljs-attr,\n.hljs-params,\n.hljs-subst {\n\tcolor: #000000; /* Black */\n}\n\n.hljs-comment, /* --- used for PureBASIC Comments --- */\n.hljs-regexp,\n.hljs-section,\n.hljs-selector-pseudo,\n.hljs-addition {\n\tcolor: #00AAAA; /* Persian Green (approx.) */\n}\n\n.hljs-title, /* --- used for PureBASIC Procedures Names --- */\n.hljs-tag,\n.hljs-variable,\n.hljs-code  {\n\tcolor: #006666; /* Blue Stone (approx.) */\n}\n\n.hljs-keyword, /* --- used for PureBASIC Keywords --- */\n.hljs-class,\n.hljs-meta-keyword,\n.hljs-selector-class,\n.hljs-built_in,\n.hljs-builtin-name {\n\tcolor: #006666; /* Blue Stone (approx.) */\n\tfont-weight: bold;\n}\n\n.hljs-string, /* --- used for PureBASIC Strings --- */\n.hljs-selector-attr {\n\tcolor: #0080FF; /* Azure Radiance (approx.) */\n}\n\n.hljs-symbol, /* --- used for PureBASIC Constants --- */\n.hljs-link,\n.hljs-deletion,\n.hljs-attribute {\n\tcolor: #924B72; /* Cannon Pink (approx.) */\n}\n\n.hljs-meta,\n.hljs-literal,\n.hljs-selector-id {\n\tcolor: #924B72; /* Cannon Pink (approx.) */\n\tfont-weight: bold;\n}\n\n.hljs-strong,\n.hljs-name {\n\tfont-weight: bold;\n}\n\n.hljs-emphasis {\n\tfont-style: italic;\n}\n"
  },
  {
    "path": "lib/highlight/styles/qtcreator_dark.css",
    "content": "/*\n\nQt Creator dark color scheme\n\n*/\n\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #000000;\n}\n\n.hljs,\n.hljs-subst,\n.hljs-tag,\n.hljs-title {\n  color: #aaaaaa;\n}\n\n.hljs-strong,\n.hljs-emphasis {\n  color: #a8a8a2;\n}\n\n.hljs-bullet,\n.hljs-quote,\n.hljs-number,\n.hljs-regexp,\n.hljs-literal {\n  color: #ff55ff;\n}\n\n.hljs-code\n.hljs-selector-class {\n  color: #aaaaff;\n}\n\n.hljs-emphasis,\n.hljs-stronge,\n.hljs-type {\n  font-style: italic;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-function,\n.hljs-section,\n.hljs-symbol,\n.hljs-name {\n  color: #ffff55;\n}\n\n.hljs-attribute {\n  color: #ff5555;\n}\n\n.hljs-variable,\n.hljs-params,\n.hljs-class .hljs-title {\n  color: #8888ff;\n}\n\n.hljs-string,\n.hljs-selector-id,\n.hljs-selector-attr,\n.hljs-selector-pseudo,\n.hljs-type,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-template-tag,\n.hljs-template-variable,\n.hljs-addition,\n.hljs-link {\n  color: #ff55ff;\n}\n\n.hljs-comment,\n.hljs-meta,\n.hljs-deletion {\n  color: #55ffff;\n}\n"
  },
  {
    "path": "lib/highlight/styles/qtcreator_light.css",
    "content": "/*\n\nQt Creator light color scheme\n\n*/\n\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #ffffff;\n}\n\n.hljs,\n.hljs-subst,\n.hljs-tag,\n.hljs-title {\n  color: #000000;\n}\n\n.hljs-strong,\n.hljs-emphasis {\n  color: #000000;\n}\n\n.hljs-bullet,\n.hljs-quote,\n.hljs-number,\n.hljs-regexp,\n.hljs-literal {\n  color: #000080;\n}\n\n.hljs-code\n.hljs-selector-class {\n  color: #800080;\n}\n\n.hljs-emphasis,\n.hljs-stronge,\n.hljs-type {\n  font-style: italic;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-function,\n.hljs-section,\n.hljs-symbol,\n.hljs-name {\n  color: #808000;\n}\n\n.hljs-attribute {\n  color: #800000;\n}\n\n.hljs-variable,\n.hljs-params,\n.hljs-class .hljs-title {\n  color: #0055AF;\n}\n\n.hljs-string,\n.hljs-selector-id,\n.hljs-selector-attr,\n.hljs-selector-pseudo,\n.hljs-type,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-template-tag,\n.hljs-template-variable,\n.hljs-addition,\n.hljs-link {\n  color: #008000;\n}\n\n.hljs-comment,\n.hljs-meta,\n.hljs-deletion {\n  color: #008000;\n}\n"
  },
  {
    "path": "lib/highlight/styles/railscasts.css",
    "content": "/*\n\nRailscasts-like style (c) Visoft, Inc. (Damien White)\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #232323;\n  color: #e6e1dc;\n}\n\n.hljs-comment,\n.hljs-quote {\n  color: #bc9458;\n  font-style: italic;\n}\n\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #c26230;\n}\n\n.hljs-string,\n.hljs-number,\n.hljs-regexp,\n.hljs-variable,\n.hljs-template-variable {\n  color: #a5c261;\n}\n\n.hljs-subst {\n  color: #519f50;\n}\n\n.hljs-tag,\n.hljs-name {\n  color: #e8bf6a;\n}\n\n.hljs-type {\n  color: #da4939;\n}\n\n\n.hljs-symbol,\n.hljs-bullet,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-attr,\n.hljs-link {\n  color: #6d9cbe;\n}\n\n.hljs-params {\n  color: #d0d0ff;\n}\n\n.hljs-attribute {\n  color: #cda869;\n}\n\n.hljs-meta {\n  color: #9b859d;\n}\n\n.hljs-title,\n.hljs-section {\n  color: #ffc66d;\n}\n\n.hljs-addition {\n  background-color: #144212;\n  color: #e6e1dc;\n  display: inline-block;\n  width: 100%;\n}\n\n.hljs-deletion {\n  background-color: #600;\n  color: #e6e1dc;\n  display: inline-block;\n  width: 100%;\n}\n\n.hljs-selector-class {\n  color: #9b703f;\n}\n\n.hljs-selector-id {\n  color: #8b98ab;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n\n.hljs-link {\n  text-decoration: underline;\n}\n"
  },
  {
    "path": "lib/highlight/styles/rainbow.css",
    "content": "/*\n\nStyle with support for rainbow parens\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #474949;\n  color: #d1d9e1;\n}\n\n\n.hljs-comment,\n.hljs-quote {\n  color: #969896;\n  font-style: italic;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-literal,\n.hljs-type,\n.hljs-addition {\n  color: #cc99cc;\n}\n\n.hljs-number,\n.hljs-selector-attr,\n.hljs-selector-pseudo {\n  color: #f99157;\n}\n\n.hljs-string,\n.hljs-doctag,\n.hljs-regexp {\n  color: #8abeb7;\n}\n\n.hljs-title,\n.hljs-name,\n.hljs-section,\n.hljs-built_in {\n  color: #b5bd68;\n}\n\n.hljs-variable,\n.hljs-template-variable,\n.hljs-selector-id,\n.hljs-class .hljs-title {\n   color: #ffcc66;\n}\n\n.hljs-section,\n.hljs-name,\n.hljs-strong {\n  font-weight: bold;\n}\n\n.hljs-symbol,\n.hljs-bullet,\n.hljs-subst,\n.hljs-meta,\n.hljs-link {\n  color: #f99157;\n}\n\n.hljs-deletion {\n  color: #dc322f;\n}\n\n.hljs-formula {\n  background: #eee8d5;\n}\n\n.hljs-attr,\n.hljs-attribute {\n  color: #81a2be;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n"
  },
  {
    "path": "lib/highlight/styles/school-book.css",
    "content": "/*\n\nSchool Book style from goldblog.com.ua (c) Zaripov Yura <yur4ik7@ukr.net>\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 15px 0.5em 0.5em 30px;\n  font-size: 11px;\n  line-height:16px;\n}\n\npre{\n  background:#f6f6ae url(./school-book.png);\n  border-top: solid 2px #d2e8b9;\n  border-bottom: solid 1px #d2e8b9;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-literal {\n  color:#005599;\n  font-weight:bold;\n}\n\n.hljs,\n.hljs-subst {\n  color: #3e5915;\n}\n\n.hljs-string,\n.hljs-title,\n.hljs-section,\n.hljs-type,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-attribute,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-addition,\n.hljs-variable,\n.hljs-template-tag,\n.hljs-template-variable,\n.hljs-link {\n  color: #2c009f;\n}\n\n.hljs-comment,\n.hljs-quote,\n.hljs-deletion,\n.hljs-meta {\n  color: #e60415;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-literal,\n.hljs-doctag,\n.hljs-title,\n.hljs-section,\n.hljs-type,\n.hljs-name,\n.hljs-selector-id,\n.hljs-strong {\n  font-weight: bold;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n"
  },
  {
    "path": "lib/highlight/styles/solarized-dark.css",
    "content": "/*\n\nOrginal Style from ethanschoonover.com/solarized (c) Jeremy Hull <sourdrums@gmail.com>\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #002b36;\n  color: #839496;\n}\n\n.hljs-comment,\n.hljs-quote {\n  color: #586e75;\n}\n\n/* Solarized Green */\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-addition {\n  color: #859900;\n}\n\n/* Solarized Cyan */\n.hljs-number,\n.hljs-string,\n.hljs-meta .hljs-meta-string,\n.hljs-literal,\n.hljs-doctag,\n.hljs-regexp {\n  color: #2aa198;\n}\n\n/* Solarized Blue */\n.hljs-title,\n.hljs-section,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #268bd2;\n}\n\n/* Solarized Yellow */\n.hljs-attribute,\n.hljs-attr,\n.hljs-variable,\n.hljs-template-variable,\n.hljs-class .hljs-title,\n.hljs-type {\n  color: #b58900;\n}\n\n/* Solarized Orange */\n.hljs-symbol,\n.hljs-bullet,\n.hljs-subst,\n.hljs-meta,\n.hljs-meta .hljs-keyword,\n.hljs-selector-attr,\n.hljs-selector-pseudo,\n.hljs-link {\n  color: #cb4b16;\n}\n\n/* Solarized Red */\n.hljs-built_in,\n.hljs-deletion {\n  color: #dc322f;\n}\n\n.hljs-formula {\n  background: #073642;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/solarized-light.css",
    "content": "/*\n\nOrginal Style from ethanschoonover.com/solarized (c) Jeremy Hull <sourdrums@gmail.com>\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #fdf6e3;\n  color: #657b83;\n}\n\n.hljs-comment,\n.hljs-quote {\n  color: #93a1a1;\n}\n\n/* Solarized Green */\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-addition {\n  color: #859900;\n}\n\n/* Solarized Cyan */\n.hljs-number,\n.hljs-string,\n.hljs-meta .hljs-meta-string,\n.hljs-literal,\n.hljs-doctag,\n.hljs-regexp {\n  color: #2aa198;\n}\n\n/* Solarized Blue */\n.hljs-title,\n.hljs-section,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #268bd2;\n}\n\n/* Solarized Yellow */\n.hljs-attribute,\n.hljs-attr,\n.hljs-variable,\n.hljs-template-variable,\n.hljs-class .hljs-title,\n.hljs-type {\n  color: #b58900;\n}\n\n/* Solarized Orange */\n.hljs-symbol,\n.hljs-bullet,\n.hljs-subst,\n.hljs-meta,\n.hljs-meta .hljs-keyword,\n.hljs-selector-attr,\n.hljs-selector-pseudo,\n.hljs-link {\n  color: #cb4b16;\n}\n\n/* Solarized Red */\n.hljs-built_in,\n.hljs-deletion {\n  color: #dc322f;\n}\n\n.hljs-formula {\n  background: #eee8d5;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/sunburst.css",
    "content": "/*\n\nSunburst-like style (c) Vasily Polovnyov <vast@whiteants.net>\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #000;\n  color: #f8f8f8;\n}\n\n.hljs-comment,\n.hljs-quote {\n  color: #aeaeae;\n  font-style: italic;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-type {\n  color: #e28964;\n}\n\n.hljs-string {\n  color: #65b042;\n}\n\n.hljs-subst {\n  color: #daefa3;\n}\n\n.hljs-regexp,\n.hljs-link {\n  color: #e9c062;\n}\n\n.hljs-title,\n.hljs-section,\n.hljs-tag,\n.hljs-name {\n  color: #89bdff;\n}\n\n.hljs-class .hljs-title,\n.hljs-doctag {\n  text-decoration: underline;\n}\n\n.hljs-symbol,\n.hljs-bullet,\n.hljs-number {\n  color: #3387cc;\n}\n\n.hljs-params,\n.hljs-variable,\n.hljs-template-variable {\n  color: #3e87e3;\n}\n\n.hljs-attribute {\n  color: #cda869;\n}\n\n.hljs-meta {\n  color: #8996a8;\n}\n\n.hljs-formula {\n  background-color: #0e2231;\n  color: #f8f8f8;\n  font-style: italic;\n}\n\n.hljs-addition {\n  background-color: #253b22;\n  color: #f8f8f8;\n}\n\n.hljs-deletion {\n  background-color: #420e09;\n  color: #f8f8f8;\n}\n\n.hljs-selector-class {\n  color: #9b703f;\n}\n\n.hljs-selector-id {\n  color: #8b98ab;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/tomorrow-night-blue.css",
    "content": "/* Tomorrow Night Blue Theme */\n/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */\n/* Original theme - https://github.com/chriskempson/tomorrow-theme */\n/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */\n\n/* Tomorrow Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #7285b7;\n}\n\n/* Tomorrow Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-tag,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-regexp,\n.hljs-deletion {\n  color: #ff9da4;\n}\n\n/* Tomorrow Orange */\n.hljs-number,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params,\n.hljs-meta,\n.hljs-link {\n  color: #ffc58f;\n}\n\n/* Tomorrow Yellow */\n.hljs-attribute {\n  color: #ffeead;\n}\n\n/* Tomorrow Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-addition {\n  color: #d1f1a9;\n}\n\n/* Tomorrow Blue */\n.hljs-title,\n.hljs-section {\n  color: #bbdaff;\n}\n\n/* Tomorrow Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #ebbbff;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #002451;\n  color: white;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/tomorrow-night-bright.css",
    "content": "/* Tomorrow Night Bright Theme */\n/* Original theme - https://github.com/chriskempson/tomorrow-theme */\n/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */\n\n/* Tomorrow Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #969896;\n}\n\n/* Tomorrow Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-tag,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-regexp,\n.hljs-deletion {\n  color: #d54e53;\n}\n\n/* Tomorrow Orange */\n.hljs-number,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params,\n.hljs-meta,\n.hljs-link {\n  color: #e78c45;\n}\n\n/* Tomorrow Yellow */\n.hljs-attribute {\n  color: #e7c547;\n}\n\n/* Tomorrow Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-addition {\n  color: #b9ca4a;\n}\n\n/* Tomorrow Blue */\n.hljs-title,\n.hljs-section {\n  color: #7aa6da;\n}\n\n/* Tomorrow Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #c397d8;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: black;\n  color: #eaeaea;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/tomorrow-night-eighties.css",
    "content": "/* Tomorrow Night Eighties Theme */\n/* Original theme - https://github.com/chriskempson/tomorrow-theme */\n/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */\n\n/* Tomorrow Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #999999;\n}\n\n/* Tomorrow Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-tag,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-regexp,\n.hljs-deletion {\n  color: #f2777a;\n}\n\n/* Tomorrow Orange */\n.hljs-number,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params,\n.hljs-meta,\n.hljs-link {\n  color: #f99157;\n}\n\n/* Tomorrow Yellow */\n.hljs-attribute {\n  color: #ffcc66;\n}\n\n/* Tomorrow Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-addition {\n  color: #99cc99;\n}\n\n/* Tomorrow Blue */\n.hljs-title,\n.hljs-section {\n  color: #6699cc;\n}\n\n/* Tomorrow Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #cc99cc;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #2d2d2d;\n  color: #cccccc;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/tomorrow-night.css",
    "content": "/* Tomorrow Night Theme */\n/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */\n/* Original theme - https://github.com/chriskempson/tomorrow-theme */\n/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */\n\n/* Tomorrow Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #969896;\n}\n\n/* Tomorrow Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-tag,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-regexp,\n.hljs-deletion {\n  color: #cc6666;\n}\n\n/* Tomorrow Orange */\n.hljs-number,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params,\n.hljs-meta,\n.hljs-link {\n  color: #de935f;\n}\n\n/* Tomorrow Yellow */\n.hljs-attribute {\n  color: #f0c674;\n}\n\n/* Tomorrow Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-addition {\n  color: #b5bd68;\n}\n\n/* Tomorrow Blue */\n.hljs-title,\n.hljs-section {\n  color: #81a2be;\n}\n\n/* Tomorrow Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #b294bb;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: #1d1f21;\n  color: #c5c8c6;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/tomorrow.css",
    "content": "/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */\n\n/* Tomorrow Comment */\n.hljs-comment,\n.hljs-quote {\n  color: #8e908c;\n}\n\n/* Tomorrow Red */\n.hljs-variable,\n.hljs-template-variable,\n.hljs-tag,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-regexp,\n.hljs-deletion {\n  color: #c82829;\n}\n\n/* Tomorrow Orange */\n.hljs-number,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-literal,\n.hljs-type,\n.hljs-params,\n.hljs-meta,\n.hljs-link {\n  color: #f5871f;\n}\n\n/* Tomorrow Yellow */\n.hljs-attribute {\n  color: #eab700;\n}\n\n/* Tomorrow Green */\n.hljs-string,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-addition {\n  color: #718c00;\n}\n\n/* Tomorrow Blue */\n.hljs-title,\n.hljs-section {\n  color: #4271ae;\n}\n\n/* Tomorrow Purple */\n.hljs-keyword,\n.hljs-selector-tag {\n  color: #8959a8;\n}\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  background: white;\n  color: #4d4d4c;\n  padding: 0.5em;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/vs.css",
    "content": "/*\n\nVisual Studio-like style based on original C# coloring by Jason Diamond <jason@diamond.name>\n\n*/\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: white;\n  color: black;\n}\n\n.hljs-comment,\n.hljs-quote,\n.hljs-variable {\n  color: #008000;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-built_in,\n.hljs-name,\n.hljs-tag {\n  color: #00f;\n}\n\n.hljs-string,\n.hljs-title,\n.hljs-section,\n.hljs-attribute,\n.hljs-literal,\n.hljs-template-tag,\n.hljs-template-variable,\n.hljs-type,\n.hljs-addition {\n  color: #a31515;\n}\n\n.hljs-deletion,\n.hljs-selector-attr,\n.hljs-selector-pseudo,\n.hljs-meta {\n  color: #2b91af;\n}\n\n.hljs-doctag {\n  color: #808080;\n}\n\n.hljs-attr {\n  color: #f00;\n}\n\n.hljs-symbol,\n.hljs-bullet,\n.hljs-link {\n  color: #00b0e8;\n}\n\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/highlight/styles/xcode.css",
    "content": "/*\n\nXCode style (c) Angel Garcia <angelgarcia.mail@gmail.com>\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #fff;\n  color: black;\n}\n\n.hljs-comment,\n.hljs-quote {\n  color: #006a00;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-literal {\n  color: #aa0d91;\n}\n\n.hljs-name {\n  color: #008;\n}\n\n.hljs-variable,\n.hljs-template-variable {\n  color: #660;\n}\n\n.hljs-string {\n  color: #c41a16;\n}\n\n.hljs-regexp,\n.hljs-link {\n  color: #080;\n}\n\n.hljs-title,\n.hljs-tag,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-number,\n.hljs-meta {\n  color: #1c00cf;\n}\n\n.hljs-section,\n.hljs-class .hljs-title,\n.hljs-type,\n.hljs-attr,\n.hljs-built_in,\n.hljs-builtin-name,\n.hljs-params {\n  color: #5c2699;\n}\n\n.hljs-attribute,\n.hljs-subst {\n  color: #000;\n}\n\n.hljs-formula {\n  background-color: #eee;\n  font-style: italic;\n}\n\n.hljs-addition {\n  background-color: #baeeba;\n}\n\n.hljs-deletion {\n  background-color: #ffc8bd;\n}\n\n.hljs-selector-id,\n.hljs-selector-class {\n  color: #9b703f;\n}\n\n.hljs-doctag,\n.hljs-strong {\n  font-weight: bold;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n"
  },
  {
    "path": "lib/highlight/styles/xt256.css",
    "content": "\n/*\n  xt256.css\n\n  Contact: initbar [at] protonmail [dot] ch\n         : github.com/initbar\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  color: #eaeaea;\n  background: #000;\n  padding: 0.5;\n}\n\n.hljs-subst {\n  color: #eaeaea;\n}\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n\n.hljs-builtin-name,\n.hljs-type {\n  color: #eaeaea;\n}\n\n.hljs-params {\n  color: #da0000;\n}\n\n.hljs-literal,\n.hljs-number,\n.hljs-name {\n  color: #ff0000;\n  font-weight: bolder;\n}\n\n.hljs-comment {\n  color: #969896;\n}\n\n.hljs-selector-id,\n.hljs-quote {\n  color: #00ffff;\n}\n\n.hljs-template-variable,\n.hljs-variable,\n.hljs-title {\n  color: #00ffff;\n  font-weight: bold;\n}\n\n.hljs-selector-class,\n.hljs-keyword,\n.hljs-symbol {\n  color: #fff000;\n}\n\n.hljs-string,\n.hljs-bullet {\n  color: #00ff00;\n}\n\n.hljs-tag,\n.hljs-section {\n  color: #000fff;\n}\n\n.hljs-selector-tag {\n  color: #000fff;\n  font-weight: bold;\n}\n\n.hljs-attribute,\n.hljs-built_in,\n.hljs-regexp,\n.hljs-link {\n  color: #ff00ff;\n}\n\n.hljs-meta {\n  color: #fff;\n  font-weight: bolder;\n}\n"
  },
  {
    "path": "lib/highlight/styles/zenburn.css",
    "content": "/*\n\nZenburn style from voldmar.ru (c) Vladimir Epifanov <voldmar@voldmar.ru>\nbased on dark.css by Ivan Sagalaev\n\n*/\n\n.hljs {\n  display: block;\n  overflow-x: auto;\n  padding: 0.5em;\n  background: #3f3f3f;\n  color: #dcdcdc;\n}\n\n.hljs-keyword,\n.hljs-selector-tag,\n.hljs-tag {\n  color: #e3ceab;\n}\n\n.hljs-template-tag {\n  color: #dcdcdc;\n}\n\n.hljs-number {\n  color: #8cd0d3;\n}\n\n.hljs-variable,\n.hljs-template-variable,\n.hljs-attribute {\n  color: #efdcbc;\n}\n\n.hljs-literal {\n  color: #efefaf;\n}\n\n.hljs-subst {\n  color: #8f8f8f;\n}\n\n.hljs-title,\n.hljs-name,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-section,\n.hljs-type {\n  color: #efef8f;\n}\n\n.hljs-symbol,\n.hljs-bullet,\n.hljs-link {\n  color: #dca3a3;\n}\n\n.hljs-deletion,\n.hljs-string,\n.hljs-built_in,\n.hljs-builtin-name {\n  color: #cc9393;\n}\n\n.hljs-addition,\n.hljs-comment,\n.hljs-quote,\n.hljs-meta {\n  color: #7f9f7f;\n}\n\n\n.hljs-emphasis {\n  font-style: italic;\n}\n\n.hljs-strong {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "lib/html2canvas.js",
    "content": "/*\r\n  html2canvas 0.4.1 <http://html2canvas.hertzen.com>\r\n  Copyright (c) 2013 Niklas von Hertzen\r\n\r\n  Released under MIT License\r\n*/\r\n\r\n(function(window, document, undefined){\r\n\r\n\"use strict\";\r\n\r\nvar _html2canvas = {},\r\npreviousElement,\r\ncomputedCSS,\r\nhtml2canvas;\r\n\r\n_html2canvas.Util = {};\r\n\r\n_html2canvas.Util.log = function(a) {\r\n  if (_html2canvas.logging && window.console && window.console.log) {\r\n    window.console.log(a);\r\n  }\r\n};\r\n\r\n_html2canvas.Util.trimText = (function(isNative){\r\n  return function(input) {\r\n    return isNative ? isNative.apply(input) : ((input || '') + '').replace( /^\\s+|\\s+$/g , '' );\r\n  };\r\n})(String.prototype.trim);\r\n\r\n_html2canvas.Util.asFloat = function(v) {\r\n  return parseFloat(v);\r\n};\r\n\r\n(function() {\r\n  // TODO: support all possible length values\r\n  var TEXT_SHADOW_PROPERTY = /((rgba|rgb)\\([^\\)]+\\)(\\s-?\\d+px){0,})/g;\r\n  var TEXT_SHADOW_VALUES = /(-?\\d+px)|(#.+)|(rgb\\(.+\\))|(rgba\\(.+\\))/g;\r\n  _html2canvas.Util.parseTextShadows = function (value) {\r\n    if (!value || value === 'none') {\r\n      return [];\r\n    }\r\n\r\n    // find multiple shadow declarations\r\n    var shadows = value.match(TEXT_SHADOW_PROPERTY),\r\n      results = [];\r\n    for (var i = 0; shadows && (i < shadows.length); i++) {\r\n      var s = shadows[i].match(TEXT_SHADOW_VALUES);\r\n      results.push({\r\n        color: s[0],\r\n        offsetX: s[1] ? s[1].replace('px', '') : 0,\r\n        offsetY: s[2] ? s[2].replace('px', '') : 0,\r\n        blur: s[3] ? s[3].replace('px', '') : 0\r\n      });\r\n    }\r\n    return results;\r\n  };\r\n})();\r\n\r\n\r\n_html2canvas.Util.parseBackgroundImage = function (value) {\r\n    var whitespace = ' \\r\\n\\t',\r\n        method, definition, prefix, prefix_i, block, results = [],\r\n        c, mode = 0, numParen = 0, quote, args;\r\n\r\n    var appendResult = function(){\r\n        if(method) {\r\n            if(definition.substr( 0, 1 ) === '\"') {\r\n                definition = definition.substr( 1, definition.length - 2 );\r\n            }\r\n            if(definition) {\r\n                args.push(definition);\r\n            }\r\n            if(method.substr( 0, 1 ) === '-' &&\r\n                    (prefix_i = method.indexOf( '-', 1 ) + 1) > 0) {\r\n                prefix = method.substr( 0, prefix_i);\r\n                method = method.substr( prefix_i );\r\n            }\r\n            results.push({\r\n                prefix: prefix,\r\n                method: method.toLowerCase(),\r\n                value: block,\r\n                args: args\r\n            });\r\n        }\r\n        args = []; //for some odd reason, setting .length = 0 didn't work in safari\r\n        method =\r\n            prefix =\r\n            definition =\r\n            block = '';\r\n    };\r\n\r\n    appendResult();\r\n    for(var i = 0, ii = value.length; i<ii; i++) {\r\n        c = value[i];\r\n        if(mode === 0 && whitespace.indexOf( c ) > -1){\r\n            continue;\r\n        }\r\n        switch(c) {\r\n            case '\"':\r\n                if(!quote) {\r\n                    quote = c;\r\n                }\r\n                else if(quote === c) {\r\n                    quote = null;\r\n                }\r\n                break;\r\n\r\n            case '(':\r\n                if(quote) { break; }\r\n                else if(mode === 0) {\r\n                    mode = 1;\r\n                    block += c;\r\n                    continue;\r\n                } else {\r\n                    numParen++;\r\n                }\r\n                break;\r\n\r\n            case ')':\r\n                if(quote) { break; }\r\n                else if(mode === 1) {\r\n                    if(numParen === 0) {\r\n                        mode = 0;\r\n                        block += c;\r\n                        appendResult();\r\n                        continue;\r\n                    } else {\r\n                        numParen--;\r\n                    }\r\n                }\r\n                break;\r\n\r\n            case ',':\r\n                if(quote) { break; }\r\n                else if(mode === 0) {\r\n                    appendResult();\r\n                    continue;\r\n                }\r\n                else if (mode === 1) {\r\n                    if(numParen === 0 && !method.match(/^url$/i)) {\r\n                        args.push(definition);\r\n                        definition = '';\r\n                        block += c;\r\n                        continue;\r\n                    }\r\n                }\r\n                break;\r\n        }\r\n\r\n        block += c;\r\n        if(mode === 0) { method += c; }\r\n        else { definition += c; }\r\n    }\r\n    appendResult();\r\n\r\n    return results;\r\n};\r\n\r\n_html2canvas.Util.Bounds = function (element) {\r\n  var clientRect, bounds = {};\r\n\r\n  if (element.getBoundingClientRect){\r\n    clientRect = element.getBoundingClientRect();\r\n\r\n    // TODO add scroll position to bounds, so no scrolling of window necessary\r\n    bounds.top = clientRect.top;\r\n    bounds.bottom = clientRect.bottom || (clientRect.top + clientRect.height);\r\n    bounds.left = clientRect.left;\r\n\r\n    bounds.width = element.offsetWidth;\r\n    bounds.height = element.offsetHeight;\r\n  }\r\n\r\n  return bounds;\r\n};\r\n\r\n// TODO ideally, we'd want everything to go through this function instead of Util.Bounds,\r\n// but would require further work to calculate the correct positions for elements with offsetParents\r\n_html2canvas.Util.OffsetBounds = function (element) {\r\n  var parent = element.offsetParent ? _html2canvas.Util.OffsetBounds(element.offsetParent) : {top: 0, left: 0};\r\n\r\n  return {\r\n    top: element.offsetTop + parent.top,\r\n    bottom: element.offsetTop + element.offsetHeight + parent.top,\r\n    left: element.offsetLeft + parent.left,\r\n    width: element.offsetWidth,\r\n    height: element.offsetHeight\r\n  };\r\n};\r\n\r\nfunction toPX(element, attribute, value ) {\r\n    var rsLeft = element.runtimeStyle && element.runtimeStyle[attribute],\r\n        left,\r\n        style = element.style;\r\n\r\n    // Check if we are not dealing with pixels, (Opera has issues with this)\r\n    // Ported from jQuery css.js\r\n    // From the awesome hack by Dean Edwards\r\n    // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\r\n\r\n    // If we're not dealing with a regular pixel number\r\n    // but a number that has a weird ending, we need to convert it to pixels\r\n\r\n    if ( !/^-?[0-9]+\\.?[0-9]*(?:px)?$/i.test( value ) && /^-?\\d/.test(value) ) {\r\n        // Remember the original values\r\n        left = style.left;\r\n\r\n        // Put in the new values to get a computed value out\r\n        if (rsLeft) {\r\n            element.runtimeStyle.left = element.currentStyle.left;\r\n        }\r\n        style.left = attribute === \"fontSize\" ? \"1em\" : (value || 0);\r\n        value = style.pixelLeft + \"px\";\r\n\r\n        // Revert the changed values\r\n        style.left = left;\r\n        if (rsLeft) {\r\n            element.runtimeStyle.left = rsLeft;\r\n        }\r\n    }\r\n\r\n    if (!/^(thin|medium|thick)$/i.test(value)) {\r\n        return Math.round(parseFloat(value)) + \"px\";\r\n    }\r\n\r\n    return value;\r\n}\r\n\r\nfunction asInt(val) {\r\n    return parseInt(val, 10);\r\n}\r\n\r\nfunction parseBackgroundSizePosition(value, element, attribute, index) {\r\n    value = (value || '').split(',');\r\n    value = value[index || 0] || value[0] || 'auto';\r\n    value = _html2canvas.Util.trimText(value).split(' ');\r\n\r\n    if(attribute === 'backgroundSize' && (!value[0] || value[0].match(/cover|contain|auto/))) {\r\n        //these values will be handled in the parent function\r\n    } else {\r\n        value[0] = (value[0].indexOf( \"%\" ) === -1) ? toPX(element, attribute + \"X\", value[0]) : value[0];\r\n        if(value[1] === undefined) {\r\n            if(attribute === 'backgroundSize') {\r\n                value[1] = 'auto';\r\n                return value;\r\n            } else {\r\n                // IE 9 doesn't return double digit always\r\n                value[1] = value[0];\r\n            }\r\n        }\r\n        value[1] = (value[1].indexOf(\"%\") === -1) ? toPX(element, attribute + \"Y\", value[1]) : value[1];\r\n    }\r\n    return value;\r\n}\r\n\r\n_html2canvas.Util.getCSS = function (element, attribute, index) {\r\n    if (previousElement !== element) {\r\n      computedCSS = document.defaultView.getComputedStyle(element, null);\r\n    }\r\n\r\n    var value = computedCSS[attribute];\r\n\r\n    if (/^background(Size|Position)$/.test(attribute)) {\r\n        return parseBackgroundSizePosition(value, element, attribute, index);\r\n    } else if (/border(Top|Bottom)(Left|Right)Radius/.test(attribute)) {\r\n      var arr = value.split(\" \");\r\n      if (arr.length <= 1) {\r\n          arr[1] = arr[0];\r\n      }\r\n      return arr.map(asInt);\r\n    }\r\n\r\n  return value;\r\n};\r\n\r\n_html2canvas.Util.resizeBounds = function( current_width, current_height, target_width, target_height, stretch_mode ){\r\n  var target_ratio = target_width / target_height,\r\n    current_ratio = current_width / current_height,\r\n    output_width, output_height;\r\n\r\n  if(!stretch_mode || stretch_mode === 'auto') {\r\n    output_width = target_width;\r\n    output_height = target_height;\r\n  } else if(target_ratio < current_ratio ^ stretch_mode === 'contain') {\r\n    output_height = target_height;\r\n    output_width = target_height * current_ratio;\r\n  } else {\r\n    output_width = target_width;\r\n    output_height = target_width / current_ratio;\r\n  }\r\n\r\n  return {\r\n    width: output_width,\r\n    height: output_height\r\n  };\r\n};\r\n\r\nfunction backgroundBoundsFactory( prop, el, bounds, image, imageIndex, backgroundSize ) {\r\n    var bgposition =  _html2canvas.Util.getCSS( el, prop, imageIndex ) ,\r\n    topPos,\r\n    left,\r\n    percentage,\r\n    val;\r\n\r\n    if (bgposition.length === 1){\r\n      val = bgposition[0];\r\n\r\n      bgposition = [];\r\n\r\n      bgposition[0] = val;\r\n      bgposition[1] = val;\r\n    }\r\n\r\n    if (bgposition[0].toString().indexOf(\"%\") !== -1){\r\n      percentage = (parseFloat(bgposition[0])/100);\r\n      left = bounds.width * percentage;\r\n      if(prop !== 'backgroundSize') {\r\n        left -= (backgroundSize || image).width*percentage;\r\n      }\r\n    } else {\r\n      if(prop === 'backgroundSize') {\r\n        if(bgposition[0] === 'auto') {\r\n          left = image.width;\r\n        } else {\r\n          if (/contain|cover/.test(bgposition[0])) {\r\n            var resized = _html2canvas.Util.resizeBounds(image.width, image.height, bounds.width, bounds.height, bgposition[0]);\r\n            left = resized.width;\r\n            topPos = resized.height;\r\n          } else {\r\n            left = parseInt(bgposition[0], 10);\r\n          }\r\n        }\r\n      } else {\r\n        left = parseInt( bgposition[0], 10);\r\n      }\r\n    }\r\n\r\n\r\n    if(bgposition[1] === 'auto') {\r\n      topPos = left / image.width * image.height;\r\n    } else if (bgposition[1].toString().indexOf(\"%\") !== -1){\r\n      percentage = (parseFloat(bgposition[1])/100);\r\n      topPos =  bounds.height * percentage;\r\n      if(prop !== 'backgroundSize') {\r\n        topPos -= (backgroundSize || image).height * percentage;\r\n      }\r\n\r\n    } else {\r\n      topPos = parseInt(bgposition[1],10);\r\n    }\r\n\r\n    return [left, topPos];\r\n}\r\n\r\n_html2canvas.Util.BackgroundPosition = function( el, bounds, image, imageIndex, backgroundSize ) {\r\n    var result = backgroundBoundsFactory( 'backgroundPosition', el, bounds, image, imageIndex, backgroundSize );\r\n    return { left: result[0], top: result[1] };\r\n};\r\n\r\n_html2canvas.Util.BackgroundSize = function( el, bounds, image, imageIndex ) {\r\n    var result = backgroundBoundsFactory( 'backgroundSize', el, bounds, image, imageIndex );\r\n    return { width: result[0], height: result[1] };\r\n};\r\n\r\n_html2canvas.Util.Extend = function (options, defaults) {\r\n  for (var key in options) {\r\n    if (options.hasOwnProperty(key)) {\r\n      defaults[key] = options[key];\r\n    }\r\n  }\r\n  return defaults;\r\n};\r\n\r\n\r\n/*\r\n * Derived from jQuery.contents()\r\n * Copyright 2010, John Resig\r\n * Dual licensed under the MIT or GPL Version 2 licenses.\r\n * http://jquery.org/license\r\n */\r\n_html2canvas.Util.Children = function( elem ) {\r\n  var children;\r\n  try {\r\n    children = (elem.nodeName && elem.nodeName.toUpperCase() === \"IFRAME\") ? elem.contentDocument || elem.contentWindow.document : (function(array) {\r\n      var ret = [];\r\n      if (array !== null) {\r\n        (function(first, second ) {\r\n          var i = first.length,\r\n          j = 0;\r\n\r\n          if (typeof second.length === \"number\") {\r\n            for (var l = second.length; j < l; j++) {\r\n              first[i++] = second[j];\r\n            }\r\n          } else {\r\n            while (second[j] !== undefined) {\r\n              first[i++] = second[j++];\r\n            }\r\n          }\r\n\r\n          first.length = i;\r\n\r\n          return first;\r\n        })(ret, array);\r\n      }\r\n      return ret;\r\n    })(elem.childNodes);\r\n\r\n  } catch (ex) {\r\n    _html2canvas.Util.log(\"html2canvas.Util.Children failed with exception: \" + ex.message);\r\n    children = [];\r\n  }\r\n  return children;\r\n};\r\n\r\n_html2canvas.Util.isTransparent = function(backgroundColor) {\r\n  return (backgroundColor === \"transparent\" || backgroundColor === \"rgba(0, 0, 0, 0)\");\r\n};\r\n_html2canvas.Util.Font = (function () {\r\n\r\n  var fontData = {};\r\n\r\n  return function(font, fontSize, doc) {\r\n    if (fontData[font + \"-\" + fontSize] !== undefined) {\r\n      return fontData[font + \"-\" + fontSize];\r\n    }\r\n\r\n    var container = doc.createElement('div'),\r\n    img = doc.createElement('img'),\r\n    span = doc.createElement('span'),\r\n    sampleText = 'Hidden Text',\r\n    baseline,\r\n    middle,\r\n    metricsObj;\r\n\r\n    container.style.visibility = \"hidden\";\r\n    container.style.fontFamily = font;\r\n    container.style.fontSize = fontSize;\r\n    container.style.margin = 0;\r\n    container.style.padding = 0;\r\n\r\n    doc.body.appendChild(container);\r\n\r\n    // http://probablyprogramming.com/2009/03/15/the-tiniest-gif-ever (handtinywhite.gif)\r\n    img.src = \"data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=\";\r\n    img.width = 1;\r\n    img.height = 1;\r\n\r\n    img.style.margin = 0;\r\n    img.style.padding = 0;\r\n    img.style.verticalAlign = \"baseline\";\r\n\r\n    span.style.fontFamily = font;\r\n    span.style.fontSize = fontSize;\r\n    span.style.margin = 0;\r\n    span.style.padding = 0;\r\n\r\n    span.appendChild(doc.createTextNode(sampleText));\r\n    container.appendChild(span);\r\n    container.appendChild(img);\r\n    baseline = (img.offsetTop - span.offsetTop) + 1;\r\n\r\n    container.removeChild(span);\r\n    container.appendChild(doc.createTextNode(sampleText));\r\n\r\n    container.style.lineHeight = \"normal\";\r\n    img.style.verticalAlign = \"super\";\r\n\r\n    middle = (img.offsetTop-container.offsetTop) + 1;\r\n    metricsObj = {\r\n      baseline: baseline,\r\n      lineWidth: 1,\r\n      middle: middle\r\n    };\r\n\r\n    fontData[font + \"-\" + fontSize] = metricsObj;\r\n\r\n    doc.body.removeChild(container);\r\n\r\n    return metricsObj;\r\n  };\r\n})();\r\n\r\n(function(){\r\n  var Util = _html2canvas.Util,\r\n    Generate = {};\r\n\r\n  _html2canvas.Generate = Generate;\r\n\r\n  var reGradients = [\r\n  /^(-webkit-linear-gradient)\\(([a-z\\s]+)([\\w\\d\\.\\s,%\\(\\)]+)\\)$/,\r\n  /^(-o-linear-gradient)\\(([a-z\\s]+)([\\w\\d\\.\\s,%\\(\\)]+)\\)$/,\r\n  /^(-webkit-gradient)\\((linear|radial),\\s((?:\\d{1,3}%?)\\s(?:\\d{1,3}%?),\\s(?:\\d{1,3}%?)\\s(?:\\d{1,3}%?))([\\w\\d\\.\\s,%\\(\\)\\-]+)\\)$/,\r\n  /^(-moz-linear-gradient)\\(((?:\\d{1,3}%?)\\s(?:\\d{1,3}%?))([\\w\\d\\.\\s,%\\(\\)]+)\\)$/,\r\n  /^(-webkit-radial-gradient)\\(((?:\\d{1,3}%?)\\s(?:\\d{1,3}%?)),\\s(\\w+)\\s([a-z\\-]+)([\\w\\d\\.\\s,%\\(\\)]+)\\)$/,\r\n  /^(-moz-radial-gradient)\\(((?:\\d{1,3}%?)\\s(?:\\d{1,3}%?)),\\s(\\w+)\\s?([a-z\\-]*)([\\w\\d\\.\\s,%\\(\\)]+)\\)$/,\r\n  /^(-o-radial-gradient)\\(((?:\\d{1,3}%?)\\s(?:\\d{1,3}%?)),\\s(\\w+)\\s([a-z\\-]+)([\\w\\d\\.\\s,%\\(\\)]+)\\)$/\r\n  ];\r\n\r\n  /*\r\n * TODO: Add IE10 vendor prefix (-ms) support\r\n * TODO: Add W3C gradient (linear-gradient) support\r\n * TODO: Add old Webkit -webkit-gradient(radial, ...) support\r\n * TODO: Maybe some RegExp optimizations are possible ;o)\r\n */\r\n  Generate.parseGradient = function(css, bounds) {\r\n    var gradient, i, len = reGradients.length, m1, stop, m2, m2Len, step, m3, tl,tr,br,bl;\r\n\r\n    for(i = 0; i < len; i+=1){\r\n      m1 = css.match(reGradients[i]);\r\n      if(m1) {\r\n        break;\r\n      }\r\n    }\r\n\r\n    if(m1) {\r\n      switch(m1[1]) {\r\n        case '-webkit-linear-gradient':\r\n        case '-o-linear-gradient':\r\n\r\n          gradient = {\r\n            type: 'linear',\r\n            x0: null,\r\n            y0: null,\r\n            x1: null,\r\n            y1: null,\r\n            colorStops: []\r\n          };\r\n\r\n          // get coordinates\r\n          m2 = m1[2].match(/\\w+/g);\r\n          if(m2){\r\n            m2Len = m2.length;\r\n            for(i = 0; i < m2Len; i+=1){\r\n              switch(m2[i]) {\r\n                case 'top':\r\n                  gradient.y0 = 0;\r\n                  gradient.y1 = bounds.height;\r\n                  break;\r\n\r\n                case 'right':\r\n                  gradient.x0 = bounds.width;\r\n                  gradient.x1 = 0;\r\n                  break;\r\n\r\n                case 'bottom':\r\n                  gradient.y0 = bounds.height;\r\n                  gradient.y1 = 0;\r\n                  break;\r\n\r\n                case 'left':\r\n                  gradient.x0 = 0;\r\n                  gradient.x1 = bounds.width;\r\n                  break;\r\n              }\r\n            }\r\n          }\r\n          if(gradient.x0 === null && gradient.x1 === null){ // center\r\n            gradient.x0 = gradient.x1 = bounds.width / 2;\r\n          }\r\n          if(gradient.y0 === null && gradient.y1 === null){ // center\r\n            gradient.y0 = gradient.y1 = bounds.height / 2;\r\n          }\r\n\r\n          // get colors and stops\r\n          m2 = m1[3].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\)(?:\\s\\d{1,3}(?:%|px))?)+/g);\r\n          if(m2){\r\n            m2Len = m2.length;\r\n            step = 1 / Math.max(m2Len - 1, 1);\r\n            for(i = 0; i < m2Len; i+=1){\r\n              m3 = m2[i].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\))\\s*(\\d{1,3})?(%|px)?/);\r\n              if(m3[2]){\r\n                stop = parseFloat(m3[2]);\r\n                if(m3[3] === '%'){\r\n                  stop /= 100;\r\n                } else { // px - stupid opera\r\n                  stop /= bounds.width;\r\n                }\r\n              } else {\r\n                stop = i * step;\r\n              }\r\n              gradient.colorStops.push({\r\n                color: m3[1],\r\n                stop: stop\r\n              });\r\n            }\r\n          }\r\n          break;\r\n\r\n        case '-webkit-gradient':\r\n\r\n          gradient = {\r\n            type: m1[2] === 'radial' ? 'circle' : m1[2], // TODO: Add radial gradient support for older mozilla definitions\r\n            x0: 0,\r\n            y0: 0,\r\n            x1: 0,\r\n            y1: 0,\r\n            colorStops: []\r\n          };\r\n\r\n          // get coordinates\r\n          m2 = m1[3].match(/(\\d{1,3})%?\\s(\\d{1,3})%?,\\s(\\d{1,3})%?\\s(\\d{1,3})%?/);\r\n          if(m2){\r\n            gradient.x0 = (m2[1] * bounds.width) / 100;\r\n            gradient.y0 = (m2[2] * bounds.height) / 100;\r\n            gradient.x1 = (m2[3] * bounds.width) / 100;\r\n            gradient.y1 = (m2[4] * bounds.height) / 100;\r\n          }\r\n\r\n          // get colors and stops\r\n          m2 = m1[4].match(/((?:from|to|color-stop)\\((?:[0-9\\.]+,\\s)?(?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\)\\))+/g);\r\n          if(m2){\r\n            m2Len = m2.length;\r\n            for(i = 0; i < m2Len; i+=1){\r\n              m3 = m2[i].match(/(from|to|color-stop)\\(([0-9\\.]+)?(?:,\\s)?((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\))\\)/);\r\n              stop = parseFloat(m3[2]);\r\n              if(m3[1] === 'from') {\r\n                stop = 0.0;\r\n              }\r\n              if(m3[1] === 'to') {\r\n                stop = 1.0;\r\n              }\r\n              gradient.colorStops.push({\r\n                color: m3[3],\r\n                stop: stop\r\n              });\r\n            }\r\n          }\r\n          break;\r\n\r\n        case '-moz-linear-gradient':\r\n\r\n          gradient = {\r\n            type: 'linear',\r\n            x0: 0,\r\n            y0: 0,\r\n            x1: 0,\r\n            y1: 0,\r\n            colorStops: []\r\n          };\r\n\r\n          // get coordinates\r\n          m2 = m1[2].match(/(\\d{1,3})%?\\s(\\d{1,3})%?/);\r\n\r\n          // m2[1] == 0%   -> left\r\n          // m2[1] == 50%  -> center\r\n          // m2[1] == 100% -> right\r\n\r\n          // m2[2] == 0%   -> top\r\n          // m2[2] == 50%  -> center\r\n          // m2[2] == 100% -> bottom\r\n\r\n          if(m2){\r\n            gradient.x0 = (m2[1] * bounds.width) / 100;\r\n            gradient.y0 = (m2[2] * bounds.height) / 100;\r\n            gradient.x1 = bounds.width - gradient.x0;\r\n            gradient.y1 = bounds.height - gradient.y0;\r\n          }\r\n\r\n          // get colors and stops\r\n          m2 = m1[3].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\)(?:\\s\\d{1,3}%)?)+/g);\r\n          if(m2){\r\n            m2Len = m2.length;\r\n            step = 1 / Math.max(m2Len - 1, 1);\r\n            for(i = 0; i < m2Len; i+=1){\r\n              m3 = m2[i].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\))\\s*(\\d{1,3})?(%)?/);\r\n              if(m3[2]){\r\n                stop = parseFloat(m3[2]);\r\n                if(m3[3]){ // percentage\r\n                  stop /= 100;\r\n                }\r\n              } else {\r\n                stop = i * step;\r\n              }\r\n              gradient.colorStops.push({\r\n                color: m3[1],\r\n                stop: stop\r\n              });\r\n            }\r\n          }\r\n          break;\r\n\r\n        case '-webkit-radial-gradient':\r\n        case '-moz-radial-gradient':\r\n        case '-o-radial-gradient':\r\n\r\n          gradient = {\r\n            type: 'circle',\r\n            x0: 0,\r\n            y0: 0,\r\n            x1: bounds.width,\r\n            y1: bounds.height,\r\n            cx: 0,\r\n            cy: 0,\r\n            rx: 0,\r\n            ry: 0,\r\n            colorStops: []\r\n          };\r\n\r\n          // center\r\n          m2 = m1[2].match(/(\\d{1,3})%?\\s(\\d{1,3})%?/);\r\n          if(m2){\r\n            gradient.cx = (m2[1] * bounds.width) / 100;\r\n            gradient.cy = (m2[2] * bounds.height) / 100;\r\n          }\r\n\r\n          // size\r\n          m2 = m1[3].match(/\\w+/);\r\n          m3 = m1[4].match(/[a-z\\-]*/);\r\n          if(m2 && m3){\r\n            switch(m3[0]){\r\n              case 'farthest-corner':\r\n              case 'cover': // is equivalent to farthest-corner\r\n              case '': // mozilla removes \"cover\" from definition :(\r\n                tl = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.cy, 2));\r\n                tr = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));\r\n                br = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));\r\n                bl = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.cy, 2));\r\n                gradient.rx = gradient.ry = Math.max(tl, tr, br, bl);\r\n                break;\r\n              case 'closest-corner':\r\n                tl = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.cy, 2));\r\n                tr = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));\r\n                br = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));\r\n                bl = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.cy, 2));\r\n                gradient.rx = gradient.ry = Math.min(tl, tr, br, bl);\r\n                break;\r\n              case 'farthest-side':\r\n                if(m2[0] === 'circle'){\r\n                  gradient.rx = gradient.ry = Math.max(\r\n                    gradient.cx,\r\n                    gradient.cy,\r\n                    gradient.x1 - gradient.cx,\r\n                    gradient.y1 - gradient.cy\r\n                    );\r\n                } else { // ellipse\r\n\r\n                  gradient.type = m2[0];\r\n\r\n                  gradient.rx = Math.max(\r\n                    gradient.cx,\r\n                    gradient.x1 - gradient.cx\r\n                    );\r\n                  gradient.ry = Math.max(\r\n                    gradient.cy,\r\n                    gradient.y1 - gradient.cy\r\n                    );\r\n                }\r\n                break;\r\n              case 'closest-side':\r\n              case 'contain': // is equivalent to closest-side\r\n                if(m2[0] === 'circle'){\r\n                  gradient.rx = gradient.ry = Math.min(\r\n                    gradient.cx,\r\n                    gradient.cy,\r\n                    gradient.x1 - gradient.cx,\r\n                    gradient.y1 - gradient.cy\r\n                    );\r\n                } else { // ellipse\r\n\r\n                  gradient.type = m2[0];\r\n\r\n                  gradient.rx = Math.min(\r\n                    gradient.cx,\r\n                    gradient.x1 - gradient.cx\r\n                    );\r\n                  gradient.ry = Math.min(\r\n                    gradient.cy,\r\n                    gradient.y1 - gradient.cy\r\n                    );\r\n                }\r\n                break;\r\n\r\n            // TODO: add support for \"30px 40px\" sizes (webkit only)\r\n            }\r\n          }\r\n\r\n          // color stops\r\n          m2 = m1[5].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\)(?:\\s\\d{1,3}(?:%|px))?)+/g);\r\n          if(m2){\r\n            m2Len = m2.length;\r\n            step = 1 / Math.max(m2Len - 1, 1);\r\n            for(i = 0; i < m2Len; i+=1){\r\n              m3 = m2[i].match(/((?:rgb|rgba)\\(\\d{1,3},\\s\\d{1,3},\\s\\d{1,3}(?:,\\s[0-9\\.]+)?\\))\\s*(\\d{1,3})?(%|px)?/);\r\n              if(m3[2]){\r\n                stop = parseFloat(m3[2]);\r\n                if(m3[3] === '%'){\r\n                  stop /= 100;\r\n                } else { // px - stupid opera\r\n                  stop /= bounds.width;\r\n                }\r\n              } else {\r\n                stop = i * step;\r\n              }\r\n              gradient.colorStops.push({\r\n                color: m3[1],\r\n                stop: stop\r\n              });\r\n            }\r\n          }\r\n          break;\r\n      }\r\n    }\r\n\r\n    return gradient;\r\n  };\r\n\r\n  function addScrollStops(grad) {\r\n    return function(colorStop) {\r\n      try {\r\n        grad.addColorStop(colorStop.stop, colorStop.color);\r\n      }\r\n      catch(e) {\r\n        Util.log(['failed to add color stop: ', e, '; tried to add: ', colorStop]);\r\n      }\r\n    };\r\n  }\r\n\r\n  Generate.Gradient = function(src, bounds) {\r\n    if(bounds.width === 0 || bounds.height === 0) {\r\n      return;\r\n    }\r\n\r\n    var canvas = document.createElement('canvas'),\r\n    ctx = canvas.getContext('2d'),\r\n    gradient, grad;\r\n\r\n    canvas.width = bounds.width;\r\n    canvas.height = bounds.height;\r\n\r\n    // TODO: add support for multi defined background gradients\r\n    gradient = _html2canvas.Generate.parseGradient(src, bounds);\r\n\r\n    if(gradient) {\r\n      switch(gradient.type) {\r\n        case 'linear':\r\n          grad = ctx.createLinearGradient(gradient.x0, gradient.y0, gradient.x1, gradient.y1);\r\n          gradient.colorStops.forEach(addScrollStops(grad));\r\n          ctx.fillStyle = grad;\r\n          ctx.fillRect(0, 0, bounds.width, bounds.height);\r\n          break;\r\n\r\n        case 'circle':\r\n          grad = ctx.createRadialGradient(gradient.cx, gradient.cy, 0, gradient.cx, gradient.cy, gradient.rx);\r\n          gradient.colorStops.forEach(addScrollStops(grad));\r\n          ctx.fillStyle = grad;\r\n          ctx.fillRect(0, 0, bounds.width, bounds.height);\r\n          break;\r\n\r\n        case 'ellipse':\r\n          var canvasRadial = document.createElement('canvas'),\r\n            ctxRadial = canvasRadial.getContext('2d'),\r\n            ri = Math.max(gradient.rx, gradient.ry),\r\n            di = ri * 2;\r\n\r\n          canvasRadial.width = canvasRadial.height = di;\r\n\r\n          grad = ctxRadial.createRadialGradient(gradient.rx, gradient.ry, 0, gradient.rx, gradient.ry, ri);\r\n          gradient.colorStops.forEach(addScrollStops(grad));\r\n\r\n          ctxRadial.fillStyle = grad;\r\n          ctxRadial.fillRect(0, 0, di, di);\r\n\r\n          ctx.fillStyle = gradient.colorStops[gradient.colorStops.length - 1].color;\r\n          ctx.fillRect(0, 0, canvas.width, canvas.height);\r\n          ctx.drawImage(canvasRadial, gradient.cx - gradient.rx, gradient.cy - gradient.ry, 2 * gradient.rx, 2 * gradient.ry);\r\n          break;\r\n      }\r\n    }\r\n\r\n    return canvas;\r\n  };\r\n\r\n  Generate.ListAlpha = function(number) {\r\n    var tmp = \"\",\r\n    modulus;\r\n\r\n    do {\r\n      modulus = number % 26;\r\n      tmp = String.fromCharCode((modulus) + 64) + tmp;\r\n      number = number / 26;\r\n    }while((number*26) > 26);\r\n\r\n    return tmp;\r\n  };\r\n\r\n  Generate.ListRoman = function(number) {\r\n    var romanArray = [\"M\", \"CM\", \"D\", \"CD\", \"C\", \"XC\", \"L\", \"XL\", \"X\", \"IX\", \"V\", \"IV\", \"I\"],\r\n    decimal = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1],\r\n    roman = \"\",\r\n    v,\r\n    len = romanArray.length;\r\n\r\n    if (number <= 0 || number >= 4000) {\r\n      return number;\r\n    }\r\n\r\n    for (v=0; v < len; v+=1) {\r\n      while (number >= decimal[v]) {\r\n        number -= decimal[v];\r\n        roman += romanArray[v];\r\n      }\r\n    }\r\n\r\n    return roman;\r\n  };\r\n})();\r\nfunction h2cRenderContext(width, height) {\r\n  var storage = [];\r\n  return {\r\n    storage: storage,\r\n    width: width,\r\n    height: height,\r\n    clip: function() {\r\n      storage.push({\r\n        type: \"function\",\r\n        name: \"clip\",\r\n        'arguments': arguments\r\n      });\r\n    },\r\n    translate: function() {\r\n      storage.push({\r\n        type: \"function\",\r\n        name: \"translate\",\r\n        'arguments': arguments\r\n      });\r\n    },\r\n    fill: function() {\r\n      storage.push({\r\n        type: \"function\",\r\n        name: \"fill\",\r\n        'arguments': arguments\r\n      });\r\n    },\r\n    save: function() {\r\n      storage.push({\r\n        type: \"function\",\r\n        name: \"save\",\r\n        'arguments': arguments\r\n      });\r\n    },\r\n    restore: function() {\r\n      storage.push({\r\n        type: \"function\",\r\n        name: \"restore\",\r\n        'arguments': arguments\r\n      });\r\n    },\r\n    fillRect: function () {\r\n      storage.push({\r\n        type: \"function\",\r\n        name: \"fillRect\",\r\n        'arguments': arguments\r\n      });\r\n    },\r\n    createPattern: function() {\r\n      storage.push({\r\n        type: \"function\",\r\n        name: \"createPattern\",\r\n        'arguments': arguments\r\n      });\r\n    },\r\n    drawShape: function() {\r\n\r\n      var shape = [];\r\n\r\n      storage.push({\r\n        type: \"function\",\r\n        name: \"drawShape\",\r\n        'arguments': shape\r\n      });\r\n\r\n      return {\r\n        moveTo: function() {\r\n          shape.push({\r\n            name: \"moveTo\",\r\n            'arguments': arguments\r\n          });\r\n        },\r\n        lineTo: function() {\r\n          shape.push({\r\n            name: \"lineTo\",\r\n            'arguments': arguments\r\n          });\r\n        },\r\n        arcTo: function() {\r\n          shape.push({\r\n            name: \"arcTo\",\r\n            'arguments': arguments\r\n          });\r\n        },\r\n        bezierCurveTo: function() {\r\n          shape.push({\r\n            name: \"bezierCurveTo\",\r\n            'arguments': arguments\r\n          });\r\n        },\r\n        quadraticCurveTo: function() {\r\n          shape.push({\r\n            name: \"quadraticCurveTo\",\r\n            'arguments': arguments\r\n          });\r\n        }\r\n      };\r\n\r\n    },\r\n    drawImage: function () {\r\n      storage.push({\r\n        type: \"function\",\r\n        name: \"drawImage\",\r\n        'arguments': arguments\r\n      });\r\n    },\r\n    fillText: function () {\r\n      storage.push({\r\n        type: \"function\",\r\n        name: \"fillText\",\r\n        'arguments': arguments\r\n      });\r\n    },\r\n    setVariable: function (variable, value) {\r\n      storage.push({\r\n        type: \"variable\",\r\n        name: variable,\r\n        'arguments': value\r\n      });\r\n      return value;\r\n    }\r\n  };\r\n}\r\n_html2canvas.Parse = function (images, options) {\r\n  window.scroll(0,0);\r\n\r\n  var element = (( options.elements === undefined ) ? document.body : options.elements[0]), // select body by default\r\n  numDraws = 0,\r\n  doc = element.ownerDocument,\r\n  Util = _html2canvas.Util,\r\n  support = Util.Support(options, doc),\r\n  ignoreElementsRegExp = new RegExp(\"(\" + options.ignoreElements + \")\"),\r\n  body = doc.body,\r\n  getCSS = Util.getCSS,\r\n  pseudoHide = \"___html2canvas___pseudoelement\",\r\n  hidePseudoElements = doc.createElement('style');\r\n\r\n  hidePseudoElements.innerHTML = '.' + pseudoHide + '-before:before { content: \"\" !important; display: none !important; }' +\r\n  '.' + pseudoHide + '-after:after { content: \"\" !important; display: none !important; }';\r\n\r\n  body.appendChild(hidePseudoElements);\r\n\r\n  images = images || {};\r\n\r\n  function documentWidth () {\r\n    return Math.max(\r\n      Math.max(doc.body.scrollWidth, doc.documentElement.scrollWidth),\r\n      Math.max(doc.body.offsetWidth, doc.documentElement.offsetWidth),\r\n      Math.max(doc.body.clientWidth, doc.documentElement.clientWidth)\r\n      );\r\n  }\r\n\r\n  function documentHeight () {\r\n    return Math.max(\r\n      Math.max(doc.body.scrollHeight, doc.documentElement.scrollHeight),\r\n      Math.max(doc.body.offsetHeight, doc.documentElement.offsetHeight),\r\n      Math.max(doc.body.clientHeight, doc.documentElement.clientHeight)\r\n      );\r\n  }\r\n\r\n  function getCSSInt(element, attribute) {\r\n    var val = parseInt(getCSS(element, attribute), 10);\r\n    return (isNaN(val)) ? 0 : val; // borders in old IE are throwing 'medium' for demo.html\r\n  }\r\n\r\n  function renderRect (ctx, x, y, w, h, bgcolor) {\r\n    if (bgcolor !== \"transparent\"){\r\n      ctx.setVariable(\"fillStyle\", bgcolor);\r\n      ctx.fillRect(x, y, w, h);\r\n      numDraws+=1;\r\n    }\r\n  }\r\n\r\n  function capitalize(m, p1, p2) {\r\n    if (m.length > 0) {\r\n      return p1 + p2.toUpperCase();\r\n    }\r\n  }\r\n\r\n  function textTransform (text, transform) {\r\n    switch(transform){\r\n      case \"lowercase\":\r\n        return text.toLowerCase();\r\n      case \"capitalize\":\r\n        return text.replace( /(^|\\s|:|-|\\(|\\))([a-z])/g, capitalize);\r\n      case \"uppercase\":\r\n        return text.toUpperCase();\r\n      default:\r\n        return text;\r\n    }\r\n  }\r\n\r\n  function noLetterSpacing(letter_spacing) {\r\n    return (/^(normal|none|0px)$/.test(letter_spacing));\r\n  }\r\n\r\n  function drawText(currentText, x, y, ctx){\r\n    if (currentText !== null && Util.trimText(currentText).length > 0) {\r\n      ctx.fillText(currentText, x, y);\r\n      numDraws+=1;\r\n    }\r\n  }\r\n\r\n  function setTextVariables(ctx, el, text_decoration, color) {\r\n    var align = false,\r\n    bold = getCSS(el, \"fontWeight\"),\r\n    family = getCSS(el, \"fontFamily\"),\r\n    size = getCSS(el, \"fontSize\"),\r\n    shadows = Util.parseTextShadows(getCSS(el, \"textShadow\"));\r\n\r\n    switch(parseInt(bold, 10)){\r\n      case 401:\r\n        bold = \"bold\";\r\n        break;\r\n      case 400:\r\n        bold = \"normal\";\r\n        break;\r\n    }\r\n\r\n    ctx.setVariable(\"fillStyle\", color);\r\n    ctx.setVariable(\"font\", [getCSS(el, \"fontStyle\"), getCSS(el, \"fontVariant\"), bold, size, family].join(\" \"));\r\n    ctx.setVariable(\"textAlign\", (align) ? \"right\" : \"left\");\r\n\r\n    if (shadows.length) {\r\n      // TODO: support multiple text shadows\r\n      // apply the first text shadow\r\n      ctx.setVariable(\"shadowColor\", shadows[0].color);\r\n      ctx.setVariable(\"shadowOffsetX\", shadows[0].offsetX);\r\n      ctx.setVariable(\"shadowOffsetY\", shadows[0].offsetY);\r\n      ctx.setVariable(\"shadowBlur\", shadows[0].blur);\r\n    }\r\n\r\n    if (text_decoration !== \"none\"){\r\n      return Util.Font(family, size, doc);\r\n    }\r\n  }\r\n\r\n  function renderTextDecoration(ctx, text_decoration, bounds, metrics, color) {\r\n    switch(text_decoration) {\r\n      case \"underline\":\r\n        // Draws a line at the baseline of the font\r\n        // TODO As some browsers display the line as more than 1px if the font-size is big, need to take that into account both in position and size\r\n        renderRect(ctx, bounds.left, Math.round(bounds.top + metrics.baseline + metrics.lineWidth), bounds.width, 1, color);\r\n        break;\r\n      case \"overline\":\r\n        renderRect(ctx, bounds.left, Math.round(bounds.top), bounds.width, 1, color);\r\n        break;\r\n      case \"line-through\":\r\n        // TODO try and find exact position for line-through\r\n        renderRect(ctx, bounds.left, Math.ceil(bounds.top + metrics.middle + metrics.lineWidth), bounds.width, 1, color);\r\n        break;\r\n    }\r\n  }\r\n\r\n  function getTextBounds(state, text, textDecoration, isLast, transform) {\r\n    var bounds;\r\n    if (support.rangeBounds && !transform) {\r\n      if (textDecoration !== \"none\" || Util.trimText(text).length !== 0) {\r\n        bounds = textRangeBounds(text, state.node, state.textOffset);\r\n      }\r\n      state.textOffset += text.length;\r\n    } else if (state.node && typeof state.node.nodeValue === \"string\" ){\r\n      var newTextNode = (isLast) ? state.node.splitText(text.length) : null;\r\n      bounds = textWrapperBounds(state.node, transform);\r\n      state.node = newTextNode;\r\n    }\r\n    return bounds;\r\n  }\r\n\r\n  function textRangeBounds(text, textNode, textOffset) {\r\n    var range = doc.createRange();\r\n    range.setStart(textNode, textOffset);\r\n    range.setEnd(textNode, textOffset + text.length);\r\n    return range.getBoundingClientRect();\r\n  }\r\n\r\n  function textWrapperBounds(oldTextNode, transform) {\r\n    var parent = oldTextNode.parentNode,\r\n    wrapElement = doc.createElement('wrapper'),\r\n    backupText = oldTextNode.cloneNode(true);\r\n\r\n    wrapElement.appendChild(oldTextNode.cloneNode(true));\r\n    parent.replaceChild(wrapElement, oldTextNode);\r\n\r\n    var bounds = transform ? Util.OffsetBounds(wrapElement) : Util.Bounds(wrapElement);\r\n    parent.replaceChild(backupText, wrapElement);\r\n    return bounds;\r\n  }\r\n\r\n  function renderText(el, textNode, stack) {\r\n    var ctx = stack.ctx,\r\n    color = getCSS(el, \"color\"),\r\n    textDecoration = getCSS(el, \"textDecoration\"),\r\n    textAlign = getCSS(el, \"textAlign\"),\r\n    metrics,\r\n    textList,\r\n    state = {\r\n      node: textNode,\r\n      textOffset: 0\r\n    };\r\n\r\n    if (Util.trimText(textNode.nodeValue).length > 0) {\r\n      textNode.nodeValue = textTransform(textNode.nodeValue, getCSS(el, \"textTransform\"));\r\n      textAlign = textAlign.replace([\"-webkit-auto\"],[\"auto\"]);\r\n\r\n      textList = (!options.letterRendering && /^(left|right|justify|auto)$/.test(textAlign) && noLetterSpacing(getCSS(el, \"letterSpacing\"))) ?\r\n      textNode.nodeValue.split(/(\\b| )/)\r\n      : textNode.nodeValue.split(\"\");\r\n\r\n      metrics = setTextVariables(ctx, el, textDecoration, color);\r\n\r\n      if (options.chinese) {\r\n        textList.forEach(function(word, index) {\r\n          if (/.*[\\u4E00-\\u9FA5].*$/.test(word)) {\r\n            word = word.split(\"\");\r\n            word.unshift(index, 1);\r\n            textList.splice.apply(textList, word);\r\n          }\r\n        });\r\n      }\r\n\r\n      textList.forEach(function(text, index) {\r\n        var bounds = getTextBounds(state, text, textDecoration, (index < textList.length - 1), stack.transform.matrix);\r\n        if (bounds) {\r\n          drawText(text, bounds.left, bounds.bottom, ctx);\r\n          renderTextDecoration(ctx, textDecoration, bounds, metrics, color);\r\n        }\r\n      });\r\n    }\r\n  }\r\n\r\n  function listPosition (element, val) {\r\n    var boundElement = doc.createElement( \"boundelement\" ),\r\n    originalType,\r\n    bounds;\r\n\r\n    boundElement.style.display = \"inline\";\r\n\r\n    originalType = element.style.listStyleType;\r\n    element.style.listStyleType = \"none\";\r\n\r\n    boundElement.appendChild(doc.createTextNode(val));\r\n\r\n    element.insertBefore(boundElement, element.firstChild);\r\n\r\n    bounds = Util.Bounds(boundElement);\r\n    element.removeChild(boundElement);\r\n    element.style.listStyleType = originalType;\r\n    return bounds;\r\n  }\r\n\r\n  function elementIndex(el) {\r\n    var i = -1,\r\n    count = 1,\r\n    childs = el.parentNode.childNodes;\r\n\r\n    if (el.parentNode) {\r\n      while(childs[++i] !== el) {\r\n        if (childs[i].nodeType === 1) {\r\n          count++;\r\n        }\r\n      }\r\n      return count;\r\n    } else {\r\n      return -1;\r\n    }\r\n  }\r\n\r\n  function listItemText(element, type) {\r\n    var currentIndex = elementIndex(element), text;\r\n    switch(type){\r\n      case \"decimal\":\r\n        text = currentIndex;\r\n        break;\r\n      case \"decimal-leading-zero\":\r\n        text = (currentIndex.toString().length === 1) ? currentIndex = \"0\" + currentIndex.toString() : currentIndex.toString();\r\n        break;\r\n      case \"upper-roman\":\r\n        text = _html2canvas.Generate.ListRoman( currentIndex );\r\n        break;\r\n      case \"lower-roman\":\r\n        text = _html2canvas.Generate.ListRoman( currentIndex ).toLowerCase();\r\n        break;\r\n      case \"lower-alpha\":\r\n        text = _html2canvas.Generate.ListAlpha( currentIndex ).toLowerCase();\r\n        break;\r\n      case \"upper-alpha\":\r\n        text = _html2canvas.Generate.ListAlpha( currentIndex );\r\n        break;\r\n    }\r\n\r\n    return text + \". \";\r\n  }\r\n\r\n  function renderListItem(element, stack, elBounds) {\r\n    var x,\r\n    text,\r\n    ctx = stack.ctx,\r\n    type = getCSS(element, \"listStyleType\"),\r\n    listBounds;\r\n\r\n    if (/^(decimal|decimal-leading-zero|upper-alpha|upper-latin|upper-roman|lower-alpha|lower-greek|lower-latin|lower-roman)$/i.test(type)) {\r\n      text = listItemText(element, type);\r\n      listBounds = listPosition(element, text);\r\n      setTextVariables(ctx, element, \"none\", getCSS(element, \"color\"));\r\n\r\n      if (getCSS(element, \"listStylePosition\") === \"inside\") {\r\n        ctx.setVariable(\"textAlign\", \"left\");\r\n        x = elBounds.left;\r\n      } else {\r\n        return;\r\n      }\r\n\r\n      drawText(text, x, listBounds.bottom, ctx);\r\n    }\r\n  }\r\n\r\n  function loadImage (src){\r\n    var img = images[src];\r\n    return (img && img.succeeded === true) ? img.img : false;\r\n  }\r\n\r\n  function clipBounds(src, dst){\r\n    var x = Math.max(src.left, dst.left),\r\n    y = Math.max(src.top, dst.top),\r\n    x2 = Math.min((src.left + src.width), (dst.left + dst.width)),\r\n    y2 = Math.min((src.top + src.height), (dst.top + dst.height));\r\n\r\n    return {\r\n      left:x,\r\n      top:y,\r\n      width:x2-x,\r\n      height:y2-y\r\n    };\r\n  }\r\n\r\n  function setZ(element, stack, parentStack){\r\n    var newContext,\r\n    isPositioned = stack.cssPosition !== 'static',\r\n    zIndex = isPositioned ? getCSS(element, 'zIndex') : 'auto',\r\n    opacity = getCSS(element, 'opacity'),\r\n    isFloated = getCSS(element, 'cssFloat') !== 'none';\r\n\r\n    // https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context\r\n    // When a new stacking context should be created:\r\n    // the root element (HTML),\r\n    // positioned (absolutely or relatively) with a z-index value other than \"auto\",\r\n    // elements with an opacity value less than 1. (See the specification for opacity),\r\n    // on mobile WebKit and Chrome 22+, position: fixed always creates a new stacking context, even when z-index is \"auto\" (See this post)\r\n\r\n    stack.zIndex = newContext = h2czContext(zIndex);\r\n    newContext.isPositioned = isPositioned;\r\n    newContext.isFloated = isFloated;\r\n    newContext.opacity = opacity;\r\n    newContext.ownStacking = (zIndex !== 'auto' || opacity < 1);\r\n\r\n    if (parentStack) {\r\n      parentStack.zIndex.children.push(stack);\r\n    }\r\n  }\r\n\r\n  function renderImage(ctx, element, image, bounds, borders) {\r\n\r\n    var paddingLeft = getCSSInt(element, 'paddingLeft'),\r\n    paddingTop = getCSSInt(element, 'paddingTop'),\r\n    paddingRight = getCSSInt(element, 'paddingRight'),\r\n    paddingBottom = getCSSInt(element, 'paddingBottom');\r\n\r\n    drawImage(\r\n      ctx,\r\n      image,\r\n      0, //sx\r\n      0, //sy\r\n      image.width, //sw\r\n      image.height, //sh\r\n      bounds.left + paddingLeft + borders[3].width, //dx\r\n      bounds.top + paddingTop + borders[0].width, // dy\r\n      bounds.width - (borders[1].width + borders[3].width + paddingLeft + paddingRight), //dw\r\n      bounds.height - (borders[0].width + borders[2].width + paddingTop + paddingBottom) //dh\r\n      );\r\n  }\r\n\r\n  function getBorderData(element) {\r\n    return [\"Top\", \"Right\", \"Bottom\", \"Left\"].map(function(side) {\r\n      return {\r\n        width: getCSSInt(element, 'border' + side + 'Width'),\r\n        color: getCSS(element, 'border' + side + 'Color')\r\n      };\r\n    });\r\n  }\r\n\r\n  function getBorderRadiusData(element) {\r\n    return [\"TopLeft\", \"TopRight\", \"BottomRight\", \"BottomLeft\"].map(function(side) {\r\n      return getCSS(element, 'border' + side + 'Radius');\r\n    });\r\n  }\r\n\r\n  var getCurvePoints = (function(kappa) {\r\n\r\n    return function(x, y, r1, r2) {\r\n      var ox = (r1) * kappa, // control point offset horizontal\r\n      oy = (r2) * kappa, // control point offset vertical\r\n      xm = x + r1, // x-middle\r\n      ym = y + r2; // y-middle\r\n      return {\r\n        topLeft: bezierCurve({\r\n          x:x,\r\n          y:ym\r\n        }, {\r\n          x:x,\r\n          y:ym - oy\r\n        }, {\r\n          x:xm - ox,\r\n          y:y\r\n        }, {\r\n          x:xm,\r\n          y:y\r\n        }),\r\n        topRight: bezierCurve({\r\n          x:x,\r\n          y:y\r\n        }, {\r\n          x:x + ox,\r\n          y:y\r\n        }, {\r\n          x:xm,\r\n          y:ym - oy\r\n        }, {\r\n          x:xm,\r\n          y:ym\r\n        }),\r\n        bottomRight: bezierCurve({\r\n          x:xm,\r\n          y:y\r\n        }, {\r\n          x:xm,\r\n          y:y + oy\r\n        }, {\r\n          x:x + ox,\r\n          y:ym\r\n        }, {\r\n          x:x,\r\n          y:ym\r\n        }),\r\n        bottomLeft: bezierCurve({\r\n          x:xm,\r\n          y:ym\r\n        }, {\r\n          x:xm - ox,\r\n          y:ym\r\n        }, {\r\n          x:x,\r\n          y:y + oy\r\n        }, {\r\n          x:x,\r\n          y:y\r\n        })\r\n      };\r\n    };\r\n  })(4 * ((Math.sqrt(2) - 1) / 3));\r\n\r\n  function bezierCurve(start, startControl, endControl, end) {\r\n\r\n    var lerp = function (a, b, t) {\r\n      return {\r\n        x:a.x + (b.x - a.x) * t,\r\n        y:a.y + (b.y - a.y) * t\r\n      };\r\n    };\r\n\r\n    return {\r\n      start: start,\r\n      startControl: startControl,\r\n      endControl: endControl,\r\n      end: end,\r\n      subdivide: function(t) {\r\n        var ab = lerp(start, startControl, t),\r\n        bc = lerp(startControl, endControl, t),\r\n        cd = lerp(endControl, end, t),\r\n        abbc = lerp(ab, bc, t),\r\n        bccd = lerp(bc, cd, t),\r\n        dest = lerp(abbc, bccd, t);\r\n        return [bezierCurve(start, ab, abbc, dest), bezierCurve(dest, bccd, cd, end)];\r\n      },\r\n      curveTo: function(borderArgs) {\r\n        borderArgs.push([\"bezierCurve\", startControl.x, startControl.y, endControl.x, endControl.y, end.x, end.y]);\r\n      },\r\n      curveToReversed: function(borderArgs) {\r\n        borderArgs.push([\"bezierCurve\", endControl.x, endControl.y, startControl.x, startControl.y, start.x, start.y]);\r\n      }\r\n    };\r\n  }\r\n\r\n  function parseCorner(borderArgs, radius1, radius2, corner1, corner2, x, y) {\r\n    if (radius1[0] > 0 || radius1[1] > 0) {\r\n      borderArgs.push([\"line\", corner1[0].start.x, corner1[0].start.y]);\r\n      corner1[0].curveTo(borderArgs);\r\n      corner1[1].curveTo(borderArgs);\r\n    } else {\r\n      borderArgs.push([\"line\", x, y]);\r\n    }\r\n\r\n    if (radius2[0] > 0 || radius2[1] > 0) {\r\n      borderArgs.push([\"line\", corner2[0].start.x, corner2[0].start.y]);\r\n    }\r\n  }\r\n\r\n  function drawSide(borderData, radius1, radius2, outer1, inner1, outer2, inner2) {\r\n    var borderArgs = [];\r\n\r\n    if (radius1[0] > 0 || radius1[1] > 0) {\r\n      borderArgs.push([\"line\", outer1[1].start.x, outer1[1].start.y]);\r\n      outer1[1].curveTo(borderArgs);\r\n    } else {\r\n      borderArgs.push([ \"line\", borderData.c1[0], borderData.c1[1]]);\r\n    }\r\n\r\n    if (radius2[0] > 0 || radius2[1] > 0) {\r\n      borderArgs.push([\"line\", outer2[0].start.x, outer2[0].start.y]);\r\n      outer2[0].curveTo(borderArgs);\r\n      borderArgs.push([\"line\", inner2[0].end.x, inner2[0].end.y]);\r\n      inner2[0].curveToReversed(borderArgs);\r\n    } else {\r\n      borderArgs.push([ \"line\", borderData.c2[0], borderData.c2[1]]);\r\n      borderArgs.push([ \"line\", borderData.c3[0], borderData.c3[1]]);\r\n    }\r\n\r\n    if (radius1[0] > 0 || radius1[1] > 0) {\r\n      borderArgs.push([\"line\", inner1[1].end.x, inner1[1].end.y]);\r\n      inner1[1].curveToReversed(borderArgs);\r\n    } else {\r\n      borderArgs.push([ \"line\", borderData.c4[0], borderData.c4[1]]);\r\n    }\r\n\r\n    return borderArgs;\r\n  }\r\n\r\n  function calculateCurvePoints(bounds, borderRadius, borders) {\r\n\r\n    var x = bounds.left,\r\n    y = bounds.top,\r\n    width = bounds.width,\r\n    height = bounds.height,\r\n\r\n    tlh = borderRadius[0][0],\r\n    tlv = borderRadius[0][1],\r\n    trh = borderRadius[1][0],\r\n    trv = borderRadius[1][1],\r\n    brh = borderRadius[2][0],\r\n    brv = borderRadius[2][1],\r\n    blh = borderRadius[3][0],\r\n    blv = borderRadius[3][1],\r\n\r\n    topWidth = width - trh,\r\n    rightHeight = height - brv,\r\n    bottomWidth = width - brh,\r\n    leftHeight = height - blv;\r\n\r\n    return {\r\n      topLeftOuter: getCurvePoints(\r\n        x,\r\n        y,\r\n        tlh,\r\n        tlv\r\n        ).topLeft.subdivide(0.5),\r\n\r\n      topLeftInner: getCurvePoints(\r\n        x + borders[3].width,\r\n        y + borders[0].width,\r\n        Math.max(0, tlh - borders[3].width),\r\n        Math.max(0, tlv - borders[0].width)\r\n        ).topLeft.subdivide(0.5),\r\n\r\n      topRightOuter: getCurvePoints(\r\n        x + topWidth,\r\n        y,\r\n        trh,\r\n        trv\r\n        ).topRight.subdivide(0.5),\r\n\r\n      topRightInner: getCurvePoints(\r\n        x + Math.min(topWidth, width + borders[3].width),\r\n        y + borders[0].width,\r\n        (topWidth > width + borders[3].width) ? 0 :trh - borders[3].width,\r\n        trv - borders[0].width\r\n        ).topRight.subdivide(0.5),\r\n\r\n      bottomRightOuter: getCurvePoints(\r\n        x + bottomWidth,\r\n        y + rightHeight,\r\n        brh,\r\n        brv\r\n        ).bottomRight.subdivide(0.5),\r\n\r\n      bottomRightInner: getCurvePoints(\r\n        x + Math.min(bottomWidth, width + borders[3].width),\r\n        y + Math.min(rightHeight, height + borders[0].width),\r\n        Math.max(0, brh - borders[1].width),\r\n        Math.max(0, brv - borders[2].width)\r\n        ).bottomRight.subdivide(0.5),\r\n\r\n      bottomLeftOuter: getCurvePoints(\r\n        x,\r\n        y + leftHeight,\r\n        blh,\r\n        blv\r\n        ).bottomLeft.subdivide(0.5),\r\n\r\n      bottomLeftInner: getCurvePoints(\r\n        x + borders[3].width,\r\n        y + leftHeight,\r\n        Math.max(0, blh - borders[3].width),\r\n        Math.max(0, blv - borders[2].width)\r\n        ).bottomLeft.subdivide(0.5)\r\n    };\r\n  }\r\n\r\n  function getBorderClip(element, borderPoints, borders, radius, bounds) {\r\n    var backgroundClip = getCSS(element, 'backgroundClip'),\r\n    borderArgs = [];\r\n\r\n    switch(backgroundClip) {\r\n      case \"content-box\":\r\n      case \"padding-box\":\r\n        parseCorner(borderArgs, radius[0], radius[1], borderPoints.topLeftInner, borderPoints.topRightInner, bounds.left + borders[3].width, bounds.top + borders[0].width);\r\n        parseCorner(borderArgs, radius[1], radius[2], borderPoints.topRightInner, borderPoints.bottomRightInner, bounds.left + bounds.width - borders[1].width, bounds.top + borders[0].width);\r\n        parseCorner(borderArgs, radius[2], radius[3], borderPoints.bottomRightInner, borderPoints.bottomLeftInner, bounds.left + bounds.width - borders[1].width, bounds.top + bounds.height - borders[2].width);\r\n        parseCorner(borderArgs, radius[3], radius[0], borderPoints.bottomLeftInner, borderPoints.topLeftInner, bounds.left + borders[3].width, bounds.top + bounds.height - borders[2].width);\r\n        break;\r\n\r\n      default:\r\n        parseCorner(borderArgs, radius[0], radius[1], borderPoints.topLeftOuter, borderPoints.topRightOuter, bounds.left, bounds.top);\r\n        parseCorner(borderArgs, radius[1], radius[2], borderPoints.topRightOuter, borderPoints.bottomRightOuter, bounds.left + bounds.width, bounds.top);\r\n        parseCorner(borderArgs, radius[2], radius[3], borderPoints.bottomRightOuter, borderPoints.bottomLeftOuter, bounds.left + bounds.width, bounds.top + bounds.height);\r\n        parseCorner(borderArgs, radius[3], radius[0], borderPoints.bottomLeftOuter, borderPoints.topLeftOuter, bounds.left, bounds.top + bounds.height);\r\n        break;\r\n    }\r\n\r\n    return borderArgs;\r\n  }\r\n\r\n  function parseBorders(element, bounds, borders){\r\n    var x = bounds.left,\r\n    y = bounds.top,\r\n    width = bounds.width,\r\n    height = bounds.height,\r\n    borderSide,\r\n    bx,\r\n    by,\r\n    bw,\r\n    bh,\r\n    borderArgs,\r\n    // http://www.w3.org/TR/css3-background/#the-border-radius\r\n    borderRadius = getBorderRadiusData(element),\r\n    borderPoints = calculateCurvePoints(bounds, borderRadius, borders),\r\n    borderData = {\r\n      clip: getBorderClip(element, borderPoints, borders, borderRadius, bounds),\r\n      borders: []\r\n    };\r\n\r\n    for (borderSide = 0; borderSide < 4; borderSide++) {\r\n\r\n      if (borders[borderSide].width > 0) {\r\n        bx = x;\r\n        by = y;\r\n        bw = width;\r\n        bh = height - (borders[2].width);\r\n\r\n        switch(borderSide) {\r\n          case 0:\r\n            // top border\r\n            bh = borders[0].width;\r\n\r\n            borderArgs = drawSide({\r\n              c1: [bx, by],\r\n              c2: [bx + bw, by],\r\n              c3: [bx + bw - borders[1].width, by + bh],\r\n              c4: [bx + borders[3].width, by + bh]\r\n            }, borderRadius[0], borderRadius[1],\r\n            borderPoints.topLeftOuter, borderPoints.topLeftInner, borderPoints.topRightOuter, borderPoints.topRightInner);\r\n            break;\r\n          case 1:\r\n            // right border\r\n            bx = x + width - (borders[1].width);\r\n            bw = borders[1].width;\r\n\r\n            borderArgs = drawSide({\r\n              c1: [bx + bw, by],\r\n              c2: [bx + bw, by + bh + borders[2].width],\r\n              c3: [bx, by + bh],\r\n              c4: [bx, by + borders[0].width]\r\n            }, borderRadius[1], borderRadius[2],\r\n            borderPoints.topRightOuter, borderPoints.topRightInner, borderPoints.bottomRightOuter, borderPoints.bottomRightInner);\r\n            break;\r\n          case 2:\r\n            // bottom border\r\n            by = (by + height) - (borders[2].width);\r\n            bh = borders[2].width;\r\n\r\n            borderArgs = drawSide({\r\n              c1: [bx + bw, by + bh],\r\n              c2: [bx, by + bh],\r\n              c3: [bx + borders[3].width, by],\r\n              c4: [bx + bw - borders[3].width, by]\r\n            }, borderRadius[2], borderRadius[3],\r\n            borderPoints.bottomRightOuter, borderPoints.bottomRightInner, borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner);\r\n            break;\r\n          case 3:\r\n            // left border\r\n            bw = borders[3].width;\r\n\r\n            borderArgs = drawSide({\r\n              c1: [bx, by + bh + borders[2].width],\r\n              c2: [bx, by],\r\n              c3: [bx + bw, by + borders[0].width],\r\n              c4: [bx + bw, by + bh]\r\n            }, borderRadius[3], borderRadius[0],\r\n            borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner, borderPoints.topLeftOuter, borderPoints.topLeftInner);\r\n            break;\r\n        }\r\n\r\n        borderData.borders.push({\r\n          args: borderArgs,\r\n          color: borders[borderSide].color\r\n        });\r\n\r\n      }\r\n    }\r\n\r\n    return borderData;\r\n  }\r\n\r\n  function createShape(ctx, args) {\r\n    var shape = ctx.drawShape();\r\n    args.forEach(function(border, index) {\r\n      shape[(index === 0) ? \"moveTo\" : border[0] + \"To\" ].apply(null, border.slice(1));\r\n    });\r\n    return shape;\r\n  }\r\n\r\n  function renderBorders(ctx, borderArgs, color) {\r\n    if (color !== \"transparent\") {\r\n      ctx.setVariable( \"fillStyle\", color);\r\n      createShape(ctx, borderArgs);\r\n      ctx.fill();\r\n      numDraws+=1;\r\n    }\r\n  }\r\n\r\n  function renderFormValue (el, bounds, stack){\r\n\r\n    var valueWrap = doc.createElement('valuewrap'),\r\n    cssPropertyArray = ['lineHeight','textAlign','fontFamily','color','fontSize','paddingLeft','paddingTop','width','height','border','borderLeftWidth','borderTopWidth'],\r\n    textValue,\r\n    textNode;\r\n\r\n    cssPropertyArray.forEach(function(property) {\r\n      try {\r\n        valueWrap.style[property] = getCSS(el, property);\r\n      } catch(e) {\r\n        // Older IE has issues with \"border\"\r\n        Util.log(\"html2canvas: Parse: Exception caught in renderFormValue: \" + e.message);\r\n      }\r\n    });\r\n\r\n    valueWrap.style.borderColor = \"black\";\r\n    valueWrap.style.borderStyle = \"solid\";\r\n    valueWrap.style.display = \"block\";\r\n    valueWrap.style.position = \"absolute\";\r\n\r\n    if (/^(submit|reset|button|text|password)$/.test(el.type) || el.nodeName === \"SELECT\"){\r\n      valueWrap.style.lineHeight = getCSS(el, \"height\");\r\n    }\r\n\r\n    valueWrap.style.top = bounds.top + \"px\";\r\n    valueWrap.style.left = bounds.left + \"px\";\r\n\r\n    textValue = (el.nodeName === \"SELECT\") ? (el.options[el.selectedIndex] || 0).text : el.value;\r\n    if(!textValue) {\r\n      textValue = el.placeholder;\r\n    }\r\n\r\n    textNode = doc.createTextNode(textValue);\r\n\r\n    valueWrap.appendChild(textNode);\r\n    body.appendChild(valueWrap);\r\n\r\n    renderText(el, textNode, stack);\r\n    body.removeChild(valueWrap);\r\n  }\r\n\r\n  function drawImage (ctx) {\r\n    ctx.drawImage.apply(ctx, Array.prototype.slice.call(arguments, 1));\r\n    numDraws+=1;\r\n  }\r\n\r\n  function getPseudoElement(el, which) {\r\n    var elStyle = window.getComputedStyle(el, which);\r\n    if(!elStyle || !elStyle.content || elStyle.content === \"none\" || elStyle.content === \"-moz-alt-content\" || elStyle.display === \"none\") {\r\n      return;\r\n    }\r\n    var content = elStyle.content + '',\r\n    first = content.substr( 0, 1 );\r\n    //strips quotes\r\n    if(first === content.substr( content.length - 1 ) && first.match(/'|\"/)) {\r\n      content = content.substr( 1, content.length - 2 );\r\n    }\r\n\r\n    var isImage = content.substr( 0, 3 ) === 'url',\r\n    elps = document.createElement( isImage ? 'img' : 'span' );\r\n\r\n    elps.className = pseudoHide + \"-before \" + pseudoHide + \"-after\";\r\n\r\n    Object.keys(elStyle).filter(indexedProperty).forEach(function(prop) {\r\n      // Prevent assigning of read only CSS Rules, ex. length, parentRule\r\n      try {\r\n        elps.style[prop] = elStyle[prop];\r\n      } catch (e) {\r\n        Util.log(['Tried to assign readonly property ', prop, 'Error:', e]);\r\n      }\r\n    });\r\n\r\n    if(isImage) {\r\n      elps.src = Util.parseBackgroundImage(content)[0].args[0];\r\n    } else {\r\n      elps.innerHTML = content;\r\n    }\r\n    return elps;\r\n  }\r\n\r\n  function indexedProperty(property) {\r\n    return (isNaN(window.parseInt(property, 10)));\r\n  }\r\n\r\n  function injectPseudoElements(el, stack) {\r\n    var before = getPseudoElement(el, ':before'),\r\n    after = getPseudoElement(el, ':after');\r\n    if(!before && !after) {\r\n      return;\r\n    }\r\n\r\n    if(before) {\r\n      el.className += \" \" + pseudoHide + \"-before\";\r\n      el.parentNode.insertBefore(before, el);\r\n      parseElement(before, stack, true);\r\n      el.parentNode.removeChild(before);\r\n      el.className = el.className.replace(pseudoHide + \"-before\", \"\").trim();\r\n    }\r\n\r\n    if (after) {\r\n      el.className += \" \" + pseudoHide + \"-after\";\r\n      el.appendChild(after);\r\n      parseElement(after, stack, true);\r\n      el.removeChild(after);\r\n      el.className = el.className.replace(pseudoHide + \"-after\", \"\").trim();\r\n    }\r\n\r\n  }\r\n\r\n  function renderBackgroundRepeat(ctx, image, backgroundPosition, bounds) {\r\n    var offsetX = Math.round(bounds.left + backgroundPosition.left),\r\n    offsetY = Math.round(bounds.top + backgroundPosition.top);\r\n\r\n    ctx.createPattern(image);\r\n    ctx.translate(offsetX, offsetY);\r\n    ctx.fill();\r\n    ctx.translate(-offsetX, -offsetY);\r\n  }\r\n\r\n  function backgroundRepeatShape(ctx, image, backgroundPosition, bounds, left, top, width, height) {\r\n    var args = [];\r\n    args.push([\"line\", Math.round(left), Math.round(top)]);\r\n    args.push([\"line\", Math.round(left + width), Math.round(top)]);\r\n    args.push([\"line\", Math.round(left + width), Math.round(height + top)]);\r\n    args.push([\"line\", Math.round(left), Math.round(height + top)]);\r\n    createShape(ctx, args);\r\n    ctx.save();\r\n    ctx.clip();\r\n    renderBackgroundRepeat(ctx, image, backgroundPosition, bounds);\r\n    ctx.restore();\r\n  }\r\n\r\n  function renderBackgroundColor(ctx, backgroundBounds, bgcolor) {\r\n    renderRect(\r\n      ctx,\r\n      backgroundBounds.left,\r\n      backgroundBounds.top,\r\n      backgroundBounds.width,\r\n      backgroundBounds.height,\r\n      bgcolor\r\n      );\r\n  }\r\n\r\n  function renderBackgroundRepeating(el, bounds, ctx, image, imageIndex) {\r\n    var backgroundSize = Util.BackgroundSize(el, bounds, image, imageIndex),\r\n    backgroundPosition = Util.BackgroundPosition(el, bounds, image, imageIndex, backgroundSize),\r\n    backgroundRepeat = getCSS(el, \"backgroundRepeat\").split(\",\").map(Util.trimText);\r\n\r\n    image = resizeImage(image, backgroundSize);\r\n\r\n    backgroundRepeat = backgroundRepeat[imageIndex] || backgroundRepeat[0];\r\n\r\n    switch (backgroundRepeat) {\r\n      case \"repeat-x\":\r\n        backgroundRepeatShape(ctx, image, backgroundPosition, bounds,\r\n          bounds.left, bounds.top + backgroundPosition.top, 99999, image.height);\r\n        break;\r\n\r\n      case \"repeat-y\":\r\n        backgroundRepeatShape(ctx, image, backgroundPosition, bounds,\r\n          bounds.left + backgroundPosition.left, bounds.top, image.width, 99999);\r\n        break;\r\n\r\n      case \"no-repeat\":\r\n        backgroundRepeatShape(ctx, image, backgroundPosition, bounds,\r\n          bounds.left + backgroundPosition.left, bounds.top + backgroundPosition.top, image.width, image.height);\r\n        break;\r\n\r\n      default:\r\n        renderBackgroundRepeat(ctx, image, backgroundPosition, {\r\n          top: bounds.top,\r\n          left: bounds.left,\r\n          width: image.width,\r\n          height: image.height\r\n        });\r\n        break;\r\n    }\r\n  }\r\n\r\n  function renderBackgroundImage(element, bounds, ctx) {\r\n    var backgroundImage = getCSS(element, \"backgroundImage\"),\r\n    backgroundImages = Util.parseBackgroundImage(backgroundImage),\r\n    image,\r\n    imageIndex = backgroundImages.length;\r\n\r\n    while(imageIndex--) {\r\n      backgroundImage = backgroundImages[imageIndex];\r\n\r\n      if (!backgroundImage.args || backgroundImage.args.length === 0) {\r\n        continue;\r\n      }\r\n\r\n      var key = backgroundImage.method === 'url' ?\r\n      backgroundImage.args[0] :\r\n      backgroundImage.value;\r\n\r\n      image = loadImage(key);\r\n\r\n      // TODO add support for background-origin\r\n      if (image) {\r\n        renderBackgroundRepeating(element, bounds, ctx, image, imageIndex);\r\n      } else {\r\n        Util.log(\"html2canvas: Error loading background:\", backgroundImage);\r\n      }\r\n    }\r\n  }\r\n\r\n  function resizeImage(image, bounds) {\r\n    if(image.width === bounds.width && image.height === bounds.height) {\r\n      return image;\r\n    }\r\n\r\n    var ctx, canvas = doc.createElement('canvas');\r\n    canvas.width = bounds.width;\r\n    canvas.height = bounds.height;\r\n    ctx = canvas.getContext(\"2d\");\r\n    drawImage(ctx, image, 0, 0, image.width, image.height, 0, 0, bounds.width, bounds.height );\r\n    return canvas;\r\n  }\r\n\r\n  function setOpacity(ctx, element, parentStack) {\r\n    return ctx.setVariable(\"globalAlpha\", getCSS(element, \"opacity\") * ((parentStack) ? parentStack.opacity : 1));\r\n  }\r\n\r\n  function removePx(str) {\r\n    return str.replace(\"px\", \"\");\r\n  }\r\n\r\n  var transformRegExp = /(matrix)\\((.+)\\)/;\r\n\r\n  function getTransform(element, parentStack) {\r\n    var transform = getCSS(element, \"transform\") || getCSS(element, \"-webkit-transform\") || getCSS(element, \"-moz-transform\") || getCSS(element, \"-ms-transform\") || getCSS(element, \"-o-transform\");\r\n    var transformOrigin = getCSS(element, \"transform-origin\") || getCSS(element, \"-webkit-transform-origin\") || getCSS(element, \"-moz-transform-origin\") || getCSS(element, \"-ms-transform-origin\") || getCSS(element, \"-o-transform-origin\") || \"0px 0px\";\r\n\r\n    transformOrigin = transformOrigin.split(\" \").map(removePx).map(Util.asFloat);\r\n\r\n    var matrix;\r\n    if (transform && transform !== \"none\") {\r\n      var match = transform.match(transformRegExp);\r\n      if (match) {\r\n        switch(match[1]) {\r\n          case \"matrix\":\r\n            matrix = match[2].split(\",\").map(Util.trimText).map(Util.asFloat);\r\n            break;\r\n        }\r\n      }\r\n    }\r\n\r\n    return {\r\n      origin: transformOrigin,\r\n      matrix: matrix\r\n    };\r\n  }\r\n\r\n  function createStack(element, parentStack, bounds, transform) {\r\n    var ctx = h2cRenderContext((!parentStack) ? documentWidth() : bounds.width , (!parentStack) ? documentHeight() : bounds.height),\r\n    stack = {\r\n      ctx: ctx,\r\n      opacity: setOpacity(ctx, element, parentStack),\r\n      cssPosition: getCSS(element, \"position\"),\r\n      borders: getBorderData(element),\r\n      transform: transform,\r\n      clip: (parentStack && parentStack.clip) ? Util.Extend( {}, parentStack.clip ) : null\r\n    };\r\n\r\n    setZ(element, stack, parentStack);\r\n\r\n    // TODO correct overflow for absolute content residing under a static position\r\n    if (options.useOverflow === true && /(hidden|scroll|auto)/.test(getCSS(element, \"overflow\")) === true && /(BODY)/i.test(element.nodeName) === false){\r\n      stack.clip = (stack.clip) ? clipBounds(stack.clip, bounds) : bounds;\r\n    }\r\n\r\n    return stack;\r\n  }\r\n\r\n  function getBackgroundBounds(borders, bounds, clip) {\r\n    var backgroundBounds = {\r\n      left: bounds.left + borders[3].width,\r\n      top: bounds.top + borders[0].width,\r\n      width: bounds.width - (borders[1].width + borders[3].width),\r\n      height: bounds.height - (borders[0].width + borders[2].width)\r\n    };\r\n\r\n    if (clip) {\r\n      backgroundBounds = clipBounds(backgroundBounds, clip);\r\n    }\r\n\r\n    return backgroundBounds;\r\n  }\r\n\r\n  function getBounds(element, transform) {\r\n    var bounds = (transform.matrix) ? Util.OffsetBounds(element) : Util.Bounds(element);\r\n    transform.origin[0] += bounds.left;\r\n    transform.origin[1] += bounds.top;\r\n    return bounds;\r\n  }\r\n\r\n  function renderElement(element, parentStack, pseudoElement, ignoreBackground) {\r\n    var transform = getTransform(element, parentStack),\r\n    bounds = getBounds(element, transform),\r\n    image,\r\n    stack = createStack(element, parentStack, bounds, transform),\r\n    borders = stack.borders,\r\n    ctx = stack.ctx,\r\n    backgroundBounds = getBackgroundBounds(borders, bounds, stack.clip),\r\n    borderData = parseBorders(element, bounds, borders),\r\n    backgroundColor = (ignoreElementsRegExp.test(element.nodeName)) ? \"#efefef\" : getCSS(element, \"backgroundColor\");\r\n\r\n\r\n    createShape(ctx, borderData.clip);\r\n\r\n    ctx.save();\r\n    ctx.clip();\r\n\r\n    if (backgroundBounds.height > 0 && backgroundBounds.width > 0 && !ignoreBackground) {\r\n      renderBackgroundColor(ctx, bounds, backgroundColor);\r\n      renderBackgroundImage(element, backgroundBounds, ctx);\r\n    } else if (ignoreBackground) {\r\n      stack.backgroundColor =  backgroundColor;\r\n    }\r\n\r\n    ctx.restore();\r\n\r\n    borderData.borders.forEach(function(border) {\r\n      renderBorders(ctx, border.args, border.color);\r\n    });\r\n\r\n    if (!pseudoElement) {\r\n      injectPseudoElements(element, stack);\r\n    }\r\n\r\n    switch(element.nodeName){\r\n      case \"IMG\":\r\n        if ((image = loadImage(element.getAttribute('src')))) {\r\n          renderImage(ctx, element, image, bounds, borders);\r\n        } else {\r\n          Util.log(\"html2canvas: Error loading <img>:\" + element.getAttribute('src'));\r\n        }\r\n        break;\r\n      case \"INPUT\":\r\n        // TODO add all relevant type's, i.e. HTML5 new stuff\r\n        // todo add support for placeholder attribute for browsers which support it\r\n        if (/^(text|url|email|submit|button|reset)$/.test(element.type) && (element.value || element.placeholder || \"\").length > 0){\r\n          renderFormValue(element, bounds, stack);\r\n        }\r\n        break;\r\n      case \"TEXTAREA\":\r\n        if ((element.value || element.placeholder || \"\").length > 0){\r\n          renderFormValue(element, bounds, stack);\r\n        }\r\n        break;\r\n      case \"SELECT\":\r\n        if ((element.options||element.placeholder || \"\").length > 0){\r\n          renderFormValue(element, bounds, stack);\r\n        }\r\n        break;\r\n      case \"LI\":\r\n        renderListItem(element, stack, backgroundBounds);\r\n        break;\r\n      case \"CANVAS\":\r\n        renderImage(ctx, element, element, bounds, borders);\r\n        break;\r\n    }\r\n\r\n    return stack;\r\n  }\r\n\r\n  function isElementVisible(element) {\r\n    return (getCSS(element, 'display') !== \"none\" && getCSS(element, 'visibility') !== \"hidden\" && !element.hasAttribute(\"data-html2canvas-ignore\"));\r\n  }\r\n\r\n  function parseElement (element, stack, pseudoElement) {\r\n    if (isElementVisible(element)) {\r\n      stack = renderElement(element, stack, pseudoElement, false) || stack;\r\n      if (!ignoreElementsRegExp.test(element.nodeName)) {\r\n        parseChildren(element, stack, pseudoElement);\r\n      }\r\n    }\r\n  }\r\n\r\n  function parseChildren(element, stack, pseudoElement) {\r\n    Util.Children(element).forEach(function(node) {\r\n      if (node.nodeType === node.ELEMENT_NODE) {\r\n        parseElement(node, stack, pseudoElement);\r\n      } else if (node.nodeType === node.TEXT_NODE) {\r\n        renderText(element, node, stack);\r\n      }\r\n    });\r\n  }\r\n\r\n  function init() {\r\n    var background = getCSS(document.documentElement, \"backgroundColor\"),\r\n      transparentBackground = (Util.isTransparent(background) && element === document.body),\r\n      stack = renderElement(element, null, false, transparentBackground);\r\n    parseChildren(element, stack);\r\n\r\n    if (transparentBackground) {\r\n      background = stack.backgroundColor;\r\n    }\r\n\r\n    body.removeChild(hidePseudoElements);\r\n    return {\r\n      backgroundColor: background,\r\n      stack: stack\r\n    };\r\n  }\r\n\r\n  return init();\r\n};\r\n\r\nfunction h2czContext(zindex) {\r\n  return {\r\n    zindex: zindex,\r\n    children: []\r\n  };\r\n}\r\n\r\n_html2canvas.Preload = function( options ) {\r\n\r\n  var images = {\r\n    numLoaded: 0,   // also failed are counted here\r\n    numFailed: 0,\r\n    numTotal: 0,\r\n    cleanupDone: false\r\n  },\r\n  pageOrigin,\r\n  Util = _html2canvas.Util,\r\n  methods,\r\n  i,\r\n  count = 0,\r\n  element = options.elements[0] || document.body,\r\n  doc = element.ownerDocument,\r\n  domImages = element.getElementsByTagName('img'), // Fetch images of the present element only\r\n  imgLen = domImages.length,\r\n  link = doc.createElement(\"a\"),\r\n  supportCORS = (function( img ){\r\n    return (img.crossOrigin !== undefined);\r\n  })(new Image()),\r\n  timeoutTimer;\r\n\r\n  link.href = window.location.href;\r\n  pageOrigin  = link.protocol + link.host;\r\n\r\n  function isSameOrigin(url){\r\n    link.href = url;\r\n    link.href = link.href; // YES, BELIEVE IT OR NOT, that is required for IE9 - http://jsfiddle.net/niklasvh/2e48b/\r\n    var origin = link.protocol + link.host;\r\n    return (origin === pageOrigin);\r\n  }\r\n\r\n  function start(){\r\n    Util.log(\"html2canvas: start: images: \" + images.numLoaded + \" / \" + images.numTotal + \" (failed: \" + images.numFailed + \")\");\r\n    if (!images.firstRun && images.numLoaded >= images.numTotal){\r\n      Util.log(\"Finished loading images: # \" + images.numTotal + \" (failed: \" + images.numFailed + \")\");\r\n\r\n      if (typeof options.complete === \"function\"){\r\n        options.complete(images);\r\n      }\r\n\r\n    }\r\n  }\r\n\r\n  // TODO modify proxy to serve images with CORS enabled, where available\r\n  function proxyGetImage(url, img, imageObj){\r\n    var callback_name,\r\n    scriptUrl = options.proxy,\r\n    script;\r\n\r\n    link.href = url;\r\n    url = link.href; // work around for pages with base href=\"\" set - WARNING: this may change the url\r\n\r\n    callback_name = 'html2canvas_' + (count++);\r\n    imageObj.callbackname = callback_name;\r\n\r\n    if (scriptUrl.indexOf(\"?\") > -1) {\r\n      scriptUrl += \"&\";\r\n    } else {\r\n      scriptUrl += \"?\";\r\n    }\r\n    scriptUrl += 'url=' + encodeURIComponent(url) + '&callback=' + callback_name;\r\n    script = doc.createElement(\"script\");\r\n\r\n    window[callback_name] = function(a){\r\n      if (a.substring(0,6) === \"error:\"){\r\n        imageObj.succeeded = false;\r\n        images.numLoaded++;\r\n        images.numFailed++;\r\n        start();\r\n      } else {\r\n        setImageLoadHandlers(img, imageObj);\r\n        img.src = a;\r\n      }\r\n      window[callback_name] = undefined; // to work with IE<9  // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)\r\n      try {\r\n        delete window[callback_name];  // for all browser that support this\r\n      } catch(ex) {}\r\n      script.parentNode.removeChild(script);\r\n      script = null;\r\n      delete imageObj.script;\r\n      delete imageObj.callbackname;\r\n    };\r\n\r\n    script.setAttribute(\"type\", \"text/javascript\");\r\n    script.setAttribute(\"src\", scriptUrl);\r\n    imageObj.script = script;\r\n    window.document.body.appendChild(script);\r\n\r\n  }\r\n\r\n  function loadPseudoElement(element, type) {\r\n    var style = window.getComputedStyle(element, type),\r\n    content = style.content;\r\n    if (content.substr(0, 3) === 'url') {\r\n      methods.loadImage(_html2canvas.Util.parseBackgroundImage(content)[0].args[0]);\r\n    }\r\n    loadBackgroundImages(style.backgroundImage, element);\r\n  }\r\n\r\n  function loadPseudoElementImages(element) {\r\n    loadPseudoElement(element, \":before\");\r\n    loadPseudoElement(element, \":after\");\r\n  }\r\n\r\n  function loadGradientImage(backgroundImage, bounds) {\r\n    var img = _html2canvas.Generate.Gradient(backgroundImage, bounds);\r\n\r\n    if (img !== undefined){\r\n      images[backgroundImage] = {\r\n        img: img,\r\n        succeeded: true\r\n      };\r\n      images.numTotal++;\r\n      images.numLoaded++;\r\n      start();\r\n    }\r\n  }\r\n\r\n  function invalidBackgrounds(background_image) {\r\n    return (background_image && background_image.method && background_image.args && background_image.args.length > 0 );\r\n  }\r\n\r\n  function loadBackgroundImages(background_image, el) {\r\n    var bounds;\r\n\r\n    _html2canvas.Util.parseBackgroundImage(background_image).filter(invalidBackgrounds).forEach(function(background_image) {\r\n      if (background_image.method === 'url') {\r\n        methods.loadImage(background_image.args[0]);\r\n      } else if(background_image.method.match(/\\-?gradient$/)) {\r\n        if(bounds === undefined) {\r\n          bounds = _html2canvas.Util.Bounds(el);\r\n        }\r\n        loadGradientImage(background_image.value, bounds);\r\n      }\r\n    });\r\n  }\r\n\r\n  function getImages (el) {\r\n    var elNodeType = false;\r\n\r\n    // Firefox fails with permission denied on pages with iframes\r\n    try {\r\n      Util.Children(el).forEach(getImages);\r\n    }\r\n    catch( e ) {}\r\n\r\n    try {\r\n      elNodeType = el.nodeType;\r\n    } catch (ex) {\r\n      elNodeType = false;\r\n      Util.log(\"html2canvas: failed to access some element's nodeType - Exception: \" + ex.message);\r\n    }\r\n\r\n    if (elNodeType === 1 || elNodeType === undefined) {\r\n      loadPseudoElementImages(el);\r\n      try {\r\n        loadBackgroundImages(Util.getCSS(el, 'backgroundImage'), el);\r\n      } catch(e) {\r\n        Util.log(\"html2canvas: failed to get background-image - Exception: \" + e.message);\r\n      }\r\n      loadBackgroundImages(el);\r\n    }\r\n  }\r\n\r\n  function setImageLoadHandlers(img, imageObj) {\r\n    img.onload = function() {\r\n      if ( imageObj.timer !== undefined ) {\r\n        // CORS succeeded\r\n        window.clearTimeout( imageObj.timer );\r\n      }\r\n\r\n      images.numLoaded++;\r\n      imageObj.succeeded = true;\r\n      img.onerror = img.onload = null;\r\n      start();\r\n    };\r\n    img.onerror = function() {\r\n      if (img.crossOrigin === \"anonymous\") {\r\n        // CORS failed\r\n        window.clearTimeout( imageObj.timer );\r\n\r\n        // let's try with proxy instead\r\n        if ( options.proxy ) {\r\n          var src = img.src;\r\n          img = new Image();\r\n          imageObj.img = img;\r\n          img.src = src;\r\n\r\n          proxyGetImage( img.src, img, imageObj );\r\n          return;\r\n        }\r\n      }\r\n\r\n      images.numLoaded++;\r\n      images.numFailed++;\r\n      imageObj.succeeded = false;\r\n      img.onerror = img.onload = null;\r\n      start();\r\n    };\r\n  }\r\n\r\n  methods = {\r\n    loadImage: function( src ) {\r\n      var img, imageObj;\r\n      if ( src && images[src] === undefined ) {\r\n        img = new Image();\r\n        if ( src.match(/data:image\\/.*;base64,/i) ) {\r\n          img.src = src.replace(/url\\(['\"]{0,}|['\"]{0,}\\)$/ig, '');\r\n          imageObj = images[src] = {\r\n            img: img\r\n          };\r\n          images.numTotal++;\r\n          setImageLoadHandlers(img, imageObj);\r\n        } else if ( isSameOrigin( src ) || options.allowTaint ===  true ) {\r\n          imageObj = images[src] = {\r\n            img: img\r\n          };\r\n          images.numTotal++;\r\n          setImageLoadHandlers(img, imageObj);\r\n          img.src = src;\r\n        } else if ( supportCORS && !options.allowTaint && options.useCORS ) {\r\n          // attempt to load with CORS\r\n\r\n          img.crossOrigin = \"anonymous\";\r\n          imageObj = images[src] = {\r\n            img: img\r\n          };\r\n          images.numTotal++;\r\n          setImageLoadHandlers(img, imageObj);\r\n          img.src = src;\r\n        } else if ( options.proxy ) {\r\n          imageObj = images[src] = {\r\n            img: img\r\n          };\r\n          images.numTotal++;\r\n          proxyGetImage( src, img, imageObj );\r\n        }\r\n      }\r\n\r\n    },\r\n    cleanupDOM: function(cause) {\r\n      var img, src;\r\n      if (!images.cleanupDone) {\r\n        if (cause && typeof cause === \"string\") {\r\n          Util.log(\"html2canvas: Cleanup because: \" + cause);\r\n        } else {\r\n          Util.log(\"html2canvas: Cleanup after timeout: \" + options.timeout + \" ms.\");\r\n        }\r\n\r\n        for (src in images) {\r\n          if (images.hasOwnProperty(src)) {\r\n            img = images[src];\r\n            if (typeof img === \"object\" && img.callbackname && img.succeeded === undefined) {\r\n              // cancel proxy image request\r\n              window[img.callbackname] = undefined; // to work with IE<9  // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)\r\n              try {\r\n                delete window[img.callbackname];  // for all browser that support this\r\n              } catch(ex) {}\r\n              if (img.script && img.script.parentNode) {\r\n                img.script.setAttribute(\"src\", \"about:blank\");  // try to cancel running request\r\n                img.script.parentNode.removeChild(img.script);\r\n              }\r\n              images.numLoaded++;\r\n              images.numFailed++;\r\n              Util.log(\"html2canvas: Cleaned up failed img: '\" + src + \"' Steps: \" + images.numLoaded + \" / \" + images.numTotal);\r\n            }\r\n          }\r\n        }\r\n\r\n        // cancel any pending requests\r\n        if(window.stop !== undefined) {\r\n          window.stop();\r\n        } else if(document.execCommand !== undefined) {\r\n          document.execCommand(\"Stop\", false);\r\n        }\r\n        if (document.close !== undefined) {\r\n          document.close();\r\n        }\r\n        images.cleanupDone = true;\r\n        if (!(cause && typeof cause === \"string\")) {\r\n          start();\r\n        }\r\n      }\r\n    },\r\n\r\n    renderingDone: function() {\r\n      if (timeoutTimer) {\r\n        window.clearTimeout(timeoutTimer);\r\n      }\r\n    }\r\n  };\r\n\r\n  if (options.timeout > 0) {\r\n    timeoutTimer = window.setTimeout(methods.cleanupDOM, options.timeout);\r\n  }\r\n\r\n  Util.log('html2canvas: Preload starts: finding background-images');\r\n  images.firstRun = true;\r\n\r\n  getImages(element);\r\n\r\n  Util.log('html2canvas: Preload: Finding images');\r\n  // load <img> images\r\n  for (i = 0; i < imgLen; i+=1){\r\n    methods.loadImage( domImages[i].getAttribute( \"src\" ) );\r\n  }\r\n\r\n  images.firstRun = false;\r\n  Util.log('html2canvas: Preload: Done.');\r\n  if (images.numTotal === images.numLoaded) {\r\n    start();\r\n  }\r\n\r\n  return methods;\r\n};\r\n\r\n_html2canvas.Renderer = function(parseQueue, options){\r\n\r\n  // http://www.w3.org/TR/CSS21/zindex.html\r\n  function createRenderQueue(parseQueue) {\r\n    var queue = [],\r\n    rootContext;\r\n\r\n    rootContext = (function buildStackingContext(rootNode) {\r\n      var rootContext = {};\r\n      function insert(context, node, specialParent) {\r\n        var zi = (node.zIndex.zindex === 'auto') ? 0 : Number(node.zIndex.zindex),\r\n        contextForChildren = context, // the stacking context for children\r\n        isPositioned = node.zIndex.isPositioned,\r\n        isFloated = node.zIndex.isFloated,\r\n        stub = {node: node},\r\n        childrenDest = specialParent; // where children without z-index should be pushed into\r\n\r\n        if (node.zIndex.ownStacking) {\r\n          // '!' comes before numbers in sorted array\r\n          contextForChildren = stub.context = { '!': [{node:node, children: []}]};\r\n          childrenDest = undefined;\r\n        } else if (isPositioned || isFloated) {\r\n          childrenDest = stub.children = [];\r\n        }\r\n\r\n        if (zi === 0 && specialParent) {\r\n          specialParent.push(stub);\r\n        } else {\r\n          if (!context[zi]) { context[zi] = []; }\r\n          context[zi].push(stub);\r\n        }\r\n\r\n        node.zIndex.children.forEach(function(childNode) {\r\n          insert(contextForChildren, childNode, childrenDest);\r\n        });\r\n      }\r\n      insert(rootContext, rootNode);\r\n      return rootContext;\r\n    })(parseQueue);\r\n\r\n    function sortZ(context) {\r\n      Object.keys(context).sort().forEach(function(zi) {\r\n        var nonPositioned = [],\r\n        floated = [],\r\n        positioned = [],\r\n        list = [];\r\n\r\n        // positioned after static\r\n        context[zi].forEach(function(v) {\r\n          if (v.node.zIndex.isPositioned || v.node.zIndex.opacity < 1) {\r\n            // http://www.w3.org/TR/css3-color/#transparency\r\n            // non-positioned element with opactiy < 1 should be stacked as if it were a positioned element with ‘z-index: 0’ and ‘opacity: 1’.\r\n            positioned.push(v);\r\n          } else if (v.node.zIndex.isFloated) {\r\n            floated.push(v);\r\n          } else {\r\n            nonPositioned.push(v);\r\n          }\r\n        });\r\n\r\n        (function walk(arr) {\r\n          arr.forEach(function(v) {\r\n            list.push(v);\r\n            if (v.children) { walk(v.children); }\r\n          });\r\n        })(nonPositioned.concat(floated, positioned));\r\n\r\n        list.forEach(function(v) {\r\n          if (v.context) {\r\n            sortZ(v.context);\r\n          } else {\r\n            queue.push(v.node);\r\n          }\r\n        });\r\n      });\r\n    }\r\n\r\n    sortZ(rootContext);\r\n\r\n    return queue;\r\n  }\r\n\r\n  function getRenderer(rendererName) {\r\n    var renderer;\r\n\r\n    if (typeof options.renderer === \"string\" && _html2canvas.Renderer[rendererName] !== undefined) {\r\n      renderer = _html2canvas.Renderer[rendererName](options);\r\n    } else if (typeof rendererName === \"function\") {\r\n      renderer = rendererName(options);\r\n    } else {\r\n      throw new Error(\"Unknown renderer\");\r\n    }\r\n\r\n    if ( typeof renderer !== \"function\" ) {\r\n      throw new Error(\"Invalid renderer defined\");\r\n    }\r\n    return renderer;\r\n  }\r\n\r\n  return getRenderer(options.renderer)(parseQueue, options, document, createRenderQueue(parseQueue.stack), _html2canvas);\r\n};\r\n\r\n_html2canvas.Util.Support = function (options, doc) {\r\n\r\n  function supportSVGRendering() {\r\n    var img = new Image(),\r\n    canvas = doc.createElement(\"canvas\"),\r\n    ctx = (canvas.getContext === undefined) ? false : canvas.getContext(\"2d\");\r\n    if (ctx === false) {\r\n      return false;\r\n    }\r\n    canvas.width = canvas.height = 10;\r\n    img.src = [\r\n    \"data:image/svg+xml,\",\r\n    \"<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'>\",\r\n    \"<foreignObject width='10' height='10'>\",\r\n    \"<div xmlns='http://www.w3.org/1999/xhtml' style='width:10;height:10;'>\",\r\n    \"sup\",\r\n    \"</div>\",\r\n    \"</foreignObject>\",\r\n    \"</svg>\"\r\n    ].join(\"\");\r\n    try {\r\n      ctx.drawImage(img, 0, 0);\r\n      canvas.toDataURL();\r\n    } catch(e) {\r\n      return false;\r\n    }\r\n    _html2canvas.Util.log('html2canvas: Parse: SVG powered rendering available');\r\n    return true;\r\n  }\r\n\r\n  // Test whether we can use ranges to measure bounding boxes\r\n  // Opera doesn't provide valid bounds.height/bottom even though it supports the method.\r\n\r\n  function supportRangeBounds() {\r\n    var r, testElement, rangeBounds, rangeHeight, support = false;\r\n\r\n    if (doc.createRange) {\r\n      r = doc.createRange();\r\n      if (r.getBoundingClientRect) {\r\n        testElement = doc.createElement('boundtest');\r\n        testElement.style.height = \"123px\";\r\n        testElement.style.display = \"block\";\r\n        doc.body.appendChild(testElement);\r\n\r\n        r.selectNode(testElement);\r\n        rangeBounds = r.getBoundingClientRect();\r\n        rangeHeight = rangeBounds.height;\r\n\r\n        if (rangeHeight === 123) {\r\n          support = true;\r\n        }\r\n        doc.body.removeChild(testElement);\r\n      }\r\n    }\r\n\r\n    return support;\r\n  }\r\n\r\n  return {\r\n    rangeBounds: supportRangeBounds(),\r\n    svgRendering: options.svgRendering && supportSVGRendering()\r\n  };\r\n};\r\nwindow.html2canvas = function(elements, opts) {\r\n  elements = (elements.length) ? elements : [elements];\r\n  var queue,\r\n  canvas,\r\n  options = {\r\n    // general\r\n    logging: false,\r\n    elements: elements,\r\n    background: \"#fff\",\r\n\r\n    // preload options\r\n    proxy: null,\r\n    timeout: 0,    // no timeout\r\n    useCORS: false, // try to load images as CORS (where available), before falling back to proxy\r\n    allowTaint: false, // whether to allow images to taint the canvas, won't need proxy if set to true\r\n\r\n    // parse options\r\n    svgRendering: false, // use svg powered rendering where available (FF11+)\r\n    ignoreElements: \"IFRAME|OBJECT|PARAM\",\r\n    useOverflow: true,\r\n    letterRendering: false,\r\n    chinese: false,\r\n\r\n    // render options\r\n\r\n    width: null,\r\n    height: null,\r\n    taintTest: true, // do a taint test with all images before applying to canvas\r\n    renderer: \"Canvas\"\r\n  };\r\n\r\n  options = _html2canvas.Util.Extend(opts, options);\r\n\r\n  _html2canvas.logging = options.logging;\r\n  options.complete = function( images ) {\r\n\r\n    if (typeof options.onpreloaded === \"function\") {\r\n      if ( options.onpreloaded( images ) === false ) {\r\n        return;\r\n      }\r\n    }\r\n    queue = _html2canvas.Parse( images, options );\r\n\r\n    if (typeof options.onparsed === \"function\") {\r\n      if ( options.onparsed( queue ) === false ) {\r\n        return;\r\n      }\r\n    }\r\n\r\n    canvas = _html2canvas.Renderer( queue, options );\r\n\r\n    if (typeof options.onrendered === \"function\") {\r\n      options.onrendered( canvas );\r\n    }\r\n\r\n\r\n  };\r\n\r\n  // for pages without images, we still want this to be async, i.e. return methods before executing\r\n  window.setTimeout( function(){\r\n    _html2canvas.Preload( options );\r\n  }, 0 );\r\n\r\n  return {\r\n    render: function( queue, opts ) {\r\n      return _html2canvas.Renderer( queue, _html2canvas.Util.Extend(opts, options) );\r\n    },\r\n    parse: function( images, opts ) {\r\n      return _html2canvas.Parse( images, _html2canvas.Util.Extend(opts, options) );\r\n    },\r\n    preload: function( opts ) {\r\n      return _html2canvas.Preload( _html2canvas.Util.Extend(opts, options) );\r\n    },\r\n    log: _html2canvas.Util.log\r\n  };\r\n};\r\n\r\nwindow.html2canvas.log = _html2canvas.Util.log; // for renderers\r\nwindow.html2canvas.Renderer = {\r\n  Canvas: undefined // We are assuming this will be used\r\n};\r\n_html2canvas.Renderer.Canvas = function(options) {\r\n  options = options || {};\r\n\r\n  var doc = document,\r\n  safeImages = [],\r\n  testCanvas = document.createElement(\"canvas\"),\r\n  testctx = testCanvas.getContext(\"2d\"),\r\n  Util = _html2canvas.Util,\r\n  canvas = options.canvas || doc.createElement('canvas');\r\n\r\n  function createShape(ctx, args) {\r\n    ctx.beginPath();\r\n    args.forEach(function(arg) {\r\n      ctx[arg.name].apply(ctx, arg['arguments']);\r\n    });\r\n    ctx.closePath();\r\n  }\r\n\r\n  function safeImage(item) {\r\n    if (safeImages.indexOf(item['arguments'][0].src ) === -1) {\r\n      testctx.drawImage(item['arguments'][0], 0, 0);\r\n      try {\r\n        testctx.getImageData(0, 0, 1, 1);\r\n      } catch(e) {\r\n        testCanvas = doc.createElement(\"canvas\");\r\n        testctx = testCanvas.getContext(\"2d\");\r\n        return false;\r\n      }\r\n      safeImages.push(item['arguments'][0].src);\r\n    }\r\n    return true;\r\n  }\r\n\r\n  function renderItem(ctx, item) {\r\n    switch(item.type){\r\n      case \"variable\":\r\n        ctx[item.name] = item['arguments'];\r\n        break;\r\n      case \"function\":\r\n        switch(item.name) {\r\n          case \"createPattern\":\r\n            if (item['arguments'][0].width > 0 && item['arguments'][0].height > 0) {\r\n              try {\r\n                ctx.fillStyle = ctx.createPattern(item['arguments'][0], \"repeat\");\r\n              }\r\n              catch(e) {\r\n                Util.log(\"html2canvas: Renderer: Error creating pattern\", e.message);\r\n              }\r\n            }\r\n            break;\r\n          case \"drawShape\":\r\n            createShape(ctx, item['arguments']);\r\n            break;\r\n          case \"drawImage\":\r\n            if (item['arguments'][8] > 0 && item['arguments'][7] > 0) {\r\n              if (!options.taintTest || (options.taintTest && safeImage(item))) {\r\n                ctx.drawImage.apply( ctx, item['arguments'] );\r\n              }\r\n            }\r\n            break;\r\n          default:\r\n            ctx[item.name].apply(ctx, item['arguments']);\r\n        }\r\n        break;\r\n    }\r\n  }\r\n\r\n  return function(parsedData, options, document, queue, _html2canvas) {\r\n    var ctx = canvas.getContext(\"2d\"),\r\n    newCanvas,\r\n    bounds,\r\n    fstyle,\r\n    zStack = parsedData.stack;\r\n\r\n    canvas.width = canvas.style.width =  options.width || zStack.ctx.width;\r\n    canvas.height = canvas.style.height = options.height || zStack.ctx.height;\r\n\r\n    fstyle = ctx.fillStyle;\r\n    ctx.fillStyle = (Util.isTransparent(zStack.backgroundColor) && options.background !== undefined) ? options.background : parsedData.backgroundColor;\r\n    ctx.fillRect(0, 0, canvas.width, canvas.height);\r\n    ctx.fillStyle = fstyle;\r\n\r\n    queue.forEach(function(storageContext) {\r\n      // set common settings for canvas\r\n      ctx.textBaseline = \"bottom\";\r\n      ctx.save();\r\n\r\n      if (storageContext.transform.matrix) {\r\n        ctx.translate(storageContext.transform.origin[0], storageContext.transform.origin[1]);\r\n        ctx.transform.apply(ctx, storageContext.transform.matrix);\r\n        ctx.translate(-storageContext.transform.origin[0], -storageContext.transform.origin[1]);\r\n      }\r\n\r\n      if (storageContext.clip){\r\n        ctx.beginPath();\r\n        ctx.rect(storageContext.clip.left, storageContext.clip.top, storageContext.clip.width, storageContext.clip.height);\r\n        ctx.clip();\r\n      }\r\n\r\n      if (storageContext.ctx.storage) {\r\n        storageContext.ctx.storage.forEach(function(item) {\r\n          renderItem(ctx, item);\r\n        });\r\n      }\r\n\r\n      ctx.restore();\r\n    });\r\n\r\n    Util.log(\"html2canvas: Renderer: Canvas renderer done - returning canvas obj\");\r\n\r\n    if (options.elements.length === 1) {\r\n      if (typeof options.elements[0] === \"object\" && options.elements[0].nodeName !== \"BODY\") {\r\n        // crop image to the bounds of selected (single) element\r\n        bounds = _html2canvas.Util.Bounds(options.elements[0]);\r\n        newCanvas = document.createElement('canvas');\r\n        newCanvas.width = Math.ceil(bounds.width);\r\n        newCanvas.height = Math.ceil(bounds.height);\r\n        ctx = newCanvas.getContext(\"2d\");\r\n\r\n        ctx.drawImage(canvas, bounds.left, bounds.top, bounds.width, bounds.height, 0, 0, bounds.width, bounds.height);\r\n        canvas = null;\r\n        return newCanvas;\r\n      }\r\n    }\r\n\r\n    return canvas;\r\n  };\r\n};\r\n})(window,document);"
  },
  {
    "path": "lib/idb-keyval-min.js",
    "content": "!function(){\"use strict\";function e(){return t||(t=new Promise(function(e,n){var t=indexedDB.open(\"keyval-store\",1);t.onerror=function(){n(t.error)},t.onupgradeneeded=function(){t.result.createObjectStore(\"keyval\")},t.onsuccess=function(){e(t.result)}})),t}function n(n,t){return e().then(function(e){return new Promise(function(r,o){var u=e.transaction(\"keyval\",n);u.oncomplete=function(){r()},u.onerror=function(){o(u.error)},t(u.objectStore(\"keyval\"))})})}var t,r={get:function(e){var t;return n(\"readonly\",function(n){t=n.get(e)}).then(function(){return t.result})},set:function(e,t){return n(\"readwrite\",function(n){n.put(t,e)})},\"delete\":function(e){return n(\"readwrite\",function(n){n[\"delete\"](e)})},clear:function(){return n(\"readwrite\",function(e){e.clear()})},keys:function(){var e=[];return n(\"readonly\",function(n){(n.openKeyCursor||n.openCursor).call(n).onsuccess=function(){this.result&&(e.push(this.result.key),this.result[\"continue\"]())}}).then(function(){return e})}};\"undefined\"!=typeof module&&module.exports?module.exports=r:\"function\"==typeof define&&define.amd?define(\"idbKeyval\",[],function(){return r}):self.idbKeyval=r}();\n"
  },
  {
    "path": "lib/jquery-ui.custom.js",
    "content": "/*! jQuery UI - v1.12.1 - 2016-09-14\n* http://jqueryui.com\n* Includes: widget.js, position.js, data.js, disable-selection.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js, focusable.js, form-reset-mixin.js, jquery-1-7.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js\n* Copyright jQuery Foundation and other contributors; Licensed MIT */\n\n(function( factory ) {\n\tif ( typeof define === \"function\" && define.amd ) {\n\n\t\t// AMD. Register as an anonymous module.\n\t\tdefine([ \"jquery\" ], factory );\n\t} else {\n\n\t\t// Browser globals\n\t\tfactory( jQuery );\n\t}\n}(function( $ ) {\n\n$.ui = $.ui || {};\n\nvar version = $.ui.version = \"1.12.1\";\n\n\n/*!\n * jQuery UI Widget 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Widget\n//>>group: Core\n//>>description: Provides a factory for creating stateful widgets with a common API.\n//>>docs: http://api.jqueryui.com/jQuery.widget/\n//>>demos: http://jqueryui.com/widget/\n\n\n\nvar widgetUuid = 0;\nvar widgetSlice = Array.prototype.slice;\n\n$.cleanData = ( function( orig ) {\n\treturn function( elems ) {\n\t\tvar events, elem, i;\n\t\tfor ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {\n\t\t\ttry {\n\n\t\t\t\t// Only trigger remove when necessary to save time\n\t\t\t\tevents = $._data( elem, \"events\" );\n\t\t\t\tif ( events && events.remove ) {\n\t\t\t\t\t$( elem ).triggerHandler( \"remove\" );\n\t\t\t\t}\n\n\t\t\t// Http://bugs.jquery.com/ticket/8235\n\t\t\t} catch ( e ) {}\n\t\t}\n\t\torig( elems );\n\t};\n} )( $.cleanData );\n\n$.widget = function( name, base, prototype ) {\n\tvar existingConstructor, constructor, basePrototype;\n\n\t// ProxiedPrototype allows the provided prototype to remain unmodified\n\t// so that it can be used as a mixin for multiple widgets (#8876)\n\tvar proxiedPrototype = {};\n\n\tvar namespace = name.split( \".\" )[ 0 ];\n\tname = name.split( \".\" )[ 1 ];\n\tvar fullName = namespace + \"-\" + name;\n\n\tif ( !prototype ) {\n\t\tprototype = base;\n\t\tbase = $.Widget;\n\t}\n\n\tif ( $.isArray( prototype ) ) {\n\t\tprototype = $.extend.apply( null, [ {} ].concat( prototype ) );\n\t}\n\n\t// Create selector for plugin\n\t$.expr[ \":\" ][ fullName.toLowerCase() ] = function( elem ) {\n\t\treturn !!$.data( elem, fullName );\n\t};\n\n\t$[ namespace ] = $[ namespace ] || {};\n\texistingConstructor = $[ namespace ][ name ];\n\tconstructor = $[ namespace ][ name ] = function( options, element ) {\n\n\t\t// Allow instantiation without \"new\" keyword\n\t\tif ( !this._createWidget ) {\n\t\t\treturn new constructor( options, element );\n\t\t}\n\n\t\t// Allow instantiation without initializing for simple inheritance\n\t\t// must use \"new\" keyword (the code above always passes args)\n\t\tif ( arguments.length ) {\n\t\t\tthis._createWidget( options, element );\n\t\t}\n\t};\n\n\t// Extend with the existing constructor to carry over any static properties\n\t$.extend( constructor, existingConstructor, {\n\t\tversion: prototype.version,\n\n\t\t// Copy the object used to create the prototype in case we need to\n\t\t// redefine the widget later\n\t\t_proto: $.extend( {}, prototype ),\n\n\t\t// Track widgets that inherit from this widget in case this widget is\n\t\t// redefined after a widget inherits from it\n\t\t_childConstructors: []\n\t} );\n\n\tbasePrototype = new base();\n\n\t// We need to make the options hash a property directly on the new instance\n\t// otherwise we'll modify the options hash on the prototype that we're\n\t// inheriting from\n\tbasePrototype.options = $.widget.extend( {}, basePrototype.options );\n\t$.each( prototype, function( prop, value ) {\n\t\tif ( !$.isFunction( value ) ) {\n\t\t\tproxiedPrototype[ prop ] = value;\n\t\t\treturn;\n\t\t}\n\t\tproxiedPrototype[ prop ] = ( function() {\n\t\t\tfunction _super() {\n\t\t\t\treturn base.prototype[ prop ].apply( this, arguments );\n\t\t\t}\n\n\t\t\tfunction _superApply( args ) {\n\t\t\t\treturn base.prototype[ prop ].apply( this, args );\n\t\t\t}\n\n\t\t\treturn function() {\n\t\t\t\tvar __super = this._super;\n\t\t\t\tvar __superApply = this._superApply;\n\t\t\t\tvar returnValue;\n\n\t\t\t\tthis._super = _super;\n\t\t\t\tthis._superApply = _superApply;\n\n\t\t\t\treturnValue = value.apply( this, arguments );\n\n\t\t\t\tthis._super = __super;\n\t\t\t\tthis._superApply = __superApply;\n\n\t\t\t\treturn returnValue;\n\t\t\t};\n\t\t} )();\n\t} );\n\tconstructor.prototype = $.widget.extend( basePrototype, {\n\n\t\t// TODO: remove support for widgetEventPrefix\n\t\t// always use the name + a colon as the prefix, e.g., draggable:start\n\t\t// don't prefix for widgets that aren't DOM-based\n\t\twidgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name\n\t}, proxiedPrototype, {\n\t\tconstructor: constructor,\n\t\tnamespace: namespace,\n\t\twidgetName: name,\n\t\twidgetFullName: fullName\n\t} );\n\n\t// If this widget is being redefined then we need to find all widgets that\n\t// are inheriting from it and redefine all of them so that they inherit from\n\t// the new version of this widget. We're essentially trying to replace one\n\t// level in the prototype chain.\n\tif ( existingConstructor ) {\n\t\t$.each( existingConstructor._childConstructors, function( i, child ) {\n\t\t\tvar childPrototype = child.prototype;\n\n\t\t\t// Redefine the child widget using the same prototype that was\n\t\t\t// originally used, but inherit from the new version of the base\n\t\t\t$.widget( childPrototype.namespace + \".\" + childPrototype.widgetName, constructor,\n\t\t\t\tchild._proto );\n\t\t} );\n\n\t\t// Remove the list of existing child constructors from the old constructor\n\t\t// so the old child constructors can be garbage collected\n\t\tdelete existingConstructor._childConstructors;\n\t} else {\n\t\tbase._childConstructors.push( constructor );\n\t}\n\n\t$.widget.bridge( name, constructor );\n\n\treturn constructor;\n};\n\n$.widget.extend = function( target ) {\n\tvar input = widgetSlice.call( arguments, 1 );\n\tvar inputIndex = 0;\n\tvar inputLength = input.length;\n\tvar key;\n\tvar value;\n\n\tfor ( ; inputIndex < inputLength; inputIndex++ ) {\n\t\tfor ( key in input[ inputIndex ] ) {\n\t\t\tvalue = input[ inputIndex ][ key ];\n\t\t\tif ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {\n\n\t\t\t\t// Clone objects\n\t\t\t\tif ( $.isPlainObject( value ) ) {\n\t\t\t\t\ttarget[ key ] = $.isPlainObject( target[ key ] ) ?\n\t\t\t\t\t\t$.widget.extend( {}, target[ key ], value ) :\n\n\t\t\t\t\t\t// Don't extend strings, arrays, etc. with objects\n\t\t\t\t\t\t$.widget.extend( {}, value );\n\n\t\t\t\t// Copy everything else by reference\n\t\t\t\t} else {\n\t\t\t\t\ttarget[ key ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn target;\n};\n\n$.widget.bridge = function( name, object ) {\n\tvar fullName = object.prototype.widgetFullName || name;\n\t$.fn[ name ] = function( options ) {\n\t\tvar isMethodCall = typeof options === \"string\";\n\t\tvar args = widgetSlice.call( arguments, 1 );\n\t\tvar returnValue = this;\n\n\t\tif ( isMethodCall ) {\n\n\t\t\t// If this is an empty collection, we need to have the instance method\n\t\t\t// return undefined instead of the jQuery instance\n\t\t\tif ( !this.length && options === \"instance\" ) {\n\t\t\t\treturnValue = undefined;\n\t\t\t} else {\n\t\t\t\tthis.each( function() {\n\t\t\t\t\tvar methodValue;\n\t\t\t\t\tvar instance = $.data( this, fullName );\n\n\t\t\t\t\tif ( options === \"instance\" ) {\n\t\t\t\t\t\treturnValue = instance;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !instance ) {\n\t\t\t\t\t\treturn $.error( \"cannot call methods on \" + name +\n\t\t\t\t\t\t\t\" prior to initialization; \" +\n\t\t\t\t\t\t\t\"attempted to call method '\" + options + \"'\" );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === \"_\" ) {\n\t\t\t\t\t\treturn $.error( \"no such method '\" + options + \"' for \" + name +\n\t\t\t\t\t\t\t\" widget instance\" );\n\t\t\t\t\t}\n\n\t\t\t\t\tmethodValue = instance[ options ].apply( instance, args );\n\n\t\t\t\t\tif ( methodValue !== instance && methodValue !== undefined ) {\n\t\t\t\t\t\treturnValue = methodValue && methodValue.jquery ?\n\t\t\t\t\t\t\treturnValue.pushStack( methodValue.get() ) :\n\t\t\t\t\t\t\tmethodValue;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t} else {\n\n\t\t\t// Allow multiple hashes to be passed on init\n\t\t\tif ( args.length ) {\n\t\t\t\toptions = $.widget.extend.apply( null, [ options ].concat( args ) );\n\t\t\t}\n\n\t\t\tthis.each( function() {\n\t\t\t\tvar instance = $.data( this, fullName );\n\t\t\t\tif ( instance ) {\n\t\t\t\t\tinstance.option( options || {} );\n\t\t\t\t\tif ( instance._init ) {\n\t\t\t\t\t\tinstance._init();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t$.data( this, fullName, new object( options, this ) );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\treturn returnValue;\n\t};\n};\n\n$.Widget = function( /* options, element */ ) {};\n$.Widget._childConstructors = [];\n\n$.Widget.prototype = {\n\twidgetName: \"widget\",\n\twidgetEventPrefix: \"\",\n\tdefaultElement: \"<div>\",\n\n\toptions: {\n\t\tclasses: {},\n\t\tdisabled: false,\n\n\t\t// Callbacks\n\t\tcreate: null\n\t},\n\n\t_createWidget: function( options, element ) {\n\t\telement = $( element || this.defaultElement || this )[ 0 ];\n\t\tthis.element = $( element );\n\t\tthis.uuid = widgetUuid++;\n\t\tthis.eventNamespace = \".\" + this.widgetName + this.uuid;\n\n\t\tthis.bindings = $();\n\t\tthis.hoverable = $();\n\t\tthis.focusable = $();\n\t\tthis.classesElementLookup = {};\n\n\t\tif ( element !== this ) {\n\t\t\t$.data( element, this.widgetFullName, this );\n\t\t\tthis._on( true, this.element, {\n\t\t\t\tremove: function( event ) {\n\t\t\t\t\tif ( event.target === element ) {\n\t\t\t\t\t\tthis.destroy();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t\tthis.document = $( element.style ?\n\n\t\t\t\t// Element within the document\n\t\t\t\telement.ownerDocument :\n\n\t\t\t\t// Element is window or document\n\t\t\t\telement.document || element );\n\t\t\tthis.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );\n\t\t}\n\n\t\tthis.options = $.widget.extend( {},\n\t\t\tthis.options,\n\t\t\tthis._getCreateOptions(),\n\t\t\toptions );\n\n\t\tthis._create();\n\n\t\tif ( this.options.disabled ) {\n\t\t\tthis._setOptionDisabled( this.options.disabled );\n\t\t}\n\n\t\tthis._trigger( \"create\", null, this._getCreateEventData() );\n\t\tthis._init();\n\t},\n\n\t_getCreateOptions: function() {\n\t\treturn {};\n\t},\n\n\t_getCreateEventData: $.noop,\n\n\t_create: $.noop,\n\n\t_init: $.noop,\n\n\tdestroy: function() {\n\t\tvar that = this;\n\n\t\tthis._destroy();\n\t\t$.each( this.classesElementLookup, function( key, value ) {\n\t\t\tthat._removeClass( value, key );\n\t\t} );\n\n\t\t// We can probably remove the unbind calls in 2.0\n\t\t// all event bindings should go through this._on()\n\t\tthis.element\n\t\t\t.off( this.eventNamespace )\n\t\t\t.removeData( this.widgetFullName );\n\t\tthis.widget()\n\t\t\t.off( this.eventNamespace )\n\t\t\t.removeAttr( \"aria-disabled\" );\n\n\t\t// Clean up events and states\n\t\tthis.bindings.off( this.eventNamespace );\n\t},\n\n\t_destroy: $.noop,\n\n\twidget: function() {\n\t\treturn this.element;\n\t},\n\n\toption: function( key, value ) {\n\t\tvar options = key;\n\t\tvar parts;\n\t\tvar curOption;\n\t\tvar i;\n\n\t\tif ( arguments.length === 0 ) {\n\n\t\t\t// Don't return a reference to the internal hash\n\t\t\treturn $.widget.extend( {}, this.options );\n\t\t}\n\n\t\tif ( typeof key === \"string\" ) {\n\n\t\t\t// Handle nested keys, e.g., \"foo.bar\" => { foo: { bar: ___ } }\n\t\t\toptions = {};\n\t\t\tparts = key.split( \".\" );\n\t\t\tkey = parts.shift();\n\t\t\tif ( parts.length ) {\n\t\t\t\tcurOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );\n\t\t\t\tfor ( i = 0; i < parts.length - 1; i++ ) {\n\t\t\t\t\tcurOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};\n\t\t\t\t\tcurOption = curOption[ parts[ i ] ];\n\t\t\t\t}\n\t\t\t\tkey = parts.pop();\n\t\t\t\tif ( arguments.length === 1 ) {\n\t\t\t\t\treturn curOption[ key ] === undefined ? null : curOption[ key ];\n\t\t\t\t}\n\t\t\t\tcurOption[ key ] = value;\n\t\t\t} else {\n\t\t\t\tif ( arguments.length === 1 ) {\n\t\t\t\t\treturn this.options[ key ] === undefined ? null : this.options[ key ];\n\t\t\t\t}\n\t\t\t\toptions[ key ] = value;\n\t\t\t}\n\t\t}\n\n\t\tthis._setOptions( options );\n\n\t\treturn this;\n\t},\n\n\t_setOptions: function( options ) {\n\t\tvar key;\n\n\t\tfor ( key in options ) {\n\t\t\tthis._setOption( key, options[ key ] );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"classes\" ) {\n\t\t\tthis._setOptionClasses( value );\n\t\t}\n\n\t\tthis.options[ key ] = value;\n\n\t\tif ( key === \"disabled\" ) {\n\t\t\tthis._setOptionDisabled( value );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_setOptionClasses: function( value ) {\n\t\tvar classKey, elements, currentElements;\n\n\t\tfor ( classKey in value ) {\n\t\t\tcurrentElements = this.classesElementLookup[ classKey ];\n\t\t\tif ( value[ classKey ] === this.options.classes[ classKey ] ||\n\t\t\t\t\t!currentElements ||\n\t\t\t\t\t!currentElements.length ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// We are doing this to create a new jQuery object because the _removeClass() call\n\t\t\t// on the next line is going to destroy the reference to the current elements being\n\t\t\t// tracked. We need to save a copy of this collection so that we can add the new classes\n\t\t\t// below.\n\t\t\telements = $( currentElements.get() );\n\t\t\tthis._removeClass( currentElements, classKey );\n\n\t\t\t// We don't use _addClass() here, because that uses this.options.classes\n\t\t\t// for generating the string of classes. We want to use the value passed in from\n\t\t\t// _setOption(), this is the new value of the classes option which was passed to\n\t\t\t// _setOption(). We pass this value directly to _classes().\n\t\t\telements.addClass( this._classes( {\n\t\t\t\telement: elements,\n\t\t\t\tkeys: classKey,\n\t\t\t\tclasses: value,\n\t\t\t\tadd: true\n\t\t\t} ) );\n\t\t}\n\t},\n\n\t_setOptionDisabled: function( value ) {\n\t\tthis._toggleClass( this.widget(), this.widgetFullName + \"-disabled\", null, !!value );\n\n\t\t// If the widget is becoming disabled, then nothing is interactive\n\t\tif ( value ) {\n\t\t\tthis._removeClass( this.hoverable, null, \"ui-state-hover\" );\n\t\t\tthis._removeClass( this.focusable, null, \"ui-state-focus\" );\n\t\t}\n\t},\n\n\tenable: function() {\n\t\treturn this._setOptions( { disabled: false } );\n\t},\n\n\tdisable: function() {\n\t\treturn this._setOptions( { disabled: true } );\n\t},\n\n\t_classes: function( options ) {\n\t\tvar full = [];\n\t\tvar that = this;\n\n\t\toptions = $.extend( {\n\t\t\telement: this.element,\n\t\t\tclasses: this.options.classes || {}\n\t\t}, options );\n\n\t\tfunction processClassString( classes, checkOption ) {\n\t\t\tvar current, i;\n\t\t\tfor ( i = 0; i < classes.length; i++ ) {\n\t\t\t\tcurrent = that.classesElementLookup[ classes[ i ] ] || $();\n\t\t\t\tif ( options.add ) {\n\t\t\t\t\tcurrent = $( $.unique( current.get().concat( options.element.get() ) ) );\n\t\t\t\t} else {\n\t\t\t\t\tcurrent = $( current.not( options.element ).get() );\n\t\t\t\t}\n\t\t\t\tthat.classesElementLookup[ classes[ i ] ] = current;\n\t\t\t\tfull.push( classes[ i ] );\n\t\t\t\tif ( checkOption && options.classes[ classes[ i ] ] ) {\n\t\t\t\t\tfull.push( options.classes[ classes[ i ] ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis._on( options.element, {\n\t\t\t\"remove\": \"_untrackClassesElement\"\n\t\t} );\n\n\t\tif ( options.keys ) {\n\t\t\tprocessClassString( options.keys.match( /\\S+/g ) || [], true );\n\t\t}\n\t\tif ( options.extra ) {\n\t\t\tprocessClassString( options.extra.match( /\\S+/g ) || [] );\n\t\t}\n\n\t\treturn full.join( \" \" );\n\t},\n\n\t_untrackClassesElement: function( event ) {\n\t\tvar that = this;\n\t\t$.each( that.classesElementLookup, function( key, value ) {\n\t\t\tif ( $.inArray( event.target, value ) !== -1 ) {\n\t\t\t\tthat.classesElementLookup[ key ] = $( value.not( event.target ).get() );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_removeClass: function( element, keys, extra ) {\n\t\treturn this._toggleClass( element, keys, extra, false );\n\t},\n\n\t_addClass: function( element, keys, extra ) {\n\t\treturn this._toggleClass( element, keys, extra, true );\n\t},\n\n\t_toggleClass: function( element, keys, extra, add ) {\n\t\tadd = ( typeof add === \"boolean\" ) ? add : extra;\n\t\tvar shift = ( typeof element === \"string\" || element === null ),\n\t\t\toptions = {\n\t\t\t\textra: shift ? keys : extra,\n\t\t\t\tkeys: shift ? element : keys,\n\t\t\t\telement: shift ? this.element : element,\n\t\t\t\tadd: add\n\t\t\t};\n\t\toptions.element.toggleClass( this._classes( options ), add );\n\t\treturn this;\n\t},\n\n\t_on: function( suppressDisabledCheck, element, handlers ) {\n\t\tvar delegateElement;\n\t\tvar instance = this;\n\n\t\t// No suppressDisabledCheck flag, shuffle arguments\n\t\tif ( typeof suppressDisabledCheck !== \"boolean\" ) {\n\t\t\thandlers = element;\n\t\t\telement = suppressDisabledCheck;\n\t\t\tsuppressDisabledCheck = false;\n\t\t}\n\n\t\t// No element argument, shuffle and use this.element\n\t\tif ( !handlers ) {\n\t\t\thandlers = element;\n\t\t\telement = this.element;\n\t\t\tdelegateElement = this.widget();\n\t\t} else {\n\t\t\telement = delegateElement = $( element );\n\t\t\tthis.bindings = this.bindings.add( element );\n\t\t}\n\n\t\t$.each( handlers, function( event, handler ) {\n\t\t\tfunction handlerProxy() {\n\n\t\t\t\t// Allow widgets to customize the disabled handling\n\t\t\t\t// - disabled as an array instead of boolean\n\t\t\t\t// - disabled class as method for disabling individual parts\n\t\t\t\tif ( !suppressDisabledCheck &&\n\t\t\t\t\t\t( instance.options.disabled === true ||\n\t\t\t\t\t\t$( this ).hasClass( \"ui-state-disabled\" ) ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\treturn ( typeof handler === \"string\" ? instance[ handler ] : handler )\n\t\t\t\t\t.apply( instance, arguments );\n\t\t\t}\n\n\t\t\t// Copy the guid so direct unbinding works\n\t\t\tif ( typeof handler !== \"string\" ) {\n\t\t\t\thandlerProxy.guid = handler.guid =\n\t\t\t\t\thandler.guid || handlerProxy.guid || $.guid++;\n\t\t\t}\n\n\t\t\tvar match = event.match( /^([\\w:-]*)\\s*(.*)$/ );\n\t\t\tvar eventName = match[ 1 ] + instance.eventNamespace;\n\t\t\tvar selector = match[ 2 ];\n\n\t\t\tif ( selector ) {\n\t\t\t\tdelegateElement.on( eventName, selector, handlerProxy );\n\t\t\t} else {\n\t\t\t\telement.on( eventName, handlerProxy );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_off: function( element, eventName ) {\n\t\teventName = ( eventName || \"\" ).split( \" \" ).join( this.eventNamespace + \" \" ) +\n\t\t\tthis.eventNamespace;\n\t\telement.off( eventName ).off( eventName );\n\n\t\t// Clear the stack to avoid memory leaks (#10056)\n\t\tthis.bindings = $( this.bindings.not( element ).get() );\n\t\tthis.focusable = $( this.focusable.not( element ).get() );\n\t\tthis.hoverable = $( this.hoverable.not( element ).get() );\n\t},\n\n\t_delay: function( handler, delay ) {\n\t\tfunction handlerProxy() {\n\t\t\treturn ( typeof handler === \"string\" ? instance[ handler ] : handler )\n\t\t\t\t.apply( instance, arguments );\n\t\t}\n\t\tvar instance = this;\n\t\treturn setTimeout( handlerProxy, delay || 0 );\n\t},\n\n\t_hoverable: function( element ) {\n\t\tthis.hoverable = this.hoverable.add( element );\n\t\tthis._on( element, {\n\t\t\tmouseenter: function( event ) {\n\t\t\t\tthis._addClass( $( event.currentTarget ), null, \"ui-state-hover\" );\n\t\t\t},\n\t\t\tmouseleave: function( event ) {\n\t\t\t\tthis._removeClass( $( event.currentTarget ), null, \"ui-state-hover\" );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_focusable: function( element ) {\n\t\tthis.focusable = this.focusable.add( element );\n\t\tthis._on( element, {\n\t\t\tfocusin: function( event ) {\n\t\t\t\tthis._addClass( $( event.currentTarget ), null, \"ui-state-focus\" );\n\t\t\t},\n\t\t\tfocusout: function( event ) {\n\t\t\t\tthis._removeClass( $( event.currentTarget ), null, \"ui-state-focus\" );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_trigger: function( type, event, data ) {\n\t\tvar prop, orig;\n\t\tvar callback = this.options[ type ];\n\n\t\tdata = data || {};\n\t\tevent = $.Event( event );\n\t\tevent.type = ( type === this.widgetEventPrefix ?\n\t\t\ttype :\n\t\t\tthis.widgetEventPrefix + type ).toLowerCase();\n\n\t\t// The original event may come from any element\n\t\t// so we need to reset the target on the new event\n\t\tevent.target = this.element[ 0 ];\n\n\t\t// Copy original event properties over to the new event\n\t\torig = event.originalEvent;\n\t\tif ( orig ) {\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tif ( !( prop in event ) ) {\n\t\t\t\t\tevent[ prop ] = orig[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.element.trigger( event, data );\n\t\treturn !( $.isFunction( callback ) &&\n\t\t\tcallback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||\n\t\t\tevent.isDefaultPrevented() );\n\t}\n};\n\n$.each( { show: \"fadeIn\", hide: \"fadeOut\" }, function( method, defaultEffect ) {\n\t$.Widget.prototype[ \"_\" + method ] = function( element, options, callback ) {\n\t\tif ( typeof options === \"string\" ) {\n\t\t\toptions = { effect: options };\n\t\t}\n\n\t\tvar hasOptions;\n\t\tvar effectName = !options ?\n\t\t\tmethod :\n\t\t\toptions === true || typeof options === \"number\" ?\n\t\t\t\tdefaultEffect :\n\t\t\t\toptions.effect || defaultEffect;\n\n\t\toptions = options || {};\n\t\tif ( typeof options === \"number\" ) {\n\t\t\toptions = { duration: options };\n\t\t}\n\n\t\thasOptions = !$.isEmptyObject( options );\n\t\toptions.complete = callback;\n\n\t\tif ( options.delay ) {\n\t\t\telement.delay( options.delay );\n\t\t}\n\n\t\tif ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {\n\t\t\telement[ method ]( options );\n\t\t} else if ( effectName !== method && element[ effectName ] ) {\n\t\t\telement[ effectName ]( options.duration, options.easing, callback );\n\t\t} else {\n\t\t\telement.queue( function( next ) {\n\t\t\t\t$( this )[ method ]();\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback.call( element[ 0 ] );\n\t\t\t\t}\n\t\t\t\tnext();\n\t\t\t} );\n\t\t}\n\t};\n} );\n\nvar widget = $.widget;\n\n\n/*!\n * jQuery UI Position 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n *\n * http://api.jqueryui.com/position/\n */\n\n//>>label: Position\n//>>group: Core\n//>>description: Positions elements relative to other elements.\n//>>docs: http://api.jqueryui.com/position/\n//>>demos: http://jqueryui.com/position/\n\n\n( function() {\nvar cachedScrollbarWidth,\n\tmax = Math.max,\n\tabs = Math.abs,\n\trhorizontal = /left|center|right/,\n\trvertical = /top|center|bottom/,\n\troffset = /[\\+\\-]\\d+(\\.[\\d]+)?%?/,\n\trposition = /^\\w+/,\n\trpercent = /%$/,\n\t_position = $.fn.position;\n\nfunction getOffsets( offsets, width, height ) {\n\treturn [\n\t\tparseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),\n\t\tparseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )\n\t];\n}\n\nfunction parseCss( element, property ) {\n\treturn parseInt( $.css( element, property ), 10 ) || 0;\n}\n\nfunction getDimensions( elem ) {\n\tvar raw = elem[ 0 ];\n\tif ( raw.nodeType === 9 ) {\n\t\treturn {\n\t\t\twidth: elem.width(),\n\t\t\theight: elem.height(),\n\t\t\toffset: { top: 0, left: 0 }\n\t\t};\n\t}\n\tif ( $.isWindow( raw ) ) {\n\t\treturn {\n\t\t\twidth: elem.width(),\n\t\t\theight: elem.height(),\n\t\t\toffset: { top: elem.scrollTop(), left: elem.scrollLeft() }\n\t\t};\n\t}\n\tif ( raw.preventDefault ) {\n\t\treturn {\n\t\t\twidth: 0,\n\t\t\theight: 0,\n\t\t\toffset: { top: raw.pageY, left: raw.pageX }\n\t\t};\n\t}\n\treturn {\n\t\twidth: elem.outerWidth(),\n\t\theight: elem.outerHeight(),\n\t\toffset: elem.offset()\n\t};\n}\n\n$.position = {\n\tscrollbarWidth: function() {\n\t\tif ( cachedScrollbarWidth !== undefined ) {\n\t\t\treturn cachedScrollbarWidth;\n\t\t}\n\t\tvar w1, w2,\n\t\t\tdiv = $( \"<div \" +\n\t\t\t\t\"style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'>\" +\n\t\t\t\t\"<div style='height:100px;width:auto;'></div></div>\" ),\n\t\t\tinnerDiv = div.children()[ 0 ];\n\n\t\t$( \"body\" ).append( div );\n\t\tw1 = innerDiv.offsetWidth;\n\t\tdiv.css( \"overflow\", \"scroll\" );\n\n\t\tw2 = innerDiv.offsetWidth;\n\n\t\tif ( w1 === w2 ) {\n\t\t\tw2 = div[ 0 ].clientWidth;\n\t\t}\n\n\t\tdiv.remove();\n\n\t\treturn ( cachedScrollbarWidth = w1 - w2 );\n\t},\n\tgetScrollInfo: function( within ) {\n\t\tvar overflowX = within.isWindow || within.isDocument ? \"\" :\n\t\t\t\twithin.element.css( \"overflow-x\" ),\n\t\t\toverflowY = within.isWindow || within.isDocument ? \"\" :\n\t\t\t\twithin.element.css( \"overflow-y\" ),\n\t\t\thasOverflowX = overflowX === \"scroll\" ||\n\t\t\t\t( overflowX === \"auto\" && within.width < within.element[ 0 ].scrollWidth ),\n\t\t\thasOverflowY = overflowY === \"scroll\" ||\n\t\t\t\t( overflowY === \"auto\" && within.height < within.element[ 0 ].scrollHeight );\n\t\treturn {\n\t\t\twidth: hasOverflowY ? $.position.scrollbarWidth() : 0,\n\t\t\theight: hasOverflowX ? $.position.scrollbarWidth() : 0\n\t\t};\n\t},\n\tgetWithinInfo: function( element ) {\n\t\tvar withinElement = $( element || window ),\n\t\t\tisWindow = $.isWindow( withinElement[ 0 ] ),\n\t\t\tisDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,\n\t\t\thasOffset = !isWindow && !isDocument;\n\t\treturn {\n\t\t\telement: withinElement,\n\t\t\tisWindow: isWindow,\n\t\t\tisDocument: isDocument,\n\t\t\toffset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },\n\t\t\tscrollLeft: withinElement.scrollLeft(),\n\t\t\tscrollTop: withinElement.scrollTop(),\n\t\t\twidth: withinElement.outerWidth(),\n\t\t\theight: withinElement.outerHeight()\n\t\t};\n\t}\n};\n\n$.fn.position = function( options ) {\n\tif ( !options || !options.of ) {\n\t\treturn _position.apply( this, arguments );\n\t}\n\n\t// Make a copy, we don't want to modify arguments\n\toptions = $.extend( {}, options );\n\n\tvar atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,\n\t\ttarget = $( options.of ),\n\t\twithin = $.position.getWithinInfo( options.within ),\n\t\tscrollInfo = $.position.getScrollInfo( within ),\n\t\tcollision = ( options.collision || \"flip\" ).split( \" \" ),\n\t\toffsets = {};\n\n\tdimensions = getDimensions( target );\n\tif ( target[ 0 ].preventDefault ) {\n\n\t\t// Force left top to allow flipping\n\t\toptions.at = \"left top\";\n\t}\n\ttargetWidth = dimensions.width;\n\ttargetHeight = dimensions.height;\n\ttargetOffset = dimensions.offset;\n\n\t// Clone to reuse original targetOffset later\n\tbasePosition = $.extend( {}, targetOffset );\n\n\t// Force my and at to have valid horizontal and vertical positions\n\t// if a value is missing or invalid, it will be converted to center\n\t$.each( [ \"my\", \"at\" ], function() {\n\t\tvar pos = ( options[ this ] || \"\" ).split( \" \" ),\n\t\t\thorizontalOffset,\n\t\t\tverticalOffset;\n\n\t\tif ( pos.length === 1 ) {\n\t\t\tpos = rhorizontal.test( pos[ 0 ] ) ?\n\t\t\t\tpos.concat( [ \"center\" ] ) :\n\t\t\t\trvertical.test( pos[ 0 ] ) ?\n\t\t\t\t\t[ \"center\" ].concat( pos ) :\n\t\t\t\t\t[ \"center\", \"center\" ];\n\t\t}\n\t\tpos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : \"center\";\n\t\tpos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : \"center\";\n\n\t\t// Calculate offsets\n\t\thorizontalOffset = roffset.exec( pos[ 0 ] );\n\t\tverticalOffset = roffset.exec( pos[ 1 ] );\n\t\toffsets[ this ] = [\n\t\t\thorizontalOffset ? horizontalOffset[ 0 ] : 0,\n\t\t\tverticalOffset ? verticalOffset[ 0 ] : 0\n\t\t];\n\n\t\t// Reduce to just the positions without the offsets\n\t\toptions[ this ] = [\n\t\t\trposition.exec( pos[ 0 ] )[ 0 ],\n\t\t\trposition.exec( pos[ 1 ] )[ 0 ]\n\t\t];\n\t} );\n\n\t// Normalize collision option\n\tif ( collision.length === 1 ) {\n\t\tcollision[ 1 ] = collision[ 0 ];\n\t}\n\n\tif ( options.at[ 0 ] === \"right\" ) {\n\t\tbasePosition.left += targetWidth;\n\t} else if ( options.at[ 0 ] === \"center\" ) {\n\t\tbasePosition.left += targetWidth / 2;\n\t}\n\n\tif ( options.at[ 1 ] === \"bottom\" ) {\n\t\tbasePosition.top += targetHeight;\n\t} else if ( options.at[ 1 ] === \"center\" ) {\n\t\tbasePosition.top += targetHeight / 2;\n\t}\n\n\tatOffset = getOffsets( offsets.at, targetWidth, targetHeight );\n\tbasePosition.left += atOffset[ 0 ];\n\tbasePosition.top += atOffset[ 1 ];\n\n\treturn this.each( function() {\n\t\tvar collisionPosition, using,\n\t\t\telem = $( this ),\n\t\t\telemWidth = elem.outerWidth(),\n\t\t\telemHeight = elem.outerHeight(),\n\t\t\tmarginLeft = parseCss( this, \"marginLeft\" ),\n\t\t\tmarginTop = parseCss( this, \"marginTop\" ),\n\t\t\tcollisionWidth = elemWidth + marginLeft + parseCss( this, \"marginRight\" ) +\n\t\t\t\tscrollInfo.width,\n\t\t\tcollisionHeight = elemHeight + marginTop + parseCss( this, \"marginBottom\" ) +\n\t\t\t\tscrollInfo.height,\n\t\t\tposition = $.extend( {}, basePosition ),\n\t\t\tmyOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );\n\n\t\tif ( options.my[ 0 ] === \"right\" ) {\n\t\t\tposition.left -= elemWidth;\n\t\t} else if ( options.my[ 0 ] === \"center\" ) {\n\t\t\tposition.left -= elemWidth / 2;\n\t\t}\n\n\t\tif ( options.my[ 1 ] === \"bottom\" ) {\n\t\t\tposition.top -= elemHeight;\n\t\t} else if ( options.my[ 1 ] === \"center\" ) {\n\t\t\tposition.top -= elemHeight / 2;\n\t\t}\n\n\t\tposition.left += myOffset[ 0 ];\n\t\tposition.top += myOffset[ 1 ];\n\n\t\tcollisionPosition = {\n\t\t\tmarginLeft: marginLeft,\n\t\t\tmarginTop: marginTop\n\t\t};\n\n\t\t$.each( [ \"left\", \"top\" ], function( i, dir ) {\n\t\t\tif ( $.ui.position[ collision[ i ] ] ) {\n\t\t\t\t$.ui.position[ collision[ i ] ][ dir ]( position, {\n\t\t\t\t\ttargetWidth: targetWidth,\n\t\t\t\t\ttargetHeight: targetHeight,\n\t\t\t\t\telemWidth: elemWidth,\n\t\t\t\t\telemHeight: elemHeight,\n\t\t\t\t\tcollisionPosition: collisionPosition,\n\t\t\t\t\tcollisionWidth: collisionWidth,\n\t\t\t\t\tcollisionHeight: collisionHeight,\n\t\t\t\t\toffset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],\n\t\t\t\t\tmy: options.my,\n\t\t\t\t\tat: options.at,\n\t\t\t\t\twithin: within,\n\t\t\t\t\telem: elem\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\n\t\tif ( options.using ) {\n\n\t\t\t// Adds feedback as second argument to using callback, if present\n\t\t\tusing = function( props ) {\n\t\t\t\tvar left = targetOffset.left - position.left,\n\t\t\t\t\tright = left + targetWidth - elemWidth,\n\t\t\t\t\ttop = targetOffset.top - position.top,\n\t\t\t\t\tbottom = top + targetHeight - elemHeight,\n\t\t\t\t\tfeedback = {\n\t\t\t\t\t\ttarget: {\n\t\t\t\t\t\t\telement: target,\n\t\t\t\t\t\t\tleft: targetOffset.left,\n\t\t\t\t\t\t\ttop: targetOffset.top,\n\t\t\t\t\t\t\twidth: targetWidth,\n\t\t\t\t\t\t\theight: targetHeight\n\t\t\t\t\t\t},\n\t\t\t\t\t\telement: {\n\t\t\t\t\t\t\telement: elem,\n\t\t\t\t\t\t\tleft: position.left,\n\t\t\t\t\t\t\ttop: position.top,\n\t\t\t\t\t\t\twidth: elemWidth,\n\t\t\t\t\t\t\theight: elemHeight\n\t\t\t\t\t\t},\n\t\t\t\t\t\thorizontal: right < 0 ? \"left\" : left > 0 ? \"right\" : \"center\",\n\t\t\t\t\t\tvertical: bottom < 0 ? \"top\" : top > 0 ? \"bottom\" : \"middle\"\n\t\t\t\t\t};\n\t\t\t\tif ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {\n\t\t\t\t\tfeedback.horizontal = \"center\";\n\t\t\t\t}\n\t\t\t\tif ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {\n\t\t\t\t\tfeedback.vertical = \"middle\";\n\t\t\t\t}\n\t\t\t\tif ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {\n\t\t\t\t\tfeedback.important = \"horizontal\";\n\t\t\t\t} else {\n\t\t\t\t\tfeedback.important = \"vertical\";\n\t\t\t\t}\n\t\t\t\toptions.using.call( this, props, feedback );\n\t\t\t};\n\t\t}\n\n\t\telem.offset( $.extend( position, { using: using } ) );\n\t} );\n};\n\n$.ui.position = {\n\tfit: {\n\t\tleft: function( position, data ) {\n\t\t\tvar within = data.within,\n\t\t\t\twithinOffset = within.isWindow ? within.scrollLeft : within.offset.left,\n\t\t\t\touterWidth = within.width,\n\t\t\t\tcollisionPosLeft = position.left - data.collisionPosition.marginLeft,\n\t\t\t\toverLeft = withinOffset - collisionPosLeft,\n\t\t\t\toverRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,\n\t\t\t\tnewOverRight;\n\n\t\t\t// Element is wider than within\n\t\t\tif ( data.collisionWidth > outerWidth ) {\n\n\t\t\t\t// Element is initially over the left side of within\n\t\t\t\tif ( overLeft > 0 && overRight <= 0 ) {\n\t\t\t\t\tnewOverRight = position.left + overLeft + data.collisionWidth - outerWidth -\n\t\t\t\t\t\twithinOffset;\n\t\t\t\t\tposition.left += overLeft - newOverRight;\n\n\t\t\t\t// Element is initially over right side of within\n\t\t\t\t} else if ( overRight > 0 && overLeft <= 0 ) {\n\t\t\t\t\tposition.left = withinOffset;\n\n\t\t\t\t// Element is initially over both left and right sides of within\n\t\t\t\t} else {\n\t\t\t\t\tif ( overLeft > overRight ) {\n\t\t\t\t\t\tposition.left = withinOffset + outerWidth - data.collisionWidth;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tposition.left = withinOffset;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Too far left -> align with left edge\n\t\t\t} else if ( overLeft > 0 ) {\n\t\t\t\tposition.left += overLeft;\n\n\t\t\t// Too far right -> align with right edge\n\t\t\t} else if ( overRight > 0 ) {\n\t\t\t\tposition.left -= overRight;\n\n\t\t\t// Adjust based on position and margin\n\t\t\t} else {\n\t\t\t\tposition.left = max( position.left - collisionPosLeft, position.left );\n\t\t\t}\n\t\t},\n\t\ttop: function( position, data ) {\n\t\t\tvar within = data.within,\n\t\t\t\twithinOffset = within.isWindow ? within.scrollTop : within.offset.top,\n\t\t\t\touterHeight = data.within.height,\n\t\t\t\tcollisionPosTop = position.top - data.collisionPosition.marginTop,\n\t\t\t\toverTop = withinOffset - collisionPosTop,\n\t\t\t\toverBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,\n\t\t\t\tnewOverBottom;\n\n\t\t\t// Element is taller than within\n\t\t\tif ( data.collisionHeight > outerHeight ) {\n\n\t\t\t\t// Element is initially over the top of within\n\t\t\t\tif ( overTop > 0 && overBottom <= 0 ) {\n\t\t\t\t\tnewOverBottom = position.top + overTop + data.collisionHeight - outerHeight -\n\t\t\t\t\t\twithinOffset;\n\t\t\t\t\tposition.top += overTop - newOverBottom;\n\n\t\t\t\t// Element is initially over bottom of within\n\t\t\t\t} else if ( overBottom > 0 && overTop <= 0 ) {\n\t\t\t\t\tposition.top = withinOffset;\n\n\t\t\t\t// Element is initially over both top and bottom of within\n\t\t\t\t} else {\n\t\t\t\t\tif ( overTop > overBottom ) {\n\t\t\t\t\t\tposition.top = withinOffset + outerHeight - data.collisionHeight;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tposition.top = withinOffset;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Too far up -> align with top\n\t\t\t} else if ( overTop > 0 ) {\n\t\t\t\tposition.top += overTop;\n\n\t\t\t// Too far down -> align with bottom edge\n\t\t\t} else if ( overBottom > 0 ) {\n\t\t\t\tposition.top -= overBottom;\n\n\t\t\t// Adjust based on position and margin\n\t\t\t} else {\n\t\t\t\tposition.top = max( position.top - collisionPosTop, position.top );\n\t\t\t}\n\t\t}\n\t},\n\tflip: {\n\t\tleft: function( position, data ) {\n\t\t\tvar within = data.within,\n\t\t\t\twithinOffset = within.offset.left + within.scrollLeft,\n\t\t\t\touterWidth = within.width,\n\t\t\t\toffsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,\n\t\t\t\tcollisionPosLeft = position.left - data.collisionPosition.marginLeft,\n\t\t\t\toverLeft = collisionPosLeft - offsetLeft,\n\t\t\t\toverRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,\n\t\t\t\tmyOffset = data.my[ 0 ] === \"left\" ?\n\t\t\t\t\t-data.elemWidth :\n\t\t\t\t\tdata.my[ 0 ] === \"right\" ?\n\t\t\t\t\t\tdata.elemWidth :\n\t\t\t\t\t\t0,\n\t\t\t\tatOffset = data.at[ 0 ] === \"left\" ?\n\t\t\t\t\tdata.targetWidth :\n\t\t\t\t\tdata.at[ 0 ] === \"right\" ?\n\t\t\t\t\t\t-data.targetWidth :\n\t\t\t\t\t\t0,\n\t\t\t\toffset = -2 * data.offset[ 0 ],\n\t\t\t\tnewOverRight,\n\t\t\t\tnewOverLeft;\n\n\t\t\tif ( overLeft < 0 ) {\n\t\t\t\tnewOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -\n\t\t\t\t\touterWidth - withinOffset;\n\t\t\t\tif ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {\n\t\t\t\t\tposition.left += myOffset + atOffset + offset;\n\t\t\t\t}\n\t\t\t} else if ( overRight > 0 ) {\n\t\t\t\tnewOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +\n\t\t\t\t\tatOffset + offset - offsetLeft;\n\t\t\t\tif ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {\n\t\t\t\t\tposition.left += myOffset + atOffset + offset;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\ttop: function( position, data ) {\n\t\t\tvar within = data.within,\n\t\t\t\twithinOffset = within.offset.top + within.scrollTop,\n\t\t\t\touterHeight = within.height,\n\t\t\t\toffsetTop = within.isWindow ? within.scrollTop : within.offset.top,\n\t\t\t\tcollisionPosTop = position.top - data.collisionPosition.marginTop,\n\t\t\t\toverTop = collisionPosTop - offsetTop,\n\t\t\t\toverBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,\n\t\t\t\ttop = data.my[ 1 ] === \"top\",\n\t\t\t\tmyOffset = top ?\n\t\t\t\t\t-data.elemHeight :\n\t\t\t\t\tdata.my[ 1 ] === \"bottom\" ?\n\t\t\t\t\t\tdata.elemHeight :\n\t\t\t\t\t\t0,\n\t\t\t\tatOffset = data.at[ 1 ] === \"top\" ?\n\t\t\t\t\tdata.targetHeight :\n\t\t\t\t\tdata.at[ 1 ] === \"bottom\" ?\n\t\t\t\t\t\t-data.targetHeight :\n\t\t\t\t\t\t0,\n\t\t\t\toffset = -2 * data.offset[ 1 ],\n\t\t\t\tnewOverTop,\n\t\t\t\tnewOverBottom;\n\t\t\tif ( overTop < 0 ) {\n\t\t\t\tnewOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -\n\t\t\t\t\touterHeight - withinOffset;\n\t\t\t\tif ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {\n\t\t\t\t\tposition.top += myOffset + atOffset + offset;\n\t\t\t\t}\n\t\t\t} else if ( overBottom > 0 ) {\n\t\t\t\tnewOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +\n\t\t\t\t\toffset - offsetTop;\n\t\t\t\tif ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {\n\t\t\t\t\tposition.top += myOffset + atOffset + offset;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tflipfit: {\n\t\tleft: function() {\n\t\t\t$.ui.position.flip.left.apply( this, arguments );\n\t\t\t$.ui.position.fit.left.apply( this, arguments );\n\t\t},\n\t\ttop: function() {\n\t\t\t$.ui.position.flip.top.apply( this, arguments );\n\t\t\t$.ui.position.fit.top.apply( this, arguments );\n\t\t}\n\t}\n};\n\n} )();\n\nvar position = $.ui.position;\n\n\n/*!\n * jQuery UI :data 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: :data Selector\n//>>group: Core\n//>>description: Selects elements which have data stored under the specified key.\n//>>docs: http://api.jqueryui.com/data-selector/\n\n\nvar data = $.extend( $.expr[ \":\" ], {\n\tdata: $.expr.createPseudo ?\n\t\t$.expr.createPseudo( function( dataName ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn !!$.data( elem, dataName );\n\t\t\t};\n\t\t} ) :\n\n\t\t// Support: jQuery <1.8\n\t\tfunction( elem, i, match ) {\n\t\t\treturn !!$.data( elem, match[ 3 ] );\n\t\t}\n} );\n\n/*!\n * jQuery UI Disable Selection 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: disableSelection\n//>>group: Core\n//>>description: Disable selection of text content within the set of matched elements.\n//>>docs: http://api.jqueryui.com/disableSelection/\n\n// This file is deprecated\n\n\nvar disableSelection = $.fn.extend( {\n\tdisableSelection: ( function() {\n\t\tvar eventType = \"onselectstart\" in document.createElement( \"div\" ) ?\n\t\t\t\"selectstart\" :\n\t\t\t\"mousedown\";\n\n\t\treturn function() {\n\t\t\treturn this.on( eventType + \".ui-disableSelection\", function( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t} );\n\t\t};\n\t} )(),\n\n\tenableSelection: function() {\n\t\treturn this.off( \".ui-disableSelection\" );\n\t}\n} );\n\n\n/*!\n * jQuery UI Effects 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Effects Core\n//>>group: Effects\n// jscs:disable maximumLineLength\n//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects.\n// jscs:enable maximumLineLength\n//>>docs: http://api.jqueryui.com/category/effects-core/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar dataSpace = \"ui-effects-\",\n\tdataSpaceStyle = \"ui-effects-style\",\n\tdataSpaceAnimated = \"ui-effects-animated\",\n\n\t// Create a local jQuery because jQuery Color relies on it and the\n\t// global may not exist with AMD and a custom build (#10199)\n\tjQuery = $;\n\n$.effects = {\n\teffect: {}\n};\n\n/*!\n * jQuery Color Animations v2.1.2\n * https://github.com/jquery/jquery-color\n *\n * Copyright 2014 jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n *\n * Date: Wed Jan 16 08:47:09 2013 -0600\n */\n( function( jQuery, undefined ) {\n\n\tvar stepHooks = \"backgroundColor borderBottomColor borderLeftColor borderRightColor \" +\n\t\t\"borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor\",\n\n\t// Plusequals test for += 100 -= 100\n\trplusequals = /^([\\-+])=\\s*(\\d+\\.?\\d*)/,\n\n\t// A set of RE's that can match strings and generate color tuples.\n\tstringParsers = [ {\n\t\t\tre: /rgba?\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*(?:,\\s*(\\d?(?:\\.\\d+)?)\\s*)?\\)/,\n\t\t\tparse: function( execResult ) {\n\t\t\t\treturn [\n\t\t\t\t\texecResult[ 1 ],\n\t\t\t\t\texecResult[ 2 ],\n\t\t\t\t\texecResult[ 3 ],\n\t\t\t\t\texecResult[ 4 ]\n\t\t\t\t];\n\t\t\t}\n\t\t}, {\n\t\t\tre: /rgba?\\(\\s*(\\d+(?:\\.\\d+)?)\\%\\s*,\\s*(\\d+(?:\\.\\d+)?)\\%\\s*,\\s*(\\d+(?:\\.\\d+)?)\\%\\s*(?:,\\s*(\\d?(?:\\.\\d+)?)\\s*)?\\)/,\n\t\t\tparse: function( execResult ) {\n\t\t\t\treturn [\n\t\t\t\t\texecResult[ 1 ] * 2.55,\n\t\t\t\t\texecResult[ 2 ] * 2.55,\n\t\t\t\t\texecResult[ 3 ] * 2.55,\n\t\t\t\t\texecResult[ 4 ]\n\t\t\t\t];\n\t\t\t}\n\t\t}, {\n\n\t\t\t// This regex ignores A-F because it's compared against an already lowercased string\n\t\t\tre: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,\n\t\t\tparse: function( execResult ) {\n\t\t\t\treturn [\n\t\t\t\t\tparseInt( execResult[ 1 ], 16 ),\n\t\t\t\t\tparseInt( execResult[ 2 ], 16 ),\n\t\t\t\t\tparseInt( execResult[ 3 ], 16 )\n\t\t\t\t];\n\t\t\t}\n\t\t}, {\n\n\t\t\t// This regex ignores A-F because it's compared against an already lowercased string\n\t\t\tre: /#([a-f0-9])([a-f0-9])([a-f0-9])/,\n\t\t\tparse: function( execResult ) {\n\t\t\t\treturn [\n\t\t\t\t\tparseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),\n\t\t\t\t\tparseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),\n\t\t\t\t\tparseInt( execResult[ 3 ] + execResult[ 3 ], 16 )\n\t\t\t\t];\n\t\t\t}\n\t\t}, {\n\t\t\tre: /hsla?\\(\\s*(\\d+(?:\\.\\d+)?)\\s*,\\s*(\\d+(?:\\.\\d+)?)\\%\\s*,\\s*(\\d+(?:\\.\\d+)?)\\%\\s*(?:,\\s*(\\d?(?:\\.\\d+)?)\\s*)?\\)/,\n\t\t\tspace: \"hsla\",\n\t\t\tparse: function( execResult ) {\n\t\t\t\treturn [\n\t\t\t\t\texecResult[ 1 ],\n\t\t\t\t\texecResult[ 2 ] / 100,\n\t\t\t\t\texecResult[ 3 ] / 100,\n\t\t\t\t\texecResult[ 4 ]\n\t\t\t\t];\n\t\t\t}\n\t\t} ],\n\n\t// JQuery.Color( )\n\tcolor = jQuery.Color = function( color, green, blue, alpha ) {\n\t\treturn new jQuery.Color.fn.parse( color, green, blue, alpha );\n\t},\n\tspaces = {\n\t\trgba: {\n\t\t\tprops: {\n\t\t\t\tred: {\n\t\t\t\t\tidx: 0,\n\t\t\t\t\ttype: \"byte\"\n\t\t\t\t},\n\t\t\t\tgreen: {\n\t\t\t\t\tidx: 1,\n\t\t\t\t\ttype: \"byte\"\n\t\t\t\t},\n\t\t\t\tblue: {\n\t\t\t\t\tidx: 2,\n\t\t\t\t\ttype: \"byte\"\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\thsla: {\n\t\t\tprops: {\n\t\t\t\thue: {\n\t\t\t\t\tidx: 0,\n\t\t\t\t\ttype: \"degrees\"\n\t\t\t\t},\n\t\t\t\tsaturation: {\n\t\t\t\t\tidx: 1,\n\t\t\t\t\ttype: \"percent\"\n\t\t\t\t},\n\t\t\t\tlightness: {\n\t\t\t\t\tidx: 2,\n\t\t\t\t\ttype: \"percent\"\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tpropTypes = {\n\t\t\"byte\": {\n\t\t\tfloor: true,\n\t\t\tmax: 255\n\t\t},\n\t\t\"percent\": {\n\t\t\tmax: 1\n\t\t},\n\t\t\"degrees\": {\n\t\t\tmod: 360,\n\t\t\tfloor: true\n\t\t}\n\t},\n\tsupport = color.support = {},\n\n\t// Element for support tests\n\tsupportElem = jQuery( \"<p>\" )[ 0 ],\n\n\t// Colors = jQuery.Color.names\n\tcolors,\n\n\t// Local aliases of functions called often\n\teach = jQuery.each;\n\n// Determine rgba support immediately\nsupportElem.style.cssText = \"background-color:rgba(1,1,1,.5)\";\nsupport.rgba = supportElem.style.backgroundColor.indexOf( \"rgba\" ) > -1;\n\n// Define cache name and alpha properties\n// for rgba and hsla spaces\neach( spaces, function( spaceName, space ) {\n\tspace.cache = \"_\" + spaceName;\n\tspace.props.alpha = {\n\t\tidx: 3,\n\t\ttype: \"percent\",\n\t\tdef: 1\n\t};\n} );\n\nfunction clamp( value, prop, allowEmpty ) {\n\tvar type = propTypes[ prop.type ] || {};\n\n\tif ( value == null ) {\n\t\treturn ( allowEmpty || !prop.def ) ? null : prop.def;\n\t}\n\n\t// ~~ is an short way of doing floor for positive numbers\n\tvalue = type.floor ? ~~value : parseFloat( value );\n\n\t// IE will pass in empty strings as value for alpha,\n\t// which will hit this case\n\tif ( isNaN( value ) ) {\n\t\treturn prop.def;\n\t}\n\n\tif ( type.mod ) {\n\n\t\t// We add mod before modding to make sure that negatives values\n\t\t// get converted properly: -10 -> 350\n\t\treturn ( value + type.mod ) % type.mod;\n\t}\n\n\t// For now all property types without mod have min and max\n\treturn 0 > value ? 0 : type.max < value ? type.max : value;\n}\n\nfunction stringParse( string ) {\n\tvar inst = color(),\n\t\trgba = inst._rgba = [];\n\n\tstring = string.toLowerCase();\n\n\teach( stringParsers, function( i, parser ) {\n\t\tvar parsed,\n\t\t\tmatch = parser.re.exec( string ),\n\t\t\tvalues = match && parser.parse( match ),\n\t\t\tspaceName = parser.space || \"rgba\";\n\n\t\tif ( values ) {\n\t\t\tparsed = inst[ spaceName ]( values );\n\n\t\t\t// If this was an rgba parse the assignment might happen twice\n\t\t\t// oh well....\n\t\t\tinst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];\n\t\t\trgba = inst._rgba = parsed._rgba;\n\n\t\t\t// Exit each( stringParsers ) here because we matched\n\t\t\treturn false;\n\t\t}\n\t} );\n\n\t// Found a stringParser that handled it\n\tif ( rgba.length ) {\n\n\t\t// If this came from a parsed string, force \"transparent\" when alpha is 0\n\t\t// chrome, (and maybe others) return \"transparent\" as rgba(0,0,0,0)\n\t\tif ( rgba.join() === \"0,0,0,0\" ) {\n\t\t\tjQuery.extend( rgba, colors.transparent );\n\t\t}\n\t\treturn inst;\n\t}\n\n\t// Named colors\n\treturn colors[ string ];\n}\n\ncolor.fn = jQuery.extend( color.prototype, {\n\tparse: function( red, green, blue, alpha ) {\n\t\tif ( red === undefined ) {\n\t\t\tthis._rgba = [ null, null, null, null ];\n\t\t\treturn this;\n\t\t}\n\t\tif ( red.jquery || red.nodeType ) {\n\t\t\tred = jQuery( red ).css( green );\n\t\t\tgreen = undefined;\n\t\t}\n\n\t\tvar inst = this,\n\t\t\ttype = jQuery.type( red ),\n\t\t\trgba = this._rgba = [];\n\n\t\t// More than 1 argument specified - assume ( red, green, blue, alpha )\n\t\tif ( green !== undefined ) {\n\t\t\tred = [ red, green, blue, alpha ];\n\t\t\ttype = \"array\";\n\t\t}\n\n\t\tif ( type === \"string\" ) {\n\t\t\treturn this.parse( stringParse( red ) || colors._default );\n\t\t}\n\n\t\tif ( type === \"array\" ) {\n\t\t\teach( spaces.rgba.props, function( key, prop ) {\n\t\t\t\trgba[ prop.idx ] = clamp( red[ prop.idx ], prop );\n\t\t\t} );\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( type === \"object\" ) {\n\t\t\tif ( red instanceof color ) {\n\t\t\t\teach( spaces, function( spaceName, space ) {\n\t\t\t\t\tif ( red[ space.cache ] ) {\n\t\t\t\t\t\tinst[ space.cache ] = red[ space.cache ].slice();\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\teach( spaces, function( spaceName, space ) {\n\t\t\t\t\tvar cache = space.cache;\n\t\t\t\t\teach( space.props, function( key, prop ) {\n\n\t\t\t\t\t\t// If the cache doesn't exist, and we know how to convert\n\t\t\t\t\t\tif ( !inst[ cache ] && space.to ) {\n\n\t\t\t\t\t\t\t// If the value was null, we don't need to copy it\n\t\t\t\t\t\t\t// if the key was alpha, we don't need to copy it either\n\t\t\t\t\t\t\tif ( key === \"alpha\" || red[ key ] == null ) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tinst[ cache ] = space.to( inst._rgba );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// This is the only case where we allow nulls for ALL properties.\n\t\t\t\t\t\t// call clamp with alwaysAllowEmpty\n\t\t\t\t\t\tinst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );\n\t\t\t\t\t} );\n\n\t\t\t\t\t// Everything defined but alpha?\n\t\t\t\t\tif ( inst[ cache ] &&\n\t\t\t\t\t\t\tjQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {\n\n\t\t\t\t\t\t// Use the default of 1\n\t\t\t\t\t\tinst[ cache ][ 3 ] = 1;\n\t\t\t\t\t\tif ( space.from ) {\n\t\t\t\t\t\t\tinst._rgba = space.from( inst[ cache ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t},\n\tis: function( compare ) {\n\t\tvar is = color( compare ),\n\t\t\tsame = true,\n\t\t\tinst = this;\n\n\t\teach( spaces, function( _, space ) {\n\t\t\tvar localCache,\n\t\t\t\tisCache = is[ space.cache ];\n\t\t\tif ( isCache ) {\n\t\t\t\tlocalCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];\n\t\t\t\teach( space.props, function( _, prop ) {\n\t\t\t\t\tif ( isCache[ prop.idx ] != null ) {\n\t\t\t\t\t\tsame = ( isCache[ prop.idx ] === localCache[ prop.idx ] );\n\t\t\t\t\t\treturn same;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t\treturn same;\n\t\t} );\n\t\treturn same;\n\t},\n\t_space: function() {\n\t\tvar used = [],\n\t\t\tinst = this;\n\t\teach( spaces, function( spaceName, space ) {\n\t\t\tif ( inst[ space.cache ] ) {\n\t\t\t\tused.push( spaceName );\n\t\t\t}\n\t\t} );\n\t\treturn used.pop();\n\t},\n\ttransition: function( other, distance ) {\n\t\tvar end = color( other ),\n\t\t\tspaceName = end._space(),\n\t\t\tspace = spaces[ spaceName ],\n\t\t\tstartColor = this.alpha() === 0 ? color( \"transparent\" ) : this,\n\t\t\tstart = startColor[ space.cache ] || space.to( startColor._rgba ),\n\t\t\tresult = start.slice();\n\n\t\tend = end[ space.cache ];\n\t\teach( space.props, function( key, prop ) {\n\t\t\tvar index = prop.idx,\n\t\t\t\tstartValue = start[ index ],\n\t\t\t\tendValue = end[ index ],\n\t\t\t\ttype = propTypes[ prop.type ] || {};\n\n\t\t\t// If null, don't override start value\n\t\t\tif ( endValue === null ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If null - use end\n\t\t\tif ( startValue === null ) {\n\t\t\t\tresult[ index ] = endValue;\n\t\t\t} else {\n\t\t\t\tif ( type.mod ) {\n\t\t\t\t\tif ( endValue - startValue > type.mod / 2 ) {\n\t\t\t\t\t\tstartValue += type.mod;\n\t\t\t\t\t} else if ( startValue - endValue > type.mod / 2 ) {\n\t\t\t\t\t\tstartValue -= type.mod;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresult[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );\n\t\t\t}\n\t\t} );\n\t\treturn this[ spaceName ]( result );\n\t},\n\tblend: function( opaque ) {\n\n\t\t// If we are already opaque - return ourself\n\t\tif ( this._rgba[ 3 ] === 1 ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar rgb = this._rgba.slice(),\n\t\t\ta = rgb.pop(),\n\t\t\tblend = color( opaque )._rgba;\n\n\t\treturn color( jQuery.map( rgb, function( v, i ) {\n\t\t\treturn ( 1 - a ) * blend[ i ] + a * v;\n\t\t} ) );\n\t},\n\ttoRgbaString: function() {\n\t\tvar prefix = \"rgba(\",\n\t\t\trgba = jQuery.map( this._rgba, function( v, i ) {\n\t\t\t\treturn v == null ? ( i > 2 ? 1 : 0 ) : v;\n\t\t\t} );\n\n\t\tif ( rgba[ 3 ] === 1 ) {\n\t\t\trgba.pop();\n\t\t\tprefix = \"rgb(\";\n\t\t}\n\n\t\treturn prefix + rgba.join() + \")\";\n\t},\n\ttoHslaString: function() {\n\t\tvar prefix = \"hsla(\",\n\t\t\thsla = jQuery.map( this.hsla(), function( v, i ) {\n\t\t\t\tif ( v == null ) {\n\t\t\t\t\tv = i > 2 ? 1 : 0;\n\t\t\t\t}\n\n\t\t\t\t// Catch 1 and 2\n\t\t\t\tif ( i && i < 3 ) {\n\t\t\t\t\tv = Math.round( v * 100 ) + \"%\";\n\t\t\t\t}\n\t\t\t\treturn v;\n\t\t\t} );\n\n\t\tif ( hsla[ 3 ] === 1 ) {\n\t\t\thsla.pop();\n\t\t\tprefix = \"hsl(\";\n\t\t}\n\t\treturn prefix + hsla.join() + \")\";\n\t},\n\ttoHexString: function( includeAlpha ) {\n\t\tvar rgba = this._rgba.slice(),\n\t\t\talpha = rgba.pop();\n\n\t\tif ( includeAlpha ) {\n\t\t\trgba.push( ~~( alpha * 255 ) );\n\t\t}\n\n\t\treturn \"#\" + jQuery.map( rgba, function( v ) {\n\n\t\t\t// Default to 0 when nulls exist\n\t\t\tv = ( v || 0 ).toString( 16 );\n\t\t\treturn v.length === 1 ? \"0\" + v : v;\n\t\t} ).join( \"\" );\n\t},\n\ttoString: function() {\n\t\treturn this._rgba[ 3 ] === 0 ? \"transparent\" : this.toRgbaString();\n\t}\n} );\ncolor.fn.parse.prototype = color.fn;\n\n// Hsla conversions adapted from:\n// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021\n\nfunction hue2rgb( p, q, h ) {\n\th = ( h + 1 ) % 1;\n\tif ( h * 6 < 1 ) {\n\t\treturn p + ( q - p ) * h * 6;\n\t}\n\tif ( h * 2 < 1 ) {\n\t\treturn q;\n\t}\n\tif ( h * 3 < 2 ) {\n\t\treturn p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;\n\t}\n\treturn p;\n}\n\nspaces.hsla.to = function( rgba ) {\n\tif ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {\n\t\treturn [ null, null, null, rgba[ 3 ] ];\n\t}\n\tvar r = rgba[ 0 ] / 255,\n\t\tg = rgba[ 1 ] / 255,\n\t\tb = rgba[ 2 ] / 255,\n\t\ta = rgba[ 3 ],\n\t\tmax = Math.max( r, g, b ),\n\t\tmin = Math.min( r, g, b ),\n\t\tdiff = max - min,\n\t\tadd = max + min,\n\t\tl = add * 0.5,\n\t\th, s;\n\n\tif ( min === max ) {\n\t\th = 0;\n\t} else if ( r === max ) {\n\t\th = ( 60 * ( g - b ) / diff ) + 360;\n\t} else if ( g === max ) {\n\t\th = ( 60 * ( b - r ) / diff ) + 120;\n\t} else {\n\t\th = ( 60 * ( r - g ) / diff ) + 240;\n\t}\n\n\t// Chroma (diff) == 0 means greyscale which, by definition, saturation = 0%\n\t// otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)\n\tif ( diff === 0 ) {\n\t\ts = 0;\n\t} else if ( l <= 0.5 ) {\n\t\ts = diff / add;\n\t} else {\n\t\ts = diff / ( 2 - add );\n\t}\n\treturn [ Math.round( h ) % 360, s, l, a == null ? 1 : a ];\n};\n\nspaces.hsla.from = function( hsla ) {\n\tif ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {\n\t\treturn [ null, null, null, hsla[ 3 ] ];\n\t}\n\tvar h = hsla[ 0 ] / 360,\n\t\ts = hsla[ 1 ],\n\t\tl = hsla[ 2 ],\n\t\ta = hsla[ 3 ],\n\t\tq = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,\n\t\tp = 2 * l - q;\n\n\treturn [\n\t\tMath.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),\n\t\tMath.round( hue2rgb( p, q, h ) * 255 ),\n\t\tMath.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),\n\t\ta\n\t];\n};\n\neach( spaces, function( spaceName, space ) {\n\tvar props = space.props,\n\t\tcache = space.cache,\n\t\tto = space.to,\n\t\tfrom = space.from;\n\n\t// Makes rgba() and hsla()\n\tcolor.fn[ spaceName ] = function( value ) {\n\n\t\t// Generate a cache for this space if it doesn't exist\n\t\tif ( to && !this[ cache ] ) {\n\t\t\tthis[ cache ] = to( this._rgba );\n\t\t}\n\t\tif ( value === undefined ) {\n\t\t\treturn this[ cache ].slice();\n\t\t}\n\n\t\tvar ret,\n\t\t\ttype = jQuery.type( value ),\n\t\t\tarr = ( type === \"array\" || type === \"object\" ) ? value : arguments,\n\t\t\tlocal = this[ cache ].slice();\n\n\t\teach( props, function( key, prop ) {\n\t\t\tvar val = arr[ type === \"object\" ? key : prop.idx ];\n\t\t\tif ( val == null ) {\n\t\t\t\tval = local[ prop.idx ];\n\t\t\t}\n\t\t\tlocal[ prop.idx ] = clamp( val, prop );\n\t\t} );\n\n\t\tif ( from ) {\n\t\t\tret = color( from( local ) );\n\t\t\tret[ cache ] = local;\n\t\t\treturn ret;\n\t\t} else {\n\t\t\treturn color( local );\n\t\t}\n\t};\n\n\t// Makes red() green() blue() alpha() hue() saturation() lightness()\n\teach( props, function( key, prop ) {\n\n\t\t// Alpha is included in more than one space\n\t\tif ( color.fn[ key ] ) {\n\t\t\treturn;\n\t\t}\n\t\tcolor.fn[ key ] = function( value ) {\n\t\t\tvar vtype = jQuery.type( value ),\n\t\t\t\tfn = ( key === \"alpha\" ? ( this._hsla ? \"hsla\" : \"rgba\" ) : spaceName ),\n\t\t\t\tlocal = this[ fn ](),\n\t\t\t\tcur = local[ prop.idx ],\n\t\t\t\tmatch;\n\n\t\t\tif ( vtype === \"undefined\" ) {\n\t\t\t\treturn cur;\n\t\t\t}\n\n\t\t\tif ( vtype === \"function\" ) {\n\t\t\t\tvalue = value.call( this, cur );\n\t\t\t\tvtype = jQuery.type( value );\n\t\t\t}\n\t\t\tif ( value == null && prop.empty ) {\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\tif ( vtype === \"string\" ) {\n\t\t\t\tmatch = rplusequals.exec( value );\n\t\t\t\tif ( match ) {\n\t\t\t\t\tvalue = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === \"+\" ? 1 : -1 );\n\t\t\t\t}\n\t\t\t}\n\t\t\tlocal[ prop.idx ] = value;\n\t\t\treturn this[ fn ]( local );\n\t\t};\n\t} );\n} );\n\n// Add cssHook and .fx.step function for each named hook.\n// accept a space separated string of properties\ncolor.hook = function( hook ) {\n\tvar hooks = hook.split( \" \" );\n\teach( hooks, function( i, hook ) {\n\t\tjQuery.cssHooks[ hook ] = {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar parsed, curElem,\n\t\t\t\t\tbackgroundColor = \"\";\n\n\t\t\t\tif ( value !== \"transparent\" && ( jQuery.type( value ) !== \"string\" ||\n\t\t\t\t\t\t( parsed = stringParse( value ) ) ) ) {\n\t\t\t\t\tvalue = color( parsed || value );\n\t\t\t\t\tif ( !support.rgba && value._rgba[ 3 ] !== 1 ) {\n\t\t\t\t\t\tcurElem = hook === \"backgroundColor\" ? elem.parentNode : elem;\n\t\t\t\t\t\twhile (\n\t\t\t\t\t\t\t( backgroundColor === \"\" || backgroundColor === \"transparent\" ) &&\n\t\t\t\t\t\t\tcurElem && curElem.style\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tbackgroundColor = jQuery.css( curElem, \"backgroundColor\" );\n\t\t\t\t\t\t\t\tcurElem = curElem.parentNode;\n\t\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvalue = value.blend( backgroundColor && backgroundColor !== \"transparent\" ?\n\t\t\t\t\t\t\tbackgroundColor :\n\t\t\t\t\t\t\t\"_default\" );\n\t\t\t\t\t}\n\n\t\t\t\t\tvalue = value.toRgbaString();\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\telem.style[ hook ] = value;\n\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t// Wrapped to prevent IE from throwing errors on \"invalid\" values like\n\t\t\t\t\t// 'auto' or 'inherit'\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tjQuery.fx.step[ hook ] = function( fx ) {\n\t\t\tif ( !fx.colorInit ) {\n\t\t\t\tfx.start = color( fx.elem, hook );\n\t\t\t\tfx.end = color( fx.end );\n\t\t\t\tfx.colorInit = true;\n\t\t\t}\n\t\t\tjQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );\n\t\t};\n\t} );\n\n};\n\ncolor.hook( stepHooks );\n\njQuery.cssHooks.borderColor = {\n\texpand: function( value ) {\n\t\tvar expanded = {};\n\n\t\teach( [ \"Top\", \"Right\", \"Bottom\", \"Left\" ], function( i, part ) {\n\t\t\texpanded[ \"border\" + part + \"Color\" ] = value;\n\t\t} );\n\t\treturn expanded;\n\t}\n};\n\n// Basic color names only.\n// Usage of any of the other color names requires adding yourself or including\n// jquery.color.svg-names.js.\ncolors = jQuery.Color.names = {\n\n\t// 4.1. Basic color keywords\n\taqua: \"#00ffff\",\n\tblack: \"#000000\",\n\tblue: \"#0000ff\",\n\tfuchsia: \"#ff00ff\",\n\tgray: \"#808080\",\n\tgreen: \"#008000\",\n\tlime: \"#00ff00\",\n\tmaroon: \"#800000\",\n\tnavy: \"#000080\",\n\tolive: \"#808000\",\n\tpurple: \"#800080\",\n\tred: \"#ff0000\",\n\tsilver: \"#c0c0c0\",\n\tteal: \"#008080\",\n\twhite: \"#ffffff\",\n\tyellow: \"#ffff00\",\n\n\t// 4.2.3. \"transparent\" color keyword\n\ttransparent: [ null, null, null, 0 ],\n\n\t_default: \"#ffffff\"\n};\n\n} )( jQuery );\n\n/******************************************************************************/\n/****************************** CLASS ANIMATIONS ******************************/\n/******************************************************************************/\n( function() {\n\nvar classAnimationActions = [ \"add\", \"remove\", \"toggle\" ],\n\tshorthandStyles = {\n\t\tborder: 1,\n\t\tborderBottom: 1,\n\t\tborderColor: 1,\n\t\tborderLeft: 1,\n\t\tborderRight: 1,\n\t\tborderTop: 1,\n\t\tborderWidth: 1,\n\t\tmargin: 1,\n\t\tpadding: 1\n\t};\n\n$.each(\n\t[ \"borderLeftStyle\", \"borderRightStyle\", \"borderBottomStyle\", \"borderTopStyle\" ],\n\tfunction( _, prop ) {\n\t\t$.fx.step[ prop ] = function( fx ) {\n\t\t\tif ( fx.end !== \"none\" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {\n\t\t\t\tjQuery.style( fx.elem, prop, fx.end );\n\t\t\t\tfx.setAttr = true;\n\t\t\t}\n\t\t};\n\t}\n);\n\nfunction getElementStyles( elem ) {\n\tvar key, len,\n\t\tstyle = elem.ownerDocument.defaultView ?\n\t\t\telem.ownerDocument.defaultView.getComputedStyle( elem, null ) :\n\t\t\telem.currentStyle,\n\t\tstyles = {};\n\n\tif ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {\n\t\tlen = style.length;\n\t\twhile ( len-- ) {\n\t\t\tkey = style[ len ];\n\t\t\tif ( typeof style[ key ] === \"string\" ) {\n\t\t\t\tstyles[ $.camelCase( key ) ] = style[ key ];\n\t\t\t}\n\t\t}\n\n\t// Support: Opera, IE <9\n\t} else {\n\t\tfor ( key in style ) {\n\t\t\tif ( typeof style[ key ] === \"string\" ) {\n\t\t\t\tstyles[ key ] = style[ key ];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn styles;\n}\n\nfunction styleDifference( oldStyle, newStyle ) {\n\tvar diff = {},\n\t\tname, value;\n\n\tfor ( name in newStyle ) {\n\t\tvalue = newStyle[ name ];\n\t\tif ( oldStyle[ name ] !== value ) {\n\t\t\tif ( !shorthandStyles[ name ] ) {\n\t\t\t\tif ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {\n\t\t\t\t\tdiff[ name ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn diff;\n}\n\n// Support: jQuery <1.8\nif ( !$.fn.addBack ) {\n\t$.fn.addBack = function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter( selector )\n\t\t);\n\t};\n}\n\n$.effects.animateClass = function( value, duration, easing, callback ) {\n\tvar o = $.speed( duration, easing, callback );\n\n\treturn this.queue( function() {\n\t\tvar animated = $( this ),\n\t\t\tbaseClass = animated.attr( \"class\" ) || \"\",\n\t\t\tapplyClassChange,\n\t\t\tallAnimations = o.children ? animated.find( \"*\" ).addBack() : animated;\n\n\t\t// Map the animated objects to store the original styles.\n\t\tallAnimations = allAnimations.map( function() {\n\t\t\tvar el = $( this );\n\t\t\treturn {\n\t\t\t\tel: el,\n\t\t\t\tstart: getElementStyles( this )\n\t\t\t};\n\t\t} );\n\n\t\t// Apply class change\n\t\tapplyClassChange = function() {\n\t\t\t$.each( classAnimationActions, function( i, action ) {\n\t\t\t\tif ( value[ action ] ) {\n\t\t\t\t\tanimated[ action + \"Class\" ]( value[ action ] );\n\t\t\t\t}\n\t\t\t} );\n\t\t};\n\t\tapplyClassChange();\n\n\t\t// Map all animated objects again - calculate new styles and diff\n\t\tallAnimations = allAnimations.map( function() {\n\t\t\tthis.end = getElementStyles( this.el[ 0 ] );\n\t\t\tthis.diff = styleDifference( this.start, this.end );\n\t\t\treturn this;\n\t\t} );\n\n\t\t// Apply original class\n\t\tanimated.attr( \"class\", baseClass );\n\n\t\t// Map all animated objects again - this time collecting a promise\n\t\tallAnimations = allAnimations.map( function() {\n\t\t\tvar styleInfo = this,\n\t\t\t\tdfd = $.Deferred(),\n\t\t\t\topts = $.extend( {}, o, {\n\t\t\t\t\tqueue: false,\n\t\t\t\t\tcomplete: function() {\n\t\t\t\t\t\tdfd.resolve( styleInfo );\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\tthis.el.animate( this.diff, opts );\n\t\t\treturn dfd.promise();\n\t\t} );\n\n\t\t// Once all animations have completed:\n\t\t$.when.apply( $, allAnimations.get() ).done( function() {\n\n\t\t\t// Set the final class\n\t\t\tapplyClassChange();\n\n\t\t\t// For each animated element,\n\t\t\t// clear all css properties that were animated\n\t\t\t$.each( arguments, function() {\n\t\t\t\tvar el = this.el;\n\t\t\t\t$.each( this.diff, function( key ) {\n\t\t\t\t\tel.css( key, \"\" );\n\t\t\t\t} );\n\t\t\t} );\n\n\t\t\t// This is guarnteed to be there if you use jQuery.speed()\n\t\t\t// it also handles dequeuing the next anim...\n\t\t\to.complete.call( animated[ 0 ] );\n\t\t} );\n\t} );\n};\n\n$.fn.extend( {\n\taddClass: ( function( orig ) {\n\t\treturn function( classNames, speed, easing, callback ) {\n\t\t\treturn speed ?\n\t\t\t\t$.effects.animateClass.call( this,\n\t\t\t\t\t{ add: classNames }, speed, easing, callback ) :\n\t\t\t\torig.apply( this, arguments );\n\t\t};\n\t} )( $.fn.addClass ),\n\n\tremoveClass: ( function( orig ) {\n\t\treturn function( classNames, speed, easing, callback ) {\n\t\t\treturn arguments.length > 1 ?\n\t\t\t\t$.effects.animateClass.call( this,\n\t\t\t\t\t{ remove: classNames }, speed, easing, callback ) :\n\t\t\t\torig.apply( this, arguments );\n\t\t};\n\t} )( $.fn.removeClass ),\n\n\ttoggleClass: ( function( orig ) {\n\t\treturn function( classNames, force, speed, easing, callback ) {\n\t\t\tif ( typeof force === \"boolean\" || force === undefined ) {\n\t\t\t\tif ( !speed ) {\n\n\t\t\t\t\t// Without speed parameter\n\t\t\t\t\treturn orig.apply( this, arguments );\n\t\t\t\t} else {\n\t\t\t\t\treturn $.effects.animateClass.call( this,\n\t\t\t\t\t\t( force ? { add: classNames } : { remove: classNames } ),\n\t\t\t\t\t\tspeed, easing, callback );\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// Without force parameter\n\t\t\t\treturn $.effects.animateClass.call( this,\n\t\t\t\t\t{ toggle: classNames }, force, speed, easing );\n\t\t\t}\n\t\t};\n\t} )( $.fn.toggleClass ),\n\n\tswitchClass: function( remove, add, speed, easing, callback ) {\n\t\treturn $.effects.animateClass.call( this, {\n\t\t\tadd: add,\n\t\t\tremove: remove\n\t\t}, speed, easing, callback );\n\t}\n} );\n\n} )();\n\n/******************************************************************************/\n/*********************************** EFFECTS **********************************/\n/******************************************************************************/\n\n( function() {\n\nif ( $.expr && $.expr.filters && $.expr.filters.animated ) {\n\t$.expr.filters.animated = ( function( orig ) {\n\t\treturn function( elem ) {\n\t\t\treturn !!$( elem ).data( dataSpaceAnimated ) || orig( elem );\n\t\t};\n\t} )( $.expr.filters.animated );\n}\n\nif ( $.uiBackCompat !== false ) {\n\t$.extend( $.effects, {\n\n\t\t// Saves a set of properties in a data storage\n\t\tsave: function( element, set ) {\n\t\t\tvar i = 0, length = set.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( set[ i ] !== null ) {\n\t\t\t\t\telement.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t// Restores a set of previously saved properties from a data storage\n\t\trestore: function( element, set ) {\n\t\t\tvar val, i = 0, length = set.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( set[ i ] !== null ) {\n\t\t\t\t\tval = element.data( dataSpace + set[ i ] );\n\t\t\t\t\telement.css( set[ i ], val );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tsetMode: function( el, mode ) {\n\t\t\tif ( mode === \"toggle\" ) {\n\t\t\t\tmode = el.is( \":hidden\" ) ? \"show\" : \"hide\";\n\t\t\t}\n\t\t\treturn mode;\n\t\t},\n\n\t\t// Wraps the element around a wrapper that copies position properties\n\t\tcreateWrapper: function( element ) {\n\n\t\t\t// If the element is already wrapped, return it\n\t\t\tif ( element.parent().is( \".ui-effects-wrapper\" ) ) {\n\t\t\t\treturn element.parent();\n\t\t\t}\n\n\t\t\t// Wrap the element\n\t\t\tvar props = {\n\t\t\t\t\twidth: element.outerWidth( true ),\n\t\t\t\t\theight: element.outerHeight( true ),\n\t\t\t\t\t\"float\": element.css( \"float\" )\n\t\t\t\t},\n\t\t\t\twrapper = $( \"<div></div>\" )\n\t\t\t\t\t.addClass( \"ui-effects-wrapper\" )\n\t\t\t\t\t.css( {\n\t\t\t\t\t\tfontSize: \"100%\",\n\t\t\t\t\t\tbackground: \"transparent\",\n\t\t\t\t\t\tborder: \"none\",\n\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\tpadding: 0\n\t\t\t\t\t} ),\n\n\t\t\t\t// Store the size in case width/height are defined in % - Fixes #5245\n\t\t\t\tsize = {\n\t\t\t\t\twidth: element.width(),\n\t\t\t\t\theight: element.height()\n\t\t\t\t},\n\t\t\t\tactive = document.activeElement;\n\n\t\t\t// Support: Firefox\n\t\t\t// Firefox incorrectly exposes anonymous content\n\t\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=561664\n\t\t\ttry {\n\t\t\t\tactive.id;\n\t\t\t} catch ( e ) {\n\t\t\t\tactive = document.body;\n\t\t\t}\n\n\t\t\telement.wrap( wrapper );\n\n\t\t\t// Fixes #7595 - Elements lose focus when wrapped.\n\t\t\tif ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {\n\t\t\t\t$( active ).trigger( \"focus\" );\n\t\t\t}\n\n\t\t\t// Hotfix for jQuery 1.4 since some change in wrap() seems to actually\n\t\t\t// lose the reference to the wrapped element\n\t\t\twrapper = element.parent();\n\n\t\t\t// Transfer positioning properties to the wrapper\n\t\t\tif ( element.css( \"position\" ) === \"static\" ) {\n\t\t\t\twrapper.css( { position: \"relative\" } );\n\t\t\t\telement.css( { position: \"relative\" } );\n\t\t\t} else {\n\t\t\t\t$.extend( props, {\n\t\t\t\t\tposition: element.css( \"position\" ),\n\t\t\t\t\tzIndex: element.css( \"z-index\" )\n\t\t\t\t} );\n\t\t\t\t$.each( [ \"top\", \"left\", \"bottom\", \"right\" ], function( i, pos ) {\n\t\t\t\t\tprops[ pos ] = element.css( pos );\n\t\t\t\t\tif ( isNaN( parseInt( props[ pos ], 10 ) ) ) {\n\t\t\t\t\t\tprops[ pos ] = \"auto\";\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\telement.css( {\n\t\t\t\t\tposition: \"relative\",\n\t\t\t\t\ttop: 0,\n\t\t\t\t\tleft: 0,\n\t\t\t\t\tright: \"auto\",\n\t\t\t\t\tbottom: \"auto\"\n\t\t\t\t} );\n\t\t\t}\n\t\t\telement.css( size );\n\n\t\t\treturn wrapper.css( props ).show();\n\t\t},\n\n\t\tremoveWrapper: function( element ) {\n\t\t\tvar active = document.activeElement;\n\n\t\t\tif ( element.parent().is( \".ui-effects-wrapper\" ) ) {\n\t\t\t\telement.parent().replaceWith( element );\n\n\t\t\t\t// Fixes #7595 - Elements lose focus when wrapped.\n\t\t\t\tif ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {\n\t\t\t\t\t$( active ).trigger( \"focus\" );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn element;\n\t\t}\n\t} );\n}\n\n$.extend( $.effects, {\n\tversion: \"1.12.1\",\n\n\tdefine: function( name, mode, effect ) {\n\t\tif ( !effect ) {\n\t\t\teffect = mode;\n\t\t\tmode = \"effect\";\n\t\t}\n\n\t\t$.effects.effect[ name ] = effect;\n\t\t$.effects.effect[ name ].mode = mode;\n\n\t\treturn effect;\n\t},\n\n\tscaledDimensions: function( element, percent, direction ) {\n\t\tif ( percent === 0 ) {\n\t\t\treturn {\n\t\t\t\theight: 0,\n\t\t\t\twidth: 0,\n\t\t\t\touterHeight: 0,\n\t\t\t\touterWidth: 0\n\t\t\t};\n\t\t}\n\n\t\tvar x = direction !== \"horizontal\" ? ( ( percent || 100 ) / 100 ) : 1,\n\t\t\ty = direction !== \"vertical\" ? ( ( percent || 100 ) / 100 ) : 1;\n\n\t\treturn {\n\t\t\theight: element.height() * y,\n\t\t\twidth: element.width() * x,\n\t\t\touterHeight: element.outerHeight() * y,\n\t\t\touterWidth: element.outerWidth() * x\n\t\t};\n\n\t},\n\n\tclipToBox: function( animation ) {\n\t\treturn {\n\t\t\twidth: animation.clip.right - animation.clip.left,\n\t\t\theight: animation.clip.bottom - animation.clip.top,\n\t\t\tleft: animation.clip.left,\n\t\t\ttop: animation.clip.top\n\t\t};\n\t},\n\n\t// Injects recently queued functions to be first in line (after \"inprogress\")\n\tunshift: function( element, queueLength, count ) {\n\t\tvar queue = element.queue();\n\n\t\tif ( queueLength > 1 ) {\n\t\t\tqueue.splice.apply( queue,\n\t\t\t\t[ 1, 0 ].concat( queue.splice( queueLength, count ) ) );\n\t\t}\n\t\telement.dequeue();\n\t},\n\n\tsaveStyle: function( element ) {\n\t\telement.data( dataSpaceStyle, element[ 0 ].style.cssText );\n\t},\n\n\trestoreStyle: function( element ) {\n\t\telement[ 0 ].style.cssText = element.data( dataSpaceStyle ) || \"\";\n\t\telement.removeData( dataSpaceStyle );\n\t},\n\n\tmode: function( element, mode ) {\n\t\tvar hidden = element.is( \":hidden\" );\n\n\t\tif ( mode === \"toggle\" ) {\n\t\t\tmode = hidden ? \"show\" : \"hide\";\n\t\t}\n\t\tif ( hidden ? mode === \"hide\" : mode === \"show\" ) {\n\t\t\tmode = \"none\";\n\t\t}\n\t\treturn mode;\n\t},\n\n\t// Translates a [top,left] array into a baseline value\n\tgetBaseline: function( origin, original ) {\n\t\tvar y, x;\n\n\t\tswitch ( origin[ 0 ] ) {\n\t\tcase \"top\":\n\t\t\ty = 0;\n\t\t\tbreak;\n\t\tcase \"middle\":\n\t\t\ty = 0.5;\n\t\t\tbreak;\n\t\tcase \"bottom\":\n\t\t\ty = 1;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\ty = origin[ 0 ] / original.height;\n\t\t}\n\n\t\tswitch ( origin[ 1 ] ) {\n\t\tcase \"left\":\n\t\t\tx = 0;\n\t\t\tbreak;\n\t\tcase \"center\":\n\t\t\tx = 0.5;\n\t\t\tbreak;\n\t\tcase \"right\":\n\t\t\tx = 1;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tx = origin[ 1 ] / original.width;\n\t\t}\n\n\t\treturn {\n\t\t\tx: x,\n\t\t\ty: y\n\t\t};\n\t},\n\n\t// Creates a placeholder element so that the original element can be made absolute\n\tcreatePlaceholder: function( element ) {\n\t\tvar placeholder,\n\t\t\tcssPosition = element.css( \"position\" ),\n\t\t\tposition = element.position();\n\n\t\t// Lock in margins first to account for form elements, which\n\t\t// will change margin if you explicitly set height\n\t\t// see: http://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380\n\t\t// Support: Safari\n\t\telement.css( {\n\t\t\tmarginTop: element.css( \"marginTop\" ),\n\t\t\tmarginBottom: element.css( \"marginBottom\" ),\n\t\t\tmarginLeft: element.css( \"marginLeft\" ),\n\t\t\tmarginRight: element.css( \"marginRight\" )\n\t\t} )\n\t\t.outerWidth( element.outerWidth() )\n\t\t.outerHeight( element.outerHeight() );\n\n\t\tif ( /^(static|relative)/.test( cssPosition ) ) {\n\t\t\tcssPosition = \"absolute\";\n\n\t\t\tplaceholder = $( \"<\" + element[ 0 ].nodeName + \">\" ).insertAfter( element ).css( {\n\n\t\t\t\t// Convert inline to inline block to account for inline elements\n\t\t\t\t// that turn to inline block based on content (like img)\n\t\t\t\tdisplay: /^(inline|ruby)/.test( element.css( \"display\" ) ) ?\n\t\t\t\t\t\"inline-block\" :\n\t\t\t\t\t\"block\",\n\t\t\t\tvisibility: \"hidden\",\n\n\t\t\t\t// Margins need to be set to account for margin collapse\n\t\t\t\tmarginTop: element.css( \"marginTop\" ),\n\t\t\t\tmarginBottom: element.css( \"marginBottom\" ),\n\t\t\t\tmarginLeft: element.css( \"marginLeft\" ),\n\t\t\t\tmarginRight: element.css( \"marginRight\" ),\n\t\t\t\t\"float\": element.css( \"float\" )\n\t\t\t} )\n\t\t\t.outerWidth( element.outerWidth() )\n\t\t\t.outerHeight( element.outerHeight() )\n\t\t\t.addClass( \"ui-effects-placeholder\" );\n\n\t\t\telement.data( dataSpace + \"placeholder\", placeholder );\n\t\t}\n\n\t\telement.css( {\n\t\t\tposition: cssPosition,\n\t\t\tleft: position.left,\n\t\t\ttop: position.top\n\t\t} );\n\n\t\treturn placeholder;\n\t},\n\n\tremovePlaceholder: function( element ) {\n\t\tvar dataKey = dataSpace + \"placeholder\",\n\t\t\t\tplaceholder = element.data( dataKey );\n\n\t\tif ( placeholder ) {\n\t\t\tplaceholder.remove();\n\t\t\telement.removeData( dataKey );\n\t\t}\n\t},\n\n\t// Removes a placeholder if it exists and restores\n\t// properties that were modified during placeholder creation\n\tcleanUp: function( element ) {\n\t\t$.effects.restoreStyle( element );\n\t\t$.effects.removePlaceholder( element );\n\t},\n\n\tsetTransition: function( element, list, factor, value ) {\n\t\tvalue = value || {};\n\t\t$.each( list, function( i, x ) {\n\t\t\tvar unit = element.cssUnit( x );\n\t\t\tif ( unit[ 0 ] > 0 ) {\n\t\t\t\tvalue[ x ] = unit[ 0 ] * factor + unit[ 1 ];\n\t\t\t}\n\t\t} );\n\t\treturn value;\n\t}\n} );\n\n// Return an effect options object for the given parameters:\nfunction _normalizeArguments( effect, options, speed, callback ) {\n\n\t// Allow passing all options as the first parameter\n\tif ( $.isPlainObject( effect ) ) {\n\t\toptions = effect;\n\t\teffect = effect.effect;\n\t}\n\n\t// Convert to an object\n\teffect = { effect: effect };\n\n\t// Catch (effect, null, ...)\n\tif ( options == null ) {\n\t\toptions = {};\n\t}\n\n\t// Catch (effect, callback)\n\tif ( $.isFunction( options ) ) {\n\t\tcallback = options;\n\t\tspeed = null;\n\t\toptions = {};\n\t}\n\n\t// Catch (effect, speed, ?)\n\tif ( typeof options === \"number\" || $.fx.speeds[ options ] ) {\n\t\tcallback = speed;\n\t\tspeed = options;\n\t\toptions = {};\n\t}\n\n\t// Catch (effect, options, callback)\n\tif ( $.isFunction( speed ) ) {\n\t\tcallback = speed;\n\t\tspeed = null;\n\t}\n\n\t// Add options to effect\n\tif ( options ) {\n\t\t$.extend( effect, options );\n\t}\n\n\tspeed = speed || options.duration;\n\teffect.duration = $.fx.off ? 0 :\n\t\ttypeof speed === \"number\" ? speed :\n\t\tspeed in $.fx.speeds ? $.fx.speeds[ speed ] :\n\t\t$.fx.speeds._default;\n\n\teffect.complete = callback || options.complete;\n\n\treturn effect;\n}\n\nfunction standardAnimationOption( option ) {\n\n\t// Valid standard speeds (nothing, number, named speed)\n\tif ( !option || typeof option === \"number\" || $.fx.speeds[ option ] ) {\n\t\treturn true;\n\t}\n\n\t// Invalid strings - treat as \"normal\" speed\n\tif ( typeof option === \"string\" && !$.effects.effect[ option ] ) {\n\t\treturn true;\n\t}\n\n\t// Complete callback\n\tif ( $.isFunction( option ) ) {\n\t\treturn true;\n\t}\n\n\t// Options hash (but not naming an effect)\n\tif ( typeof option === \"object\" && !option.effect ) {\n\t\treturn true;\n\t}\n\n\t// Didn't match any standard API\n\treturn false;\n}\n\n$.fn.extend( {\n\teffect: function( /* effect, options, speed, callback */ ) {\n\t\tvar args = _normalizeArguments.apply( this, arguments ),\n\t\t\teffectMethod = $.effects.effect[ args.effect ],\n\t\t\tdefaultMode = effectMethod.mode,\n\t\t\tqueue = args.queue,\n\t\t\tqueueName = queue || \"fx\",\n\t\t\tcomplete = args.complete,\n\t\t\tmode = args.mode,\n\t\t\tmodes = [],\n\t\t\tprefilter = function( next ) {\n\t\t\t\tvar el = $( this ),\n\t\t\t\t\tnormalizedMode = $.effects.mode( el, mode ) || defaultMode;\n\n\t\t\t\t// Sentinel for duck-punching the :animated psuedo-selector\n\t\t\t\tel.data( dataSpaceAnimated, true );\n\n\t\t\t\t// Save effect mode for later use,\n\t\t\t\t// we can't just call $.effects.mode again later,\n\t\t\t\t// as the .show() below destroys the initial state\n\t\t\t\tmodes.push( normalizedMode );\n\n\t\t\t\t// See $.uiBackCompat inside of run() for removal of defaultMode in 1.13\n\t\t\t\tif ( defaultMode && ( normalizedMode === \"show\" ||\n\t\t\t\t\t\t( normalizedMode === defaultMode && normalizedMode === \"hide\" ) ) ) {\n\t\t\t\t\tel.show();\n\t\t\t\t}\n\n\t\t\t\tif ( !defaultMode || normalizedMode !== \"none\" ) {\n\t\t\t\t\t$.effects.saveStyle( el );\n\t\t\t\t}\n\n\t\t\t\tif ( $.isFunction( next ) ) {\n\t\t\t\t\tnext();\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( $.fx.off || !effectMethod ) {\n\n\t\t\t// Delegate to the original method (e.g., .show()) if possible\n\t\t\tif ( mode ) {\n\t\t\t\treturn this[ mode ]( args.duration, complete );\n\t\t\t} else {\n\t\t\t\treturn this.each( function() {\n\t\t\t\t\tif ( complete ) {\n\t\t\t\t\t\tcomplete.call( this );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\n\t\tfunction run( next ) {\n\t\t\tvar elem = $( this );\n\n\t\t\tfunction cleanup() {\n\t\t\t\telem.removeData( dataSpaceAnimated );\n\n\t\t\t\t$.effects.cleanUp( elem );\n\n\t\t\t\tif ( args.mode === \"hide\" ) {\n\t\t\t\t\telem.hide();\n\t\t\t\t}\n\n\t\t\t\tdone();\n\t\t\t}\n\n\t\t\tfunction done() {\n\t\t\t\tif ( $.isFunction( complete ) ) {\n\t\t\t\t\tcomplete.call( elem[ 0 ] );\n\t\t\t\t}\n\n\t\t\t\tif ( $.isFunction( next ) ) {\n\t\t\t\t\tnext();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override mode option on a per element basis,\n\t\t\t// as toggle can be either show or hide depending on element state\n\t\t\targs.mode = modes.shift();\n\n\t\t\tif ( $.uiBackCompat !== false && !defaultMode ) {\n\t\t\t\tif ( elem.is( \":hidden\" ) ? mode === \"hide\" : mode === \"show\" ) {\n\n\t\t\t\t\t// Call the core method to track \"olddisplay\" properly\n\t\t\t\t\telem[ mode ]();\n\t\t\t\t\tdone();\n\t\t\t\t} else {\n\t\t\t\t\teffectMethod.call( elem[ 0 ], args, done );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ( args.mode === \"none\" ) {\n\n\t\t\t\t\t// Call the core method to track \"olddisplay\" properly\n\t\t\t\t\telem[ mode ]();\n\t\t\t\t\tdone();\n\t\t\t\t} else {\n\t\t\t\t\teffectMethod.call( elem[ 0 ], args, cleanup );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Run prefilter on all elements first to ensure that\n\t\t// any showing or hiding happens before placeholder creation,\n\t\t// which ensures that any layout changes are correctly captured.\n\t\treturn queue === false ?\n\t\t\tthis.each( prefilter ).each( run ) :\n\t\t\tthis.queue( queueName, prefilter ).queue( queueName, run );\n\t},\n\n\tshow: ( function( orig ) {\n\t\treturn function( option ) {\n\t\t\tif ( standardAnimationOption( option ) ) {\n\t\t\t\treturn orig.apply( this, arguments );\n\t\t\t} else {\n\t\t\t\tvar args = _normalizeArguments.apply( this, arguments );\n\t\t\t\targs.mode = \"show\";\n\t\t\t\treturn this.effect.call( this, args );\n\t\t\t}\n\t\t};\n\t} )( $.fn.show ),\n\n\thide: ( function( orig ) {\n\t\treturn function( option ) {\n\t\t\tif ( standardAnimationOption( option ) ) {\n\t\t\t\treturn orig.apply( this, arguments );\n\t\t\t} else {\n\t\t\t\tvar args = _normalizeArguments.apply( this, arguments );\n\t\t\t\targs.mode = \"hide\";\n\t\t\t\treturn this.effect.call( this, args );\n\t\t\t}\n\t\t};\n\t} )( $.fn.hide ),\n\n\ttoggle: ( function( orig ) {\n\t\treturn function( option ) {\n\t\t\tif ( standardAnimationOption( option ) || typeof option === \"boolean\" ) {\n\t\t\t\treturn orig.apply( this, arguments );\n\t\t\t} else {\n\t\t\t\tvar args = _normalizeArguments.apply( this, arguments );\n\t\t\t\targs.mode = \"toggle\";\n\t\t\t\treturn this.effect.call( this, args );\n\t\t\t}\n\t\t};\n\t} )( $.fn.toggle ),\n\n\tcssUnit: function( key ) {\n\t\tvar style = this.css( key ),\n\t\t\tval = [];\n\n\t\t$.each( [ \"em\", \"px\", \"%\", \"pt\" ], function( i, unit ) {\n\t\t\tif ( style.indexOf( unit ) > 0 ) {\n\t\t\t\tval = [ parseFloat( style ), unit ];\n\t\t\t}\n\t\t} );\n\t\treturn val;\n\t},\n\n\tcssClip: function( clipObj ) {\n\t\tif ( clipObj ) {\n\t\t\treturn this.css( \"clip\", \"rect(\" + clipObj.top + \"px \" + clipObj.right + \"px \" +\n\t\t\t\tclipObj.bottom + \"px \" + clipObj.left + \"px)\" );\n\t\t}\n\t\treturn parseClip( this.css( \"clip\" ), this );\n\t},\n\n\ttransfer: function( options, done ) {\n\t\tvar element = $( this ),\n\t\t\ttarget = $( options.to ),\n\t\t\ttargetFixed = target.css( \"position\" ) === \"fixed\",\n\t\t\tbody = $( \"body\" ),\n\t\t\tfixTop = targetFixed ? body.scrollTop() : 0,\n\t\t\tfixLeft = targetFixed ? body.scrollLeft() : 0,\n\t\t\tendPosition = target.offset(),\n\t\t\tanimation = {\n\t\t\t\ttop: endPosition.top - fixTop,\n\t\t\t\tleft: endPosition.left - fixLeft,\n\t\t\t\theight: target.innerHeight(),\n\t\t\t\twidth: target.innerWidth()\n\t\t\t},\n\t\t\tstartPosition = element.offset(),\n\t\t\ttransfer = $( \"<div class='ui-effects-transfer'></div>\" )\n\t\t\t\t.appendTo( \"body\" )\n\t\t\t\t.addClass( options.className )\n\t\t\t\t.css( {\n\t\t\t\t\ttop: startPosition.top - fixTop,\n\t\t\t\t\tleft: startPosition.left - fixLeft,\n\t\t\t\t\theight: element.innerHeight(),\n\t\t\t\t\twidth: element.innerWidth(),\n\t\t\t\t\tposition: targetFixed ? \"fixed\" : \"absolute\"\n\t\t\t\t} )\n\t\t\t\t.animate( animation, options.duration, options.easing, function() {\n\t\t\t\t\ttransfer.remove();\n\t\t\t\t\tif ( $.isFunction( done ) ) {\n\t\t\t\t\t\tdone();\n\t\t\t\t\t}\n\t\t\t\t} );\n\t}\n} );\n\nfunction parseClip( str, element ) {\n\t\tvar outerWidth = element.outerWidth(),\n\t\t\touterHeight = element.outerHeight(),\n\t\t\tclipRegex = /^rect\\((-?\\d*\\.?\\d*px|-?\\d+%|auto),?\\s*(-?\\d*\\.?\\d*px|-?\\d+%|auto),?\\s*(-?\\d*\\.?\\d*px|-?\\d+%|auto),?\\s*(-?\\d*\\.?\\d*px|-?\\d+%|auto)\\)$/,\n\t\t\tvalues = clipRegex.exec( str ) || [ \"\", 0, outerWidth, outerHeight, 0 ];\n\n\t\treturn {\n\t\t\ttop: parseFloat( values[ 1 ] ) || 0,\n\t\t\tright: values[ 2 ] === \"auto\" ? outerWidth : parseFloat( values[ 2 ] ),\n\t\t\tbottom: values[ 3 ] === \"auto\" ? outerHeight : parseFloat( values[ 3 ] ),\n\t\t\tleft: parseFloat( values[ 4 ] ) || 0\n\t\t};\n}\n\n$.fx.step.clip = function( fx ) {\n\tif ( !fx.clipInit ) {\n\t\tfx.start = $( fx.elem ).cssClip();\n\t\tif ( typeof fx.end === \"string\" ) {\n\t\t\tfx.end = parseClip( fx.end, fx.elem );\n\t\t}\n\t\tfx.clipInit = true;\n\t}\n\n\t$( fx.elem ).cssClip( {\n\t\ttop: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top,\n\t\tright: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right,\n\t\tbottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom,\n\t\tleft: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left\n\t} );\n};\n\n} )();\n\n/******************************************************************************/\n/*********************************** EASING ***********************************/\n/******************************************************************************/\n\n( function() {\n\n// Based on easing equations from Robert Penner (http://www.robertpenner.com/easing)\n\nvar baseEasings = {};\n\n$.each( [ \"Quad\", \"Cubic\", \"Quart\", \"Quint\", \"Expo\" ], function( i, name ) {\n\tbaseEasings[ name ] = function( p ) {\n\t\treturn Math.pow( p, i + 2 );\n\t};\n} );\n\n$.extend( baseEasings, {\n\tSine: function( p ) {\n\t\treturn 1 - Math.cos( p * Math.PI / 2 );\n\t},\n\tCirc: function( p ) {\n\t\treturn 1 - Math.sqrt( 1 - p * p );\n\t},\n\tElastic: function( p ) {\n\t\treturn p === 0 || p === 1 ? p :\n\t\t\t-Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 );\n\t},\n\tBack: function( p ) {\n\t\treturn p * p * ( 3 * p - 2 );\n\t},\n\tBounce: function( p ) {\n\t\tvar pow2,\n\t\t\tbounce = 4;\n\n\t\twhile ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}\n\t\treturn 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );\n\t}\n} );\n\n$.each( baseEasings, function( name, easeIn ) {\n\t$.easing[ \"easeIn\" + name ] = easeIn;\n\t$.easing[ \"easeOut\" + name ] = function( p ) {\n\t\treturn 1 - easeIn( 1 - p );\n\t};\n\t$.easing[ \"easeInOut\" + name ] = function( p ) {\n\t\treturn p < 0.5 ?\n\t\t\teaseIn( p * 2 ) / 2 :\n\t\t\t1 - easeIn( p * -2 + 2 ) / 2;\n\t};\n} );\n\n} )();\n\nvar effect = $.effects;\n\n\n/*!\n * jQuery UI Effects Blind 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Blind Effect\n//>>group: Effects\n//>>description: Blinds the element.\n//>>docs: http://api.jqueryui.com/blind-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectBlind = $.effects.define( \"blind\", \"hide\", function( options, done ) {\n\tvar map = {\n\t\t\tup: [ \"bottom\", \"top\" ],\n\t\t\tvertical: [ \"bottom\", \"top\" ],\n\t\t\tdown: [ \"top\", \"bottom\" ],\n\t\t\tleft: [ \"right\", \"left\" ],\n\t\t\thorizontal: [ \"right\", \"left\" ],\n\t\t\tright: [ \"left\", \"right\" ]\n\t\t},\n\t\telement = $( this ),\n\t\tdirection = options.direction || \"up\",\n\t\tstart = element.cssClip(),\n\t\tanimate = { clip: $.extend( {}, start ) },\n\t\tplaceholder = $.effects.createPlaceholder( element );\n\n\tanimate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ];\n\n\tif ( options.mode === \"show\" ) {\n\t\telement.cssClip( animate.clip );\n\t\tif ( placeholder ) {\n\t\t\tplaceholder.css( $.effects.clipToBox( animate ) );\n\t\t}\n\n\t\tanimate.clip = start;\n\t}\n\n\tif ( placeholder ) {\n\t\tplaceholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing );\n\t}\n\n\telement.animate( animate, {\n\t\tqueue: false,\n\t\tduration: options.duration,\n\t\teasing: options.easing,\n\t\tcomplete: done\n\t} );\n} );\n\n\n/*!\n * jQuery UI Effects Bounce 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Bounce Effect\n//>>group: Effects\n//>>description: Bounces an element horizontally or vertically n times.\n//>>docs: http://api.jqueryui.com/bounce-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectBounce = $.effects.define( \"bounce\", function( options, done ) {\n\tvar upAnim, downAnim, refValue,\n\t\telement = $( this ),\n\n\t\t// Defaults:\n\t\tmode = options.mode,\n\t\thide = mode === \"hide\",\n\t\tshow = mode === \"show\",\n\t\tdirection = options.direction || \"up\",\n\t\tdistance = options.distance,\n\t\ttimes = options.times || 5,\n\n\t\t// Number of internal animations\n\t\tanims = times * 2 + ( show || hide ? 1 : 0 ),\n\t\tspeed = options.duration / anims,\n\t\teasing = options.easing,\n\n\t\t// Utility:\n\t\tref = ( direction === \"up\" || direction === \"down\" ) ? \"top\" : \"left\",\n\t\tmotion = ( direction === \"up\" || direction === \"left\" ),\n\t\ti = 0,\n\n\t\tqueuelen = element.queue().length;\n\n\t$.effects.createPlaceholder( element );\n\n\trefValue = element.css( ref );\n\n\t// Default distance for the BIGGEST bounce is the outer Distance / 3\n\tif ( !distance ) {\n\t\tdistance = element[ ref === \"top\" ? \"outerHeight\" : \"outerWidth\" ]() / 3;\n\t}\n\n\tif ( show ) {\n\t\tdownAnim = { opacity: 1 };\n\t\tdownAnim[ ref ] = refValue;\n\n\t\t// If we are showing, force opacity 0 and set the initial position\n\t\t// then do the \"first\" animation\n\t\telement\n\t\t\t.css( \"opacity\", 0 )\n\t\t\t.css( ref, motion ? -distance * 2 : distance * 2 )\n\t\t\t.animate( downAnim, speed, easing );\n\t}\n\n\t// Start at the smallest distance if we are hiding\n\tif ( hide ) {\n\t\tdistance = distance / Math.pow( 2, times - 1 );\n\t}\n\n\tdownAnim = {};\n\tdownAnim[ ref ] = refValue;\n\n\t// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here\n\tfor ( ; i < times; i++ ) {\n\t\tupAnim = {};\n\t\tupAnim[ ref ] = ( motion ? \"-=\" : \"+=\" ) + distance;\n\n\t\telement\n\t\t\t.animate( upAnim, speed, easing )\n\t\t\t.animate( downAnim, speed, easing );\n\n\t\tdistance = hide ? distance * 2 : distance / 2;\n\t}\n\n\t// Last Bounce when Hiding\n\tif ( hide ) {\n\t\tupAnim = { opacity: 0 };\n\t\tupAnim[ ref ] = ( motion ? \"-=\" : \"+=\" ) + distance;\n\n\t\telement.animate( upAnim, speed, easing );\n\t}\n\n\telement.queue( done );\n\n\t$.effects.unshift( element, queuelen, anims + 1 );\n} );\n\n\n/*!\n * jQuery UI Effects Clip 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Clip Effect\n//>>group: Effects\n//>>description: Clips the element on and off like an old TV.\n//>>docs: http://api.jqueryui.com/clip-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectClip = $.effects.define( \"clip\", \"hide\", function( options, done ) {\n\tvar start,\n\t\tanimate = {},\n\t\telement = $( this ),\n\t\tdirection = options.direction || \"vertical\",\n\t\tboth = direction === \"both\",\n\t\thorizontal = both || direction === \"horizontal\",\n\t\tvertical = both || direction === \"vertical\";\n\n\tstart = element.cssClip();\n\tanimate.clip = {\n\t\ttop: vertical ? ( start.bottom - start.top ) / 2 : start.top,\n\t\tright: horizontal ? ( start.right - start.left ) / 2 : start.right,\n\t\tbottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom,\n\t\tleft: horizontal ? ( start.right - start.left ) / 2 : start.left\n\t};\n\n\t$.effects.createPlaceholder( element );\n\n\tif ( options.mode === \"show\" ) {\n\t\telement.cssClip( animate.clip );\n\t\tanimate.clip = start;\n\t}\n\n\telement.animate( animate, {\n\t\tqueue: false,\n\t\tduration: options.duration,\n\t\teasing: options.easing,\n\t\tcomplete: done\n\t} );\n\n} );\n\n\n/*!\n * jQuery UI Effects Drop 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Drop Effect\n//>>group: Effects\n//>>description: Moves an element in one direction and hides it at the same time.\n//>>docs: http://api.jqueryui.com/drop-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectDrop = $.effects.define( \"drop\", \"hide\", function( options, done ) {\n\n\tvar distance,\n\t\telement = $( this ),\n\t\tmode = options.mode,\n\t\tshow = mode === \"show\",\n\t\tdirection = options.direction || \"left\",\n\t\tref = ( direction === \"up\" || direction === \"down\" ) ? \"top\" : \"left\",\n\t\tmotion = ( direction === \"up\" || direction === \"left\" ) ? \"-=\" : \"+=\",\n\t\toppositeMotion = ( motion === \"+=\" ) ? \"-=\" : \"+=\",\n\t\tanimation = {\n\t\t\topacity: 0\n\t\t};\n\n\t$.effects.createPlaceholder( element );\n\n\tdistance = options.distance ||\n\t\telement[ ref === \"top\" ? \"outerHeight\" : \"outerWidth\" ]( true ) / 2;\n\n\tanimation[ ref ] = motion + distance;\n\n\tif ( show ) {\n\t\telement.css( animation );\n\n\t\tanimation[ ref ] = oppositeMotion + distance;\n\t\tanimation.opacity = 1;\n\t}\n\n\t// Animate\n\telement.animate( animation, {\n\t\tqueue: false,\n\t\tduration: options.duration,\n\t\teasing: options.easing,\n\t\tcomplete: done\n\t} );\n} );\n\n\n/*!\n * jQuery UI Effects Explode 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Explode Effect\n//>>group: Effects\n// jscs:disable maximumLineLength\n//>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness.\n// jscs:enable maximumLineLength\n//>>docs: http://api.jqueryui.com/explode-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectExplode = $.effects.define( \"explode\", \"hide\", function( options, done ) {\n\n\tvar i, j, left, top, mx, my,\n\t\trows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3,\n\t\tcells = rows,\n\t\telement = $( this ),\n\t\tmode = options.mode,\n\t\tshow = mode === \"show\",\n\n\t\t// Show and then visibility:hidden the element before calculating offset\n\t\toffset = element.show().css( \"visibility\", \"hidden\" ).offset(),\n\n\t\t// Width and height of a piece\n\t\twidth = Math.ceil( element.outerWidth() / cells ),\n\t\theight = Math.ceil( element.outerHeight() / rows ),\n\t\tpieces = [];\n\n\t// Children animate complete:\n\tfunction childComplete() {\n\t\tpieces.push( this );\n\t\tif ( pieces.length === rows * cells ) {\n\t\t\tanimComplete();\n\t\t}\n\t}\n\n\t// Clone the element for each row and cell.\n\tfor ( i = 0; i < rows; i++ ) { // ===>\n\t\ttop = offset.top + i * height;\n\t\tmy = i - ( rows - 1 ) / 2;\n\n\t\tfor ( j = 0; j < cells; j++ ) { // |||\n\t\t\tleft = offset.left + j * width;\n\t\t\tmx = j - ( cells - 1 ) / 2;\n\n\t\t\t// Create a clone of the now hidden main element that will be absolute positioned\n\t\t\t// within a wrapper div off the -left and -top equal to size of our pieces\n\t\t\telement\n\t\t\t\t.clone()\n\t\t\t\t.appendTo( \"body\" )\n\t\t\t\t.wrap( \"<div></div>\" )\n\t\t\t\t.css( {\n\t\t\t\t\tposition: \"absolute\",\n\t\t\t\t\tvisibility: \"visible\",\n\t\t\t\t\tleft: -j * width,\n\t\t\t\t\ttop: -i * height\n\t\t\t\t} )\n\n\t\t\t\t// Select the wrapper - make it overflow: hidden and absolute positioned based on\n\t\t\t\t// where the original was located +left and +top equal to the size of pieces\n\t\t\t\t.parent()\n\t\t\t\t\t.addClass( \"ui-effects-explode\" )\n\t\t\t\t\t.css( {\n\t\t\t\t\t\tposition: \"absolute\",\n\t\t\t\t\t\toverflow: \"hidden\",\n\t\t\t\t\t\twidth: width,\n\t\t\t\t\t\theight: height,\n\t\t\t\t\t\tleft: left + ( show ? mx * width : 0 ),\n\t\t\t\t\t\ttop: top + ( show ? my * height : 0 ),\n\t\t\t\t\t\topacity: show ? 0 : 1\n\t\t\t\t\t} )\n\t\t\t\t\t.animate( {\n\t\t\t\t\t\tleft: left + ( show ? 0 : mx * width ),\n\t\t\t\t\t\ttop: top + ( show ? 0 : my * height ),\n\t\t\t\t\t\topacity: show ? 1 : 0\n\t\t\t\t\t}, options.duration || 500, options.easing, childComplete );\n\t\t}\n\t}\n\n\tfunction animComplete() {\n\t\telement.css( {\n\t\t\tvisibility: \"visible\"\n\t\t} );\n\t\t$( pieces ).remove();\n\t\tdone();\n\t}\n} );\n\n\n/*!\n * jQuery UI Effects Fade 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Fade Effect\n//>>group: Effects\n//>>description: Fades the element.\n//>>docs: http://api.jqueryui.com/fade-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectFade = $.effects.define( \"fade\", \"toggle\", function( options, done ) {\n\tvar show = options.mode === \"show\";\n\n\t$( this )\n\t\t.css( \"opacity\", show ? 0 : 1 )\n\t\t.animate( {\n\t\t\topacity: show ? 1 : 0\n\t\t}, {\n\t\t\tqueue: false,\n\t\t\tduration: options.duration,\n\t\t\teasing: options.easing,\n\t\t\tcomplete: done\n\t\t} );\n} );\n\n\n/*!\n * jQuery UI Effects Fold 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Fold Effect\n//>>group: Effects\n//>>description: Folds an element first horizontally and then vertically.\n//>>docs: http://api.jqueryui.com/fold-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectFold = $.effects.define( \"fold\", \"hide\", function( options, done ) {\n\n\t// Create element\n\tvar element = $( this ),\n\t\tmode = options.mode,\n\t\tshow = mode === \"show\",\n\t\thide = mode === \"hide\",\n\t\tsize = options.size || 15,\n\t\tpercent = /([0-9]+)%/.exec( size ),\n\t\thorizFirst = !!options.horizFirst,\n\t\tref = horizFirst ? [ \"right\", \"bottom\" ] : [ \"bottom\", \"right\" ],\n\t\tduration = options.duration / 2,\n\n\t\tplaceholder = $.effects.createPlaceholder( element ),\n\n\t\tstart = element.cssClip(),\n\t\tanimation1 = { clip: $.extend( {}, start ) },\n\t\tanimation2 = { clip: $.extend( {}, start ) },\n\n\t\tdistance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ],\n\n\t\tqueuelen = element.queue().length;\n\n\tif ( percent ) {\n\t\tsize = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];\n\t}\n\tanimation1.clip[ ref[ 0 ] ] = size;\n\tanimation2.clip[ ref[ 0 ] ] = size;\n\tanimation2.clip[ ref[ 1 ] ] = 0;\n\n\tif ( show ) {\n\t\telement.cssClip( animation2.clip );\n\t\tif ( placeholder ) {\n\t\t\tplaceholder.css( $.effects.clipToBox( animation2 ) );\n\t\t}\n\n\t\tanimation2.clip = start;\n\t}\n\n\t// Animate\n\telement\n\t\t.queue( function( next ) {\n\t\t\tif ( placeholder ) {\n\t\t\t\tplaceholder\n\t\t\t\t\t.animate( $.effects.clipToBox( animation1 ), duration, options.easing )\n\t\t\t\t\t.animate( $.effects.clipToBox( animation2 ), duration, options.easing );\n\t\t\t}\n\n\t\t\tnext();\n\t\t} )\n\t\t.animate( animation1, duration, options.easing )\n\t\t.animate( animation2, duration, options.easing )\n\t\t.queue( done );\n\n\t$.effects.unshift( element, queuelen, 4 );\n} );\n\n\n/*!\n * jQuery UI Effects Highlight 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Highlight Effect\n//>>group: Effects\n//>>description: Highlights the background of an element in a defined color for a custom duration.\n//>>docs: http://api.jqueryui.com/highlight-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectHighlight = $.effects.define( \"highlight\", \"show\", function( options, done ) {\n\tvar element = $( this ),\n\t\tanimation = {\n\t\t\tbackgroundColor: element.css( \"backgroundColor\" )\n\t\t};\n\n\tif ( options.mode === \"hide\" ) {\n\t\tanimation.opacity = 0;\n\t}\n\n\t$.effects.saveStyle( element );\n\n\telement\n\t\t.css( {\n\t\t\tbackgroundImage: \"none\",\n\t\t\tbackgroundColor: options.color || \"#ffff99\"\n\t\t} )\n\t\t.animate( animation, {\n\t\t\tqueue: false,\n\t\t\tduration: options.duration,\n\t\t\teasing: options.easing,\n\t\t\tcomplete: done\n\t\t} );\n} );\n\n\n/*!\n * jQuery UI Effects Size 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Size Effect\n//>>group: Effects\n//>>description: Resize an element to a specified width and height.\n//>>docs: http://api.jqueryui.com/size-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectSize = $.effects.define( \"size\", function( options, done ) {\n\n\t// Create element\n\tvar baseline, factor, temp,\n\t\telement = $( this ),\n\n\t\t// Copy for children\n\t\tcProps = [ \"fontSize\" ],\n\t\tvProps = [ \"borderTopWidth\", \"borderBottomWidth\", \"paddingTop\", \"paddingBottom\" ],\n\t\thProps = [ \"borderLeftWidth\", \"borderRightWidth\", \"paddingLeft\", \"paddingRight\" ],\n\n\t\t// Set options\n\t\tmode = options.mode,\n\t\trestore = mode !== \"effect\",\n\t\tscale = options.scale || \"both\",\n\t\torigin = options.origin || [ \"middle\", \"center\" ],\n\t\tposition = element.css( \"position\" ),\n\t\tpos = element.position(),\n\t\toriginal = $.effects.scaledDimensions( element ),\n\t\tfrom = options.from || original,\n\t\tto = options.to || $.effects.scaledDimensions( element, 0 );\n\n\t$.effects.createPlaceholder( element );\n\n\tif ( mode === \"show\" ) {\n\t\ttemp = from;\n\t\tfrom = to;\n\t\tto = temp;\n\t}\n\n\t// Set scaling factor\n\tfactor = {\n\t\tfrom: {\n\t\t\ty: from.height / original.height,\n\t\t\tx: from.width / original.width\n\t\t},\n\t\tto: {\n\t\t\ty: to.height / original.height,\n\t\t\tx: to.width / original.width\n\t\t}\n\t};\n\n\t// Scale the css box\n\tif ( scale === \"box\" || scale === \"both\" ) {\n\n\t\t// Vertical props scaling\n\t\tif ( factor.from.y !== factor.to.y ) {\n\t\t\tfrom = $.effects.setTransition( element, vProps, factor.from.y, from );\n\t\t\tto = $.effects.setTransition( element, vProps, factor.to.y, to );\n\t\t}\n\n\t\t// Horizontal props scaling\n\t\tif ( factor.from.x !== factor.to.x ) {\n\t\t\tfrom = $.effects.setTransition( element, hProps, factor.from.x, from );\n\t\t\tto = $.effects.setTransition( element, hProps, factor.to.x, to );\n\t\t}\n\t}\n\n\t// Scale the content\n\tif ( scale === \"content\" || scale === \"both\" ) {\n\n\t\t// Vertical props scaling\n\t\tif ( factor.from.y !== factor.to.y ) {\n\t\t\tfrom = $.effects.setTransition( element, cProps, factor.from.y, from );\n\t\t\tto = $.effects.setTransition( element, cProps, factor.to.y, to );\n\t\t}\n\t}\n\n\t// Adjust the position properties based on the provided origin points\n\tif ( origin ) {\n\t\tbaseline = $.effects.getBaseline( origin, original );\n\t\tfrom.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top;\n\t\tfrom.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left;\n\t\tto.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top;\n\t\tto.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left;\n\t}\n\telement.css( from );\n\n\t// Animate the children if desired\n\tif ( scale === \"content\" || scale === \"both\" ) {\n\n\t\tvProps = vProps.concat( [ \"marginTop\", \"marginBottom\" ] ).concat( cProps );\n\t\thProps = hProps.concat( [ \"marginLeft\", \"marginRight\" ] );\n\n\t\t// Only animate children with width attributes specified\n\t\t// TODO: is this right? should we include anything with css width specified as well\n\t\telement.find( \"*[width]\" ).each( function() {\n\t\t\tvar child = $( this ),\n\t\t\t\tchildOriginal = $.effects.scaledDimensions( child ),\n\t\t\t\tchildFrom = {\n\t\t\t\t\theight: childOriginal.height * factor.from.y,\n\t\t\t\t\twidth: childOriginal.width * factor.from.x,\n\t\t\t\t\touterHeight: childOriginal.outerHeight * factor.from.y,\n\t\t\t\t\touterWidth: childOriginal.outerWidth * factor.from.x\n\t\t\t\t},\n\t\t\t\tchildTo = {\n\t\t\t\t\theight: childOriginal.height * factor.to.y,\n\t\t\t\t\twidth: childOriginal.width * factor.to.x,\n\t\t\t\t\touterHeight: childOriginal.height * factor.to.y,\n\t\t\t\t\touterWidth: childOriginal.width * factor.to.x\n\t\t\t\t};\n\n\t\t\t// Vertical props scaling\n\t\t\tif ( factor.from.y !== factor.to.y ) {\n\t\t\t\tchildFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom );\n\t\t\t\tchildTo = $.effects.setTransition( child, vProps, factor.to.y, childTo );\n\t\t\t}\n\n\t\t\t// Horizontal props scaling\n\t\t\tif ( factor.from.x !== factor.to.x ) {\n\t\t\t\tchildFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom );\n\t\t\t\tchildTo = $.effects.setTransition( child, hProps, factor.to.x, childTo );\n\t\t\t}\n\n\t\t\tif ( restore ) {\n\t\t\t\t$.effects.saveStyle( child );\n\t\t\t}\n\n\t\t\t// Animate children\n\t\t\tchild.css( childFrom );\n\t\t\tchild.animate( childTo, options.duration, options.easing, function() {\n\n\t\t\t\t// Restore children\n\t\t\t\tif ( restore ) {\n\t\t\t\t\t$.effects.restoreStyle( child );\n\t\t\t\t}\n\t\t\t} );\n\t\t} );\n\t}\n\n\t// Animate\n\telement.animate( to, {\n\t\tqueue: false,\n\t\tduration: options.duration,\n\t\teasing: options.easing,\n\t\tcomplete: function() {\n\n\t\t\tvar offset = element.offset();\n\n\t\t\tif ( to.opacity === 0 ) {\n\t\t\t\telement.css( \"opacity\", from.opacity );\n\t\t\t}\n\n\t\t\tif ( !restore ) {\n\t\t\t\telement\n\t\t\t\t\t.css( \"position\", position === \"static\" ? \"relative\" : position )\n\t\t\t\t\t.offset( offset );\n\n\t\t\t\t// Need to save style here so that automatic style restoration\n\t\t\t\t// doesn't restore to the original styles from before the animation.\n\t\t\t\t$.effects.saveStyle( element );\n\t\t\t}\n\n\t\t\tdone();\n\t\t}\n\t} );\n\n} );\n\n\n/*!\n * jQuery UI Effects Scale 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Scale Effect\n//>>group: Effects\n//>>description: Grows or shrinks an element and its content.\n//>>docs: http://api.jqueryui.com/scale-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectScale = $.effects.define( \"scale\", function( options, done ) {\n\n\t// Create element\n\tvar el = $( this ),\n\t\tmode = options.mode,\n\t\tpercent = parseInt( options.percent, 10 ) ||\n\t\t\t( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== \"effect\" ? 0 : 100 ) ),\n\n\t\tnewOptions = $.extend( true, {\n\t\t\tfrom: $.effects.scaledDimensions( el ),\n\t\t\tto: $.effects.scaledDimensions( el, percent, options.direction || \"both\" ),\n\t\t\torigin: options.origin || [ \"middle\", \"center\" ]\n\t\t}, options );\n\n\t// Fade option to support puff\n\tif ( options.fade ) {\n\t\tnewOptions.from.opacity = 1;\n\t\tnewOptions.to.opacity = 0;\n\t}\n\n\t$.effects.effect.size.call( this, newOptions, done );\n} );\n\n\n/*!\n * jQuery UI Effects Puff 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Puff Effect\n//>>group: Effects\n//>>description: Creates a puff effect by scaling the element up and hiding it at the same time.\n//>>docs: http://api.jqueryui.com/puff-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectPuff = $.effects.define( \"puff\", \"hide\", function( options, done ) {\n\tvar newOptions = $.extend( true, {}, options, {\n\t\tfade: true,\n\t\tpercent: parseInt( options.percent, 10 ) || 150\n\t} );\n\n\t$.effects.effect.scale.call( this, newOptions, done );\n} );\n\n\n/*!\n * jQuery UI Effects Pulsate 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Pulsate Effect\n//>>group: Effects\n//>>description: Pulsates an element n times by changing the opacity to zero and back.\n//>>docs: http://api.jqueryui.com/pulsate-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectPulsate = $.effects.define( \"pulsate\", \"show\", function( options, done ) {\n\tvar element = $( this ),\n\t\tmode = options.mode,\n\t\tshow = mode === \"show\",\n\t\thide = mode === \"hide\",\n\t\tshowhide = show || hide,\n\n\t\t// Showing or hiding leaves off the \"last\" animation\n\t\tanims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),\n\t\tduration = options.duration / anims,\n\t\tanimateTo = 0,\n\t\ti = 1,\n\t\tqueuelen = element.queue().length;\n\n\tif ( show || !element.is( \":visible\" ) ) {\n\t\telement.css( \"opacity\", 0 ).show();\n\t\tanimateTo = 1;\n\t}\n\n\t// Anims - 1 opacity \"toggles\"\n\tfor ( ; i < anims; i++ ) {\n\t\telement.animate( { opacity: animateTo }, duration, options.easing );\n\t\tanimateTo = 1 - animateTo;\n\t}\n\n\telement.animate( { opacity: animateTo }, duration, options.easing );\n\n\telement.queue( done );\n\n\t$.effects.unshift( element, queuelen, anims + 1 );\n} );\n\n\n/*!\n * jQuery UI Effects Shake 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Shake Effect\n//>>group: Effects\n//>>description: Shakes an element horizontally or vertically n times.\n//>>docs: http://api.jqueryui.com/shake-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectShake = $.effects.define( \"shake\", function( options, done ) {\n\n\tvar i = 1,\n\t\telement = $( this ),\n\t\tdirection = options.direction || \"left\",\n\t\tdistance = options.distance || 20,\n\t\ttimes = options.times || 3,\n\t\tanims = times * 2 + 1,\n\t\tspeed = Math.round( options.duration / anims ),\n\t\tref = ( direction === \"up\" || direction === \"down\" ) ? \"top\" : \"left\",\n\t\tpositiveMotion = ( direction === \"up\" || direction === \"left\" ),\n\t\tanimation = {},\n\t\tanimation1 = {},\n\t\tanimation2 = {},\n\n\t\tqueuelen = element.queue().length;\n\n\t$.effects.createPlaceholder( element );\n\n\t// Animation\n\tanimation[ ref ] = ( positiveMotion ? \"-=\" : \"+=\" ) + distance;\n\tanimation1[ ref ] = ( positiveMotion ? \"+=\" : \"-=\" ) + distance * 2;\n\tanimation2[ ref ] = ( positiveMotion ? \"-=\" : \"+=\" ) + distance * 2;\n\n\t// Animate\n\telement.animate( animation, speed, options.easing );\n\n\t// Shakes\n\tfor ( ; i < times; i++ ) {\n\t\telement\n\t\t\t.animate( animation1, speed, options.easing )\n\t\t\t.animate( animation2, speed, options.easing );\n\t}\n\n\telement\n\t\t.animate( animation1, speed, options.easing )\n\t\t.animate( animation, speed / 2, options.easing )\n\t\t.queue( done );\n\n\t$.effects.unshift( element, queuelen, anims + 1 );\n} );\n\n\n/*!\n * jQuery UI Effects Slide 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Slide Effect\n//>>group: Effects\n//>>description: Slides an element in and out of the viewport.\n//>>docs: http://api.jqueryui.com/slide-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectSlide = $.effects.define( \"slide\", \"show\", function( options, done ) {\n\tvar startClip, startRef,\n\t\telement = $( this ),\n\t\tmap = {\n\t\t\tup: [ \"bottom\", \"top\" ],\n\t\t\tdown: [ \"top\", \"bottom\" ],\n\t\t\tleft: [ \"right\", \"left\" ],\n\t\t\tright: [ \"left\", \"right\" ]\n\t\t},\n\t\tmode = options.mode,\n\t\tdirection = options.direction || \"left\",\n\t\tref = ( direction === \"up\" || direction === \"down\" ) ? \"top\" : \"left\",\n\t\tpositiveMotion = ( direction === \"up\" || direction === \"left\" ),\n\t\tdistance = options.distance ||\n\t\t\telement[ ref === \"top\" ? \"outerHeight\" : \"outerWidth\" ]( true ),\n\t\tanimation = {};\n\n\t$.effects.createPlaceholder( element );\n\n\tstartClip = element.cssClip();\n\tstartRef = element.position()[ ref ];\n\n\t// Define hide animation\n\tanimation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef;\n\tanimation.clip = element.cssClip();\n\tanimation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ];\n\n\t// Reverse the animation if we're showing\n\tif ( mode === \"show\" ) {\n\t\telement.cssClip( animation.clip );\n\t\telement.css( ref, animation[ ref ] );\n\t\tanimation.clip = startClip;\n\t\tanimation[ ref ] = startRef;\n\t}\n\n\t// Actually animate\n\telement.animate( animation, {\n\t\tqueue: false,\n\t\tduration: options.duration,\n\t\teasing: options.easing,\n\t\tcomplete: done\n\t} );\n} );\n\n\n/*!\n * jQuery UI Effects Transfer 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Transfer Effect\n//>>group: Effects\n//>>description: Displays a transfer effect from one element to another.\n//>>docs: http://api.jqueryui.com/transfer-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effect;\nif ( $.uiBackCompat !== false ) {\n\teffect = $.effects.define( \"transfer\", function( options, done ) {\n\t\t$( this ).transfer( options, done );\n\t} );\n}\nvar effectsEffectTransfer = effect;\n\n\n/*!\n * jQuery UI Focusable 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: :focusable Selector\n//>>group: Core\n//>>description: Selects elements which can be focused.\n//>>docs: http://api.jqueryui.com/focusable-selector/\n\n\n\n// Selectors\n$.ui.focusable = function( element, hasTabindex ) {\n\tvar map, mapName, img, focusableIfVisible, fieldset,\n\t\tnodeName = element.nodeName.toLowerCase();\n\n\tif ( \"area\" === nodeName ) {\n\t\tmap = element.parentNode;\n\t\tmapName = map.name;\n\t\tif ( !element.href || !mapName || map.nodeName.toLowerCase() !== \"map\" ) {\n\t\t\treturn false;\n\t\t}\n\t\timg = $( \"img[usemap='#\" + mapName + \"']\" );\n\t\treturn img.length > 0 && img.is( \":visible\" );\n\t}\n\n\tif ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {\n\t\tfocusableIfVisible = !element.disabled;\n\n\t\tif ( focusableIfVisible ) {\n\n\t\t\t// Form controls within a disabled fieldset are disabled.\n\t\t\t// However, controls within the fieldset's legend do not get disabled.\n\t\t\t// Since controls generally aren't placed inside legends, we skip\n\t\t\t// this portion of the check.\n\t\t\tfieldset = $( element ).closest( \"fieldset\" )[ 0 ];\n\t\t\tif ( fieldset ) {\n\t\t\t\tfocusableIfVisible = !fieldset.disabled;\n\t\t\t}\n\t\t}\n\t} else if ( \"a\" === nodeName ) {\n\t\tfocusableIfVisible = element.href || hasTabindex;\n\t} else {\n\t\tfocusableIfVisible = hasTabindex;\n\t}\n\n\treturn focusableIfVisible && $( element ).is( \":visible\" ) && visible( $( element ) );\n};\n\n// Support: IE 8 only\n// IE 8 doesn't resolve inherit to visible/hidden for computed values\nfunction visible( element ) {\n\tvar visibility = element.css( \"visibility\" );\n\twhile ( visibility === \"inherit\" ) {\n\t\telement = element.parent();\n\t\tvisibility = element.css( \"visibility\" );\n\t}\n\treturn visibility !== \"hidden\";\n}\n\n$.extend( $.expr[ \":\" ], {\n\tfocusable: function( element ) {\n\t\treturn $.ui.focusable( element, $.attr( element, \"tabindex\" ) != null );\n\t}\n} );\n\nvar focusable = $.ui.focusable;\n\n\n\n\n// Support: IE8 Only\n// IE8 does not support the form attribute and when it is supplied. It overwrites the form prop\n// with a string, so we need to find the proper form.\nvar form = $.fn.form = function() {\n\treturn typeof this[ 0 ].form === \"string\" ? this.closest( \"form\" ) : $( this[ 0 ].form );\n};\n\n\n/*!\n * jQuery UI Form Reset Mixin 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Form Reset Mixin\n//>>group: Core\n//>>description: Refresh input widgets when their form is reset\n//>>docs: http://api.jqueryui.com/form-reset-mixin/\n\n\n\nvar formResetMixin = $.ui.formResetMixin = {\n\t_formResetHandler: function() {\n\t\tvar form = $( this );\n\n\t\t// Wait for the form reset to actually happen before refreshing\n\t\tsetTimeout( function() {\n\t\t\tvar instances = form.data( \"ui-form-reset-instances\" );\n\t\t\t$.each( instances, function() {\n\t\t\t\tthis.refresh();\n\t\t\t} );\n\t\t} );\n\t},\n\n\t_bindFormResetHandler: function() {\n\t\tthis.form = this.element.form();\n\t\tif ( !this.form.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar instances = this.form.data( \"ui-form-reset-instances\" ) || [];\n\t\tif ( !instances.length ) {\n\n\t\t\t// We don't use _on() here because we use a single event handler per form\n\t\t\tthis.form.on( \"reset.ui-form-reset\", this._formResetHandler );\n\t\t}\n\t\tinstances.push( this );\n\t\tthis.form.data( \"ui-form-reset-instances\", instances );\n\t},\n\n\t_unbindFormResetHandler: function() {\n\t\tif ( !this.form.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar instances = this.form.data( \"ui-form-reset-instances\" );\n\t\tinstances.splice( $.inArray( this, instances ), 1 );\n\t\tif ( instances.length ) {\n\t\t\tthis.form.data( \"ui-form-reset-instances\", instances );\n\t\t} else {\n\t\t\tthis.form\n\t\t\t\t.removeData( \"ui-form-reset-instances\" )\n\t\t\t\t.off( \"reset.ui-form-reset\" );\n\t\t}\n\t}\n};\n\n\n/*!\n * jQuery UI Support for jQuery core 1.7.x 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n *\n */\n\n//>>label: jQuery 1.7 Support\n//>>group: Core\n//>>description: Support version 1.7.x of jQuery core\n\n\n\n// Support: jQuery 1.7 only\n// Not a great way to check versions, but since we only support 1.7+ and only\n// need to detect <1.8, this is a simple check that should suffice. Checking\n// for \"1.7.\" would be a bit safer, but the version string is 1.7, not 1.7.0\n// and we'll never reach 1.70.0 (if we do, we certainly won't be supporting\n// 1.7 anymore). See #11197 for why we're not using feature detection.\nif ( $.fn.jquery.substring( 0, 3 ) === \"1.7\" ) {\n\n\t// Setters for .innerWidth(), .innerHeight(), .outerWidth(), .outerHeight()\n\t// Unlike jQuery Core 1.8+, these only support numeric values to set the\n\t// dimensions in pixels\n\t$.each( [ \"Width\", \"Height\" ], function( i, name ) {\n\t\tvar side = name === \"Width\" ? [ \"Left\", \"Right\" ] : [ \"Top\", \"Bottom\" ],\n\t\t\ttype = name.toLowerCase(),\n\t\t\torig = {\n\t\t\t\tinnerWidth: $.fn.innerWidth,\n\t\t\t\tinnerHeight: $.fn.innerHeight,\n\t\t\t\touterWidth: $.fn.outerWidth,\n\t\t\t\touterHeight: $.fn.outerHeight\n\t\t\t};\n\n\t\tfunction reduce( elem, size, border, margin ) {\n\t\t\t$.each( side, function() {\n\t\t\t\tsize -= parseFloat( $.css( elem, \"padding\" + this ) ) || 0;\n\t\t\t\tif ( border ) {\n\t\t\t\t\tsize -= parseFloat( $.css( elem, \"border\" + this + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( margin ) {\n\t\t\t\t\tsize -= parseFloat( $.css( elem, \"margin\" + this ) ) || 0;\n\t\t\t\t}\n\t\t\t} );\n\t\t\treturn size;\n\t\t}\n\n\t\t$.fn[ \"inner\" + name ] = function( size ) {\n\t\t\tif ( size === undefined ) {\n\t\t\t\treturn orig[ \"inner\" + name ].call( this );\n\t\t\t}\n\n\t\t\treturn this.each( function() {\n\t\t\t\t$( this ).css( type, reduce( this, size ) + \"px\" );\n\t\t\t} );\n\t\t};\n\n\t\t$.fn[ \"outer\" + name ] = function( size, margin ) {\n\t\t\tif ( typeof size !== \"number\" ) {\n\t\t\t\treturn orig[ \"outer\" + name ].call( this, size );\n\t\t\t}\n\n\t\t\treturn this.each( function() {\n\t\t\t\t$( this ).css( type, reduce( this, size, true, margin ) + \"px\" );\n\t\t\t} );\n\t\t};\n\t} );\n\n\t$.fn.addBack = function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter( selector )\n\t\t);\n\t};\n}\n\n;\n/*!\n * jQuery UI Keycode 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Keycode\n//>>group: Core\n//>>description: Provide keycodes as keynames\n//>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/\n\n\nvar keycode = $.ui.keyCode = {\n\tBACKSPACE: 8,\n\tCOMMA: 188,\n\tDELETE: 46,\n\tDOWN: 40,\n\tEND: 35,\n\tENTER: 13,\n\tESCAPE: 27,\n\tHOME: 36,\n\tLEFT: 37,\n\tPAGE_DOWN: 34,\n\tPAGE_UP: 33,\n\tPERIOD: 190,\n\tRIGHT: 39,\n\tSPACE: 32,\n\tTAB: 9,\n\tUP: 38\n};\n\n\n\n\n// Internal use only\nvar escapeSelector = $.ui.escapeSelector = ( function() {\n\tvar selectorEscape = /([!\"#$%&'()*+,./:;<=>?@[\\]^`{|}~])/g;\n\treturn function( selector ) {\n\t\treturn selector.replace( selectorEscape, \"\\\\$1\" );\n\t};\n} )();\n\n\n/*!\n * jQuery UI Labels 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: labels\n//>>group: Core\n//>>description: Find all the labels associated with a given input\n//>>docs: http://api.jqueryui.com/labels/\n\n\n\nvar labels = $.fn.labels = function() {\n\tvar ancestor, selector, id, labels, ancestors;\n\n\t// Check control.labels first\n\tif ( this[ 0 ].labels && this[ 0 ].labels.length ) {\n\t\treturn this.pushStack( this[ 0 ].labels );\n\t}\n\n\t// Support: IE <= 11, FF <= 37, Android <= 2.3 only\n\t// Above browsers do not support control.labels. Everything below is to support them\n\t// as well as document fragments. control.labels does not work on document fragments\n\tlabels = this.eq( 0 ).parents( \"label\" );\n\n\t// Look for the label based on the id\n\tid = this.attr( \"id\" );\n\tif ( id ) {\n\n\t\t// We don't search against the document in case the element\n\t\t// is disconnected from the DOM\n\t\tancestor = this.eq( 0 ).parents().last();\n\n\t\t// Get a full set of top level ancestors\n\t\tancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );\n\n\t\t// Create a selector for the label based on the id\n\t\tselector = \"label[for='\" + $.ui.escapeSelector( id ) + \"']\";\n\n\t\tlabels = labels.add( ancestors.find( selector ).addBack( selector ) );\n\n\t}\n\n\t// Return whatever we have found for labels\n\treturn this.pushStack( labels );\n};\n\n\n/*!\n * jQuery UI Scroll Parent 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: scrollParent\n//>>group: Core\n//>>description: Get the closest ancestor element that is scrollable.\n//>>docs: http://api.jqueryui.com/scrollParent/\n\n\n\nvar scrollParent = $.fn.scrollParent = function( includeHidden ) {\n\tvar position = this.css( \"position\" ),\n\t\texcludeStaticParent = position === \"absolute\",\n\t\toverflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,\n\t\tscrollParent = this.parents().filter( function() {\n\t\t\tvar parent = $( this );\n\t\t\tif ( excludeStaticParent && parent.css( \"position\" ) === \"static\" ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn overflowRegex.test( parent.css( \"overflow\" ) + parent.css( \"overflow-y\" ) +\n\t\t\t\tparent.css( \"overflow-x\" ) );\n\t\t} ).eq( 0 );\n\n\treturn position === \"fixed\" || !scrollParent.length ?\n\t\t$( this[ 0 ].ownerDocument || document ) :\n\t\tscrollParent;\n};\n\n\n/*!\n * jQuery UI Tabbable 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: :tabbable Selector\n//>>group: Core\n//>>description: Selects elements which can be tabbed to.\n//>>docs: http://api.jqueryui.com/tabbable-selector/\n\n\n\nvar tabbable = $.extend( $.expr[ \":\" ], {\n\ttabbable: function( element ) {\n\t\tvar tabIndex = $.attr( element, \"tabindex\" ),\n\t\t\thasTabindex = tabIndex != null;\n\t\treturn ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex );\n\t}\n} );\n\n\n/*!\n * jQuery UI Unique ID 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: uniqueId\n//>>group: Core\n//>>description: Functions to generate and remove uniqueId's\n//>>docs: http://api.jqueryui.com/uniqueId/\n\n\n\nvar uniqueId = $.fn.extend( {\n\tuniqueId: ( function() {\n\t\tvar uuid = 0;\n\n\t\treturn function() {\n\t\t\treturn this.each( function() {\n\t\t\t\tif ( !this.id ) {\n\t\t\t\t\tthis.id = \"ui-id-\" + ( ++uuid );\n\t\t\t\t}\n\t\t\t} );\n\t\t};\n\t} )(),\n\n\tremoveUniqueId: function() {\n\t\treturn this.each( function() {\n\t\t\tif ( /^ui-id-\\d+$/.test( this.id ) ) {\n\t\t\t\t$( this ).removeAttr( \"id\" );\n\t\t\t}\n\t\t} );\n\t}\n} );\n\n\n/*!\n * jQuery UI Accordion 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Accordion\n//>>group: Widgets\n// jscs:disable maximumLineLength\n//>>description: Displays collapsible content panels for presenting information in a limited amount of space.\n// jscs:enable maximumLineLength\n//>>docs: http://api.jqueryui.com/accordion/\n//>>demos: http://jqueryui.com/accordion/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/accordion.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\nvar widgetsAccordion = $.widget( \"ui.accordion\", {\n\tversion: \"1.12.1\",\n\toptions: {\n\t\tactive: 0,\n\t\tanimate: {},\n\t\tclasses: {\n\t\t\t\"ui-accordion-header\": \"ui-corner-top\",\n\t\t\t\"ui-accordion-header-collapsed\": \"ui-corner-all\",\n\t\t\t\"ui-accordion-content\": \"ui-corner-bottom\"\n\t\t},\n\t\tcollapsible: false,\n\t\tevent: \"click\",\n\t\theader: \"> li > :first-child, > :not(li):even\",\n\t\theightStyle: \"auto\",\n\t\ticons: {\n\t\t\tactiveHeader: \"ui-icon-triangle-1-s\",\n\t\t\theader: \"ui-icon-triangle-1-e\"\n\t\t},\n\n\t\t// Callbacks\n\t\tactivate: null,\n\t\tbeforeActivate: null\n\t},\n\n\thideProps: {\n\t\tborderTopWidth: \"hide\",\n\t\tborderBottomWidth: \"hide\",\n\t\tpaddingTop: \"hide\",\n\t\tpaddingBottom: \"hide\",\n\t\theight: \"hide\"\n\t},\n\n\tshowProps: {\n\t\tborderTopWidth: \"show\",\n\t\tborderBottomWidth: \"show\",\n\t\tpaddingTop: \"show\",\n\t\tpaddingBottom: \"show\",\n\t\theight: \"show\"\n\t},\n\n\t_create: function() {\n\t\tvar options = this.options;\n\n\t\tthis.prevShow = this.prevHide = $();\n\t\tthis._addClass( \"ui-accordion\", \"ui-widget ui-helper-reset\" );\n\t\tthis.element.attr( \"role\", \"tablist\" );\n\n\t\t// Don't allow collapsible: false and active: false / null\n\t\tif ( !options.collapsible && ( options.active === false || options.active == null ) ) {\n\t\t\toptions.active = 0;\n\t\t}\n\n\t\tthis._processPanels();\n\n\t\t// handle negative values\n\t\tif ( options.active < 0 ) {\n\t\t\toptions.active += this.headers.length;\n\t\t}\n\t\tthis._refresh();\n\t},\n\n\t_getCreateEventData: function() {\n\t\treturn {\n\t\t\theader: this.active,\n\t\t\tpanel: !this.active.length ? $() : this.active.next()\n\t\t};\n\t},\n\n\t_createIcons: function() {\n\t\tvar icon, children,\n\t\t\ticons = this.options.icons;\n\n\t\tif ( icons ) {\n\t\t\ticon = $( \"<span>\" );\n\t\t\tthis._addClass( icon, \"ui-accordion-header-icon\", \"ui-icon \" + icons.header );\n\t\t\ticon.prependTo( this.headers );\n\t\t\tchildren = this.active.children( \".ui-accordion-header-icon\" );\n\t\t\tthis._removeClass( children, icons.header )\n\t\t\t\t._addClass( children, null, icons.activeHeader )\n\t\t\t\t._addClass( this.headers, \"ui-accordion-icons\" );\n\t\t}\n\t},\n\n\t_destroyIcons: function() {\n\t\tthis._removeClass( this.headers, \"ui-accordion-icons\" );\n\t\tthis.headers.children( \".ui-accordion-header-icon\" ).remove();\n\t},\n\n\t_destroy: function() {\n\t\tvar contents;\n\n\t\t// Clean up main element\n\t\tthis.element.removeAttr( \"role\" );\n\n\t\t// Clean up headers\n\t\tthis.headers\n\t\t\t.removeAttr( \"role aria-expanded aria-selected aria-controls tabIndex\" )\n\t\t\t.removeUniqueId();\n\n\t\tthis._destroyIcons();\n\n\t\t// Clean up content panels\n\t\tcontents = this.headers.next()\n\t\t\t.css( \"display\", \"\" )\n\t\t\t.removeAttr( \"role aria-hidden aria-labelledby\" )\n\t\t\t.removeUniqueId();\n\n\t\tif ( this.options.heightStyle !== \"content\" ) {\n\t\t\tcontents.css( \"height\", \"\" );\n\t\t}\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"active\" ) {\n\n\t\t\t// _activate() will handle invalid values and update this.options\n\t\t\tthis._activate( value );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( key === \"event\" ) {\n\t\t\tif ( this.options.event ) {\n\t\t\t\tthis._off( this.headers, this.options.event );\n\t\t\t}\n\t\t\tthis._setupEvents( value );\n\t\t}\n\n\t\tthis._super( key, value );\n\n\t\t// Setting collapsible: false while collapsed; open first panel\n\t\tif ( key === \"collapsible\" && !value && this.options.active === false ) {\n\t\t\tthis._activate( 0 );\n\t\t}\n\n\t\tif ( key === \"icons\" ) {\n\t\t\tthis._destroyIcons();\n\t\t\tif ( value ) {\n\t\t\t\tthis._createIcons();\n\t\t\t}\n\t\t}\n\t},\n\n\t_setOptionDisabled: function( value ) {\n\t\tthis._super( value );\n\n\t\tthis.element.attr( \"aria-disabled\", value );\n\n\t\t// Support: IE8 Only\n\t\t// #5332 / #6059 - opacity doesn't cascade to positioned elements in IE\n\t\t// so we need to add the disabled class to the headers and panels\n\t\tthis._toggleClass( null, \"ui-state-disabled\", !!value );\n\t\tthis._toggleClass( this.headers.add( this.headers.next() ), null, \"ui-state-disabled\",\n\t\t\t!!value );\n\t},\n\n\t_keydown: function( event ) {\n\t\tif ( event.altKey || event.ctrlKey ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar keyCode = $.ui.keyCode,\n\t\t\tlength = this.headers.length,\n\t\t\tcurrentIndex = this.headers.index( event.target ),\n\t\t\ttoFocus = false;\n\n\t\tswitch ( event.keyCode ) {\n\t\tcase keyCode.RIGHT:\n\t\tcase keyCode.DOWN:\n\t\t\ttoFocus = this.headers[ ( currentIndex + 1 ) % length ];\n\t\t\tbreak;\n\t\tcase keyCode.LEFT:\n\t\tcase keyCode.UP:\n\t\t\ttoFocus = this.headers[ ( currentIndex - 1 + length ) % length ];\n\t\t\tbreak;\n\t\tcase keyCode.SPACE:\n\t\tcase keyCode.ENTER:\n\t\t\tthis._eventHandler( event );\n\t\t\tbreak;\n\t\tcase keyCode.HOME:\n\t\t\ttoFocus = this.headers[ 0 ];\n\t\t\tbreak;\n\t\tcase keyCode.END:\n\t\t\ttoFocus = this.headers[ length - 1 ];\n\t\t\tbreak;\n\t\t}\n\n\t\tif ( toFocus ) {\n\t\t\t$( event.target ).attr( \"tabIndex\", -1 );\n\t\t\t$( toFocus ).attr( \"tabIndex\", 0 );\n\t\t\t$( toFocus ).trigger( \"focus\" );\n\t\t\tevent.preventDefault();\n\t\t}\n\t},\n\n\t_panelKeyDown: function( event ) {\n\t\tif ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {\n\t\t\t$( event.currentTarget ).prev().trigger( \"focus\" );\n\t\t}\n\t},\n\n\trefresh: function() {\n\t\tvar options = this.options;\n\t\tthis._processPanels();\n\n\t\t// Was collapsed or no panel\n\t\tif ( ( options.active === false && options.collapsible === true ) ||\n\t\t\t\t!this.headers.length ) {\n\t\t\toptions.active = false;\n\t\t\tthis.active = $();\n\n\t\t// active false only when collapsible is true\n\t\t} else if ( options.active === false ) {\n\t\t\tthis._activate( 0 );\n\n\t\t// was active, but active panel is gone\n\t\t} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {\n\n\t\t\t// all remaining panel are disabled\n\t\t\tif ( this.headers.length === this.headers.find( \".ui-state-disabled\" ).length ) {\n\t\t\t\toptions.active = false;\n\t\t\t\tthis.active = $();\n\n\t\t\t// activate previous panel\n\t\t\t} else {\n\t\t\t\tthis._activate( Math.max( 0, options.active - 1 ) );\n\t\t\t}\n\n\t\t// was active, active panel still exists\n\t\t} else {\n\n\t\t\t// make sure active index is correct\n\t\t\toptions.active = this.headers.index( this.active );\n\t\t}\n\n\t\tthis._destroyIcons();\n\n\t\tthis._refresh();\n\t},\n\n\t_processPanels: function() {\n\t\tvar prevHeaders = this.headers,\n\t\t\tprevPanels = this.panels;\n\n\t\tthis.headers = this.element.find( this.options.header );\n\t\tthis._addClass( this.headers, \"ui-accordion-header ui-accordion-header-collapsed\",\n\t\t\t\"ui-state-default\" );\n\n\t\tthis.panels = this.headers.next().filter( \":not(.ui-accordion-content-active)\" ).hide();\n\t\tthis._addClass( this.panels, \"ui-accordion-content\", \"ui-helper-reset ui-widget-content\" );\n\n\t\t// Avoid memory leaks (#10056)\n\t\tif ( prevPanels ) {\n\t\t\tthis._off( prevHeaders.not( this.headers ) );\n\t\t\tthis._off( prevPanels.not( this.panels ) );\n\t\t}\n\t},\n\n\t_refresh: function() {\n\t\tvar maxHeight,\n\t\t\toptions = this.options,\n\t\t\theightStyle = options.heightStyle,\n\t\t\tparent = this.element.parent();\n\n\t\tthis.active = this._findActive( options.active );\n\t\tthis._addClass( this.active, \"ui-accordion-header-active\", \"ui-state-active\" )\n\t\t\t._removeClass( this.active, \"ui-accordion-header-collapsed\" );\n\t\tthis._addClass( this.active.next(), \"ui-accordion-content-active\" );\n\t\tthis.active.next().show();\n\n\t\tthis.headers\n\t\t\t.attr( \"role\", \"tab\" )\n\t\t\t.each( function() {\n\t\t\t\tvar header = $( this ),\n\t\t\t\t\theaderId = header.uniqueId().attr( \"id\" ),\n\t\t\t\t\tpanel = header.next(),\n\t\t\t\t\tpanelId = panel.uniqueId().attr( \"id\" );\n\t\t\t\theader.attr( \"aria-controls\", panelId );\n\t\t\t\tpanel.attr( \"aria-labelledby\", headerId );\n\t\t\t} )\n\t\t\t.next()\n\t\t\t\t.attr( \"role\", \"tabpanel\" );\n\n\t\tthis.headers\n\t\t\t.not( this.active )\n\t\t\t\t.attr( {\n\t\t\t\t\t\"aria-selected\": \"false\",\n\t\t\t\t\t\"aria-expanded\": \"false\",\n\t\t\t\t\ttabIndex: -1\n\t\t\t\t} )\n\t\t\t\t.next()\n\t\t\t\t\t.attr( {\n\t\t\t\t\t\t\"aria-hidden\": \"true\"\n\t\t\t\t\t} )\n\t\t\t\t\t.hide();\n\n\t\t// Make sure at least one header is in the tab order\n\t\tif ( !this.active.length ) {\n\t\t\tthis.headers.eq( 0 ).attr( \"tabIndex\", 0 );\n\t\t} else {\n\t\t\tthis.active.attr( {\n\t\t\t\t\"aria-selected\": \"true\",\n\t\t\t\t\"aria-expanded\": \"true\",\n\t\t\t\ttabIndex: 0\n\t\t\t} )\n\t\t\t\t.next()\n\t\t\t\t\t.attr( {\n\t\t\t\t\t\t\"aria-hidden\": \"false\"\n\t\t\t\t\t} );\n\t\t}\n\n\t\tthis._createIcons();\n\n\t\tthis._setupEvents( options.event );\n\n\t\tif ( heightStyle === \"fill\" ) {\n\t\t\tmaxHeight = parent.height();\n\t\t\tthis.element.siblings( \":visible\" ).each( function() {\n\t\t\t\tvar elem = $( this ),\n\t\t\t\t\tposition = elem.css( \"position\" );\n\n\t\t\t\tif ( position === \"absolute\" || position === \"fixed\" ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tmaxHeight -= elem.outerHeight( true );\n\t\t\t} );\n\n\t\t\tthis.headers.each( function() {\n\t\t\t\tmaxHeight -= $( this ).outerHeight( true );\n\t\t\t} );\n\n\t\t\tthis.headers.next()\n\t\t\t\t.each( function() {\n\t\t\t\t\t$( this ).height( Math.max( 0, maxHeight -\n\t\t\t\t\t\t$( this ).innerHeight() + $( this ).height() ) );\n\t\t\t\t} )\n\t\t\t\t.css( \"overflow\", \"auto\" );\n\t\t} else if ( heightStyle === \"auto\" ) {\n\t\t\tmaxHeight = 0;\n\t\t\tthis.headers.next()\n\t\t\t\t.each( function() {\n\t\t\t\t\tvar isVisible = $( this ).is( \":visible\" );\n\t\t\t\t\tif ( !isVisible ) {\n\t\t\t\t\t\t$( this ).show();\n\t\t\t\t\t}\n\t\t\t\t\tmaxHeight = Math.max( maxHeight, $( this ).css( \"height\", \"\" ).height() );\n\t\t\t\t\tif ( !isVisible ) {\n\t\t\t\t\t\t$( this ).hide();\n\t\t\t\t\t}\n\t\t\t\t} )\n\t\t\t\t.height( maxHeight );\n\t\t}\n\t},\n\n\t_activate: function( index ) {\n\t\tvar active = this._findActive( index )[ 0 ];\n\n\t\t// Trying to activate the already active panel\n\t\tif ( active === this.active[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Trying to collapse, simulate a click on the currently active header\n\t\tactive = active || this.active[ 0 ];\n\n\t\tthis._eventHandler( {\n\t\t\ttarget: active,\n\t\t\tcurrentTarget: active,\n\t\t\tpreventDefault: $.noop\n\t\t} );\n\t},\n\n\t_findActive: function( selector ) {\n\t\treturn typeof selector === \"number\" ? this.headers.eq( selector ) : $();\n\t},\n\n\t_setupEvents: function( event ) {\n\t\tvar events = {\n\t\t\tkeydown: \"_keydown\"\n\t\t};\n\t\tif ( event ) {\n\t\t\t$.each( event.split( \" \" ), function( index, eventName ) {\n\t\t\t\tevents[ eventName ] = \"_eventHandler\";\n\t\t\t} );\n\t\t}\n\n\t\tthis._off( this.headers.add( this.headers.next() ) );\n\t\tthis._on( this.headers, events );\n\t\tthis._on( this.headers.next(), { keydown: \"_panelKeyDown\" } );\n\t\tthis._hoverable( this.headers );\n\t\tthis._focusable( this.headers );\n\t},\n\n\t_eventHandler: function( event ) {\n\t\tvar activeChildren, clickedChildren,\n\t\t\toptions = this.options,\n\t\t\tactive = this.active,\n\t\t\tclicked = $( event.currentTarget ),\n\t\t\tclickedIsActive = clicked[ 0 ] === active[ 0 ],\n\t\t\tcollapsing = clickedIsActive && options.collapsible,\n\t\t\ttoShow = collapsing ? $() : clicked.next(),\n\t\t\ttoHide = active.next(),\n\t\t\teventData = {\n\t\t\t\toldHeader: active,\n\t\t\t\toldPanel: toHide,\n\t\t\t\tnewHeader: collapsing ? $() : clicked,\n\t\t\t\tnewPanel: toShow\n\t\t\t};\n\n\t\tevent.preventDefault();\n\n\t\tif (\n\n\t\t\t\t// click on active header, but not collapsible\n\t\t\t\t( clickedIsActive && !options.collapsible ) ||\n\n\t\t\t\t// allow canceling activation\n\t\t\t\t( this._trigger( \"beforeActivate\", event, eventData ) === false ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\toptions.active = collapsing ? false : this.headers.index( clicked );\n\n\t\t// When the call to ._toggle() comes after the class changes\n\t\t// it causes a very odd bug in IE 8 (see #6720)\n\t\tthis.active = clickedIsActive ? $() : clicked;\n\t\tthis._toggle( eventData );\n\n\t\t// Switch classes\n\t\t// corner classes on the previously active header stay after the animation\n\t\tthis._removeClass( active, \"ui-accordion-header-active\", \"ui-state-active\" );\n\t\tif ( options.icons ) {\n\t\t\tactiveChildren = active.children( \".ui-accordion-header-icon\" );\n\t\t\tthis._removeClass( activeChildren, null, options.icons.activeHeader )\n\t\t\t\t._addClass( activeChildren, null, options.icons.header );\n\t\t}\n\n\t\tif ( !clickedIsActive ) {\n\t\t\tthis._removeClass( clicked, \"ui-accordion-header-collapsed\" )\n\t\t\t\t._addClass( clicked, \"ui-accordion-header-active\", \"ui-state-active\" );\n\t\t\tif ( options.icons ) {\n\t\t\t\tclickedChildren = clicked.children( \".ui-accordion-header-icon\" );\n\t\t\t\tthis._removeClass( clickedChildren, null, options.icons.header )\n\t\t\t\t\t._addClass( clickedChildren, null, options.icons.activeHeader );\n\t\t\t}\n\n\t\t\tthis._addClass( clicked.next(), \"ui-accordion-content-active\" );\n\t\t}\n\t},\n\n\t_toggle: function( data ) {\n\t\tvar toShow = data.newPanel,\n\t\t\ttoHide = this.prevShow.length ? this.prevShow : data.oldPanel;\n\n\t\t// Handle activating a panel during the animation for another activation\n\t\tthis.prevShow.add( this.prevHide ).stop( true, true );\n\t\tthis.prevShow = toShow;\n\t\tthis.prevHide = toHide;\n\n\t\tif ( this.options.animate ) {\n\t\t\tthis._animate( toShow, toHide, data );\n\t\t} else {\n\t\t\ttoHide.hide();\n\t\t\ttoShow.show();\n\t\t\tthis._toggleComplete( data );\n\t\t}\n\n\t\ttoHide.attr( {\n\t\t\t\"aria-hidden\": \"true\"\n\t\t} );\n\t\ttoHide.prev().attr( {\n\t\t\t\"aria-selected\": \"false\",\n\t\t\t\"aria-expanded\": \"false\"\n\t\t} );\n\n\t\t// if we're switching panels, remove the old header from the tab order\n\t\t// if we're opening from collapsed state, remove the previous header from the tab order\n\t\t// if we're collapsing, then keep the collapsing header in the tab order\n\t\tif ( toShow.length && toHide.length ) {\n\t\t\ttoHide.prev().attr( {\n\t\t\t\t\"tabIndex\": -1,\n\t\t\t\t\"aria-expanded\": \"false\"\n\t\t\t} );\n\t\t} else if ( toShow.length ) {\n\t\t\tthis.headers.filter( function() {\n\t\t\t\treturn parseInt( $( this ).attr( \"tabIndex\" ), 10 ) === 0;\n\t\t\t} )\n\t\t\t\t.attr( \"tabIndex\", -1 );\n\t\t}\n\n\t\ttoShow\n\t\t\t.attr( \"aria-hidden\", \"false\" )\n\t\t\t.prev()\n\t\t\t\t.attr( {\n\t\t\t\t\t\"aria-selected\": \"true\",\n\t\t\t\t\t\"aria-expanded\": \"true\",\n\t\t\t\t\ttabIndex: 0\n\t\t\t\t} );\n\t},\n\n\t_animate: function( toShow, toHide, data ) {\n\t\tvar total, easing, duration,\n\t\t\tthat = this,\n\t\t\tadjust = 0,\n\t\t\tboxSizing = toShow.css( \"box-sizing\" ),\n\t\t\tdown = toShow.length &&\n\t\t\t\t( !toHide.length || ( toShow.index() < toHide.index() ) ),\n\t\t\tanimate = this.options.animate || {},\n\t\t\toptions = down && animate.down || animate,\n\t\t\tcomplete = function() {\n\t\t\t\tthat._toggleComplete( data );\n\t\t\t};\n\n\t\tif ( typeof options === \"number\" ) {\n\t\t\tduration = options;\n\t\t}\n\t\tif ( typeof options === \"string\" ) {\n\t\t\teasing = options;\n\t\t}\n\n\t\t// fall back from options to animation in case of partial down settings\n\t\teasing = easing || options.easing || animate.easing;\n\t\tduration = duration || options.duration || animate.duration;\n\n\t\tif ( !toHide.length ) {\n\t\t\treturn toShow.animate( this.showProps, duration, easing, complete );\n\t\t}\n\t\tif ( !toShow.length ) {\n\t\t\treturn toHide.animate( this.hideProps, duration, easing, complete );\n\t\t}\n\n\t\ttotal = toShow.show().outerHeight();\n\t\ttoHide.animate( this.hideProps, {\n\t\t\tduration: duration,\n\t\t\teasing: easing,\n\t\t\tstep: function( now, fx ) {\n\t\t\t\tfx.now = Math.round( now );\n\t\t\t}\n\t\t} );\n\t\ttoShow\n\t\t\t.hide()\n\t\t\t.animate( this.showProps, {\n\t\t\t\tduration: duration,\n\t\t\t\teasing: easing,\n\t\t\t\tcomplete: complete,\n\t\t\t\tstep: function( now, fx ) {\n\t\t\t\t\tfx.now = Math.round( now );\n\t\t\t\t\tif ( fx.prop !== \"height\" ) {\n\t\t\t\t\t\tif ( boxSizing === \"content-box\" ) {\n\t\t\t\t\t\t\tadjust += fx.now;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( that.options.heightStyle !== \"content\" ) {\n\t\t\t\t\t\tfx.now = Math.round( total - toHide.outerHeight() - adjust );\n\t\t\t\t\t\tadjust = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t},\n\n\t_toggleComplete: function( data ) {\n\t\tvar toHide = data.oldPanel,\n\t\t\tprev = toHide.prev();\n\n\t\tthis._removeClass( toHide, \"ui-accordion-content-active\" );\n\t\tthis._removeClass( prev, \"ui-accordion-header-active\" )\n\t\t\t._addClass( prev, \"ui-accordion-header-collapsed\" );\n\n\t\t// Work around for rendering bug in IE (#5421)\n\t\tif ( toHide.length ) {\n\t\t\ttoHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className;\n\t\t}\n\t\tthis._trigger( \"activate\", null, data );\n\t}\n} );\n\n\n\nvar safeActiveElement = $.ui.safeActiveElement = function( document ) {\n\tvar activeElement;\n\n\t// Support: IE 9 only\n\t// IE9 throws an \"Unspecified error\" accessing document.activeElement from an <iframe>\n\ttry {\n\t\tactiveElement = document.activeElement;\n\t} catch ( error ) {\n\t\tactiveElement = document.body;\n\t}\n\n\t// Support: IE 9 - 11 only\n\t// IE may return null instead of an element\n\t// Interestingly, this only seems to occur when NOT in an iframe\n\tif ( !activeElement ) {\n\t\tactiveElement = document.body;\n\t}\n\n\t// Support: IE 11 only\n\t// IE11 returns a seemingly empty object in some cases when accessing\n\t// document.activeElement from an <iframe>\n\tif ( !activeElement.nodeName ) {\n\t\tactiveElement = document.body;\n\t}\n\n\treturn activeElement;\n};\n\n\n/*!\n * jQuery UI Menu 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Menu\n//>>group: Widgets\n//>>description: Creates nestable menus.\n//>>docs: http://api.jqueryui.com/menu/\n//>>demos: http://jqueryui.com/menu/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/menu.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\nvar widgetsMenu = $.widget( \"ui.menu\", {\n\tversion: \"1.12.1\",\n\tdefaultElement: \"<ul>\",\n\tdelay: 300,\n\toptions: {\n\t\ticons: {\n\t\t\tsubmenu: \"ui-icon-caret-1-e\"\n\t\t},\n\t\titems: \"> *\",\n\t\tmenus: \"ul\",\n\t\tposition: {\n\t\t\tmy: \"left top\",\n\t\t\tat: \"right top\"\n\t\t},\n\t\trole: \"menu\",\n\n\t\t// Callbacks\n\t\tblur: null,\n\t\tfocus: null,\n\t\tselect: null\n\t},\n\n\t_create: function() {\n\t\tthis.activeMenu = this.element;\n\n\t\t// Flag used to prevent firing of the click handler\n\t\t// as the event bubbles up through nested menus\n\t\tthis.mouseHandled = false;\n\t\tthis.element\n\t\t\t.uniqueId()\n\t\t\t.attr( {\n\t\t\t\trole: this.options.role,\n\t\t\t\ttabIndex: 0\n\t\t\t} );\n\n\t\tthis._addClass( \"ui-menu\", \"ui-widget ui-widget-content\" );\n\t\tthis._on( {\n\n\t\t\t// Prevent focus from sticking to links inside menu after clicking\n\t\t\t// them (focus should always stay on UL during navigation).\n\t\t\t\"mousedown .ui-menu-item\": function( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t},\n\t\t\t\"click .ui-menu-item\": function( event ) {\n\t\t\t\tvar target = $( event.target );\n\t\t\t\tvar active = $( $.ui.safeActiveElement( this.document[ 0 ] ) );\n\t\t\t\tif ( !this.mouseHandled && target.not( \".ui-state-disabled\" ).length ) {\n\t\t\t\t\tthis.select( event );\n\n\t\t\t\t\t// Only set the mouseHandled flag if the event will bubble, see #9469.\n\t\t\t\t\tif ( !event.isPropagationStopped() ) {\n\t\t\t\t\t\tthis.mouseHandled = true;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Open submenu on click\n\t\t\t\t\tif ( target.has( \".ui-menu\" ).length ) {\n\t\t\t\t\t\tthis.expand( event );\n\t\t\t\t\t} else if ( !this.element.is( \":focus\" ) &&\n\t\t\t\t\t\t\tactive.closest( \".ui-menu\" ).length ) {\n\n\t\t\t\t\t\t// Redirect focus to the menu\n\t\t\t\t\t\tthis.element.trigger( \"focus\", [ true ] );\n\n\t\t\t\t\t\t// If the active item is on the top level, let it stay active.\n\t\t\t\t\t\t// Otherwise, blur the active item since it is no longer visible.\n\t\t\t\t\t\tif ( this.active && this.active.parents( \".ui-menu\" ).length === 1 ) {\n\t\t\t\t\t\t\tclearTimeout( this.timer );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"mouseenter .ui-menu-item\": function( event ) {\n\n\t\t\t\t// Ignore mouse events while typeahead is active, see #10458.\n\t\t\t\t// Prevents focusing the wrong item when typeahead causes a scroll while the mouse\n\t\t\t\t// is over an item in the menu\n\t\t\t\tif ( this.previousFilter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tvar actualTarget = $( event.target ).closest( \".ui-menu-item\" ),\n\t\t\t\t\ttarget = $( event.currentTarget );\n\n\t\t\t\t// Ignore bubbled events on parent items, see #11641\n\t\t\t\tif ( actualTarget[ 0 ] !== target[ 0 ] ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Remove ui-state-active class from siblings of the newly focused menu item\n\t\t\t\t// to avoid a jump caused by adjacent elements both having a class with a border\n\t\t\t\tthis._removeClass( target.siblings().children( \".ui-state-active\" ),\n\t\t\t\t\tnull, \"ui-state-active\" );\n\t\t\t\tthis.focus( event, target );\n\t\t\t},\n\t\t\tmouseleave: \"collapseAll\",\n\t\t\t\"mouseleave .ui-menu\": \"collapseAll\",\n\t\t\tfocus: function( event, keepActiveItem ) {\n\n\t\t\t\t// If there's already an active item, keep it active\n\t\t\t\t// If not, activate the first item\n\t\t\t\tvar item = this.active || this.element.find( this.options.items ).eq( 0 );\n\n\t\t\t\tif ( !keepActiveItem ) {\n\t\t\t\t\tthis.focus( event, item );\n\t\t\t\t}\n\t\t\t},\n\t\t\tblur: function( event ) {\n\t\t\t\tthis._delay( function() {\n\t\t\t\t\tvar notContained = !$.contains(\n\t\t\t\t\t\tthis.element[ 0 ],\n\t\t\t\t\t\t$.ui.safeActiveElement( this.document[ 0 ] )\n\t\t\t\t\t);\n\t\t\t\t\tif ( notContained ) {\n\t\t\t\t\t\tthis.collapseAll( event );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t},\n\t\t\tkeydown: \"_keydown\"\n\t\t} );\n\n\t\tthis.refresh();\n\n\t\t// Clicks outside of a menu collapse any open menus\n\t\tthis._on( this.document, {\n\t\t\tclick: function( event ) {\n\t\t\t\tif ( this._closeOnDocumentClick( event ) ) {\n\t\t\t\t\tthis.collapseAll( event );\n\t\t\t\t}\n\n\t\t\t\t// Reset the mouseHandled flag\n\t\t\t\tthis.mouseHandled = false;\n\t\t\t}\n\t\t} );\n\t},\n\n\t_destroy: function() {\n\t\tvar items = this.element.find( \".ui-menu-item\" )\n\t\t\t\t.removeAttr( \"role aria-disabled\" ),\n\t\t\tsubmenus = items.children( \".ui-menu-item-wrapper\" )\n\t\t\t\t.removeUniqueId()\n\t\t\t\t.removeAttr( \"tabIndex role aria-haspopup\" );\n\n\t\t// Destroy (sub)menus\n\t\tthis.element\n\t\t\t.removeAttr( \"aria-activedescendant\" )\n\t\t\t.find( \".ui-menu\" ).addBack()\n\t\t\t\t.removeAttr( \"role aria-labelledby aria-expanded aria-hidden aria-disabled \" +\n\t\t\t\t\t\"tabIndex\" )\n\t\t\t\t.removeUniqueId()\n\t\t\t\t.show();\n\n\t\tsubmenus.children().each( function() {\n\t\t\tvar elem = $( this );\n\t\t\tif ( elem.data( \"ui-menu-submenu-caret\" ) ) {\n\t\t\t\telem.remove();\n\t\t\t}\n\t\t} );\n\t},\n\n\t_keydown: function( event ) {\n\t\tvar match, prev, character, skip,\n\t\t\tpreventDefault = true;\n\n\t\tswitch ( event.keyCode ) {\n\t\tcase $.ui.keyCode.PAGE_UP:\n\t\t\tthis.previousPage( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.PAGE_DOWN:\n\t\t\tthis.nextPage( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.HOME:\n\t\t\tthis._move( \"first\", \"first\", event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.END:\n\t\t\tthis._move( \"last\", \"last\", event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.UP:\n\t\t\tthis.previous( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.DOWN:\n\t\t\tthis.next( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.LEFT:\n\t\t\tthis.collapse( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.RIGHT:\n\t\t\tif ( this.active && !this.active.is( \".ui-state-disabled\" ) ) {\n\t\t\t\tthis.expand( event );\n\t\t\t}\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.ENTER:\n\t\tcase $.ui.keyCode.SPACE:\n\t\t\tthis._activate( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.ESCAPE:\n\t\t\tthis.collapse( event );\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tpreventDefault = false;\n\t\t\tprev = this.previousFilter || \"\";\n\t\t\tskip = false;\n\n\t\t\t// Support number pad values\n\t\t\tcharacter = event.keyCode >= 96 && event.keyCode <= 105 ?\n\t\t\t\t( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );\n\n\t\t\tclearTimeout( this.filterTimer );\n\n\t\t\tif ( character === prev ) {\n\t\t\t\tskip = true;\n\t\t\t} else {\n\t\t\t\tcharacter = prev + character;\n\t\t\t}\n\n\t\t\tmatch = this._filterMenuItems( character );\n\t\t\tmatch = skip && match.index( this.active.next() ) !== -1 ?\n\t\t\t\tthis.active.nextAll( \".ui-menu-item\" ) :\n\t\t\t\tmatch;\n\n\t\t\t// If no matches on the current filter, reset to the last character pressed\n\t\t\t// to move down the menu to the first item that starts with that character\n\t\t\tif ( !match.length ) {\n\t\t\t\tcharacter = String.fromCharCode( event.keyCode );\n\t\t\t\tmatch = this._filterMenuItems( character );\n\t\t\t}\n\n\t\t\tif ( match.length ) {\n\t\t\t\tthis.focus( event, match );\n\t\t\t\tthis.previousFilter = character;\n\t\t\t\tthis.filterTimer = this._delay( function() {\n\t\t\t\t\tdelete this.previousFilter;\n\t\t\t\t}, 1000 );\n\t\t\t} else {\n\t\t\t\tdelete this.previousFilter;\n\t\t\t}\n\t\t}\n\n\t\tif ( preventDefault ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t},\n\n\t_activate: function( event ) {\n\t\tif ( this.active && !this.active.is( \".ui-state-disabled\" ) ) {\n\t\t\tif ( this.active.children( \"[aria-haspopup='true']\" ).length ) {\n\t\t\t\tthis.expand( event );\n\t\t\t} else {\n\t\t\t\tthis.select( event );\n\t\t\t}\n\t\t}\n\t},\n\n\trefresh: function() {\n\t\tvar menus, items, newSubmenus, newItems, newWrappers,\n\t\t\tthat = this,\n\t\t\ticon = this.options.icons.submenu,\n\t\t\tsubmenus = this.element.find( this.options.menus );\n\n\t\tthis._toggleClass( \"ui-menu-icons\", null, !!this.element.find( \".ui-icon\" ).length );\n\n\t\t// Initialize nested menus\n\t\tnewSubmenus = submenus.filter( \":not(.ui-menu)\" )\n\t\t\t.hide()\n\t\t\t.attr( {\n\t\t\t\trole: this.options.role,\n\t\t\t\t\"aria-hidden\": \"true\",\n\t\t\t\t\"aria-expanded\": \"false\"\n\t\t\t} )\n\t\t\t.each( function() {\n\t\t\t\tvar menu = $( this ),\n\t\t\t\t\titem = menu.prev(),\n\t\t\t\t\tsubmenuCaret = $( \"<span>\" ).data( \"ui-menu-submenu-caret\", true );\n\n\t\t\t\tthat._addClass( submenuCaret, \"ui-menu-icon\", \"ui-icon \" + icon );\n\t\t\t\titem\n\t\t\t\t\t.attr( \"aria-haspopup\", \"true\" )\n\t\t\t\t\t.prepend( submenuCaret );\n\t\t\t\tmenu.attr( \"aria-labelledby\", item.attr( \"id\" ) );\n\t\t\t} );\n\n\t\tthis._addClass( newSubmenus, \"ui-menu\", \"ui-widget ui-widget-content ui-front\" );\n\n\t\tmenus = submenus.add( this.element );\n\t\titems = menus.find( this.options.items );\n\n\t\t// Initialize menu-items containing spaces and/or dashes only as dividers\n\t\titems.not( \".ui-menu-item\" ).each( function() {\n\t\t\tvar item = $( this );\n\t\t\tif ( that._isDivider( item ) ) {\n\t\t\t\tthat._addClass( item, \"ui-menu-divider\", \"ui-widget-content\" );\n\t\t\t}\n\t\t} );\n\n\t\t// Don't refresh list items that are already adapted\n\t\tnewItems = items.not( \".ui-menu-item, .ui-menu-divider\" );\n\t\tnewWrappers = newItems.children()\n\t\t\t.not( \".ui-menu\" )\n\t\t\t\t.uniqueId()\n\t\t\t\t.attr( {\n\t\t\t\t\ttabIndex: -1,\n\t\t\t\t\trole: this._itemRole()\n\t\t\t\t} );\n\t\tthis._addClass( newItems, \"ui-menu-item\" )\n\t\t\t._addClass( newWrappers, \"ui-menu-item-wrapper\" );\n\n\t\t// Add aria-disabled attribute to any disabled menu item\n\t\titems.filter( \".ui-state-disabled\" ).attr( \"aria-disabled\", \"true\" );\n\n\t\t// If the active item has been removed, blur the menu\n\t\tif ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {\n\t\t\tthis.blur();\n\t\t}\n\t},\n\n\t_itemRole: function() {\n\t\treturn {\n\t\t\tmenu: \"menuitem\",\n\t\t\tlistbox: \"option\"\n\t\t}[ this.options.role ];\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"icons\" ) {\n\t\t\tvar icons = this.element.find( \".ui-menu-icon\" );\n\t\t\tthis._removeClass( icons, null, this.options.icons.submenu )\n\t\t\t\t._addClass( icons, null, value.submenu );\n\t\t}\n\t\tthis._super( key, value );\n\t},\n\n\t_setOptionDisabled: function( value ) {\n\t\tthis._super( value );\n\n\t\tthis.element.attr( \"aria-disabled\", String( value ) );\n\t\tthis._toggleClass( null, \"ui-state-disabled\", !!value );\n\t},\n\n\tfocus: function( event, item ) {\n\t\tvar nested, focused, activeParent;\n\t\tthis.blur( event, event && event.type === \"focus\" );\n\n\t\tthis._scrollIntoView( item );\n\n\t\tthis.active = item.first();\n\n\t\tfocused = this.active.children( \".ui-menu-item-wrapper\" );\n\t\tthis._addClass( focused, null, \"ui-state-active\" );\n\n\t\t// Only update aria-activedescendant if there's a role\n\t\t// otherwise we assume focus is managed elsewhere\n\t\tif ( this.options.role ) {\n\t\t\tthis.element.attr( \"aria-activedescendant\", focused.attr( \"id\" ) );\n\t\t}\n\n\t\t// Highlight active parent menu item, if any\n\t\tactiveParent = this.active\n\t\t\t.parent()\n\t\t\t\t.closest( \".ui-menu-item\" )\n\t\t\t\t\t.children( \".ui-menu-item-wrapper\" );\n\t\tthis._addClass( activeParent, null, \"ui-state-active\" );\n\n\t\tif ( event && event.type === \"keydown\" ) {\n\t\t\tthis._close();\n\t\t} else {\n\t\t\tthis.timer = this._delay( function() {\n\t\t\t\tthis._close();\n\t\t\t}, this.delay );\n\t\t}\n\n\t\tnested = item.children( \".ui-menu\" );\n\t\tif ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {\n\t\t\tthis._startOpening( nested );\n\t\t}\n\t\tthis.activeMenu = item.parent();\n\n\t\tthis._trigger( \"focus\", event, { item: item } );\n\t},\n\n\t_scrollIntoView: function( item ) {\n\t\tvar borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;\n\t\tif ( this._hasScroll() ) {\n\t\t\tborderTop = parseFloat( $.css( this.activeMenu[ 0 ], \"borderTopWidth\" ) ) || 0;\n\t\t\tpaddingTop = parseFloat( $.css( this.activeMenu[ 0 ], \"paddingTop\" ) ) || 0;\n\t\t\toffset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;\n\t\t\tscroll = this.activeMenu.scrollTop();\n\t\t\telementHeight = this.activeMenu.height();\n\t\t\titemHeight = item.outerHeight();\n\n\t\t\tif ( offset < 0 ) {\n\t\t\t\tthis.activeMenu.scrollTop( scroll + offset );\n\t\t\t} else if ( offset + itemHeight > elementHeight ) {\n\t\t\t\tthis.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );\n\t\t\t}\n\t\t}\n\t},\n\n\tblur: function( event, fromFocus ) {\n\t\tif ( !fromFocus ) {\n\t\t\tclearTimeout( this.timer );\n\t\t}\n\n\t\tif ( !this.active ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._removeClass( this.active.children( \".ui-menu-item-wrapper\" ),\n\t\t\tnull, \"ui-state-active\" );\n\n\t\tthis._trigger( \"blur\", event, { item: this.active } );\n\t\tthis.active = null;\n\t},\n\n\t_startOpening: function( submenu ) {\n\t\tclearTimeout( this.timer );\n\n\t\t// Don't open if already open fixes a Firefox bug that caused a .5 pixel\n\t\t// shift in the submenu position when mousing over the caret icon\n\t\tif ( submenu.attr( \"aria-hidden\" ) !== \"true\" ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.timer = this._delay( function() {\n\t\t\tthis._close();\n\t\t\tthis._open( submenu );\n\t\t}, this.delay );\n\t},\n\n\t_open: function( submenu ) {\n\t\tvar position = $.extend( {\n\t\t\tof: this.active\n\t\t}, this.options.position );\n\n\t\tclearTimeout( this.timer );\n\t\tthis.element.find( \".ui-menu\" ).not( submenu.parents( \".ui-menu\" ) )\n\t\t\t.hide()\n\t\t\t.attr( \"aria-hidden\", \"true\" );\n\n\t\tsubmenu\n\t\t\t.show()\n\t\t\t.removeAttr( \"aria-hidden\" )\n\t\t\t.attr( \"aria-expanded\", \"true\" )\n\t\t\t.position( position );\n\t},\n\n\tcollapseAll: function( event, all ) {\n\t\tclearTimeout( this.timer );\n\t\tthis.timer = this._delay( function() {\n\n\t\t\t// If we were passed an event, look for the submenu that contains the event\n\t\t\tvar currentMenu = all ? this.element :\n\t\t\t\t$( event && event.target ).closest( this.element.find( \".ui-menu\" ) );\n\n\t\t\t// If we found no valid submenu ancestor, use the main menu to close all\n\t\t\t// sub menus anyway\n\t\t\tif ( !currentMenu.length ) {\n\t\t\t\tcurrentMenu = this.element;\n\t\t\t}\n\n\t\t\tthis._close( currentMenu );\n\n\t\t\tthis.blur( event );\n\n\t\t\t// Work around active item staying active after menu is blurred\n\t\t\tthis._removeClass( currentMenu.find( \".ui-state-active\" ), null, \"ui-state-active\" );\n\n\t\t\tthis.activeMenu = currentMenu;\n\t\t}, this.delay );\n\t},\n\n\t// With no arguments, closes the currently active menu - if nothing is active\n\t// it closes all menus.  If passed an argument, it will search for menus BELOW\n\t_close: function( startMenu ) {\n\t\tif ( !startMenu ) {\n\t\t\tstartMenu = this.active ? this.active.parent() : this.element;\n\t\t}\n\n\t\tstartMenu.find( \".ui-menu\" )\n\t\t\t.hide()\n\t\t\t.attr( \"aria-hidden\", \"true\" )\n\t\t\t.attr( \"aria-expanded\", \"false\" );\n\t},\n\n\t_closeOnDocumentClick: function( event ) {\n\t\treturn !$( event.target ).closest( \".ui-menu\" ).length;\n\t},\n\n\t_isDivider: function( item ) {\n\n\t\t// Match hyphen, em dash, en dash\n\t\treturn !/[^\\-\\u2014\\u2013\\s]/.test( item.text() );\n\t},\n\n\tcollapse: function( event ) {\n\t\tvar newItem = this.active &&\n\t\t\tthis.active.parent().closest( \".ui-menu-item\", this.element );\n\t\tif ( newItem && newItem.length ) {\n\t\t\tthis._close();\n\t\t\tthis.focus( event, newItem );\n\t\t}\n\t},\n\n\texpand: function( event ) {\n\t\tvar newItem = this.active &&\n\t\t\tthis.active\n\t\t\t\t.children( \".ui-menu \" )\n\t\t\t\t\t.find( this.options.items )\n\t\t\t\t\t\t.first();\n\n\t\tif ( newItem && newItem.length ) {\n\t\t\tthis._open( newItem.parent() );\n\n\t\t\t// Delay so Firefox will not hide activedescendant change in expanding submenu from AT\n\t\t\tthis._delay( function() {\n\t\t\t\tthis.focus( event, newItem );\n\t\t\t} );\n\t\t}\n\t},\n\n\tnext: function( event ) {\n\t\tthis._move( \"next\", \"first\", event );\n\t},\n\n\tprevious: function( event ) {\n\t\tthis._move( \"prev\", \"last\", event );\n\t},\n\n\tisFirstItem: function() {\n\t\treturn this.active && !this.active.prevAll( \".ui-menu-item\" ).length;\n\t},\n\n\tisLastItem: function() {\n\t\treturn this.active && !this.active.nextAll( \".ui-menu-item\" ).length;\n\t},\n\n\t_move: function( direction, filter, event ) {\n\t\tvar next;\n\t\tif ( this.active ) {\n\t\t\tif ( direction === \"first\" || direction === \"last\" ) {\n\t\t\t\tnext = this.active\n\t\t\t\t\t[ direction === \"first\" ? \"prevAll\" : \"nextAll\" ]( \".ui-menu-item\" )\n\t\t\t\t\t.eq( -1 );\n\t\t\t} else {\n\t\t\t\tnext = this.active\n\t\t\t\t\t[ direction + \"All\" ]( \".ui-menu-item\" )\n\t\t\t\t\t.eq( 0 );\n\t\t\t}\n\t\t}\n\t\tif ( !next || !next.length || !this.active ) {\n\t\t\tnext = this.activeMenu.find( this.options.items )[ filter ]();\n\t\t}\n\n\t\tthis.focus( event, next );\n\t},\n\n\tnextPage: function( event ) {\n\t\tvar item, base, height;\n\n\t\tif ( !this.active ) {\n\t\t\tthis.next( event );\n\t\t\treturn;\n\t\t}\n\t\tif ( this.isLastItem() ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( this._hasScroll() ) {\n\t\t\tbase = this.active.offset().top;\n\t\t\theight = this.element.height();\n\t\t\tthis.active.nextAll( \".ui-menu-item\" ).each( function() {\n\t\t\t\titem = $( this );\n\t\t\t\treturn item.offset().top - base - height < 0;\n\t\t\t} );\n\n\t\t\tthis.focus( event, item );\n\t\t} else {\n\t\t\tthis.focus( event, this.activeMenu.find( this.options.items )\n\t\t\t\t[ !this.active ? \"first\" : \"last\" ]() );\n\t\t}\n\t},\n\n\tpreviousPage: function( event ) {\n\t\tvar item, base, height;\n\t\tif ( !this.active ) {\n\t\t\tthis.next( event );\n\t\t\treturn;\n\t\t}\n\t\tif ( this.isFirstItem() ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( this._hasScroll() ) {\n\t\t\tbase = this.active.offset().top;\n\t\t\theight = this.element.height();\n\t\t\tthis.active.prevAll( \".ui-menu-item\" ).each( function() {\n\t\t\t\titem = $( this );\n\t\t\t\treturn item.offset().top - base + height > 0;\n\t\t\t} );\n\n\t\t\tthis.focus( event, item );\n\t\t} else {\n\t\t\tthis.focus( event, this.activeMenu.find( this.options.items ).first() );\n\t\t}\n\t},\n\n\t_hasScroll: function() {\n\t\treturn this.element.outerHeight() < this.element.prop( \"scrollHeight\" );\n\t},\n\n\tselect: function( event ) {\n\n\t\t// TODO: It should never be possible to not have an active item at this\n\t\t// point, but the tests don't trigger mouseenter before click.\n\t\tthis.active = this.active || $( event.target ).closest( \".ui-menu-item\" );\n\t\tvar ui = { item: this.active };\n\t\tif ( !this.active.has( \".ui-menu\" ).length ) {\n\t\t\tthis.collapseAll( event, true );\n\t\t}\n\t\tthis._trigger( \"select\", event, ui );\n\t},\n\n\t_filterMenuItems: function( character ) {\n\t\tvar escapedCharacter = character.replace( /[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g, \"\\\\$&\" ),\n\t\t\tregex = new RegExp( \"^\" + escapedCharacter, \"i\" );\n\n\t\treturn this.activeMenu\n\t\t\t.find( this.options.items )\n\n\t\t\t\t// Only match on items, not dividers or other content (#10571)\n\t\t\t\t.filter( \".ui-menu-item\" )\n\t\t\t\t\t.filter( function() {\n\t\t\t\t\t\treturn regex.test(\n\t\t\t\t\t\t\t$.trim( $( this ).children( \".ui-menu-item-wrapper\" ).text() ) );\n\t\t\t\t\t} );\n\t}\n} );\n\n\n/*!\n * jQuery UI Autocomplete 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Autocomplete\n//>>group: Widgets\n//>>description: Lists suggested words as the user is typing.\n//>>docs: http://api.jqueryui.com/autocomplete/\n//>>demos: http://jqueryui.com/autocomplete/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/autocomplete.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\n$.widget( \"ui.autocomplete\", {\n\tversion: \"1.12.1\",\n\tdefaultElement: \"<input>\",\n\toptions: {\n\t\tappendTo: null,\n\t\tautoFocus: false,\n\t\tdelay: 300,\n\t\tminLength: 1,\n\t\tposition: {\n\t\t\tmy: \"left top\",\n\t\t\tat: \"left bottom\",\n\t\t\tcollision: \"none\"\n\t\t},\n\t\tsource: null,\n\n\t\t// Callbacks\n\t\tchange: null,\n\t\tclose: null,\n\t\tfocus: null,\n\t\topen: null,\n\t\tresponse: null,\n\t\tsearch: null,\n\t\tselect: null\n\t},\n\n\trequestIndex: 0,\n\tpending: 0,\n\n\t_create: function() {\n\n\t\t// Some browsers only repeat keydown events, not keypress events,\n\t\t// so we use the suppressKeyPress flag to determine if we've already\n\t\t// handled the keydown event. #7269\n\t\t// Unfortunately the code for & in keypress is the same as the up arrow,\n\t\t// so we use the suppressKeyPressRepeat flag to avoid handling keypress\n\t\t// events when we know the keydown event was used to modify the\n\t\t// search term. #7799\n\t\tvar suppressKeyPress, suppressKeyPressRepeat, suppressInput,\n\t\t\tnodeName = this.element[ 0 ].nodeName.toLowerCase(),\n\t\t\tisTextarea = nodeName === \"textarea\",\n\t\t\tisInput = nodeName === \"input\";\n\n\t\t// Textareas are always multi-line\n\t\t// Inputs are always single-line, even if inside a contentEditable element\n\t\t// IE also treats inputs as contentEditable\n\t\t// All other element types are determined by whether or not they're contentEditable\n\t\tthis.isMultiLine = isTextarea || !isInput && this._isContentEditable( this.element );\n\n\t\tthis.valueMethod = this.element[ isTextarea || isInput ? \"val\" : \"text\" ];\n\t\tthis.isNewMenu = true;\n\n\t\tthis._addClass( \"ui-autocomplete-input\" );\n\t\tthis.element.attr( \"autocomplete\", \"off\" );\n\n\t\tthis._on( this.element, {\n\t\t\tkeydown: function( event ) {\n\t\t\t\tif ( this.element.prop( \"readOnly\" ) ) {\n\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\tsuppressInput = true;\n\t\t\t\t\tsuppressKeyPressRepeat = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tsuppressKeyPress = false;\n\t\t\t\tsuppressInput = false;\n\t\t\t\tsuppressKeyPressRepeat = false;\n\t\t\t\tvar keyCode = $.ui.keyCode;\n\t\t\t\tswitch ( event.keyCode ) {\n\t\t\t\tcase keyCode.PAGE_UP:\n\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\tthis._move( \"previousPage\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.PAGE_DOWN:\n\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\tthis._move( \"nextPage\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.UP:\n\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\tthis._keyEvent( \"previous\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.DOWN:\n\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\tthis._keyEvent( \"next\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.ENTER:\n\n\t\t\t\t\t// when menu is open and has focus\n\t\t\t\t\tif ( this.menu.active ) {\n\n\t\t\t\t\t\t// #6055 - Opera still allows the keypress to occur\n\t\t\t\t\t\t// which causes forms to submit\n\t\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\tthis.menu.select( event );\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.TAB:\n\t\t\t\t\tif ( this.menu.active ) {\n\t\t\t\t\t\tthis.menu.select( event );\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.ESCAPE:\n\t\t\t\t\tif ( this.menu.element.is( \":visible\" ) ) {\n\t\t\t\t\t\tif ( !this.isMultiLine ) {\n\t\t\t\t\t\t\tthis._value( this.term );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.close( event );\n\n\t\t\t\t\t\t// Different browsers have different default behavior for escape\n\t\t\t\t\t\t// Single press can mean undo or clear\n\t\t\t\t\t\t// Double press in IE means clear the whole form\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tsuppressKeyPressRepeat = true;\n\n\t\t\t\t\t// search timeout should be triggered before the input value is changed\n\t\t\t\t\tthis._searchTimeout( event );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t},\n\t\t\tkeypress: function( event ) {\n\t\t\t\tif ( suppressKeyPress ) {\n\t\t\t\t\tsuppressKeyPress = false;\n\t\t\t\t\tif ( !this.isMultiLine || this.menu.element.is( \":visible\" ) ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif ( suppressKeyPressRepeat ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Replicate some key handlers to allow them to repeat in Firefox and Opera\n\t\t\t\tvar keyCode = $.ui.keyCode;\n\t\t\t\tswitch ( event.keyCode ) {\n\t\t\t\tcase keyCode.PAGE_UP:\n\t\t\t\t\tthis._move( \"previousPage\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.PAGE_DOWN:\n\t\t\t\t\tthis._move( \"nextPage\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.UP:\n\t\t\t\t\tthis._keyEvent( \"previous\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.DOWN:\n\t\t\t\t\tthis._keyEvent( \"next\", event );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t},\n\t\t\tinput: function( event ) {\n\t\t\t\tif ( suppressInput ) {\n\t\t\t\t\tsuppressInput = false;\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis._searchTimeout( event );\n\t\t\t},\n\t\t\tfocus: function() {\n\t\t\t\tthis.selectedItem = null;\n\t\t\t\tthis.previous = this._value();\n\t\t\t},\n\t\t\tblur: function( event ) {\n\t\t\t\tif ( this.cancelBlur ) {\n\t\t\t\t\tdelete this.cancelBlur;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tclearTimeout( this.searching );\n\t\t\t\tthis.close( event );\n\t\t\t\tthis._change( event );\n\t\t\t}\n\t\t} );\n\n\t\tthis._initSource();\n\t\tthis.menu = $( \"<ul>\" )\n\t\t\t.appendTo( this._appendTo() )\n\t\t\t.menu( {\n\n\t\t\t\t// disable ARIA support, the live region takes care of that\n\t\t\t\trole: null\n\t\t\t} )\n\t\t\t.hide()\n\t\t\t.menu( \"instance\" );\n\n\t\tthis._addClass( this.menu.element, \"ui-autocomplete\", \"ui-front\" );\n\t\tthis._on( this.menu.element, {\n\t\t\tmousedown: function( event ) {\n\n\t\t\t\t// prevent moving focus out of the text field\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// IE doesn't prevent moving focus even with event.preventDefault()\n\t\t\t\t// so we set a flag to know when we should ignore the blur event\n\t\t\t\tthis.cancelBlur = true;\n\t\t\t\tthis._delay( function() {\n\t\t\t\t\tdelete this.cancelBlur;\n\n\t\t\t\t\t// Support: IE 8 only\n\t\t\t\t\t// Right clicking a menu item or selecting text from the menu items will\n\t\t\t\t\t// result in focus moving out of the input. However, we've already received\n\t\t\t\t\t// and ignored the blur event because of the cancelBlur flag set above. So\n\t\t\t\t\t// we restore focus to ensure that the menu closes properly based on the user's\n\t\t\t\t\t// next actions.\n\t\t\t\t\tif ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {\n\t\t\t\t\t\tthis.element.trigger( \"focus\" );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t},\n\t\t\tmenufocus: function( event, ui ) {\n\t\t\t\tvar label, item;\n\n\t\t\t\t// support: Firefox\n\t\t\t\t// Prevent accidental activation of menu items in Firefox (#7024 #9118)\n\t\t\t\tif ( this.isNewMenu ) {\n\t\t\t\t\tthis.isNewMenu = false;\n\t\t\t\t\tif ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {\n\t\t\t\t\t\tthis.menu.blur();\n\n\t\t\t\t\t\tthis.document.one( \"mousemove\", function() {\n\t\t\t\t\t\t\t$( event.target ).trigger( event.originalEvent );\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\titem = ui.item.data( \"ui-autocomplete-item\" );\n\t\t\t\tif ( false !== this._trigger( \"focus\", event, { item: item } ) ) {\n\n\t\t\t\t\t// use value to match what will end up in the input, if it was a key event\n\t\t\t\t\tif ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {\n\t\t\t\t\t\tthis._value( item.value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Announce the value in the liveRegion\n\t\t\t\tlabel = ui.item.attr( \"aria-label\" ) || item.value;\n\t\t\t\tif ( label && $.trim( label ).length ) {\n\t\t\t\t\tthis.liveRegion.children().hide();\n\t\t\t\t\t$( \"<div>\" ).text( label ).appendTo( this.liveRegion );\n\t\t\t\t}\n\t\t\t},\n\t\t\tmenuselect: function( event, ui ) {\n\t\t\t\tvar item = ui.item.data( \"ui-autocomplete-item\" ),\n\t\t\t\t\tprevious = this.previous;\n\n\t\t\t\t// Only trigger when focus was lost (click on menu)\n\t\t\t\tif ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {\n\t\t\t\t\tthis.element.trigger( \"focus\" );\n\t\t\t\t\tthis.previous = previous;\n\n\t\t\t\t\t// #6109 - IE triggers two focus events and the second\n\t\t\t\t\t// is asynchronous, so we need to reset the previous\n\t\t\t\t\t// term synchronously and asynchronously :-(\n\t\t\t\t\tthis._delay( function() {\n\t\t\t\t\t\tthis.previous = previous;\n\t\t\t\t\t\tthis.selectedItem = item;\n\t\t\t\t\t} );\n\t\t\t\t}\n\n\t\t\t\tif ( false !== this._trigger( \"select\", event, { item: item } ) ) {\n\t\t\t\t\tthis._value( item.value );\n\t\t\t\t}\n\n\t\t\t\t// reset the term after the select event\n\t\t\t\t// this allows custom select handling to work properly\n\t\t\t\tthis.term = this._value();\n\n\t\t\t\tthis.close( event );\n\t\t\t\tthis.selectedItem = item;\n\t\t\t}\n\t\t} );\n\n\t\tthis.liveRegion = $( \"<div>\", {\n\t\t\trole: \"status\",\n\t\t\t\"aria-live\": \"assertive\",\n\t\t\t\"aria-relevant\": \"additions\"\n\t\t} )\n\t\t\t.appendTo( this.document[ 0 ].body );\n\n\t\tthis._addClass( this.liveRegion, null, \"ui-helper-hidden-accessible\" );\n\n\t\t// Turning off autocomplete prevents the browser from remembering the\n\t\t// value when navigating through history, so we re-enable autocomplete\n\t\t// if the page is unloaded before the widget is destroyed. #7790\n\t\tthis._on( this.window, {\n\t\t\tbeforeunload: function() {\n\t\t\t\tthis.element.removeAttr( \"autocomplete\" );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_destroy: function() {\n\t\tclearTimeout( this.searching );\n\t\tthis.element.removeAttr( \"autocomplete\" );\n\t\tthis.menu.element.remove();\n\t\tthis.liveRegion.remove();\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tthis._super( key, value );\n\t\tif ( key === \"source\" ) {\n\t\t\tthis._initSource();\n\t\t}\n\t\tif ( key === \"appendTo\" ) {\n\t\t\tthis.menu.element.appendTo( this._appendTo() );\n\t\t}\n\t\tif ( key === \"disabled\" && value && this.xhr ) {\n\t\t\tthis.xhr.abort();\n\t\t}\n\t},\n\n\t_isEventTargetInWidget: function( event ) {\n\t\tvar menuElement = this.menu.element[ 0 ];\n\n\t\treturn event.target === this.element[ 0 ] ||\n\t\t\tevent.target === menuElement ||\n\t\t\t$.contains( menuElement, event.target );\n\t},\n\n\t_closeOnClickOutside: function( event ) {\n\t\tif ( !this._isEventTargetInWidget( event ) ) {\n\t\t\tthis.close();\n\t\t}\n\t},\n\n\t_appendTo: function() {\n\t\tvar element = this.options.appendTo;\n\n\t\tif ( element ) {\n\t\t\telement = element.jquery || element.nodeType ?\n\t\t\t\t$( element ) :\n\t\t\t\tthis.document.find( element ).eq( 0 );\n\t\t}\n\n\t\tif ( !element || !element[ 0 ] ) {\n\t\t\telement = this.element.closest( \".ui-front, dialog\" );\n\t\t}\n\n\t\tif ( !element.length ) {\n\t\t\telement = this.document[ 0 ].body;\n\t\t}\n\n\t\treturn element;\n\t},\n\n\t_initSource: function() {\n\t\tvar array, url,\n\t\t\tthat = this;\n\t\tif ( $.isArray( this.options.source ) ) {\n\t\t\tarray = this.options.source;\n\t\t\tthis.source = function( request, response ) {\n\t\t\t\tresponse( $.ui.autocomplete.filter( array, request.term ) );\n\t\t\t};\n\t\t} else if ( typeof this.options.source === \"string\" ) {\n\t\t\turl = this.options.source;\n\t\t\tthis.source = function( request, response ) {\n\t\t\t\tif ( that.xhr ) {\n\t\t\t\t\tthat.xhr.abort();\n\t\t\t\t}\n\t\t\t\tthat.xhr = $.ajax( {\n\t\t\t\t\turl: url,\n\t\t\t\t\tdata: request,\n\t\t\t\t\tdataType: \"json\",\n\t\t\t\t\tsuccess: function( data ) {\n\t\t\t\t\t\tresponse( data );\n\t\t\t\t\t},\n\t\t\t\t\terror: function() {\n\t\t\t\t\t\tresponse( [] );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t};\n\t\t} else {\n\t\t\tthis.source = this.options.source;\n\t\t}\n\t},\n\n\t_searchTimeout: function( event ) {\n\t\tclearTimeout( this.searching );\n\t\tthis.searching = this._delay( function() {\n\n\t\t\t// Search if the value has changed, or if the user retypes the same value (see #7434)\n\t\t\tvar equalValues = this.term === this._value(),\n\t\t\t\tmenuVisible = this.menu.element.is( \":visible\" ),\n\t\t\t\tmodifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;\n\n\t\t\tif ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {\n\t\t\t\tthis.selectedItem = null;\n\t\t\t\tthis.search( null, event );\n\t\t\t}\n\t\t}, this.options.delay );\n\t},\n\n\tsearch: function( value, event ) {\n\t\tvalue = value != null ? value : this._value();\n\n\t\t// Always save the actual value, not the one passed as an argument\n\t\tthis.term = this._value();\n\n\t\tif ( value.length < this.options.minLength ) {\n\t\t\treturn this.close( event );\n\t\t}\n\n\t\tif ( this._trigger( \"search\", event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn this._search( value );\n\t},\n\n\t_search: function( value ) {\n\t\tthis.pending++;\n\t\tthis._addClass( \"ui-autocomplete-loading\" );\n\t\tthis.cancelSearch = false;\n\n\t\tthis.source( { term: value }, this._response() );\n\t},\n\n\t_response: function() {\n\t\tvar index = ++this.requestIndex;\n\n\t\treturn $.proxy( function( content ) {\n\t\t\tif ( index === this.requestIndex ) {\n\t\t\t\tthis.__response( content );\n\t\t\t}\n\n\t\t\tthis.pending--;\n\t\t\tif ( !this.pending ) {\n\t\t\t\tthis._removeClass( \"ui-autocomplete-loading\" );\n\t\t\t}\n\t\t}, this );\n\t},\n\n\t__response: function( content ) {\n\t\tif ( content ) {\n\t\t\tcontent = this._normalize( content );\n\t\t}\n\t\tthis._trigger( \"response\", null, { content: content } );\n\t\tif ( !this.options.disabled && content && content.length && !this.cancelSearch ) {\n\t\t\tthis._suggest( content );\n\t\t\tthis._trigger( \"open\" );\n\t\t} else {\n\n\t\t\t// use ._close() instead of .close() so we don't cancel future searches\n\t\t\tthis._close();\n\t\t}\n\t},\n\n\tclose: function( event ) {\n\t\tthis.cancelSearch = true;\n\t\tthis._close( event );\n\t},\n\n\t_close: function( event ) {\n\n\t\t// Remove the handler that closes the menu on outside clicks\n\t\tthis._off( this.document, \"mousedown\" );\n\n\t\tif ( this.menu.element.is( \":visible\" ) ) {\n\t\t\tthis.menu.element.hide();\n\t\t\tthis.menu.blur();\n\t\t\tthis.isNewMenu = true;\n\t\t\tthis._trigger( \"close\", event );\n\t\t}\n\t},\n\n\t_change: function( event ) {\n\t\tif ( this.previous !== this._value() ) {\n\t\t\tthis._trigger( \"change\", event, { item: this.selectedItem } );\n\t\t}\n\t},\n\n\t_normalize: function( items ) {\n\n\t\t// assume all items have the right format when the first item is complete\n\t\tif ( items.length && items[ 0 ].label && items[ 0 ].value ) {\n\t\t\treturn items;\n\t\t}\n\t\treturn $.map( items, function( item ) {\n\t\t\tif ( typeof item === \"string\" ) {\n\t\t\t\treturn {\n\t\t\t\t\tlabel: item,\n\t\t\t\t\tvalue: item\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn $.extend( {}, item, {\n\t\t\t\tlabel: item.label || item.value,\n\t\t\t\tvalue: item.value || item.label\n\t\t\t} );\n\t\t} );\n\t},\n\n\t_suggest: function( items ) {\n\t\tvar ul = this.menu.element.empty();\n\t\tthis._renderMenu( ul, items );\n\t\tthis.isNewMenu = true;\n\t\tthis.menu.refresh();\n\n\t\t// Size and position menu\n\t\tul.show();\n\t\tthis._resizeMenu();\n\t\tul.position( $.extend( {\n\t\t\tof: this.element\n\t\t}, this.options.position ) );\n\n\t\tif ( this.options.autoFocus ) {\n\t\t\tthis.menu.next();\n\t\t}\n\n\t\t// Listen for interactions outside of the widget (#6642)\n\t\tthis._on( this.document, {\n\t\t\tmousedown: \"_closeOnClickOutside\"\n\t\t} );\n\t},\n\n\t_resizeMenu: function() {\n\t\tvar ul = this.menu.element;\n\t\tul.outerWidth( Math.max(\n\n\t\t\t// Firefox wraps long text (possibly a rounding bug)\n\t\t\t// so we add 1px to avoid the wrapping (#7513)\n\t\t\tul.width( \"\" ).outerWidth() + 1,\n\t\t\tthis.element.outerWidth()\n\t\t) );\n\t},\n\n\t_renderMenu: function( ul, items ) {\n\t\tvar that = this;\n\t\t$.each( items, function( index, item ) {\n\t\t\tthat._renderItemData( ul, item );\n\t\t} );\n\t},\n\n\t_renderItemData: function( ul, item ) {\n\t\treturn this._renderItem( ul, item ).data( \"ui-autocomplete-item\", item );\n\t},\n\n\t_renderItem: function( ul, item ) {\n\t\treturn $( \"<li>\" )\n\t\t\t.append( $( \"<div>\" ).text( item.label ) )\n\t\t\t.appendTo( ul );\n\t},\n\n\t_move: function( direction, event ) {\n\t\tif ( !this.menu.element.is( \":visible\" ) ) {\n\t\t\tthis.search( null, event );\n\t\t\treturn;\n\t\t}\n\t\tif ( this.menu.isFirstItem() && /^previous/.test( direction ) ||\n\t\t\t\tthis.menu.isLastItem() && /^next/.test( direction ) ) {\n\n\t\t\tif ( !this.isMultiLine ) {\n\t\t\t\tthis._value( this.term );\n\t\t\t}\n\n\t\t\tthis.menu.blur();\n\t\t\treturn;\n\t\t}\n\t\tthis.menu[ direction ]( event );\n\t},\n\n\twidget: function() {\n\t\treturn this.menu.element;\n\t},\n\n\t_value: function() {\n\t\treturn this.valueMethod.apply( this.element, arguments );\n\t},\n\n\t_keyEvent: function( keyEvent, event ) {\n\t\tif ( !this.isMultiLine || this.menu.element.is( \":visible\" ) ) {\n\t\t\tthis._move( keyEvent, event );\n\n\t\t\t// Prevents moving cursor to beginning/end of the text field in some browsers\n\t\t\tevent.preventDefault();\n\t\t}\n\t},\n\n\t// Support: Chrome <=50\n\t// We should be able to just use this.element.prop( \"isContentEditable\" )\n\t// but hidden elements always report false in Chrome.\n\t// https://code.google.com/p/chromium/issues/detail?id=313082\n\t_isContentEditable: function( element ) {\n\t\tif ( !element.length ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar editable = element.prop( \"contentEditable\" );\n\n\t\tif ( editable === \"inherit\" ) {\n\t\t  return this._isContentEditable( element.parent() );\n\t\t}\n\n\t\treturn editable === \"true\";\n\t}\n} );\n\n$.extend( $.ui.autocomplete, {\n\tescapeRegex: function( value ) {\n\t\treturn value.replace( /[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g, \"\\\\$&\" );\n\t},\n\tfilter: function( array, term ) {\n\t\tvar matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), \"i\" );\n\t\treturn $.grep( array, function( value ) {\n\t\t\treturn matcher.test( value.label || value.value || value );\n\t\t} );\n\t}\n} );\n\n// Live region extension, adding a `messages` option\n// NOTE: This is an experimental API. We are still investigating\n// a full solution for string manipulation and internationalization.\n$.widget( \"ui.autocomplete\", $.ui.autocomplete, {\n\toptions: {\n\t\tmessages: {\n\t\t\tnoResults: \"No search results.\",\n\t\t\tresults: function( amount ) {\n\t\t\t\treturn amount + ( amount > 1 ? \" results are\" : \" result is\" ) +\n\t\t\t\t\t\" available, use up and down arrow keys to navigate.\";\n\t\t\t}\n\t\t}\n\t},\n\n\t__response: function( content ) {\n\t\tvar message;\n\t\tthis._superApply( arguments );\n\t\tif ( this.options.disabled || this.cancelSearch ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( content && content.length ) {\n\t\t\tmessage = this.options.messages.results( content.length );\n\t\t} else {\n\t\t\tmessage = this.options.messages.noResults;\n\t\t}\n\t\tthis.liveRegion.children().hide();\n\t\t$( \"<div>\" ).text( message ).appendTo( this.liveRegion );\n\t}\n} );\n\nvar widgetsAutocomplete = $.ui.autocomplete;\n\n\n/*!\n * jQuery UI Controlgroup 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Controlgroup\n//>>group: Widgets\n//>>description: Visually groups form control widgets\n//>>docs: http://api.jqueryui.com/controlgroup/\n//>>demos: http://jqueryui.com/controlgroup/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/controlgroup.css\n//>>css.theme: ../../themes/base/theme.css\n\n\nvar controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;\n\nvar widgetsControlgroup = $.widget( \"ui.controlgroup\", {\n\tversion: \"1.12.1\",\n\tdefaultElement: \"<div>\",\n\toptions: {\n\t\tdirection: \"horizontal\",\n\t\tdisabled: null,\n\t\tonlyVisible: true,\n\t\titems: {\n\t\t\t\"button\": \"input[type=button], input[type=submit], input[type=reset], button, a\",\n\t\t\t\"controlgroupLabel\": \".ui-controlgroup-label\",\n\t\t\t\"checkboxradio\": \"input[type='checkbox'], input[type='radio']\",\n\t\t\t\"selectmenu\": \"select\",\n\t\t\t\"spinner\": \".ui-spinner-input\"\n\t\t}\n\t},\n\n\t_create: function() {\n\t\tthis._enhance();\n\t},\n\n\t// To support the enhanced option in jQuery Mobile, we isolate DOM manipulation\n\t_enhance: function() {\n\t\tthis.element.attr( \"role\", \"toolbar\" );\n\t\tthis.refresh();\n\t},\n\n\t_destroy: function() {\n\t\tthis._callChildMethod( \"destroy\" );\n\t\tthis.childWidgets.removeData( \"ui-controlgroup-data\" );\n\t\tthis.element.removeAttr( \"role\" );\n\t\tif ( this.options.items.controlgroupLabel ) {\n\t\t\tthis.element\n\t\t\t\t.find( this.options.items.controlgroupLabel )\n\t\t\t\t.find( \".ui-controlgroup-label-contents\" )\n\t\t\t\t.contents().unwrap();\n\t\t}\n\t},\n\n\t_initWidgets: function() {\n\t\tvar that = this,\n\t\t\tchildWidgets = [];\n\n\t\t// First we iterate over each of the items options\n\t\t$.each( this.options.items, function( widget, selector ) {\n\t\t\tvar labels;\n\t\t\tvar options = {};\n\n\t\t\t// Make sure the widget has a selector set\n\t\t\tif ( !selector ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( widget === \"controlgroupLabel\" ) {\n\t\t\t\tlabels = that.element.find( selector );\n\t\t\t\tlabels.each( function() {\n\t\t\t\t\tvar element = $( this );\n\n\t\t\t\t\tif ( element.children( \".ui-controlgroup-label-contents\" ).length ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\telement.contents()\n\t\t\t\t\t\t.wrapAll( \"<span class='ui-controlgroup-label-contents'></span>\" );\n\t\t\t\t} );\n\t\t\t\tthat._addClass( labels, null, \"ui-widget ui-widget-content ui-state-default\" );\n\t\t\t\tchildWidgets = childWidgets.concat( labels.get() );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Make sure the widget actually exists\n\t\t\tif ( !$.fn[ widget ] ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// We assume everything is in the middle to start because we can't determine\n\t\t\t// first / last elements until all enhancments are done.\n\t\t\tif ( that[ \"_\" + widget + \"Options\" ] ) {\n\t\t\t\toptions = that[ \"_\" + widget + \"Options\" ]( \"middle\" );\n\t\t\t} else {\n\t\t\t\toptions = { classes: {} };\n\t\t\t}\n\n\t\t\t// Find instances of this widget inside controlgroup and init them\n\t\t\tthat.element\n\t\t\t\t.find( selector )\n\t\t\t\t.each( function() {\n\t\t\t\t\tvar element = $( this );\n\t\t\t\t\tvar instance = element[ widget ]( \"instance\" );\n\n\t\t\t\t\t// We need to clone the default options for this type of widget to avoid\n\t\t\t\t\t// polluting the variable options which has a wider scope than a single widget.\n\t\t\t\t\tvar instanceOptions = $.widget.extend( {}, options );\n\n\t\t\t\t\t// If the button is the child of a spinner ignore it\n\t\t\t\t\t// TODO: Find a more generic solution\n\t\t\t\t\tif ( widget === \"button\" && element.parent( \".ui-spinner\" ).length ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Create the widget if it doesn't exist\n\t\t\t\t\tif ( !instance ) {\n\t\t\t\t\t\tinstance = element[ widget ]()[ widget ]( \"instance\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( instance ) {\n\t\t\t\t\t\tinstanceOptions.classes =\n\t\t\t\t\t\t\tthat._resolveClassesValues( instanceOptions.classes, instance );\n\t\t\t\t\t}\n\t\t\t\t\telement[ widget ]( instanceOptions );\n\n\t\t\t\t\t// Store an instance of the controlgroup to be able to reference\n\t\t\t\t\t// from the outermost element for changing options and refresh\n\t\t\t\t\tvar widgetElement = element[ widget ]( \"widget\" );\n\t\t\t\t\t$.data( widgetElement[ 0 ], \"ui-controlgroup-data\",\n\t\t\t\t\t\tinstance ? instance : element[ widget ]( \"instance\" ) );\n\n\t\t\t\t\tchildWidgets.push( widgetElement[ 0 ] );\n\t\t\t\t} );\n\t\t} );\n\n\t\tthis.childWidgets = $( $.unique( childWidgets ) );\n\t\tthis._addClass( this.childWidgets, \"ui-controlgroup-item\" );\n\t},\n\n\t_callChildMethod: function( method ) {\n\t\tthis.childWidgets.each( function() {\n\t\t\tvar element = $( this ),\n\t\t\t\tdata = element.data( \"ui-controlgroup-data\" );\n\t\t\tif ( data && data[ method ] ) {\n\t\t\t\tdata[ method ]();\n\t\t\t}\n\t\t} );\n\t},\n\n\t_updateCornerClass: function( element, position ) {\n\t\tvar remove = \"ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all\";\n\t\tvar add = this._buildSimpleOptions( position, \"label\" ).classes.label;\n\n\t\tthis._removeClass( element, null, remove );\n\t\tthis._addClass( element, null, add );\n\t},\n\n\t_buildSimpleOptions: function( position, key ) {\n\t\tvar direction = this.options.direction === \"vertical\";\n\t\tvar result = {\n\t\t\tclasses: {}\n\t\t};\n\t\tresult.classes[ key ] = {\n\t\t\t\"middle\": \"\",\n\t\t\t\"first\": \"ui-corner-\" + ( direction ? \"top\" : \"left\" ),\n\t\t\t\"last\": \"ui-corner-\" + ( direction ? \"bottom\" : \"right\" ),\n\t\t\t\"only\": \"ui-corner-all\"\n\t\t}[ position ];\n\n\t\treturn result;\n\t},\n\n\t_spinnerOptions: function( position ) {\n\t\tvar options = this._buildSimpleOptions( position, \"ui-spinner\" );\n\n\t\toptions.classes[ \"ui-spinner-up\" ] = \"\";\n\t\toptions.classes[ \"ui-spinner-down\" ] = \"\";\n\n\t\treturn options;\n\t},\n\n\t_buttonOptions: function( position ) {\n\t\treturn this._buildSimpleOptions( position, \"ui-button\" );\n\t},\n\n\t_checkboxradioOptions: function( position ) {\n\t\treturn this._buildSimpleOptions( position, \"ui-checkboxradio-label\" );\n\t},\n\n\t_selectmenuOptions: function( position ) {\n\t\tvar direction = this.options.direction === \"vertical\";\n\t\treturn {\n\t\t\twidth: direction ? \"auto\" : false,\n\t\t\tclasses: {\n\t\t\t\tmiddle: {\n\t\t\t\t\t\"ui-selectmenu-button-open\": \"\",\n\t\t\t\t\t\"ui-selectmenu-button-closed\": \"\"\n\t\t\t\t},\n\t\t\t\tfirst: {\n\t\t\t\t\t\"ui-selectmenu-button-open\": \"ui-corner-\" + ( direction ? \"top\" : \"tl\" ),\n\t\t\t\t\t\"ui-selectmenu-button-closed\": \"ui-corner-\" + ( direction ? \"top\" : \"left\" )\n\t\t\t\t},\n\t\t\t\tlast: {\n\t\t\t\t\t\"ui-selectmenu-button-open\": direction ? \"\" : \"ui-corner-tr\",\n\t\t\t\t\t\"ui-selectmenu-button-closed\": \"ui-corner-\" + ( direction ? \"bottom\" : \"right\" )\n\t\t\t\t},\n\t\t\t\tonly: {\n\t\t\t\t\t\"ui-selectmenu-button-open\": \"ui-corner-top\",\n\t\t\t\t\t\"ui-selectmenu-button-closed\": \"ui-corner-all\"\n\t\t\t\t}\n\n\t\t\t}[ position ]\n\t\t};\n\t},\n\n\t_resolveClassesValues: function( classes, instance ) {\n\t\tvar result = {};\n\t\t$.each( classes, function( key ) {\n\t\t\tvar current = instance.options.classes[ key ] || \"\";\n\t\t\tcurrent = $.trim( current.replace( controlgroupCornerRegex, \"\" ) );\n\t\t\tresult[ key ] = ( current + \" \" + classes[ key ] ).replace( /\\s+/g, \" \" );\n\t\t} );\n\t\treturn result;\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"direction\" ) {\n\t\t\tthis._removeClass( \"ui-controlgroup-\" + this.options.direction );\n\t\t}\n\n\t\tthis._super( key, value );\n\t\tif ( key === \"disabled\" ) {\n\t\t\tthis._callChildMethod( value ? \"disable\" : \"enable\" );\n\t\t\treturn;\n\t\t}\n\n\t\tthis.refresh();\n\t},\n\n\trefresh: function() {\n\t\tvar children,\n\t\t\tthat = this;\n\n\t\tthis._addClass( \"ui-controlgroup ui-controlgroup-\" + this.options.direction );\n\n\t\tif ( this.options.direction === \"horizontal\" ) {\n\t\t\tthis._addClass( null, \"ui-helper-clearfix\" );\n\t\t}\n\t\tthis._initWidgets();\n\n\t\tchildren = this.childWidgets;\n\n\t\t// We filter here because we need to track all childWidgets not just the visible ones\n\t\tif ( this.options.onlyVisible ) {\n\t\t\tchildren = children.filter( \":visible\" );\n\t\t}\n\n\t\tif ( children.length ) {\n\n\t\t\t// We do this last because we need to make sure all enhancment is done\n\t\t\t// before determining first and last\n\t\t\t$.each( [ \"first\", \"last\" ], function( index, value ) {\n\t\t\t\tvar instance = children[ value ]().data( \"ui-controlgroup-data\" );\n\n\t\t\t\tif ( instance && that[ \"_\" + instance.widgetName + \"Options\" ] ) {\n\t\t\t\t\tvar options = that[ \"_\" + instance.widgetName + \"Options\" ](\n\t\t\t\t\t\tchildren.length === 1 ? \"only\" : value\n\t\t\t\t\t);\n\t\t\t\t\toptions.classes = that._resolveClassesValues( options.classes, instance );\n\t\t\t\t\tinstance.element[ instance.widgetName ]( options );\n\t\t\t\t} else {\n\t\t\t\t\tthat._updateCornerClass( children[ value ](), value );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t// Finally call the refresh method on each of the child widgets.\n\t\t\tthis._callChildMethod( \"refresh\" );\n\t\t}\n\t}\n} );\n\n/*!\n * jQuery UI Checkboxradio 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Checkboxradio\n//>>group: Widgets\n//>>description: Enhances a form with multiple themeable checkboxes or radio buttons.\n//>>docs: http://api.jqueryui.com/checkboxradio/\n//>>demos: http://jqueryui.com/checkboxradio/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/button.css\n//>>css.structure: ../../themes/base/checkboxradio.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\n$.widget( \"ui.checkboxradio\", [ $.ui.formResetMixin, {\n\tversion: \"1.12.1\",\n\toptions: {\n\t\tdisabled: null,\n\t\tlabel: null,\n\t\ticon: true,\n\t\tclasses: {\n\t\t\t\"ui-checkboxradio-label\": \"ui-corner-all\",\n\t\t\t\"ui-checkboxradio-icon\": \"ui-corner-all\"\n\t\t}\n\t},\n\n\t_getCreateOptions: function() {\n\t\tvar disabled, labels;\n\t\tvar that = this;\n\t\tvar options = this._super() || {};\n\n\t\t// We read the type here, because it makes more sense to throw a element type error first,\n\t\t// rather then the error for lack of a label. Often if its the wrong type, it\n\t\t// won't have a label (e.g. calling on a div, btn, etc)\n\t\tthis._readType();\n\n\t\tlabels = this.element.labels();\n\n\t\t// If there are multiple labels, use the last one\n\t\tthis.label = $( labels[ labels.length - 1 ] );\n\t\tif ( !this.label.length ) {\n\t\t\t$.error( \"No label found for checkboxradio widget\" );\n\t\t}\n\n\t\tthis.originalLabel = \"\";\n\n\t\t// We need to get the label text but this may also need to make sure it does not contain the\n\t\t// input itself.\n\t\tthis.label.contents().not( this.element[ 0 ] ).each( function() {\n\n\t\t\t// The label contents could be text, html, or a mix. We concat each element to get a\n\t\t\t// string representation of the label, without the input as part of it.\n\t\t\tthat.originalLabel += this.nodeType === 3 ? $( this ).text() : this.outerHTML;\n\t\t} );\n\n\t\t// Set the label option if we found label text\n\t\tif ( this.originalLabel ) {\n\t\t\toptions.label = this.originalLabel;\n\t\t}\n\n\t\tdisabled = this.element[ 0 ].disabled;\n\t\tif ( disabled != null ) {\n\t\t\toptions.disabled = disabled;\n\t\t}\n\t\treturn options;\n\t},\n\n\t_create: function() {\n\t\tvar checked = this.element[ 0 ].checked;\n\n\t\tthis._bindFormResetHandler();\n\n\t\tif ( this.options.disabled == null ) {\n\t\t\tthis.options.disabled = this.element[ 0 ].disabled;\n\t\t}\n\n\t\tthis._setOption( \"disabled\", this.options.disabled );\n\t\tthis._addClass( \"ui-checkboxradio\", \"ui-helper-hidden-accessible\" );\n\t\tthis._addClass( this.label, \"ui-checkboxradio-label\", \"ui-button ui-widget\" );\n\n\t\tif ( this.type === \"radio\" ) {\n\t\t\tthis._addClass( this.label, \"ui-checkboxradio-radio-label\" );\n\t\t}\n\n\t\tif ( this.options.label && this.options.label !== this.originalLabel ) {\n\t\t\tthis._updateLabel();\n\t\t} else if ( this.originalLabel ) {\n\t\t\tthis.options.label = this.originalLabel;\n\t\t}\n\n\t\tthis._enhance();\n\n\t\tif ( checked ) {\n\t\t\tthis._addClass( this.label, \"ui-checkboxradio-checked\", \"ui-state-active\" );\n\t\t\tif ( this.icon ) {\n\t\t\t\tthis._addClass( this.icon, null, \"ui-state-hover\" );\n\t\t\t}\n\t\t}\n\n\t\tthis._on( {\n\t\t\tchange: \"_toggleClasses\",\n\t\t\tfocus: function() {\n\t\t\t\tthis._addClass( this.label, null, \"ui-state-focus ui-visual-focus\" );\n\t\t\t},\n\t\t\tblur: function() {\n\t\t\t\tthis._removeClass( this.label, null, \"ui-state-focus ui-visual-focus\" );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_readType: function() {\n\t\tvar nodeName = this.element[ 0 ].nodeName.toLowerCase();\n\t\tthis.type = this.element[ 0 ].type;\n\t\tif ( nodeName !== \"input\" || !/radio|checkbox/.test( this.type ) ) {\n\t\t\t$.error( \"Can't create checkboxradio on element.nodeName=\" + nodeName +\n\t\t\t\t\" and element.type=\" + this.type );\n\t\t}\n\t},\n\n\t// Support jQuery Mobile enhanced option\n\t_enhance: function() {\n\t\tthis._updateIcon( this.element[ 0 ].checked );\n\t},\n\n\twidget: function() {\n\t\treturn this.label;\n\t},\n\n\t_getRadioGroup: function() {\n\t\tvar group;\n\t\tvar name = this.element[ 0 ].name;\n\t\tvar nameSelector = \"input[name='\" + $.ui.escapeSelector( name ) + \"']\";\n\n\t\tif ( !name ) {\n\t\t\treturn $( [] );\n\t\t}\n\n\t\tif ( this.form.length ) {\n\t\t\tgroup = $( this.form[ 0 ].elements ).filter( nameSelector );\n\t\t} else {\n\n\t\t\t// Not inside a form, check all inputs that also are not inside a form\n\t\t\tgroup = $( nameSelector ).filter( function() {\n\t\t\t\treturn $( this ).form().length === 0;\n\t\t\t} );\n\t\t}\n\n\t\treturn group.not( this.element );\n\t},\n\n\t_toggleClasses: function() {\n\t\tvar checked = this.element[ 0 ].checked;\n\t\tthis._toggleClass( this.label, \"ui-checkboxradio-checked\", \"ui-state-active\", checked );\n\n\t\tif ( this.options.icon && this.type === \"checkbox\" ) {\n\t\t\tthis._toggleClass( this.icon, null, \"ui-icon-check ui-state-checked\", checked )\n\t\t\t\t._toggleClass( this.icon, null, \"ui-icon-blank\", !checked );\n\t\t}\n\n\t\tif ( this.type === \"radio\" ) {\n\t\t\tthis._getRadioGroup()\n\t\t\t\t.each( function() {\n\t\t\t\t\tvar instance = $( this ).checkboxradio( \"instance\" );\n\n\t\t\t\t\tif ( instance ) {\n\t\t\t\t\t\tinstance._removeClass( instance.label,\n\t\t\t\t\t\t\t\"ui-checkboxradio-checked\", \"ui-state-active\" );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t}\n\t},\n\n\t_destroy: function() {\n\t\tthis._unbindFormResetHandler();\n\n\t\tif ( this.icon ) {\n\t\t\tthis.icon.remove();\n\t\t\tthis.iconSpace.remove();\n\t\t}\n\t},\n\n\t_setOption: function( key, value ) {\n\n\t\t// We don't allow the value to be set to nothing\n\t\tif ( key === \"label\" && !value ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._super( key, value );\n\n\t\tif ( key === \"disabled\" ) {\n\t\t\tthis._toggleClass( this.label, null, \"ui-state-disabled\", value );\n\t\t\tthis.element[ 0 ].disabled = value;\n\n\t\t\t// Don't refresh when setting disabled\n\t\t\treturn;\n\t\t}\n\t\tthis.refresh();\n\t},\n\n\t_updateIcon: function( checked ) {\n\t\tvar toAdd = \"ui-icon ui-icon-background \";\n\n\t\tif ( this.options.icon ) {\n\t\t\tif ( !this.icon ) {\n\t\t\t\tthis.icon = $( \"<span>\" );\n\t\t\t\tthis.iconSpace = $( \"<span> </span>\" );\n\t\t\t\tthis._addClass( this.iconSpace, \"ui-checkboxradio-icon-space\" );\n\t\t\t}\n\n\t\t\tif ( this.type === \"checkbox\" ) {\n\t\t\t\ttoAdd += checked ? \"ui-icon-check ui-state-checked\" : \"ui-icon-blank\";\n\t\t\t\tthis._removeClass( this.icon, null, checked ? \"ui-icon-blank\" : \"ui-icon-check\" );\n\t\t\t} else {\n\t\t\t\ttoAdd += \"ui-icon-blank\";\n\t\t\t}\n\t\t\tthis._addClass( this.icon, \"ui-checkboxradio-icon\", toAdd );\n\t\t\tif ( !checked ) {\n\t\t\t\tthis._removeClass( this.icon, null, \"ui-icon-check ui-state-checked\" );\n\t\t\t}\n\t\t\tthis.icon.prependTo( this.label ).after( this.iconSpace );\n\t\t} else if ( this.icon !== undefined ) {\n\t\t\tthis.icon.remove();\n\t\t\tthis.iconSpace.remove();\n\t\t\tdelete this.icon;\n\t\t}\n\t},\n\n\t_updateLabel: function() {\n\n\t\t// Remove the contents of the label ( minus the icon, icon space, and input )\n\t\tvar contents = this.label.contents().not( this.element[ 0 ] );\n\t\tif ( this.icon ) {\n\t\t\tcontents = contents.not( this.icon[ 0 ] );\n\t\t}\n\t\tif ( this.iconSpace ) {\n\t\t\tcontents = contents.not( this.iconSpace[ 0 ] );\n\t\t}\n\t\tcontents.remove();\n\n\t\tthis.label.append( this.options.label );\n\t},\n\n\trefresh: function() {\n\t\tvar checked = this.element[ 0 ].checked,\n\t\t\tisDisabled = this.element[ 0 ].disabled;\n\n\t\tthis._updateIcon( checked );\n\t\tthis._toggleClass( this.label, \"ui-checkboxradio-checked\", \"ui-state-active\", checked );\n\t\tif ( this.options.label !== null ) {\n\t\t\tthis._updateLabel();\n\t\t}\n\n\t\tif ( isDisabled !== this.options.disabled ) {\n\t\t\tthis._setOptions( { \"disabled\": isDisabled } );\n\t\t}\n\t}\n\n} ] );\n\nvar widgetsCheckboxradio = $.ui.checkboxradio;\n\n\n/*!\n * jQuery UI Button 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Button\n//>>group: Widgets\n//>>description: Enhances a form with themeable buttons.\n//>>docs: http://api.jqueryui.com/button/\n//>>demos: http://jqueryui.com/button/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/button.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\n$.widget( \"ui.button\", {\n\tversion: \"1.12.1\",\n\tdefaultElement: \"<button>\",\n\toptions: {\n\t\tclasses: {\n\t\t\t\"ui-button\": \"ui-corner-all\"\n\t\t},\n\t\tdisabled: null,\n\t\ticon: null,\n\t\ticonPosition: \"beginning\",\n\t\tlabel: null,\n\t\tshowLabel: true\n\t},\n\n\t_getCreateOptions: function() {\n\t\tvar disabled,\n\n\t\t\t// This is to support cases like in jQuery Mobile where the base widget does have\n\t\t\t// an implementation of _getCreateOptions\n\t\t\toptions = this._super() || {};\n\n\t\tthis.isInput = this.element.is( \"input\" );\n\n\t\tdisabled = this.element[ 0 ].disabled;\n\t\tif ( disabled != null ) {\n\t\t\toptions.disabled = disabled;\n\t\t}\n\n\t\tthis.originalLabel = this.isInput ? this.element.val() : this.element.html();\n\t\tif ( this.originalLabel ) {\n\t\t\toptions.label = this.originalLabel;\n\t\t}\n\n\t\treturn options;\n\t},\n\n\t_create: function() {\n\t\tif ( !this.option.showLabel & !this.options.icon ) {\n\t\t\tthis.options.showLabel = true;\n\t\t}\n\n\t\t// We have to check the option again here even though we did in _getCreateOptions,\n\t\t// because null may have been passed on init which would override what was set in\n\t\t// _getCreateOptions\n\t\tif ( this.options.disabled == null ) {\n\t\t\tthis.options.disabled = this.element[ 0 ].disabled || false;\n\t\t}\n\n\t\tthis.hasTitle = !!this.element.attr( \"title\" );\n\n\t\t// Check to see if the label needs to be set or if its already correct\n\t\tif ( this.options.label && this.options.label !== this.originalLabel ) {\n\t\t\tif ( this.isInput ) {\n\t\t\t\tthis.element.val( this.options.label );\n\t\t\t} else {\n\t\t\t\tthis.element.html( this.options.label );\n\t\t\t}\n\t\t}\n\t\tthis._addClass( \"ui-button\", \"ui-widget\" );\n\t\tthis._setOption( \"disabled\", this.options.disabled );\n\t\tthis._enhance();\n\n\t\tif ( this.element.is( \"a\" ) ) {\n\t\t\tthis._on( {\n\t\t\t\t\"keyup\": function( event ) {\n\t\t\t\t\tif ( event.keyCode === $.ui.keyCode.SPACE ) {\n\t\t\t\t\t\tevent.preventDefault();\n\n\t\t\t\t\t\t// Support: PhantomJS <= 1.9, IE 8 Only\n\t\t\t\t\t\t// If a native click is available use it so we actually cause navigation\n\t\t\t\t\t\t// otherwise just trigger a click event\n\t\t\t\t\t\tif ( this.element[ 0 ].click ) {\n\t\t\t\t\t\t\tthis.element[ 0 ].click();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.element.trigger( \"click\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t},\n\n\t_enhance: function() {\n\t\tif ( !this.element.is( \"button\" ) ) {\n\t\t\tthis.element.attr( \"role\", \"button\" );\n\t\t}\n\n\t\tif ( this.options.icon ) {\n\t\t\tthis._updateIcon( \"icon\", this.options.icon );\n\t\t\tthis._updateTooltip();\n\t\t}\n\t},\n\n\t_updateTooltip: function() {\n\t\tthis.title = this.element.attr( \"title\" );\n\n\t\tif ( !this.options.showLabel && !this.title ) {\n\t\t\tthis.element.attr( \"title\", this.options.label );\n\t\t}\n\t},\n\n\t_updateIcon: function( option, value ) {\n\t\tvar icon = option !== \"iconPosition\",\n\t\t\tposition = icon ? this.options.iconPosition : value,\n\t\t\tdisplayBlock = position === \"top\" || position === \"bottom\";\n\n\t\t// Create icon\n\t\tif ( !this.icon ) {\n\t\t\tthis.icon = $( \"<span>\" );\n\n\t\t\tthis._addClass( this.icon, \"ui-button-icon\", \"ui-icon\" );\n\n\t\t\tif ( !this.options.showLabel ) {\n\t\t\t\tthis._addClass( \"ui-button-icon-only\" );\n\t\t\t}\n\t\t} else if ( icon ) {\n\n\t\t\t// If we are updating the icon remove the old icon class\n\t\t\tthis._removeClass( this.icon, null, this.options.icon );\n\t\t}\n\n\t\t// If we are updating the icon add the new icon class\n\t\tif ( icon ) {\n\t\t\tthis._addClass( this.icon, null, value );\n\t\t}\n\n\t\tthis._attachIcon( position );\n\n\t\t// If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove\n\t\t// the iconSpace if there is one.\n\t\tif ( displayBlock ) {\n\t\t\tthis._addClass( this.icon, null, \"ui-widget-icon-block\" );\n\t\t\tif ( this.iconSpace ) {\n\t\t\t\tthis.iconSpace.remove();\n\t\t\t}\n\t\t} else {\n\n\t\t\t// Position is beginning or end so remove the ui-widget-icon-block class and add the\n\t\t\t// space if it does not exist\n\t\t\tif ( !this.iconSpace ) {\n\t\t\t\tthis.iconSpace = $( \"<span> </span>\" );\n\t\t\t\tthis._addClass( this.iconSpace, \"ui-button-icon-space\" );\n\t\t\t}\n\t\t\tthis._removeClass( this.icon, null, \"ui-wiget-icon-block\" );\n\t\t\tthis._attachIconSpace( position );\n\t\t}\n\t},\n\n\t_destroy: function() {\n\t\tthis.element.removeAttr( \"role\" );\n\n\t\tif ( this.icon ) {\n\t\t\tthis.icon.remove();\n\t\t}\n\t\tif ( this.iconSpace ) {\n\t\t\tthis.iconSpace.remove();\n\t\t}\n\t\tif ( !this.hasTitle ) {\n\t\t\tthis.element.removeAttr( \"title\" );\n\t\t}\n\t},\n\n\t_attachIconSpace: function( iconPosition ) {\n\t\tthis.icon[ /^(?:end|bottom)/.test( iconPosition ) ? \"before\" : \"after\" ]( this.iconSpace );\n\t},\n\n\t_attachIcon: function( iconPosition ) {\n\t\tthis.element[ /^(?:end|bottom)/.test( iconPosition ) ? \"append\" : \"prepend\" ]( this.icon );\n\t},\n\n\t_setOptions: function( options ) {\n\t\tvar newShowLabel = options.showLabel === undefined ?\n\t\t\t\tthis.options.showLabel :\n\t\t\t\toptions.showLabel,\n\t\t\tnewIcon = options.icon === undefined ? this.options.icon : options.icon;\n\n\t\tif ( !newShowLabel && !newIcon ) {\n\t\t\toptions.showLabel = true;\n\t\t}\n\t\tthis._super( options );\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"icon\" ) {\n\t\t\tif ( value ) {\n\t\t\t\tthis._updateIcon( key, value );\n\t\t\t} else if ( this.icon ) {\n\t\t\t\tthis.icon.remove();\n\t\t\t\tif ( this.iconSpace ) {\n\t\t\t\t\tthis.iconSpace.remove();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( key === \"iconPosition\" ) {\n\t\t\tthis._updateIcon( key, value );\n\t\t}\n\n\t\t// Make sure we can't end up with a button that has neither text nor icon\n\t\tif ( key === \"showLabel\" ) {\n\t\t\t\tthis._toggleClass( \"ui-button-icon-only\", null, !value );\n\t\t\t\tthis._updateTooltip();\n\t\t}\n\n\t\tif ( key === \"label\" ) {\n\t\t\tif ( this.isInput ) {\n\t\t\t\tthis.element.val( value );\n\t\t\t} else {\n\n\t\t\t\t// If there is an icon, append it, else nothing then append the value\n\t\t\t\t// this avoids removal of the icon when setting label text\n\t\t\t\tthis.element.html( value );\n\t\t\t\tif ( this.icon ) {\n\t\t\t\t\tthis._attachIcon( this.options.iconPosition );\n\t\t\t\t\tthis._attachIconSpace( this.options.iconPosition );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis._super( key, value );\n\n\t\tif ( key === \"disabled\" ) {\n\t\t\tthis._toggleClass( null, \"ui-state-disabled\", value );\n\t\t\tthis.element[ 0 ].disabled = value;\n\t\t\tif ( value ) {\n\t\t\t\tthis.element.blur();\n\t\t\t}\n\t\t}\n\t},\n\n\trefresh: function() {\n\n\t\t// Make sure to only check disabled if its an element that supports this otherwise\n\t\t// check for the disabled class to determine state\n\t\tvar isDisabled = this.element.is( \"input, button\" ) ?\n\t\t\tthis.element[ 0 ].disabled : this.element.hasClass( \"ui-button-disabled\" );\n\n\t\tif ( isDisabled !== this.options.disabled ) {\n\t\t\tthis._setOptions( { disabled: isDisabled } );\n\t\t}\n\n\t\tthis._updateTooltip();\n\t}\n} );\n\n// DEPRECATED\nif ( $.uiBackCompat !== false ) {\n\n\t// Text and Icons options\n\t$.widget( \"ui.button\", $.ui.button, {\n\t\toptions: {\n\t\t\ttext: true,\n\t\t\ticons: {\n\t\t\t\tprimary: null,\n\t\t\t\tsecondary: null\n\t\t\t}\n\t\t},\n\n\t\t_create: function() {\n\t\t\tif ( this.options.showLabel && !this.options.text ) {\n\t\t\t\tthis.options.showLabel = this.options.text;\n\t\t\t}\n\t\t\tif ( !this.options.showLabel && this.options.text ) {\n\t\t\t\tthis.options.text = this.options.showLabel;\n\t\t\t}\n\t\t\tif ( !this.options.icon && ( this.options.icons.primary ||\n\t\t\t\t\tthis.options.icons.secondary ) ) {\n\t\t\t\tif ( this.options.icons.primary ) {\n\t\t\t\t\tthis.options.icon = this.options.icons.primary;\n\t\t\t\t} else {\n\t\t\t\t\tthis.options.icon = this.options.icons.secondary;\n\t\t\t\t\tthis.options.iconPosition = \"end\";\n\t\t\t\t}\n\t\t\t} else if ( this.options.icon ) {\n\t\t\t\tthis.options.icons.primary = this.options.icon;\n\t\t\t}\n\t\t\tthis._super();\n\t\t},\n\n\t\t_setOption: function( key, value ) {\n\t\t\tif ( key === \"text\" ) {\n\t\t\t\tthis._super( \"showLabel\", value );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ( key === \"showLabel\" ) {\n\t\t\t\tthis.options.text = value;\n\t\t\t}\n\t\t\tif ( key === \"icon\" ) {\n\t\t\t\tthis.options.icons.primary = value;\n\t\t\t}\n\t\t\tif ( key === \"icons\" ) {\n\t\t\t\tif ( value.primary ) {\n\t\t\t\t\tthis._super( \"icon\", value.primary );\n\t\t\t\t\tthis._super( \"iconPosition\", \"beginning\" );\n\t\t\t\t} else if ( value.secondary ) {\n\t\t\t\t\tthis._super( \"icon\", value.secondary );\n\t\t\t\t\tthis._super( \"iconPosition\", \"end\" );\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._superApply( arguments );\n\t\t}\n\t} );\n\n\t$.fn.button = ( function( orig ) {\n\t\treturn function() {\n\t\t\tif ( !this.length || ( this.length && this[ 0 ].tagName !== \"INPUT\" ) ||\n\t\t\t\t\t( this.length && this[ 0 ].tagName === \"INPUT\" && (\n\t\t\t\t\t\tthis.attr( \"type\" ) !== \"checkbox\" && this.attr( \"type\" ) !== \"radio\"\n\t\t\t\t\t) ) ) {\n\t\t\t\treturn orig.apply( this, arguments );\n\t\t\t}\n\t\t\tif ( !$.ui.checkboxradio ) {\n\t\t\t\t$.error( \"Checkboxradio widget missing\" );\n\t\t\t}\n\t\t\tif ( arguments.length === 0 ) {\n\t\t\t\treturn this.checkboxradio( {\n\t\t\t\t\t\"icon\": false\n\t\t\t\t} );\n\t\t\t}\n\t\t\treturn this.checkboxradio.apply( this, arguments );\n\t\t};\n\t} )( $.fn.button );\n\n\t$.fn.buttonset = function() {\n\t\tif ( !$.ui.controlgroup ) {\n\t\t\t$.error( \"Controlgroup widget missing\" );\n\t\t}\n\t\tif ( arguments[ 0 ] === \"option\" && arguments[ 1 ] === \"items\" && arguments[ 2 ] ) {\n\t\t\treturn this.controlgroup.apply( this,\n\t\t\t\t[ arguments[ 0 ], \"items.button\", arguments[ 2 ] ] );\n\t\t}\n\t\tif ( arguments[ 0 ] === \"option\" && arguments[ 1 ] === \"items\" ) {\n\t\t\treturn this.controlgroup.apply( this, [ arguments[ 0 ], \"items.button\" ] );\n\t\t}\n\t\tif ( typeof arguments[ 0 ] === \"object\" && arguments[ 0 ].items ) {\n\t\t\targuments[ 0 ].items = {\n\t\t\t\tbutton: arguments[ 0 ].items\n\t\t\t};\n\t\t}\n\t\treturn this.controlgroup.apply( this, arguments );\n\t};\n}\n\nvar widgetsButton = $.ui.button;\n\n\n// jscs:disable maximumLineLength\n/* jscs:disable requireCamelCaseOrUpperCaseIdentifiers */\n/*!\n * jQuery UI Datepicker 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Datepicker\n//>>group: Widgets\n//>>description: Displays a calendar from an input or inline for selecting dates.\n//>>docs: http://api.jqueryui.com/datepicker/\n//>>demos: http://jqueryui.com/datepicker/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/datepicker.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\n$.extend( $.ui, { datepicker: { version: \"1.12.1\" } } );\n\nvar datepicker_instActive;\n\nfunction datepicker_getZindex( elem ) {\n\tvar position, value;\n\twhile ( elem.length && elem[ 0 ] !== document ) {\n\n\t\t// Ignore z-index if position is set to a value where z-index is ignored by the browser\n\t\t// This makes behavior of this function consistent across browsers\n\t\t// WebKit always returns auto if the element is positioned\n\t\tposition = elem.css( \"position\" );\n\t\tif ( position === \"absolute\" || position === \"relative\" || position === \"fixed\" ) {\n\n\t\t\t// IE returns 0 when zIndex is not specified\n\t\t\t// other browsers return a string\n\t\t\t// we ignore the case of nested elements with an explicit value of 0\n\t\t\t// <div style=\"z-index: -10;\"><div style=\"z-index: 0;\"></div></div>\n\t\t\tvalue = parseInt( elem.css( \"zIndex\" ), 10 );\n\t\t\tif ( !isNaN( value ) && value !== 0 ) {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t\telem = elem.parent();\n\t}\n\n\treturn 0;\n}\n/* Date picker manager.\n   Use the singleton instance of this class, $.datepicker, to interact with the date picker.\n   Settings for (groups of) date pickers are maintained in an instance object,\n   allowing multiple different settings on the same page. */\n\nfunction Datepicker() {\n\tthis._curInst = null; // The current instance in use\n\tthis._keyEvent = false; // If the last event was a key event\n\tthis._disabledInputs = []; // List of date picker inputs that have been disabled\n\tthis._datepickerShowing = false; // True if the popup picker is showing , false if not\n\tthis._inDialog = false; // True if showing within a \"dialog\", false if not\n\tthis._mainDivId = \"ui-datepicker-div\"; // The ID of the main datepicker division\n\tthis._inlineClass = \"ui-datepicker-inline\"; // The name of the inline marker class\n\tthis._appendClass = \"ui-datepicker-append\"; // The name of the append marker class\n\tthis._triggerClass = \"ui-datepicker-trigger\"; // The name of the trigger marker class\n\tthis._dialogClass = \"ui-datepicker-dialog\"; // The name of the dialog marker class\n\tthis._disableClass = \"ui-datepicker-disabled\"; // The name of the disabled covering marker class\n\tthis._unselectableClass = \"ui-datepicker-unselectable\"; // The name of the unselectable cell marker class\n\tthis._currentClass = \"ui-datepicker-current-day\"; // The name of the current day marker class\n\tthis._dayOverClass = \"ui-datepicker-days-cell-over\"; // The name of the day hover marker class\n\tthis.regional = []; // Available regional settings, indexed by language code\n\tthis.regional[ \"\" ] = { // Default regional settings\n\t\tcloseText: \"Done\", // Display text for close link\n\t\tprevText: \"Prev\", // Display text for previous month link\n\t\tnextText: \"Next\", // Display text for next month link\n\t\tcurrentText: \"Today\", // Display text for current month link\n\t\tmonthNames: [ \"January\",\"February\",\"March\",\"April\",\"May\",\"June\",\n\t\t\t\"July\",\"August\",\"September\",\"October\",\"November\",\"December\" ], // Names of months for drop-down and formatting\n\t\tmonthNamesShort: [ \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\" ], // For formatting\n\t\tdayNames: [ \"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\" ], // For formatting\n\t\tdayNamesShort: [ \"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\" ], // For formatting\n\t\tdayNamesMin: [ \"Su\",\"Mo\",\"Tu\",\"We\",\"Th\",\"Fr\",\"Sa\" ], // Column headings for days starting at Sunday\n\t\tweekHeader: \"Wk\", // Column header for week of the year\n\t\tdateFormat: \"mm/dd/yy\", // See format options on parseDate\n\t\tfirstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...\n\t\tisRTL: false, // True if right-to-left language, false if left-to-right\n\t\tshowMonthAfterYear: false, // True if the year select precedes month, false for month then year\n\t\tyearSuffix: \"\" // Additional text to append to the year in the month headers\n\t};\n\tthis._defaults = { // Global defaults for all the date picker instances\n\t\tshowOn: \"focus\", // \"focus\" for popup on focus,\n\t\t\t// \"button\" for trigger button, or \"both\" for either\n\t\tshowAnim: \"fadeIn\", // Name of jQuery animation for popup\n\t\tshowOptions: {}, // Options for enhanced animations\n\t\tdefaultDate: null, // Used when field is blank: actual date,\n\t\t\t// +/-number for offset from today, null for today\n\t\tappendText: \"\", // Display text following the input box, e.g. showing the format\n\t\tbuttonText: \"...\", // Text for trigger button\n\t\tbuttonImage: \"\", // URL for trigger button image\n\t\tbuttonImageOnly: false, // True if the image appears alone, false if it appears on a button\n\t\thideIfNoPrevNext: false, // True to hide next/previous month links\n\t\t\t// if not applicable, false to just disable them\n\t\tnavigationAsDateFormat: false, // True if date formatting applied to prev/today/next links\n\t\tgotoCurrent: false, // True if today link goes back to current selection instead\n\t\tchangeMonth: false, // True if month can be selected directly, false if only prev/next\n\t\tchangeYear: false, // True if year can be selected directly, false if only prev/next\n\t\tyearRange: \"c-10:c+10\", // Range of years to display in drop-down,\n\t\t\t// either relative to today's year (-nn:+nn), relative to currently displayed year\n\t\t\t// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)\n\t\tshowOtherMonths: false, // True to show dates in other months, false to leave blank\n\t\tselectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable\n\t\tshowWeek: false, // True to show week of the year, false to not show it\n\t\tcalculateWeek: this.iso8601Week, // How to calculate the week of the year,\n\t\t\t// takes a Date and returns the number of the week for it\n\t\tshortYearCutoff: \"+10\", // Short year values < this are in the current century,\n\t\t\t// > this are in the previous century,\n\t\t\t// string value starting with \"+\" for current year + value\n\t\tminDate: null, // The earliest selectable date, or null for no limit\n\t\tmaxDate: null, // The latest selectable date, or null for no limit\n\t\tduration: \"fast\", // Duration of display/closure\n\t\tbeforeShowDay: null, // Function that takes a date and returns an array with\n\t\t\t// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or \"\",\n\t\t\t// [2] = cell title (optional), e.g. $.datepicker.noWeekends\n\t\tbeforeShow: null, // Function that takes an input field and\n\t\t\t// returns a set of custom settings for the date picker\n\t\tonSelect: null, // Define a callback function when a date is selected\n\t\tonChangeMonthYear: null, // Define a callback function when the month or year is changed\n\t\tonClose: null, // Define a callback function when the datepicker is closed\n\t\tnumberOfMonths: 1, // Number of months to show at a time\n\t\tshowCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)\n\t\tstepMonths: 1, // Number of months to step back/forward\n\t\tstepBigMonths: 12, // Number of months to step back/forward for the big links\n\t\taltField: \"\", // Selector for an alternate field to store selected dates into\n\t\taltFormat: \"\", // The date format to use for the alternate field\n\t\tconstrainInput: true, // The input is constrained by the current date format\n\t\tshowButtonPanel: false, // True to show button panel, false to not show it\n\t\tautoSize: false, // True to size the input for the date format, false to leave as is\n\t\tdisabled: false // The initial disabled state\n\t};\n\t$.extend( this._defaults, this.regional[ \"\" ] );\n\tthis.regional.en = $.extend( true, {}, this.regional[ \"\" ] );\n\tthis.regional[ \"en-US\" ] = $.extend( true, {}, this.regional.en );\n\tthis.dpDiv = datepicker_bindHover( $( \"<div id='\" + this._mainDivId + \"' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>\" ) );\n}\n\n$.extend( Datepicker.prototype, {\n\t/* Class name added to elements to indicate already configured with a date picker. */\n\tmarkerClassName: \"hasDatepicker\",\n\n\t//Keep track of the maximum number of rows displayed (see #7043)\n\tmaxRows: 4,\n\n\t// TODO rename to \"widget\" when switching to widget factory\n\t_widgetDatepicker: function() {\n\t\treturn this.dpDiv;\n\t},\n\n\t/* Override the default settings for all instances of the date picker.\n\t * @param  settings  object - the new settings to use as defaults (anonymous object)\n\t * @return the manager object\n\t */\n\tsetDefaults: function( settings ) {\n\t\tdatepicker_extendRemove( this._defaults, settings || {} );\n\t\treturn this;\n\t},\n\n\t/* Attach the date picker to a jQuery selection.\n\t * @param  target\telement - the target input field or division or span\n\t * @param  settings  object - the new settings to use for this date picker instance (anonymous)\n\t */\n\t_attachDatepicker: function( target, settings ) {\n\t\tvar nodeName, inline, inst;\n\t\tnodeName = target.nodeName.toLowerCase();\n\t\tinline = ( nodeName === \"div\" || nodeName === \"span\" );\n\t\tif ( !target.id ) {\n\t\t\tthis.uuid += 1;\n\t\t\ttarget.id = \"dp\" + this.uuid;\n\t\t}\n\t\tinst = this._newInst( $( target ), inline );\n\t\tinst.settings = $.extend( {}, settings || {} );\n\t\tif ( nodeName === \"input\" ) {\n\t\t\tthis._connectDatepicker( target, inst );\n\t\t} else if ( inline ) {\n\t\t\tthis._inlineDatepicker( target, inst );\n\t\t}\n\t},\n\n\t/* Create a new instance object. */\n\t_newInst: function( target, inline ) {\n\t\tvar id = target[ 0 ].id.replace( /([^A-Za-z0-9_\\-])/g, \"\\\\\\\\$1\" ); // escape jQuery meta chars\n\t\treturn { id: id, input: target, // associated target\n\t\t\tselectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection\n\t\t\tdrawMonth: 0, drawYear: 0, // month being drawn\n\t\t\tinline: inline, // is datepicker inline or not\n\t\t\tdpDiv: ( !inline ? this.dpDiv : // presentation div\n\t\t\tdatepicker_bindHover( $( \"<div class='\" + this._inlineClass + \" ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>\" ) ) ) };\n\t},\n\n\t/* Attach the date picker to an input field. */\n\t_connectDatepicker: function( target, inst ) {\n\t\tvar input = $( target );\n\t\tinst.append = $( [] );\n\t\tinst.trigger = $( [] );\n\t\tif ( input.hasClass( this.markerClassName ) ) {\n\t\t\treturn;\n\t\t}\n\t\tthis._attachments( input, inst );\n\t\tinput.addClass( this.markerClassName ).on( \"keydown\", this._doKeyDown ).\n\t\t\ton( \"keypress\", this._doKeyPress ).on( \"keyup\", this._doKeyUp );\n\t\tthis._autoSize( inst );\n\t\t$.data( target, \"datepicker\", inst );\n\n\t\t//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)\n\t\tif ( inst.settings.disabled ) {\n\t\t\tthis._disableDatepicker( target );\n\t\t}\n\t},\n\n\t/* Make attachments based on settings. */\n\t_attachments: function( input, inst ) {\n\t\tvar showOn, buttonText, buttonImage,\n\t\t\tappendText = this._get( inst, \"appendText\" ),\n\t\t\tisRTL = this._get( inst, \"isRTL\" );\n\n\t\tif ( inst.append ) {\n\t\t\tinst.append.remove();\n\t\t}\n\t\tif ( appendText ) {\n\t\t\tinst.append = $( \"<span class='\" + this._appendClass + \"'>\" + appendText + \"</span>\" );\n\t\t\tinput[ isRTL ? \"before\" : \"after\" ]( inst.append );\n\t\t}\n\n\t\tinput.off( \"focus\", this._showDatepicker );\n\n\t\tif ( inst.trigger ) {\n\t\t\tinst.trigger.remove();\n\t\t}\n\n\t\tshowOn = this._get( inst, \"showOn\" );\n\t\tif ( showOn === \"focus\" || showOn === \"both\" ) { // pop-up date picker when in the marked field\n\t\t\tinput.on( \"focus\", this._showDatepicker );\n\t\t}\n\t\tif ( showOn === \"button\" || showOn === \"both\" ) { // pop-up date picker when button clicked\n\t\t\tbuttonText = this._get( inst, \"buttonText\" );\n\t\t\tbuttonImage = this._get( inst, \"buttonImage\" );\n\t\t\tinst.trigger = $( this._get( inst, \"buttonImageOnly\" ) ?\n\t\t\t\t$( \"<img/>\" ).addClass( this._triggerClass ).\n\t\t\t\t\tattr( { src: buttonImage, alt: buttonText, title: buttonText } ) :\n\t\t\t\t$( \"<button type='button'></button>\" ).addClass( this._triggerClass ).\n\t\t\t\t\thtml( !buttonImage ? buttonText : $( \"<img/>\" ).attr(\n\t\t\t\t\t{ src:buttonImage, alt:buttonText, title:buttonText } ) ) );\n\t\t\tinput[ isRTL ? \"before\" : \"after\" ]( inst.trigger );\n\t\t\tinst.trigger.on( \"click\", function() {\n\t\t\t\tif ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) {\n\t\t\t\t\t$.datepicker._hideDatepicker();\n\t\t\t\t} else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) {\n\t\t\t\t\t$.datepicker._hideDatepicker();\n\t\t\t\t\t$.datepicker._showDatepicker( input[ 0 ] );\n\t\t\t\t} else {\n\t\t\t\t\t$.datepicker._showDatepicker( input[ 0 ] );\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t} );\n\t\t}\n\t},\n\n\t/* Apply the maximum length for the date format. */\n\t_autoSize: function( inst ) {\n\t\tif ( this._get( inst, \"autoSize\" ) && !inst.inline ) {\n\t\t\tvar findMax, max, maxI, i,\n\t\t\t\tdate = new Date( 2009, 12 - 1, 20 ), // Ensure double digits\n\t\t\t\tdateFormat = this._get( inst, \"dateFormat\" );\n\n\t\t\tif ( dateFormat.match( /[DM]/ ) ) {\n\t\t\t\tfindMax = function( names ) {\n\t\t\t\t\tmax = 0;\n\t\t\t\t\tmaxI = 0;\n\t\t\t\t\tfor ( i = 0; i < names.length; i++ ) {\n\t\t\t\t\t\tif ( names[ i ].length > max ) {\n\t\t\t\t\t\t\tmax = names[ i ].length;\n\t\t\t\t\t\t\tmaxI = i;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn maxI;\n\t\t\t\t};\n\t\t\t\tdate.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ?\n\t\t\t\t\t\"monthNames\" : \"monthNamesShort\" ) ) ) );\n\t\t\t\tdate.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ?\n\t\t\t\t\t\"dayNames\" : \"dayNamesShort\" ) ) ) + 20 - date.getDay() );\n\t\t\t}\n\t\t\tinst.input.attr( \"size\", this._formatDate( inst, date ).length );\n\t\t}\n\t},\n\n\t/* Attach an inline date picker to a div. */\n\t_inlineDatepicker: function( target, inst ) {\n\t\tvar divSpan = $( target );\n\t\tif ( divSpan.hasClass( this.markerClassName ) ) {\n\t\t\treturn;\n\t\t}\n\t\tdivSpan.addClass( this.markerClassName ).append( inst.dpDiv );\n\t\t$.data( target, \"datepicker\", inst );\n\t\tthis._setDate( inst, this._getDefaultDate( inst ), true );\n\t\tthis._updateDatepicker( inst );\n\t\tthis._updateAlternate( inst );\n\n\t\t//If disabled option is true, disable the datepicker before showing it (see ticket #5665)\n\t\tif ( inst.settings.disabled ) {\n\t\t\tthis._disableDatepicker( target );\n\t\t}\n\n\t\t// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements\n\t\t// http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height\n\t\tinst.dpDiv.css( \"display\", \"block\" );\n\t},\n\n\t/* Pop-up the date picker in a \"dialog\" box.\n\t * @param  input element - ignored\n\t * @param  date\tstring or Date - the initial date to display\n\t * @param  onSelect  function - the function to call when a date is selected\n\t * @param  settings  object - update the dialog date picker instance's settings (anonymous object)\n\t * @param  pos int[2] - coordinates for the dialog's position within the screen or\n\t *\t\t\t\t\tevent - with x/y coordinates or\n\t *\t\t\t\t\tleave empty for default (screen centre)\n\t * @return the manager object\n\t */\n\t_dialogDatepicker: function( input, date, onSelect, settings, pos ) {\n\t\tvar id, browserWidth, browserHeight, scrollX, scrollY,\n\t\t\tinst = this._dialogInst; // internal instance\n\n\t\tif ( !inst ) {\n\t\t\tthis.uuid += 1;\n\t\t\tid = \"dp\" + this.uuid;\n\t\t\tthis._dialogInput = $( \"<input type='text' id='\" + id +\n\t\t\t\t\"' style='position: absolute; top: -100px; width: 0px;'/>\" );\n\t\t\tthis._dialogInput.on( \"keydown\", this._doKeyDown );\n\t\t\t$( \"body\" ).append( this._dialogInput );\n\t\t\tinst = this._dialogInst = this._newInst( this._dialogInput, false );\n\t\t\tinst.settings = {};\n\t\t\t$.data( this._dialogInput[ 0 ], \"datepicker\", inst );\n\t\t}\n\t\tdatepicker_extendRemove( inst.settings, settings || {} );\n\t\tdate = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date );\n\t\tthis._dialogInput.val( date );\n\n\t\tthis._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null );\n\t\tif ( !this._pos ) {\n\t\t\tbrowserWidth = document.documentElement.clientWidth;\n\t\t\tbrowserHeight = document.documentElement.clientHeight;\n\t\t\tscrollX = document.documentElement.scrollLeft || document.body.scrollLeft;\n\t\t\tscrollY = document.documentElement.scrollTop || document.body.scrollTop;\n\t\t\tthis._pos = // should use actual width/height below\n\t\t\t\t[ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ];\n\t\t}\n\n\t\t// Move input on screen for focus, but hidden behind dialog\n\t\tthis._dialogInput.css( \"left\", ( this._pos[ 0 ] + 20 ) + \"px\" ).css( \"top\", this._pos[ 1 ] + \"px\" );\n\t\tinst.settings.onSelect = onSelect;\n\t\tthis._inDialog = true;\n\t\tthis.dpDiv.addClass( this._dialogClass );\n\t\tthis._showDatepicker( this._dialogInput[ 0 ] );\n\t\tif ( $.blockUI ) {\n\t\t\t$.blockUI( this.dpDiv );\n\t\t}\n\t\t$.data( this._dialogInput[ 0 ], \"datepicker\", inst );\n\t\treturn this;\n\t},\n\n\t/* Detach a datepicker from its control.\n\t * @param  target\telement - the target input field or division or span\n\t */\n\t_destroyDatepicker: function( target ) {\n\t\tvar nodeName,\n\t\t\t$target = $( target ),\n\t\t\tinst = $.data( target, \"datepicker\" );\n\n\t\tif ( !$target.hasClass( this.markerClassName ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnodeName = target.nodeName.toLowerCase();\n\t\t$.removeData( target, \"datepicker\" );\n\t\tif ( nodeName === \"input\" ) {\n\t\t\tinst.append.remove();\n\t\t\tinst.trigger.remove();\n\t\t\t$target.removeClass( this.markerClassName ).\n\t\t\t\toff( \"focus\", this._showDatepicker ).\n\t\t\t\toff( \"keydown\", this._doKeyDown ).\n\t\t\t\toff( \"keypress\", this._doKeyPress ).\n\t\t\t\toff( \"keyup\", this._doKeyUp );\n\t\t} else if ( nodeName === \"div\" || nodeName === \"span\" ) {\n\t\t\t$target.removeClass( this.markerClassName ).empty();\n\t\t}\n\n\t\tif ( datepicker_instActive === inst ) {\n\t\t\tdatepicker_instActive = null;\n\t\t}\n\t},\n\n\t/* Enable the date picker to a jQuery selection.\n\t * @param  target\telement - the target input field or division or span\n\t */\n\t_enableDatepicker: function( target ) {\n\t\tvar nodeName, inline,\n\t\t\t$target = $( target ),\n\t\t\tinst = $.data( target, \"datepicker\" );\n\n\t\tif ( !$target.hasClass( this.markerClassName ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnodeName = target.nodeName.toLowerCase();\n\t\tif ( nodeName === \"input\" ) {\n\t\t\ttarget.disabled = false;\n\t\t\tinst.trigger.filter( \"button\" ).\n\t\t\t\teach( function() { this.disabled = false; } ).end().\n\t\t\t\tfilter( \"img\" ).css( { opacity: \"1.0\", cursor: \"\" } );\n\t\t} else if ( nodeName === \"div\" || nodeName === \"span\" ) {\n\t\t\tinline = $target.children( \".\" + this._inlineClass );\n\t\t\tinline.children().removeClass( \"ui-state-disabled\" );\n\t\t\tinline.find( \"select.ui-datepicker-month, select.ui-datepicker-year\" ).\n\t\t\t\tprop( \"disabled\", false );\n\t\t}\n\t\tthis._disabledInputs = $.map( this._disabledInputs,\n\t\t\tfunction( value ) { return ( value === target ? null : value ); } ); // delete entry\n\t},\n\n\t/* Disable the date picker to a jQuery selection.\n\t * @param  target\telement - the target input field or division or span\n\t */\n\t_disableDatepicker: function( target ) {\n\t\tvar nodeName, inline,\n\t\t\t$target = $( target ),\n\t\t\tinst = $.data( target, \"datepicker\" );\n\n\t\tif ( !$target.hasClass( this.markerClassName ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnodeName = target.nodeName.toLowerCase();\n\t\tif ( nodeName === \"input\" ) {\n\t\t\ttarget.disabled = true;\n\t\t\tinst.trigger.filter( \"button\" ).\n\t\t\t\teach( function() { this.disabled = true; } ).end().\n\t\t\t\tfilter( \"img\" ).css( { opacity: \"0.5\", cursor: \"default\" } );\n\t\t} else if ( nodeName === \"div\" || nodeName === \"span\" ) {\n\t\t\tinline = $target.children( \".\" + this._inlineClass );\n\t\t\tinline.children().addClass( \"ui-state-disabled\" );\n\t\t\tinline.find( \"select.ui-datepicker-month, select.ui-datepicker-year\" ).\n\t\t\t\tprop( \"disabled\", true );\n\t\t}\n\t\tthis._disabledInputs = $.map( this._disabledInputs,\n\t\t\tfunction( value ) { return ( value === target ? null : value ); } ); // delete entry\n\t\tthis._disabledInputs[ this._disabledInputs.length ] = target;\n\t},\n\n\t/* Is the first field in a jQuery collection disabled as a datepicker?\n\t * @param  target\telement - the target input field or division or span\n\t * @return boolean - true if disabled, false if enabled\n\t */\n\t_isDisabledDatepicker: function( target ) {\n\t\tif ( !target ) {\n\t\t\treturn false;\n\t\t}\n\t\tfor ( var i = 0; i < this._disabledInputs.length; i++ ) {\n\t\t\tif ( this._disabledInputs[ i ] === target ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t},\n\n\t/* Retrieve the instance data for the target control.\n\t * @param  target  element - the target input field or division or span\n\t * @return  object - the associated instance data\n\t * @throws  error if a jQuery problem getting data\n\t */\n\t_getInst: function( target ) {\n\t\ttry {\n\t\t\treturn $.data( target, \"datepicker\" );\n\t\t}\n\t\tcatch ( err ) {\n\t\t\tthrow \"Missing instance data for this datepicker\";\n\t\t}\n\t},\n\n\t/* Update or retrieve the settings for a date picker attached to an input field or division.\n\t * @param  target  element - the target input field or division or span\n\t * @param  name\tobject - the new settings to update or\n\t *\t\t\t\tstring - the name of the setting to change or retrieve,\n\t *\t\t\t\twhen retrieving also \"all\" for all instance settings or\n\t *\t\t\t\t\"defaults\" for all global defaults\n\t * @param  value   any - the new value for the setting\n\t *\t\t\t\t(omit if above is an object or to retrieve a value)\n\t */\n\t_optionDatepicker: function( target, name, value ) {\n\t\tvar settings, date, minDate, maxDate,\n\t\t\tinst = this._getInst( target );\n\n\t\tif ( arguments.length === 2 && typeof name === \"string\" ) {\n\t\t\treturn ( name === \"defaults\" ? $.extend( {}, $.datepicker._defaults ) :\n\t\t\t\t( inst ? ( name === \"all\" ? $.extend( {}, inst.settings ) :\n\t\t\t\tthis._get( inst, name ) ) : null ) );\n\t\t}\n\n\t\tsettings = name || {};\n\t\tif ( typeof name === \"string\" ) {\n\t\t\tsettings = {};\n\t\t\tsettings[ name ] = value;\n\t\t}\n\n\t\tif ( inst ) {\n\t\t\tif ( this._curInst === inst ) {\n\t\t\t\tthis._hideDatepicker();\n\t\t\t}\n\n\t\t\tdate = this._getDateDatepicker( target, true );\n\t\t\tminDate = this._getMinMaxDate( inst, \"min\" );\n\t\t\tmaxDate = this._getMinMaxDate( inst, \"max\" );\n\t\t\tdatepicker_extendRemove( inst.settings, settings );\n\n\t\t\t// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided\n\t\t\tif ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {\n\t\t\t\tinst.settings.minDate = this._formatDate( inst, minDate );\n\t\t\t}\n\t\t\tif ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {\n\t\t\t\tinst.settings.maxDate = this._formatDate( inst, maxDate );\n\t\t\t}\n\t\t\tif ( \"disabled\" in settings ) {\n\t\t\t\tif ( settings.disabled ) {\n\t\t\t\t\tthis._disableDatepicker( target );\n\t\t\t\t} else {\n\t\t\t\t\tthis._enableDatepicker( target );\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._attachments( $( target ), inst );\n\t\t\tthis._autoSize( inst );\n\t\t\tthis._setDate( inst, date );\n\t\t\tthis._updateAlternate( inst );\n\t\t\tthis._updateDatepicker( inst );\n\t\t}\n\t},\n\n\t// Change method deprecated\n\t_changeDatepicker: function( target, name, value ) {\n\t\tthis._optionDatepicker( target, name, value );\n\t},\n\n\t/* Redraw the date picker attached to an input field or division.\n\t * @param  target  element - the target input field or division or span\n\t */\n\t_refreshDatepicker: function( target ) {\n\t\tvar inst = this._getInst( target );\n\t\tif ( inst ) {\n\t\t\tthis._updateDatepicker( inst );\n\t\t}\n\t},\n\n\t/* Set the dates for a jQuery selection.\n\t * @param  target element - the target input field or division or span\n\t * @param  date\tDate - the new date\n\t */\n\t_setDateDatepicker: function( target, date ) {\n\t\tvar inst = this._getInst( target );\n\t\tif ( inst ) {\n\t\t\tthis._setDate( inst, date );\n\t\t\tthis._updateDatepicker( inst );\n\t\t\tthis._updateAlternate( inst );\n\t\t}\n\t},\n\n\t/* Get the date(s) for the first entry in a jQuery selection.\n\t * @param  target element - the target input field or division or span\n\t * @param  noDefault boolean - true if no default date is to be used\n\t * @return Date - the current date\n\t */\n\t_getDateDatepicker: function( target, noDefault ) {\n\t\tvar inst = this._getInst( target );\n\t\tif ( inst && !inst.inline ) {\n\t\t\tthis._setDateFromField( inst, noDefault );\n\t\t}\n\t\treturn ( inst ? this._getDate( inst ) : null );\n\t},\n\n\t/* Handle keystrokes. */\n\t_doKeyDown: function( event ) {\n\t\tvar onSelect, dateStr, sel,\n\t\t\tinst = $.datepicker._getInst( event.target ),\n\t\t\thandled = true,\n\t\t\tisRTL = inst.dpDiv.is( \".ui-datepicker-rtl\" );\n\n\t\tinst._keyEvent = true;\n\t\tif ( $.datepicker._datepickerShowing ) {\n\t\t\tswitch ( event.keyCode ) {\n\t\t\t\tcase 9: $.datepicker._hideDatepicker();\n\t\t\t\t\t\thandled = false;\n\t\t\t\t\t\tbreak; // hide on tab out\n\t\t\t\tcase 13: sel = $( \"td.\" + $.datepicker._dayOverClass + \":not(.\" +\n\t\t\t\t\t\t\t\t\t$.datepicker._currentClass + \")\", inst.dpDiv );\n\t\t\t\t\t\tif ( sel[ 0 ] ) {\n\t\t\t\t\t\t\t$.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tonSelect = $.datepicker._get( inst, \"onSelect\" );\n\t\t\t\t\t\tif ( onSelect ) {\n\t\t\t\t\t\t\tdateStr = $.datepicker._formatDate( inst );\n\n\t\t\t\t\t\t\t// Trigger custom callback\n\t\t\t\t\t\t\tonSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$.datepicker._hideDatepicker();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn false; // don't submit the form\n\t\t\t\tcase 27: $.datepicker._hideDatepicker();\n\t\t\t\t\t\tbreak; // hide on escape\n\t\t\t\tcase 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?\n\t\t\t\t\t\t\t-$.datepicker._get( inst, \"stepBigMonths\" ) :\n\t\t\t\t\t\t\t-$.datepicker._get( inst, \"stepMonths\" ) ), \"M\" );\n\t\t\t\t\t\tbreak; // previous month/year on page up/+ ctrl\n\t\t\t\tcase 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?\n\t\t\t\t\t\t\t+$.datepicker._get( inst, \"stepBigMonths\" ) :\n\t\t\t\t\t\t\t+$.datepicker._get( inst, \"stepMonths\" ) ), \"M\" );\n\t\t\t\t\t\tbreak; // next month/year on page down/+ ctrl\n\t\t\t\tcase 35: if ( event.ctrlKey || event.metaKey ) {\n\t\t\t\t\t\t\t$.datepicker._clearDate( event.target );\n\t\t\t\t\t\t}\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\t\t\t\t\t\tbreak; // clear on ctrl or command +end\n\t\t\t\tcase 36: if ( event.ctrlKey || event.metaKey ) {\n\t\t\t\t\t\t\t$.datepicker._gotoToday( event.target );\n\t\t\t\t\t\t}\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\t\t\t\t\t\tbreak; // current on ctrl or command +home\n\t\t\t\tcase 37: if ( event.ctrlKey || event.metaKey ) {\n\t\t\t\t\t\t\t$.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), \"D\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\n\t\t\t\t\t\t// -1 day on ctrl or command +left\n\t\t\t\t\t\tif ( event.originalEvent.altKey ) {\n\t\t\t\t\t\t\t$.datepicker._adjustDate( event.target, ( event.ctrlKey ?\n\t\t\t\t\t\t\t\t-$.datepicker._get( inst, \"stepBigMonths\" ) :\n\t\t\t\t\t\t\t\t-$.datepicker._get( inst, \"stepMonths\" ) ), \"M\" );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// next month/year on alt +left on Mac\n\t\t\t\t\t\tbreak;\n\t\t\t\tcase 38: if ( event.ctrlKey || event.metaKey ) {\n\t\t\t\t\t\t\t$.datepicker._adjustDate( event.target, -7, \"D\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\t\t\t\t\t\tbreak; // -1 week on ctrl or command +up\n\t\t\t\tcase 39: if ( event.ctrlKey || event.metaKey ) {\n\t\t\t\t\t\t\t$.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), \"D\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\n\t\t\t\t\t\t// +1 day on ctrl or command +right\n\t\t\t\t\t\tif ( event.originalEvent.altKey ) {\n\t\t\t\t\t\t\t$.datepicker._adjustDate( event.target, ( event.ctrlKey ?\n\t\t\t\t\t\t\t\t+$.datepicker._get( inst, \"stepBigMonths\" ) :\n\t\t\t\t\t\t\t\t+$.datepicker._get( inst, \"stepMonths\" ) ), \"M\" );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// next month/year on alt +right\n\t\t\t\t\t\tbreak;\n\t\t\t\tcase 40: if ( event.ctrlKey || event.metaKey ) {\n\t\t\t\t\t\t\t$.datepicker._adjustDate( event.target, +7, \"D\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\t\t\t\t\t\tbreak; // +1 week on ctrl or command +down\n\t\t\t\tdefault: handled = false;\n\t\t\t}\n\t\t} else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home\n\t\t\t$.datepicker._showDatepicker( this );\n\t\t} else {\n\t\t\thandled = false;\n\t\t}\n\n\t\tif ( handled ) {\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t}\n\t},\n\n\t/* Filter entered characters - based on date format. */\n\t_doKeyPress: function( event ) {\n\t\tvar chars, chr,\n\t\t\tinst = $.datepicker._getInst( event.target );\n\n\t\tif ( $.datepicker._get( inst, \"constrainInput\" ) ) {\n\t\t\tchars = $.datepicker._possibleChars( $.datepicker._get( inst, \"dateFormat\" ) );\n\t\t\tchr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode );\n\t\t\treturn event.ctrlKey || event.metaKey || ( chr < \" \" || !chars || chars.indexOf( chr ) > -1 );\n\t\t}\n\t},\n\n\t/* Synchronise manual entry and field/alternate field. */\n\t_doKeyUp: function( event ) {\n\t\tvar date,\n\t\t\tinst = $.datepicker._getInst( event.target );\n\n\t\tif ( inst.input.val() !== inst.lastVal ) {\n\t\t\ttry {\n\t\t\t\tdate = $.datepicker.parseDate( $.datepicker._get( inst, \"dateFormat\" ),\n\t\t\t\t\t( inst.input ? inst.input.val() : null ),\n\t\t\t\t\t$.datepicker._getFormatConfig( inst ) );\n\n\t\t\t\tif ( date ) { // only if valid\n\t\t\t\t\t$.datepicker._setDateFromField( inst );\n\t\t\t\t\t$.datepicker._updateAlternate( inst );\n\t\t\t\t\t$.datepicker._updateDatepicker( inst );\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch ( err ) {\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t},\n\n\t/* Pop-up the date picker for a given input field.\n\t * If false returned from beforeShow event handler do not show.\n\t * @param  input  element - the input field attached to the date picker or\n\t *\t\t\t\t\tevent - if triggered by focus\n\t */\n\t_showDatepicker: function( input ) {\n\t\tinput = input.target || input;\n\t\tif ( input.nodeName.toLowerCase() !== \"input\" ) { // find from button/image trigger\n\t\t\tinput = $( \"input\", input.parentNode )[ 0 ];\n\t\t}\n\n\t\tif ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here\n\t\t\treturn;\n\t\t}\n\n\t\tvar inst, beforeShow, beforeShowSettings, isFixed,\n\t\t\toffset, showAnim, duration;\n\n\t\tinst = $.datepicker._getInst( input );\n\t\tif ( $.datepicker._curInst && $.datepicker._curInst !== inst ) {\n\t\t\t$.datepicker._curInst.dpDiv.stop( true, true );\n\t\t\tif ( inst && $.datepicker._datepickerShowing ) {\n\t\t\t\t$.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] );\n\t\t\t}\n\t\t}\n\n\t\tbeforeShow = $.datepicker._get( inst, \"beforeShow\" );\n\t\tbeforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};\n\t\tif ( beforeShowSettings === false ) {\n\t\t\treturn;\n\t\t}\n\t\tdatepicker_extendRemove( inst.settings, beforeShowSettings );\n\n\t\tinst.lastVal = null;\n\t\t$.datepicker._lastInput = input;\n\t\t$.datepicker._setDateFromField( inst );\n\n\t\tif ( $.datepicker._inDialog ) { // hide cursor\n\t\t\tinput.value = \"\";\n\t\t}\n\t\tif ( !$.datepicker._pos ) { // position below input\n\t\t\t$.datepicker._pos = $.datepicker._findPos( input );\n\t\t\t$.datepicker._pos[ 1 ] += input.offsetHeight; // add the height\n\t\t}\n\n\t\tisFixed = false;\n\t\t$( input ).parents().each( function() {\n\t\t\tisFixed |= $( this ).css( \"position\" ) === \"fixed\";\n\t\t\treturn !isFixed;\n\t\t} );\n\n\t\toffset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] };\n\t\t$.datepicker._pos = null;\n\n\t\t//to avoid flashes on Firefox\n\t\tinst.dpDiv.empty();\n\n\t\t// determine sizing offscreen\n\t\tinst.dpDiv.css( { position: \"absolute\", display: \"block\", top: \"-1000px\" } );\n\t\t$.datepicker._updateDatepicker( inst );\n\n\t\t// fix width for dynamic number of date pickers\n\t\t// and adjust position before showing\n\t\toffset = $.datepicker._checkOffset( inst, offset, isFixed );\n\t\tinst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ?\n\t\t\t\"static\" : ( isFixed ? \"fixed\" : \"absolute\" ) ), display: \"none\",\n\t\t\tleft: offset.left + \"px\", top: offset.top + \"px\" } );\n\n\t\tif ( !inst.inline ) {\n\t\t\tshowAnim = $.datepicker._get( inst, \"showAnim\" );\n\t\t\tduration = $.datepicker._get( inst, \"duration\" );\n\t\t\tinst.dpDiv.css( \"z-index\", datepicker_getZindex( $( input ) ) + 1 );\n\t\t\t$.datepicker._datepickerShowing = true;\n\n\t\t\tif ( $.effects && $.effects.effect[ showAnim ] ) {\n\t\t\t\tinst.dpDiv.show( showAnim, $.datepicker._get( inst, \"showOptions\" ), duration );\n\t\t\t} else {\n\t\t\t\tinst.dpDiv[ showAnim || \"show\" ]( showAnim ? duration : null );\n\t\t\t}\n\n\t\t\tif ( $.datepicker._shouldFocusInput( inst ) ) {\n\t\t\t\tinst.input.trigger( \"focus\" );\n\t\t\t}\n\n\t\t\t$.datepicker._curInst = inst;\n\t\t}\n\t},\n\n\t/* Generate the date picker content. */\n\t_updateDatepicker: function( inst ) {\n\t\tthis.maxRows = 4; //Reset the max number of rows being displayed (see #7043)\n\t\tdatepicker_instActive = inst; // for delegate hover events\n\t\tinst.dpDiv.empty().append( this._generateHTML( inst ) );\n\t\tthis._attachHandlers( inst );\n\n\t\tvar origyearshtml,\n\t\t\tnumMonths = this._getNumberOfMonths( inst ),\n\t\t\tcols = numMonths[ 1 ],\n\t\t\twidth = 17,\n\t\t\tactiveCell = inst.dpDiv.find( \".\" + this._dayOverClass + \" a\" );\n\n\t\tif ( activeCell.length > 0 ) {\n\t\t\tdatepicker_handleMouseover.apply( activeCell.get( 0 ) );\n\t\t}\n\n\t\tinst.dpDiv.removeClass( \"ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4\" ).width( \"\" );\n\t\tif ( cols > 1 ) {\n\t\t\tinst.dpDiv.addClass( \"ui-datepicker-multi-\" + cols ).css( \"width\", ( width * cols ) + \"em\" );\n\t\t}\n\t\tinst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? \"add\" : \"remove\" ) +\n\t\t\t\"Class\" ]( \"ui-datepicker-multi\" );\n\t\tinst.dpDiv[ ( this._get( inst, \"isRTL\" ) ? \"add\" : \"remove\" ) +\n\t\t\t\"Class\" ]( \"ui-datepicker-rtl\" );\n\n\t\tif ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {\n\t\t\tinst.input.trigger( \"focus\" );\n\t\t}\n\n\t\t// Deffered render of the years select (to avoid flashes on Firefox)\n\t\tif ( inst.yearshtml ) {\n\t\t\torigyearshtml = inst.yearshtml;\n\t\t\tsetTimeout( function() {\n\n\t\t\t\t//assure that inst.yearshtml didn't change.\n\t\t\t\tif ( origyearshtml === inst.yearshtml && inst.yearshtml ) {\n\t\t\t\t\tinst.dpDiv.find( \"select.ui-datepicker-year:first\" ).replaceWith( inst.yearshtml );\n\t\t\t\t}\n\t\t\t\torigyearshtml = inst.yearshtml = null;\n\t\t\t}, 0 );\n\t\t}\n\t},\n\n\t// #6694 - don't focus the input if it's already focused\n\t// this breaks the change event in IE\n\t// Support: IE and jQuery <1.9\n\t_shouldFocusInput: function( inst ) {\n\t\treturn inst.input && inst.input.is( \":visible\" ) && !inst.input.is( \":disabled\" ) && !inst.input.is( \":focus\" );\n\t},\n\n\t/* Check positioning to remain on screen. */\n\t_checkOffset: function( inst, offset, isFixed ) {\n\t\tvar dpWidth = inst.dpDiv.outerWidth(),\n\t\t\tdpHeight = inst.dpDiv.outerHeight(),\n\t\t\tinputWidth = inst.input ? inst.input.outerWidth() : 0,\n\t\t\tinputHeight = inst.input ? inst.input.outerHeight() : 0,\n\t\t\tviewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),\n\t\t\tviewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );\n\n\t\toffset.left -= ( this._get( inst, \"isRTL\" ) ? ( dpWidth - inputWidth ) : 0 );\n\t\toffset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0;\n\t\toffset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0;\n\n\t\t// Now check if datepicker is showing outside window viewport - move to a better place if so.\n\t\toffset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ?\n\t\t\tMath.abs( offset.left + dpWidth - viewWidth ) : 0 );\n\t\toffset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ?\n\t\t\tMath.abs( dpHeight + inputHeight ) : 0 );\n\n\t\treturn offset;\n\t},\n\n\t/* Find an object's position on the screen. */\n\t_findPos: function( obj ) {\n\t\tvar position,\n\t\t\tinst = this._getInst( obj ),\n\t\t\tisRTL = this._get( inst, \"isRTL\" );\n\n\t\twhile ( obj && ( obj.type === \"hidden\" || obj.nodeType !== 1 || $.expr.filters.hidden( obj ) ) ) {\n\t\t\tobj = obj[ isRTL ? \"previousSibling\" : \"nextSibling\" ];\n\t\t}\n\n\t\tposition = $( obj ).offset();\n\t\treturn [ position.left, position.top ];\n\t},\n\n\t/* Hide the date picker from view.\n\t * @param  input  element - the input field attached to the date picker\n\t */\n\t_hideDatepicker: function( input ) {\n\t\tvar showAnim, duration, postProcess, onClose,\n\t\t\tinst = this._curInst;\n\n\t\tif ( !inst || ( input && inst !== $.data( input, \"datepicker\" ) ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this._datepickerShowing ) {\n\t\t\tshowAnim = this._get( inst, \"showAnim\" );\n\t\t\tduration = this._get( inst, \"duration\" );\n\t\t\tpostProcess = function() {\n\t\t\t\t$.datepicker._tidyDialog( inst );\n\t\t\t};\n\n\t\t\t// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed\n\t\t\tif ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {\n\t\t\t\tinst.dpDiv.hide( showAnim, $.datepicker._get( inst, \"showOptions\" ), duration, postProcess );\n\t\t\t} else {\n\t\t\t\tinst.dpDiv[ ( showAnim === \"slideDown\" ? \"slideUp\" :\n\t\t\t\t\t( showAnim === \"fadeIn\" ? \"fadeOut\" : \"hide\" ) ) ]( ( showAnim ? duration : null ), postProcess );\n\t\t\t}\n\n\t\t\tif ( !showAnim ) {\n\t\t\t\tpostProcess();\n\t\t\t}\n\t\t\tthis._datepickerShowing = false;\n\n\t\t\tonClose = this._get( inst, \"onClose\" );\n\t\t\tif ( onClose ) {\n\t\t\t\tonClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : \"\" ), inst ] );\n\t\t\t}\n\n\t\t\tthis._lastInput = null;\n\t\t\tif ( this._inDialog ) {\n\t\t\t\tthis._dialogInput.css( { position: \"absolute\", left: \"0\", top: \"-100px\" } );\n\t\t\t\tif ( $.blockUI ) {\n\t\t\t\t\t$.unblockUI();\n\t\t\t\t\t$( \"body\" ).append( this.dpDiv );\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._inDialog = false;\n\t\t}\n\t},\n\n\t/* Tidy up after a dialog display. */\n\t_tidyDialog: function( inst ) {\n\t\tinst.dpDiv.removeClass( this._dialogClass ).off( \".ui-datepicker-calendar\" );\n\t},\n\n\t/* Close date picker if clicked elsewhere. */\n\t_checkExternalClick: function( event ) {\n\t\tif ( !$.datepicker._curInst ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar $target = $( event.target ),\n\t\t\tinst = $.datepicker._getInst( $target[ 0 ] );\n\n\t\tif ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId &&\n\t\t\t\t$target.parents( \"#\" + $.datepicker._mainDivId ).length === 0 &&\n\t\t\t\t!$target.hasClass( $.datepicker.markerClassName ) &&\n\t\t\t\t!$target.closest( \".\" + $.datepicker._triggerClass ).length &&\n\t\t\t\t$.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) ||\n\t\t\t( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) {\n\t\t\t\t$.datepicker._hideDatepicker();\n\t\t}\n\t},\n\n\t/* Adjust one of the date sub-fields. */\n\t_adjustDate: function( id, offset, period ) {\n\t\tvar target = $( id ),\n\t\t\tinst = this._getInst( target[ 0 ] );\n\n\t\tif ( this._isDisabledDatepicker( target[ 0 ] ) ) {\n\t\t\treturn;\n\t\t}\n\t\tthis._adjustInstDate( inst, offset +\n\t\t\t( period === \"M\" ? this._get( inst, \"showCurrentAtPos\" ) : 0 ), // undo positioning\n\t\t\tperiod );\n\t\tthis._updateDatepicker( inst );\n\t},\n\n\t/* Action for current link. */\n\t_gotoToday: function( id ) {\n\t\tvar date,\n\t\t\ttarget = $( id ),\n\t\t\tinst = this._getInst( target[ 0 ] );\n\n\t\tif ( this._get( inst, \"gotoCurrent\" ) && inst.currentDay ) {\n\t\t\tinst.selectedDay = inst.currentDay;\n\t\t\tinst.drawMonth = inst.selectedMonth = inst.currentMonth;\n\t\t\tinst.drawYear = inst.selectedYear = inst.currentYear;\n\t\t} else {\n\t\t\tdate = new Date();\n\t\t\tinst.selectedDay = date.getDate();\n\t\t\tinst.drawMonth = inst.selectedMonth = date.getMonth();\n\t\t\tinst.drawYear = inst.selectedYear = date.getFullYear();\n\t\t}\n\t\tthis._notifyChange( inst );\n\t\tthis._adjustDate( target );\n\t},\n\n\t/* Action for selecting a new month/year. */\n\t_selectMonthYear: function( id, select, period ) {\n\t\tvar target = $( id ),\n\t\t\tinst = this._getInst( target[ 0 ] );\n\n\t\tinst[ \"selected\" + ( period === \"M\" ? \"Month\" : \"Year\" ) ] =\n\t\tinst[ \"draw\" + ( period === \"M\" ? \"Month\" : \"Year\" ) ] =\n\t\t\tparseInt( select.options[ select.selectedIndex ].value, 10 );\n\n\t\tthis._notifyChange( inst );\n\t\tthis._adjustDate( target );\n\t},\n\n\t/* Action for selecting a day. */\n\t_selectDay: function( id, month, year, td ) {\n\t\tvar inst,\n\t\t\ttarget = $( id );\n\n\t\tif ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tinst = this._getInst( target[ 0 ] );\n\t\tinst.selectedDay = inst.currentDay = $( \"a\", td ).html();\n\t\tinst.selectedMonth = inst.currentMonth = month;\n\t\tinst.selectedYear = inst.currentYear = year;\n\t\tthis._selectDate( id, this._formatDate( inst,\n\t\t\tinst.currentDay, inst.currentMonth, inst.currentYear ) );\n\t},\n\n\t/* Erase the input field and hide the date picker. */\n\t_clearDate: function( id ) {\n\t\tvar target = $( id );\n\t\tthis._selectDate( target, \"\" );\n\t},\n\n\t/* Update the input field with the selected date. */\n\t_selectDate: function( id, dateStr ) {\n\t\tvar onSelect,\n\t\t\ttarget = $( id ),\n\t\t\tinst = this._getInst( target[ 0 ] );\n\n\t\tdateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) );\n\t\tif ( inst.input ) {\n\t\t\tinst.input.val( dateStr );\n\t\t}\n\t\tthis._updateAlternate( inst );\n\n\t\tonSelect = this._get( inst, \"onSelect\" );\n\t\tif ( onSelect ) {\n\t\t\tonSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );  // trigger custom callback\n\t\t} else if ( inst.input ) {\n\t\t\tinst.input.trigger( \"change\" ); // fire the change event\n\t\t}\n\n\t\tif ( inst.inline ) {\n\t\t\tthis._updateDatepicker( inst );\n\t\t} else {\n\t\t\tthis._hideDatepicker();\n\t\t\tthis._lastInput = inst.input[ 0 ];\n\t\t\tif ( typeof( inst.input[ 0 ] ) !== \"object\" ) {\n\t\t\t\tinst.input.trigger( \"focus\" ); // restore focus\n\t\t\t}\n\t\t\tthis._lastInput = null;\n\t\t}\n\t},\n\n\t/* Update any alternate field to synchronise with the main field. */\n\t_updateAlternate: function( inst ) {\n\t\tvar altFormat, date, dateStr,\n\t\t\taltField = this._get( inst, \"altField\" );\n\n\t\tif ( altField ) { // update alternate field too\n\t\t\taltFormat = this._get( inst, \"altFormat\" ) || this._get( inst, \"dateFormat\" );\n\t\t\tdate = this._getDate( inst );\n\t\t\tdateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );\n\t\t\t$( altField ).val( dateStr );\n\t\t}\n\t},\n\n\t/* Set as beforeShowDay function to prevent selection of weekends.\n\t * @param  date  Date - the date to customise\n\t * @return [boolean, string] - is this date selectable?, what is its CSS class?\n\t */\n\tnoWeekends: function( date ) {\n\t\tvar day = date.getDay();\n\t\treturn [ ( day > 0 && day < 6 ), \"\" ];\n\t},\n\n\t/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.\n\t * @param  date  Date - the date to get the week for\n\t * @return  number - the number of the week within the year that contains this date\n\t */\n\tiso8601Week: function( date ) {\n\t\tvar time,\n\t\t\tcheckDate = new Date( date.getTime() );\n\n\t\t// Find Thursday of this week starting on Monday\n\t\tcheckDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );\n\n\t\ttime = checkDate.getTime();\n\t\tcheckDate.setMonth( 0 ); // Compare with Jan 1\n\t\tcheckDate.setDate( 1 );\n\t\treturn Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;\n\t},\n\n\t/* Parse a string value into a date object.\n\t * See formatDate below for the possible formats.\n\t *\n\t * @param  format string - the expected format of the date\n\t * @param  value string - the date in the above format\n\t * @param  settings Object - attributes include:\n\t *\t\t\t\t\tshortYearCutoff  number - the cutoff year for determining the century (optional)\n\t *\t\t\t\t\tdayNamesShort\tstring[7] - abbreviated names of the days from Sunday (optional)\n\t *\t\t\t\t\tdayNames\t\tstring[7] - names of the days from Sunday (optional)\n\t *\t\t\t\t\tmonthNamesShort string[12] - abbreviated names of the months (optional)\n\t *\t\t\t\t\tmonthNames\t\tstring[12] - names of the months (optional)\n\t * @return  Date - the extracted date value or null if value is blank\n\t */\n\tparseDate: function( format, value, settings ) {\n\t\tif ( format == null || value == null ) {\n\t\t\tthrow \"Invalid arguments\";\n\t\t}\n\n\t\tvalue = ( typeof value === \"object\" ? value.toString() : value + \"\" );\n\t\tif ( value === \"\" ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar iFormat, dim, extra,\n\t\t\tiValue = 0,\n\t\t\tshortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff,\n\t\t\tshortYearCutoff = ( typeof shortYearCutoffTemp !== \"string\" ? shortYearCutoffTemp :\n\t\t\t\tnew Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ),\n\t\t\tdayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,\n\t\t\tdayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,\n\t\t\tmonthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,\n\t\t\tmonthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,\n\t\t\tyear = -1,\n\t\t\tmonth = -1,\n\t\t\tday = -1,\n\t\t\tdoy = -1,\n\t\t\tliteral = false,\n\t\t\tdate,\n\n\t\t\t// Check whether a format character is doubled\n\t\t\tlookAhead = function( match ) {\n\t\t\t\tvar matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );\n\t\t\t\tif ( matches ) {\n\t\t\t\t\tiFormat++;\n\t\t\t\t}\n\t\t\t\treturn matches;\n\t\t\t},\n\n\t\t\t// Extract a number from the string value\n\t\t\tgetNumber = function( match ) {\n\t\t\t\tvar isDoubled = lookAhead( match ),\n\t\t\t\t\tsize = ( match === \"@\" ? 14 : ( match === \"!\" ? 20 :\n\t\t\t\t\t( match === \"y\" && isDoubled ? 4 : ( match === \"o\" ? 3 : 2 ) ) ) ),\n\t\t\t\t\tminSize = ( match === \"y\" ? size : 1 ),\n\t\t\t\t\tdigits = new RegExp( \"^\\\\d{\" + minSize + \",\" + size + \"}\" ),\n\t\t\t\t\tnum = value.substring( iValue ).match( digits );\n\t\t\t\tif ( !num ) {\n\t\t\t\t\tthrow \"Missing number at position \" + iValue;\n\t\t\t\t}\n\t\t\t\tiValue += num[ 0 ].length;\n\t\t\t\treturn parseInt( num[ 0 ], 10 );\n\t\t\t},\n\n\t\t\t// Extract a name from the string value and convert to an index\n\t\t\tgetName = function( match, shortNames, longNames ) {\n\t\t\t\tvar index = -1,\n\t\t\t\t\tnames = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {\n\t\t\t\t\t\treturn [ [ k, v ] ];\n\t\t\t\t\t} ).sort( function( a, b ) {\n\t\t\t\t\t\treturn -( a[ 1 ].length - b[ 1 ].length );\n\t\t\t\t\t} );\n\n\t\t\t\t$.each( names, function( i, pair ) {\n\t\t\t\t\tvar name = pair[ 1 ];\n\t\t\t\t\tif ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) {\n\t\t\t\t\t\tindex = pair[ 0 ];\n\t\t\t\t\t\tiValue += name.length;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\tif ( index !== -1 ) {\n\t\t\t\t\treturn index + 1;\n\t\t\t\t} else {\n\t\t\t\t\tthrow \"Unknown name at position \" + iValue;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// Confirm that a literal character matches the string value\n\t\t\tcheckLiteral = function() {\n\t\t\t\tif ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {\n\t\t\t\t\tthrow \"Unexpected literal at position \" + iValue;\n\t\t\t\t}\n\t\t\t\tiValue++;\n\t\t\t};\n\n\t\tfor ( iFormat = 0; iFormat < format.length; iFormat++ ) {\n\t\t\tif ( literal ) {\n\t\t\t\tif ( format.charAt( iFormat ) === \"'\" && !lookAhead( \"'\" ) ) {\n\t\t\t\t\tliteral = false;\n\t\t\t\t} else {\n\t\t\t\t\tcheckLiteral();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tswitch ( format.charAt( iFormat ) ) {\n\t\t\t\t\tcase \"d\":\n\t\t\t\t\t\tday = getNumber( \"d\" );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"D\":\n\t\t\t\t\t\tgetName( \"D\", dayNamesShort, dayNames );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"o\":\n\t\t\t\t\t\tdoy = getNumber( \"o\" );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"m\":\n\t\t\t\t\t\tmonth = getNumber( \"m\" );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"M\":\n\t\t\t\t\t\tmonth = getName( \"M\", monthNamesShort, monthNames );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"y\":\n\t\t\t\t\t\tyear = getNumber( \"y\" );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"@\":\n\t\t\t\t\t\tdate = new Date( getNumber( \"@\" ) );\n\t\t\t\t\t\tyear = date.getFullYear();\n\t\t\t\t\t\tmonth = date.getMonth() + 1;\n\t\t\t\t\t\tday = date.getDate();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"!\":\n\t\t\t\t\t\tdate = new Date( ( getNumber( \"!\" ) - this._ticksTo1970 ) / 10000 );\n\t\t\t\t\t\tyear = date.getFullYear();\n\t\t\t\t\t\tmonth = date.getMonth() + 1;\n\t\t\t\t\t\tday = date.getDate();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"'\":\n\t\t\t\t\t\tif ( lookAhead( \"'\" ) ) {\n\t\t\t\t\t\t\tcheckLiteral();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tliteral = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tcheckLiteral();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( iValue < value.length ) {\n\t\t\textra = value.substr( iValue );\n\t\t\tif ( !/^\\s+/.test( extra ) ) {\n\t\t\t\tthrow \"Extra/unparsed characters found in date: \" + extra;\n\t\t\t}\n\t\t}\n\n\t\tif ( year === -1 ) {\n\t\t\tyear = new Date().getFullYear();\n\t\t} else if ( year < 100 ) {\n\t\t\tyear += new Date().getFullYear() - new Date().getFullYear() % 100 +\n\t\t\t\t( year <= shortYearCutoff ? 0 : -100 );\n\t\t}\n\n\t\tif ( doy > -1 ) {\n\t\t\tmonth = 1;\n\t\t\tday = doy;\n\t\t\tdo {\n\t\t\t\tdim = this._getDaysInMonth( year, month - 1 );\n\t\t\t\tif ( day <= dim ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tmonth++;\n\t\t\t\tday -= dim;\n\t\t\t} while ( true );\n\t\t}\n\n\t\tdate = this._daylightSavingAdjust( new Date( year, month - 1, day ) );\n\t\tif ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {\n\t\t\tthrow \"Invalid date\"; // E.g. 31/02/00\n\t\t}\n\t\treturn date;\n\t},\n\n\t/* Standard date formats. */\n\tATOM: \"yy-mm-dd\", // RFC 3339 (ISO 8601)\n\tCOOKIE: \"D, dd M yy\",\n\tISO_8601: \"yy-mm-dd\",\n\tRFC_822: \"D, d M y\",\n\tRFC_850: \"DD, dd-M-y\",\n\tRFC_1036: \"D, d M y\",\n\tRFC_1123: \"D, d M yy\",\n\tRFC_2822: \"D, d M yy\",\n\tRSS: \"D, d M y\", // RFC 822\n\tTICKS: \"!\",\n\tTIMESTAMP: \"@\",\n\tW3C: \"yy-mm-dd\", // ISO 8601\n\n\t_ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) +\n\t\tMath.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ),\n\n\t/* Format a date object into a string value.\n\t * The format can be combinations of the following:\n\t * d  - day of month (no leading zero)\n\t * dd - day of month (two digit)\n\t * o  - day of year (no leading zeros)\n\t * oo - day of year (three digit)\n\t * D  - day name short\n\t * DD - day name long\n\t * m  - month of year (no leading zero)\n\t * mm - month of year (two digit)\n\t * M  - month name short\n\t * MM - month name long\n\t * y  - year (two digit)\n\t * yy - year (four digit)\n\t * @ - Unix timestamp (ms since 01/01/1970)\n\t * ! - Windows ticks (100ns since 01/01/0001)\n\t * \"...\" - literal text\n\t * '' - single quote\n\t *\n\t * @param  format string - the desired format of the date\n\t * @param  date Date - the date value to format\n\t * @param  settings Object - attributes include:\n\t *\t\t\t\t\tdayNamesShort\tstring[7] - abbreviated names of the days from Sunday (optional)\n\t *\t\t\t\t\tdayNames\t\tstring[7] - names of the days from Sunday (optional)\n\t *\t\t\t\t\tmonthNamesShort string[12] - abbreviated names of the months (optional)\n\t *\t\t\t\t\tmonthNames\t\tstring[12] - names of the months (optional)\n\t * @return  string - the date in the above format\n\t */\n\tformatDate: function( format, date, settings ) {\n\t\tif ( !date ) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tvar iFormat,\n\t\t\tdayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,\n\t\t\tdayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,\n\t\t\tmonthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,\n\t\t\tmonthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,\n\n\t\t\t// Check whether a format character is doubled\n\t\t\tlookAhead = function( match ) {\n\t\t\t\tvar matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );\n\t\t\t\tif ( matches ) {\n\t\t\t\t\tiFormat++;\n\t\t\t\t}\n\t\t\t\treturn matches;\n\t\t\t},\n\n\t\t\t// Format a number, with leading zero if necessary\n\t\t\tformatNumber = function( match, value, len ) {\n\t\t\t\tvar num = \"\" + value;\n\t\t\t\tif ( lookAhead( match ) ) {\n\t\t\t\t\twhile ( num.length < len ) {\n\t\t\t\t\t\tnum = \"0\" + num;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn num;\n\t\t\t},\n\n\t\t\t// Format a name, short or long as requested\n\t\t\tformatName = function( match, value, shortNames, longNames ) {\n\t\t\t\treturn ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] );\n\t\t\t},\n\t\t\toutput = \"\",\n\t\t\tliteral = false;\n\n\t\tif ( date ) {\n\t\t\tfor ( iFormat = 0; iFormat < format.length; iFormat++ ) {\n\t\t\t\tif ( literal ) {\n\t\t\t\t\tif ( format.charAt( iFormat ) === \"'\" && !lookAhead( \"'\" ) ) {\n\t\t\t\t\t\tliteral = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\toutput += format.charAt( iFormat );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tswitch ( format.charAt( iFormat ) ) {\n\t\t\t\t\t\tcase \"d\":\n\t\t\t\t\t\t\toutput += formatNumber( \"d\", date.getDate(), 2 );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"D\":\n\t\t\t\t\t\t\toutput += formatName( \"D\", date.getDay(), dayNamesShort, dayNames );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"o\":\n\t\t\t\t\t\t\toutput += formatNumber( \"o\",\n\t\t\t\t\t\t\t\tMath.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"m\":\n\t\t\t\t\t\t\toutput += formatNumber( \"m\", date.getMonth() + 1, 2 );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"M\":\n\t\t\t\t\t\t\toutput += formatName( \"M\", date.getMonth(), monthNamesShort, monthNames );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"y\":\n\t\t\t\t\t\t\toutput += ( lookAhead( \"y\" ) ? date.getFullYear() :\n\t\t\t\t\t\t\t\t( date.getFullYear() % 100 < 10 ? \"0\" : \"\" ) + date.getFullYear() % 100 );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"@\":\n\t\t\t\t\t\t\toutput += date.getTime();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"!\":\n\t\t\t\t\t\t\toutput += date.getTime() * 10000 + this._ticksTo1970;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"'\":\n\t\t\t\t\t\t\tif ( lookAhead( \"'\" ) ) {\n\t\t\t\t\t\t\t\toutput += \"'\";\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tliteral = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\toutput += format.charAt( iFormat );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn output;\n\t},\n\n\t/* Extract all possible characters from the date format. */\n\t_possibleChars: function( format ) {\n\t\tvar iFormat,\n\t\t\tchars = \"\",\n\t\t\tliteral = false,\n\n\t\t\t// Check whether a format character is doubled\n\t\t\tlookAhead = function( match ) {\n\t\t\t\tvar matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );\n\t\t\t\tif ( matches ) {\n\t\t\t\t\tiFormat++;\n\t\t\t\t}\n\t\t\t\treturn matches;\n\t\t\t};\n\n\t\tfor ( iFormat = 0; iFormat < format.length; iFormat++ ) {\n\t\t\tif ( literal ) {\n\t\t\t\tif ( format.charAt( iFormat ) === \"'\" && !lookAhead( \"'\" ) ) {\n\t\t\t\t\tliteral = false;\n\t\t\t\t} else {\n\t\t\t\t\tchars += format.charAt( iFormat );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tswitch ( format.charAt( iFormat ) ) {\n\t\t\t\t\tcase \"d\": case \"m\": case \"y\": case \"@\":\n\t\t\t\t\t\tchars += \"0123456789\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"D\": case \"M\":\n\t\t\t\t\t\treturn null; // Accept anything\n\t\t\t\t\tcase \"'\":\n\t\t\t\t\t\tif ( lookAhead( \"'\" ) ) {\n\t\t\t\t\t\t\tchars += \"'\";\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tliteral = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tchars += format.charAt( iFormat );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn chars;\n\t},\n\n\t/* Get a setting value, defaulting if necessary. */\n\t_get: function( inst, name ) {\n\t\treturn inst.settings[ name ] !== undefined ?\n\t\t\tinst.settings[ name ] : this._defaults[ name ];\n\t},\n\n\t/* Parse existing date and initialise date picker. */\n\t_setDateFromField: function( inst, noDefault ) {\n\t\tif ( inst.input.val() === inst.lastVal ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar dateFormat = this._get( inst, \"dateFormat\" ),\n\t\t\tdates = inst.lastVal = inst.input ? inst.input.val() : null,\n\t\t\tdefaultDate = this._getDefaultDate( inst ),\n\t\t\tdate = defaultDate,\n\t\t\tsettings = this._getFormatConfig( inst );\n\n\t\ttry {\n\t\t\tdate = this.parseDate( dateFormat, dates, settings ) || defaultDate;\n\t\t} catch ( event ) {\n\t\t\tdates = ( noDefault ? \"\" : dates );\n\t\t}\n\t\tinst.selectedDay = date.getDate();\n\t\tinst.drawMonth = inst.selectedMonth = date.getMonth();\n\t\tinst.drawYear = inst.selectedYear = date.getFullYear();\n\t\tinst.currentDay = ( dates ? date.getDate() : 0 );\n\t\tinst.currentMonth = ( dates ? date.getMonth() : 0 );\n\t\tinst.currentYear = ( dates ? date.getFullYear() : 0 );\n\t\tthis._adjustInstDate( inst );\n\t},\n\n\t/* Retrieve the default date shown on opening. */\n\t_getDefaultDate: function( inst ) {\n\t\treturn this._restrictMinMax( inst,\n\t\t\tthis._determineDate( inst, this._get( inst, \"defaultDate\" ), new Date() ) );\n\t},\n\n\t/* A date may be specified as an exact value or a relative one. */\n\t_determineDate: function( inst, date, defaultDate ) {\n\t\tvar offsetNumeric = function( offset ) {\n\t\t\t\tvar date = new Date();\n\t\t\t\tdate.setDate( date.getDate() + offset );\n\t\t\t\treturn date;\n\t\t\t},\n\t\t\toffsetString = function( offset ) {\n\t\t\t\ttry {\n\t\t\t\t\treturn $.datepicker.parseDate( $.datepicker._get( inst, \"dateFormat\" ),\n\t\t\t\t\t\toffset, $.datepicker._getFormatConfig( inst ) );\n\t\t\t\t}\n\t\t\t\tcatch ( e ) {\n\n\t\t\t\t\t// Ignore\n\t\t\t\t}\n\n\t\t\t\tvar date = ( offset.toLowerCase().match( /^c/ ) ?\n\t\t\t\t\t$.datepicker._getDate( inst ) : null ) || new Date(),\n\t\t\t\t\tyear = date.getFullYear(),\n\t\t\t\t\tmonth = date.getMonth(),\n\t\t\t\t\tday = date.getDate(),\n\t\t\t\t\tpattern = /([+\\-]?[0-9]+)\\s*(d|D|w|W|m|M|y|Y)?/g,\n\t\t\t\t\tmatches = pattern.exec( offset );\n\n\t\t\t\twhile ( matches ) {\n\t\t\t\t\tswitch ( matches[ 2 ] || \"d\" ) {\n\t\t\t\t\t\tcase \"d\" : case \"D\" :\n\t\t\t\t\t\t\tday += parseInt( matches[ 1 ], 10 ); break;\n\t\t\t\t\t\tcase \"w\" : case \"W\" :\n\t\t\t\t\t\t\tday += parseInt( matches[ 1 ], 10 ) * 7; break;\n\t\t\t\t\t\tcase \"m\" : case \"M\" :\n\t\t\t\t\t\t\tmonth += parseInt( matches[ 1 ], 10 );\n\t\t\t\t\t\t\tday = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"y\": case \"Y\" :\n\t\t\t\t\t\t\tyear += parseInt( matches[ 1 ], 10 );\n\t\t\t\t\t\t\tday = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tmatches = pattern.exec( offset );\n\t\t\t\t}\n\t\t\t\treturn new Date( year, month, day );\n\t\t\t},\n\t\t\tnewDate = ( date == null || date === \"\" ? defaultDate : ( typeof date === \"string\" ? offsetString( date ) :\n\t\t\t\t( typeof date === \"number\" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );\n\n\t\tnewDate = ( newDate && newDate.toString() === \"Invalid Date\" ? defaultDate : newDate );\n\t\tif ( newDate ) {\n\t\t\tnewDate.setHours( 0 );\n\t\t\tnewDate.setMinutes( 0 );\n\t\t\tnewDate.setSeconds( 0 );\n\t\t\tnewDate.setMilliseconds( 0 );\n\t\t}\n\t\treturn this._daylightSavingAdjust( newDate );\n\t},\n\n\t/* Handle switch to/from daylight saving.\n\t * Hours may be non-zero on daylight saving cut-over:\n\t * > 12 when midnight changeover, but then cannot generate\n\t * midnight datetime, so jump to 1AM, otherwise reset.\n\t * @param  date  (Date) the date to check\n\t * @return  (Date) the corrected date\n\t */\n\t_daylightSavingAdjust: function( date ) {\n\t\tif ( !date ) {\n\t\t\treturn null;\n\t\t}\n\t\tdate.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );\n\t\treturn date;\n\t},\n\n\t/* Set the date(s) directly. */\n\t_setDate: function( inst, date, noChange ) {\n\t\tvar clear = !date,\n\t\t\torigMonth = inst.selectedMonth,\n\t\t\torigYear = inst.selectedYear,\n\t\t\tnewDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );\n\n\t\tinst.selectedDay = inst.currentDay = newDate.getDate();\n\t\tinst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();\n\t\tinst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();\n\t\tif ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) {\n\t\t\tthis._notifyChange( inst );\n\t\t}\n\t\tthis._adjustInstDate( inst );\n\t\tif ( inst.input ) {\n\t\t\tinst.input.val( clear ? \"\" : this._formatDate( inst ) );\n\t\t}\n\t},\n\n\t/* Retrieve the date(s) directly. */\n\t_getDate: function( inst ) {\n\t\tvar startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === \"\" ) ? null :\n\t\t\tthis._daylightSavingAdjust( new Date(\n\t\t\tinst.currentYear, inst.currentMonth, inst.currentDay ) ) );\n\t\t\treturn startDate;\n\t},\n\n\t/* Attach the onxxx handlers.  These are declared statically so\n\t * they work with static code transformers like Caja.\n\t */\n\t_attachHandlers: function( inst ) {\n\t\tvar stepMonths = this._get( inst, \"stepMonths\" ),\n\t\t\tid = \"#\" + inst.id.replace( /\\\\\\\\/g, \"\\\\\" );\n\t\tinst.dpDiv.find( \"[data-handler]\" ).map( function() {\n\t\t\tvar handler = {\n\t\t\t\tprev: function() {\n\t\t\t\t\t$.datepicker._adjustDate( id, -stepMonths, \"M\" );\n\t\t\t\t},\n\t\t\t\tnext: function() {\n\t\t\t\t\t$.datepicker._adjustDate( id, +stepMonths, \"M\" );\n\t\t\t\t},\n\t\t\t\thide: function() {\n\t\t\t\t\t$.datepicker._hideDatepicker();\n\t\t\t\t},\n\t\t\t\ttoday: function() {\n\t\t\t\t\t$.datepicker._gotoToday( id );\n\t\t\t\t},\n\t\t\t\tselectDay: function() {\n\t\t\t\t\t$.datepicker._selectDay( id, +this.getAttribute( \"data-month\" ), +this.getAttribute( \"data-year\" ), this );\n\t\t\t\t\treturn false;\n\t\t\t\t},\n\t\t\t\tselectMonth: function() {\n\t\t\t\t\t$.datepicker._selectMonthYear( id, this, \"M\" );\n\t\t\t\t\treturn false;\n\t\t\t\t},\n\t\t\t\tselectYear: function() {\n\t\t\t\t\t$.datepicker._selectMonthYear( id, this, \"Y\" );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t};\n\t\t\t$( this ).on( this.getAttribute( \"data-event\" ), handler[ this.getAttribute( \"data-handler\" ) ] );\n\t\t} );\n\t},\n\n\t/* Generate the HTML for the current state of the date picker. */\n\t_generateHTML: function( inst ) {\n\t\tvar maxDraw, prevText, prev, nextText, next, currentText, gotoDate,\n\t\t\tcontrols, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,\n\t\t\tmonthNames, monthNamesShort, beforeShowDay, showOtherMonths,\n\t\t\tselectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,\n\t\t\tcornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,\n\t\t\tprintDate, dRow, tbody, daySettings, otherMonth, unselectable,\n\t\t\ttempDate = new Date(),\n\t\t\ttoday = this._daylightSavingAdjust(\n\t\t\t\tnew Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time\n\t\t\tisRTL = this._get( inst, \"isRTL\" ),\n\t\t\tshowButtonPanel = this._get( inst, \"showButtonPanel\" ),\n\t\t\thideIfNoPrevNext = this._get( inst, \"hideIfNoPrevNext\" ),\n\t\t\tnavigationAsDateFormat = this._get( inst, \"navigationAsDateFormat\" ),\n\t\t\tnumMonths = this._getNumberOfMonths( inst ),\n\t\t\tshowCurrentAtPos = this._get( inst, \"showCurrentAtPos\" ),\n\t\t\tstepMonths = this._get( inst, \"stepMonths\" ),\n\t\t\tisMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),\n\t\t\tcurrentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :\n\t\t\t\tnew Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),\n\t\t\tminDate = this._getMinMaxDate( inst, \"min\" ),\n\t\t\tmaxDate = this._getMinMaxDate( inst, \"max\" ),\n\t\t\tdrawMonth = inst.drawMonth - showCurrentAtPos,\n\t\t\tdrawYear = inst.drawYear;\n\n\t\tif ( drawMonth < 0 ) {\n\t\t\tdrawMonth += 12;\n\t\t\tdrawYear--;\n\t\t}\n\t\tif ( maxDate ) {\n\t\t\tmaxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(),\n\t\t\t\tmaxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );\n\t\t\tmaxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );\n\t\t\twhile ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {\n\t\t\t\tdrawMonth--;\n\t\t\t\tif ( drawMonth < 0 ) {\n\t\t\t\t\tdrawMonth = 11;\n\t\t\t\t\tdrawYear--;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinst.drawMonth = drawMonth;\n\t\tinst.drawYear = drawYear;\n\n\t\tprevText = this._get( inst, \"prevText\" );\n\t\tprevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,\n\t\t\tthis._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ),\n\t\t\tthis._getFormatConfig( inst ) ) );\n\n\t\tprev = ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ?\n\t\t\t\"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'\" +\n\t\t\t\" title='\" + prevText + \"'><span class='ui-icon ui-icon-circle-triangle-\" + ( isRTL ? \"e\" : \"w\" ) + \"'>\" + prevText + \"</span></a>\" :\n\t\t\t( hideIfNoPrevNext ? \"\" : \"<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='\" + prevText + \"'><span class='ui-icon ui-icon-circle-triangle-\" + ( isRTL ? \"e\" : \"w\" ) + \"'>\" + prevText + \"</span></a>\" ) );\n\n\t\tnextText = this._get( inst, \"nextText\" );\n\t\tnextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText,\n\t\t\tthis._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ),\n\t\t\tthis._getFormatConfig( inst ) ) );\n\n\t\tnext = ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ?\n\t\t\t\"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'\" +\n\t\t\t\" title='\" + nextText + \"'><span class='ui-icon ui-icon-circle-triangle-\" + ( isRTL ? \"w\" : \"e\" ) + \"'>\" + nextText + \"</span></a>\" :\n\t\t\t( hideIfNoPrevNext ? \"\" : \"<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='\" + nextText + \"'><span class='ui-icon ui-icon-circle-triangle-\" + ( isRTL ? \"w\" : \"e\" ) + \"'>\" + nextText + \"</span></a>\" ) );\n\n\t\tcurrentText = this._get( inst, \"currentText\" );\n\t\tgotoDate = ( this._get( inst, \"gotoCurrent\" ) && inst.currentDay ? currentDate : today );\n\t\tcurrentText = ( !navigationAsDateFormat ? currentText :\n\t\t\tthis.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) );\n\n\t\tcontrols = ( !inst.inline ? \"<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>\" +\n\t\t\tthis._get( inst, \"closeText\" ) + \"</button>\" : \"\" );\n\n\t\tbuttonPanel = ( showButtonPanel ) ? \"<div class='ui-datepicker-buttonpane ui-widget-content'>\" + ( isRTL ? controls : \"\" ) +\n\t\t\t( this._isInRange( inst, gotoDate ) ? \"<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'\" +\n\t\t\t\">\" + currentText + \"</button>\" : \"\" ) + ( isRTL ? \"\" : controls ) + \"</div>\" : \"\";\n\n\t\tfirstDay = parseInt( this._get( inst, \"firstDay\" ), 10 );\n\t\tfirstDay = ( isNaN( firstDay ) ? 0 : firstDay );\n\n\t\tshowWeek = this._get( inst, \"showWeek\" );\n\t\tdayNames = this._get( inst, \"dayNames\" );\n\t\tdayNamesMin = this._get( inst, \"dayNamesMin\" );\n\t\tmonthNames = this._get( inst, \"monthNames\" );\n\t\tmonthNamesShort = this._get( inst, \"monthNamesShort\" );\n\t\tbeforeShowDay = this._get( inst, \"beforeShowDay\" );\n\t\tshowOtherMonths = this._get( inst, \"showOtherMonths\" );\n\t\tselectOtherMonths = this._get( inst, \"selectOtherMonths\" );\n\t\tdefaultDate = this._getDefaultDate( inst );\n\t\thtml = \"\";\n\n\t\tfor ( row = 0; row < numMonths[ 0 ]; row++ ) {\n\t\t\tgroup = \"\";\n\t\t\tthis.maxRows = 4;\n\t\t\tfor ( col = 0; col < numMonths[ 1 ]; col++ ) {\n\t\t\t\tselectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );\n\t\t\t\tcornerClass = \" ui-corner-all\";\n\t\t\t\tcalender = \"\";\n\t\t\t\tif ( isMultiMonth ) {\n\t\t\t\t\tcalender += \"<div class='ui-datepicker-group\";\n\t\t\t\t\tif ( numMonths[ 1 ] > 1 ) {\n\t\t\t\t\t\tswitch ( col ) {\n\t\t\t\t\t\t\tcase 0: calender += \" ui-datepicker-group-first\";\n\t\t\t\t\t\t\t\tcornerClass = \" ui-corner-\" + ( isRTL ? \"right\" : \"left\" ); break;\n\t\t\t\t\t\t\tcase numMonths[ 1 ] - 1: calender += \" ui-datepicker-group-last\";\n\t\t\t\t\t\t\t\tcornerClass = \" ui-corner-\" + ( isRTL ? \"left\" : \"right\" ); break;\n\t\t\t\t\t\t\tdefault: calender += \" ui-datepicker-group-middle\"; cornerClass = \"\"; break;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcalender += \"'>\";\n\t\t\t\t}\n\t\t\t\tcalender += \"<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix\" + cornerClass + \"'>\" +\n\t\t\t\t\t( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : \"\" ) +\n\t\t\t\t\t( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : \"\" ) +\n\t\t\t\t\tthis._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate,\n\t\t\t\t\trow > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers\n\t\t\t\t\t\"</div><table class='ui-datepicker-calendar'><thead>\" +\n\t\t\t\t\t\"<tr>\";\n\t\t\t\tthead = ( showWeek ? \"<th class='ui-datepicker-week-col'>\" + this._get( inst, \"weekHeader\" ) + \"</th>\" : \"\" );\n\t\t\t\tfor ( dow = 0; dow < 7; dow++ ) { // days of the week\n\t\t\t\t\tday = ( dow + firstDay ) % 7;\n\t\t\t\t\tthead += \"<th scope='col'\" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? \" class='ui-datepicker-week-end'\" : \"\" ) + \">\" +\n\t\t\t\t\t\t\"<span title='\" + dayNames[ day ] + \"'>\" + dayNamesMin[ day ] + \"</span></th>\";\n\t\t\t\t}\n\t\t\t\tcalender += thead + \"</tr></thead><tbody>\";\n\t\t\t\tdaysInMonth = this._getDaysInMonth( drawYear, drawMonth );\n\t\t\t\tif ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {\n\t\t\t\t\tinst.selectedDay = Math.min( inst.selectedDay, daysInMonth );\n\t\t\t\t}\n\t\t\t\tleadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;\n\t\t\t\tcurRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate\n\t\t\t\tnumRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)\n\t\t\t\tthis.maxRows = numRows;\n\t\t\t\tprintDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );\n\t\t\t\tfor ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows\n\t\t\t\t\tcalender += \"<tr>\";\n\t\t\t\t\ttbody = ( !showWeek ? \"\" : \"<td class='ui-datepicker-week-col'>\" +\n\t\t\t\t\t\tthis._get( inst, \"calculateWeek\" )( printDate ) + \"</td>\" );\n\t\t\t\t\tfor ( dow = 0; dow < 7; dow++ ) { // create date picker days\n\t\t\t\t\t\tdaySettings = ( beforeShowDay ?\n\t\t\t\t\t\t\tbeforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, \"\" ] );\n\t\t\t\t\t\totherMonth = ( printDate.getMonth() !== drawMonth );\n\t\t\t\t\t\tunselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] ||\n\t\t\t\t\t\t\t( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );\n\t\t\t\t\t\ttbody += \"<td class='\" +\n\t\t\t\t\t\t\t( ( dow + firstDay + 6 ) % 7 >= 5 ? \" ui-datepicker-week-end\" : \"\" ) + // highlight weekends\n\t\t\t\t\t\t\t( otherMonth ? \" ui-datepicker-other-month\" : \"\" ) + // highlight days from other months\n\t\t\t\t\t\t\t( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key\n\t\t\t\t\t\t\t( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ?\n\n\t\t\t\t\t\t\t// or defaultDate is current printedDate and defaultDate is selectedDate\n\t\t\t\t\t\t\t\" \" + this._dayOverClass : \"\" ) + // highlight selected day\n\t\t\t\t\t\t\t( unselectable ? \" \" + this._unselectableClass + \" ui-state-disabled\" : \"\" ) +  // highlight unselectable days\n\t\t\t\t\t\t\t( otherMonth && !showOtherMonths ? \"\" : \" \" + daySettings[ 1 ] + // highlight custom dates\n\t\t\t\t\t\t\t( printDate.getTime() === currentDate.getTime() ? \" \" + this._currentClass : \"\" ) + // highlight selected day\n\t\t\t\t\t\t\t( printDate.getTime() === today.getTime() ? \" ui-datepicker-today\" : \"\" ) ) + \"'\" + // highlight today (if different)\n\t\t\t\t\t\t\t( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? \" title='\" + daySettings[ 2 ].replace( /'/g, \"&#39;\" ) + \"'\" : \"\" ) + // cell title\n\t\t\t\t\t\t\t( unselectable ? \"\" : \" data-handler='selectDay' data-event='click' data-month='\" + printDate.getMonth() + \"' data-year='\" + printDate.getFullYear() + \"'\" ) + \">\" + // actions\n\t\t\t\t\t\t\t( otherMonth && !showOtherMonths ? \"&#xa0;\" : // display for other months\n\t\t\t\t\t\t\t( unselectable ? \"<span class='ui-state-default'>\" + printDate.getDate() + \"</span>\" : \"<a class='ui-state-default\" +\n\t\t\t\t\t\t\t( printDate.getTime() === today.getTime() ? \" ui-state-highlight\" : \"\" ) +\n\t\t\t\t\t\t\t( printDate.getTime() === currentDate.getTime() ? \" ui-state-active\" : \"\" ) + // highlight selected day\n\t\t\t\t\t\t\t( otherMonth ? \" ui-priority-secondary\" : \"\" ) + // distinguish dates from other months\n\t\t\t\t\t\t\t\"' href='#'>\" + printDate.getDate() + \"</a>\" ) ) + \"</td>\"; // display selectable date\n\t\t\t\t\t\tprintDate.setDate( printDate.getDate() + 1 );\n\t\t\t\t\t\tprintDate = this._daylightSavingAdjust( printDate );\n\t\t\t\t\t}\n\t\t\t\t\tcalender += tbody + \"</tr>\";\n\t\t\t\t}\n\t\t\t\tdrawMonth++;\n\t\t\t\tif ( drawMonth > 11 ) {\n\t\t\t\t\tdrawMonth = 0;\n\t\t\t\t\tdrawYear++;\n\t\t\t\t}\n\t\t\t\tcalender += \"</tbody></table>\" + ( isMultiMonth ? \"</div>\" +\n\t\t\t\t\t\t\t( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? \"<div class='ui-datepicker-row-break'></div>\" : \"\" ) : \"\" );\n\t\t\t\tgroup += calender;\n\t\t\t}\n\t\t\thtml += group;\n\t\t}\n\t\thtml += buttonPanel;\n\t\tinst._keyEvent = false;\n\t\treturn html;\n\t},\n\n\t/* Generate the month and year header. */\n\t_generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate,\n\t\t\tsecondary, monthNames, monthNamesShort ) {\n\n\t\tvar inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,\n\t\t\tchangeMonth = this._get( inst, \"changeMonth\" ),\n\t\t\tchangeYear = this._get( inst, \"changeYear\" ),\n\t\t\tshowMonthAfterYear = this._get( inst, \"showMonthAfterYear\" ),\n\t\t\thtml = \"<div class='ui-datepicker-title'>\",\n\t\t\tmonthHtml = \"\";\n\n\t\t// Month selection\n\t\tif ( secondary || !changeMonth ) {\n\t\t\tmonthHtml += \"<span class='ui-datepicker-month'>\" + monthNames[ drawMonth ] + \"</span>\";\n\t\t} else {\n\t\t\tinMinYear = ( minDate && minDate.getFullYear() === drawYear );\n\t\t\tinMaxYear = ( maxDate && maxDate.getFullYear() === drawYear );\n\t\t\tmonthHtml += \"<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>\";\n\t\t\tfor ( month = 0; month < 12; month++ ) {\n\t\t\t\tif ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) {\n\t\t\t\t\tmonthHtml += \"<option value='\" + month + \"'\" +\n\t\t\t\t\t\t( month === drawMonth ? \" selected='selected'\" : \"\" ) +\n\t\t\t\t\t\t\">\" + monthNamesShort[ month ] + \"</option>\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tmonthHtml += \"</select>\";\n\t\t}\n\n\t\tif ( !showMonthAfterYear ) {\n\t\t\thtml += monthHtml + ( secondary || !( changeMonth && changeYear ) ? \"&#xa0;\" : \"\" );\n\t\t}\n\n\t\t// Year selection\n\t\tif ( !inst.yearshtml ) {\n\t\t\tinst.yearshtml = \"\";\n\t\t\tif ( secondary || !changeYear ) {\n\t\t\t\thtml += \"<span class='ui-datepicker-year'>\" + drawYear + \"</span>\";\n\t\t\t} else {\n\n\t\t\t\t// determine range of years to display\n\t\t\t\tyears = this._get( inst, \"yearRange\" ).split( \":\" );\n\t\t\t\tthisYear = new Date().getFullYear();\n\t\t\t\tdetermineYear = function( value ) {\n\t\t\t\t\tvar year = ( value.match( /c[+\\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :\n\t\t\t\t\t\t( value.match( /[+\\-].*/ ) ? thisYear + parseInt( value, 10 ) :\n\t\t\t\t\t\tparseInt( value, 10 ) ) );\n\t\t\t\t\treturn ( isNaN( year ) ? thisYear : year );\n\t\t\t\t};\n\t\t\t\tyear = determineYear( years[ 0 ] );\n\t\t\t\tendYear = Math.max( year, determineYear( years[ 1 ] || \"\" ) );\n\t\t\t\tyear = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );\n\t\t\t\tendYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );\n\t\t\t\tinst.yearshtml += \"<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>\";\n\t\t\t\tfor ( ; year <= endYear; year++ ) {\n\t\t\t\t\tinst.yearshtml += \"<option value='\" + year + \"'\" +\n\t\t\t\t\t\t( year === drawYear ? \" selected='selected'\" : \"\" ) +\n\t\t\t\t\t\t\">\" + year + \"</option>\";\n\t\t\t\t}\n\t\t\t\tinst.yearshtml += \"</select>\";\n\n\t\t\t\thtml += inst.yearshtml;\n\t\t\t\tinst.yearshtml = null;\n\t\t\t}\n\t\t}\n\n\t\thtml += this._get( inst, \"yearSuffix\" );\n\t\tif ( showMonthAfterYear ) {\n\t\t\thtml += ( secondary || !( changeMonth && changeYear ) ? \"&#xa0;\" : \"\" ) + monthHtml;\n\t\t}\n\t\thtml += \"</div>\"; // Close datepicker_header\n\t\treturn html;\n\t},\n\n\t/* Adjust one of the date sub-fields. */\n\t_adjustInstDate: function( inst, offset, period ) {\n\t\tvar year = inst.selectedYear + ( period === \"Y\" ? offset : 0 ),\n\t\t\tmonth = inst.selectedMonth + ( period === \"M\" ? offset : 0 ),\n\t\t\tday = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === \"D\" ? offset : 0 ),\n\t\t\tdate = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );\n\n\t\tinst.selectedDay = date.getDate();\n\t\tinst.drawMonth = inst.selectedMonth = date.getMonth();\n\t\tinst.drawYear = inst.selectedYear = date.getFullYear();\n\t\tif ( period === \"M\" || period === \"Y\" ) {\n\t\t\tthis._notifyChange( inst );\n\t\t}\n\t},\n\n\t/* Ensure a date is within any min/max bounds. */\n\t_restrictMinMax: function( inst, date ) {\n\t\tvar minDate = this._getMinMaxDate( inst, \"min\" ),\n\t\t\tmaxDate = this._getMinMaxDate( inst, \"max\" ),\n\t\t\tnewDate = ( minDate && date < minDate ? minDate : date );\n\t\treturn ( maxDate && newDate > maxDate ? maxDate : newDate );\n\t},\n\n\t/* Notify change of month/year. */\n\t_notifyChange: function( inst ) {\n\t\tvar onChange = this._get( inst, \"onChangeMonthYear\" );\n\t\tif ( onChange ) {\n\t\t\tonChange.apply( ( inst.input ? inst.input[ 0 ] : null ),\n\t\t\t\t[ inst.selectedYear, inst.selectedMonth + 1, inst ] );\n\t\t}\n\t},\n\n\t/* Determine the number of months to show. */\n\t_getNumberOfMonths: function( inst ) {\n\t\tvar numMonths = this._get( inst, \"numberOfMonths\" );\n\t\treturn ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === \"number\" ? [ 1, numMonths ] : numMonths ) );\n\t},\n\n\t/* Determine the current maximum date - ensure no time components are set. */\n\t_getMinMaxDate: function( inst, minMax ) {\n\t\treturn this._determineDate( inst, this._get( inst, minMax + \"Date\" ), null );\n\t},\n\n\t/* Find the number of days in a given month. */\n\t_getDaysInMonth: function( year, month ) {\n\t\treturn 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();\n\t},\n\n\t/* Find the day of the week of the first of a month. */\n\t_getFirstDayOfMonth: function( year, month ) {\n\t\treturn new Date( year, month, 1 ).getDay();\n\t},\n\n\t/* Determines if we should allow a \"next/prev\" month display change. */\n\t_canAdjustMonth: function( inst, offset, curYear, curMonth ) {\n\t\tvar numMonths = this._getNumberOfMonths( inst ),\n\t\t\tdate = this._daylightSavingAdjust( new Date( curYear,\n\t\t\tcurMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );\n\n\t\tif ( offset < 0 ) {\n\t\t\tdate.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );\n\t\t}\n\t\treturn this._isInRange( inst, date );\n\t},\n\n\t/* Is the given date in the accepted range? */\n\t_isInRange: function( inst, date ) {\n\t\tvar yearSplit, currentYear,\n\t\t\tminDate = this._getMinMaxDate( inst, \"min\" ),\n\t\t\tmaxDate = this._getMinMaxDate( inst, \"max\" ),\n\t\t\tminYear = null,\n\t\t\tmaxYear = null,\n\t\t\tyears = this._get( inst, \"yearRange\" );\n\t\t\tif ( years ) {\n\t\t\t\tyearSplit = years.split( \":\" );\n\t\t\t\tcurrentYear = new Date().getFullYear();\n\t\t\t\tminYear = parseInt( yearSplit[ 0 ], 10 );\n\t\t\t\tmaxYear = parseInt( yearSplit[ 1 ], 10 );\n\t\t\t\tif ( yearSplit[ 0 ].match( /[+\\-].*/ ) ) {\n\t\t\t\t\tminYear += currentYear;\n\t\t\t\t}\n\t\t\t\tif ( yearSplit[ 1 ].match( /[+\\-].*/ ) ) {\n\t\t\t\t\tmaxYear += currentYear;\n\t\t\t\t}\n\t\t\t}\n\n\t\treturn ( ( !minDate || date.getTime() >= minDate.getTime() ) &&\n\t\t\t( !maxDate || date.getTime() <= maxDate.getTime() ) &&\n\t\t\t( !minYear || date.getFullYear() >= minYear ) &&\n\t\t\t( !maxYear || date.getFullYear() <= maxYear ) );\n\t},\n\n\t/* Provide the configuration settings for formatting/parsing. */\n\t_getFormatConfig: function( inst ) {\n\t\tvar shortYearCutoff = this._get( inst, \"shortYearCutoff\" );\n\t\tshortYearCutoff = ( typeof shortYearCutoff !== \"string\" ? shortYearCutoff :\n\t\t\tnew Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) );\n\t\treturn { shortYearCutoff: shortYearCutoff,\n\t\t\tdayNamesShort: this._get( inst, \"dayNamesShort\" ), dayNames: this._get( inst, \"dayNames\" ),\n\t\t\tmonthNamesShort: this._get( inst, \"monthNamesShort\" ), monthNames: this._get( inst, \"monthNames\" ) };\n\t},\n\n\t/* Format the given date for display. */\n\t_formatDate: function( inst, day, month, year ) {\n\t\tif ( !day ) {\n\t\t\tinst.currentDay = inst.selectedDay;\n\t\t\tinst.currentMonth = inst.selectedMonth;\n\t\t\tinst.currentYear = inst.selectedYear;\n\t\t}\n\t\tvar date = ( day ? ( typeof day === \"object\" ? day :\n\t\t\tthis._daylightSavingAdjust( new Date( year, month, day ) ) ) :\n\t\t\tthis._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );\n\t\treturn this.formatDate( this._get( inst, \"dateFormat\" ), date, this._getFormatConfig( inst ) );\n\t}\n} );\n\n/*\n * Bind hover events for datepicker elements.\n * Done via delegate so the binding only occurs once in the lifetime of the parent div.\n * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.\n */\nfunction datepicker_bindHover( dpDiv ) {\n\tvar selector = \"button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a\";\n\treturn dpDiv.on( \"mouseout\", selector, function() {\n\t\t\t$( this ).removeClass( \"ui-state-hover\" );\n\t\t\tif ( this.className.indexOf( \"ui-datepicker-prev\" ) !== -1 ) {\n\t\t\t\t$( this ).removeClass( \"ui-datepicker-prev-hover\" );\n\t\t\t}\n\t\t\tif ( this.className.indexOf( \"ui-datepicker-next\" ) !== -1 ) {\n\t\t\t\t$( this ).removeClass( \"ui-datepicker-next-hover\" );\n\t\t\t}\n\t\t} )\n\t\t.on( \"mouseover\", selector, datepicker_handleMouseover );\n}\n\nfunction datepicker_handleMouseover() {\n\tif ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {\n\t\t$( this ).parents( \".ui-datepicker-calendar\" ).find( \"a\" ).removeClass( \"ui-state-hover\" );\n\t\t$( this ).addClass( \"ui-state-hover\" );\n\t\tif ( this.className.indexOf( \"ui-datepicker-prev\" ) !== -1 ) {\n\t\t\t$( this ).addClass( \"ui-datepicker-prev-hover\" );\n\t\t}\n\t\tif ( this.className.indexOf( \"ui-datepicker-next\" ) !== -1 ) {\n\t\t\t$( this ).addClass( \"ui-datepicker-next-hover\" );\n\t\t}\n\t}\n}\n\n/* jQuery extend now ignores nulls! */\nfunction datepicker_extendRemove( target, props ) {\n\t$.extend( target, props );\n\tfor ( var name in props ) {\n\t\tif ( props[ name ] == null ) {\n\t\t\ttarget[ name ] = props[ name ];\n\t\t}\n\t}\n\treturn target;\n}\n\n/* Invoke the datepicker functionality.\n   @param  options  string - a command, optionally followed by additional parameters or\n\t\t\t\t\tObject - settings for attaching new datepicker functionality\n   @return  jQuery object */\n$.fn.datepicker = function( options ) {\n\n\t/* Verify an empty collection wasn't passed - Fixes #6976 */\n\tif ( !this.length ) {\n\t\treturn this;\n\t}\n\n\t/* Initialise the date picker. */\n\tif ( !$.datepicker.initialized ) {\n\t\t$( document ).on( \"mousedown\", $.datepicker._checkExternalClick );\n\t\t$.datepicker.initialized = true;\n\t}\n\n\t/* Append datepicker main container to body if not exist. */\n\tif ( $( \"#\" + $.datepicker._mainDivId ).length === 0 ) {\n\t\t$( \"body\" ).append( $.datepicker.dpDiv );\n\t}\n\n\tvar otherArgs = Array.prototype.slice.call( arguments, 1 );\n\tif ( typeof options === \"string\" && ( options === \"isDisabled\" || options === \"getDate\" || options === \"widget\" ) ) {\n\t\treturn $.datepicker[ \"_\" + options + \"Datepicker\" ].\n\t\t\tapply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );\n\t}\n\tif ( options === \"option\" && arguments.length === 2 && typeof arguments[ 1 ] === \"string\" ) {\n\t\treturn $.datepicker[ \"_\" + options + \"Datepicker\" ].\n\t\t\tapply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );\n\t}\n\treturn this.each( function() {\n\t\ttypeof options === \"string\" ?\n\t\t\t$.datepicker[ \"_\" + options + \"Datepicker\" ].\n\t\t\t\tapply( $.datepicker, [ this ].concat( otherArgs ) ) :\n\t\t\t$.datepicker._attachDatepicker( this, options );\n\t} );\n};\n\n$.datepicker = new Datepicker(); // singleton instance\n$.datepicker.initialized = false;\n$.datepicker.uuid = new Date().getTime();\n$.datepicker.version = \"1.12.1\";\n\nvar widgetsDatepicker = $.datepicker;\n\n\n\n\n// This file is deprecated\nvar ie = $.ui.ie = !!/msie [\\w.]+/.exec( navigator.userAgent.toLowerCase() );\n\n/*!\n * jQuery UI Mouse 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Mouse\n//>>group: Widgets\n//>>description: Abstracts mouse-based interactions to assist in creating certain widgets.\n//>>docs: http://api.jqueryui.com/mouse/\n\n\n\nvar mouseHandled = false;\n$( document ).on( \"mouseup\", function() {\n\tmouseHandled = false;\n} );\n\nvar widgetsMouse = $.widget( \"ui.mouse\", {\n\tversion: \"1.12.1\",\n\toptions: {\n\t\tcancel: \"input, textarea, button, select, option\",\n\t\tdistance: 1,\n\t\tdelay: 0\n\t},\n\t_mouseInit: function() {\n\t\tvar that = this;\n\n\t\tthis.element\n\t\t\t.on( \"mousedown.\" + this.widgetName, function( event ) {\n\t\t\t\treturn that._mouseDown( event );\n\t\t\t} )\n\t\t\t.on( \"click.\" + this.widgetName, function( event ) {\n\t\t\t\tif ( true === $.data( event.target, that.widgetName + \".preventClickEvent\" ) ) {\n\t\t\t\t\t$.removeData( event.target, that.widgetName + \".preventClickEvent\" );\n\t\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t} );\n\n\t\tthis.started = false;\n\t},\n\n\t// TODO: make sure destroying one instance of mouse doesn't mess with\n\t// other instances of mouse\n\t_mouseDestroy: function() {\n\t\tthis.element.off( \".\" + this.widgetName );\n\t\tif ( this._mouseMoveDelegate ) {\n\t\t\tthis.document\n\t\t\t\t.off( \"mousemove.\" + this.widgetName, this._mouseMoveDelegate )\n\t\t\t\t.off( \"mouseup.\" + this.widgetName, this._mouseUpDelegate );\n\t\t}\n\t},\n\n\t_mouseDown: function( event ) {\n\n\t\t// don't let more than one widget handle mouseStart\n\t\tif ( mouseHandled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._mouseMoved = false;\n\n\t\t// We may have missed mouseup (out of window)\n\t\t( this._mouseStarted && this._mouseUp( event ) );\n\n\t\tthis._mouseDownEvent = event;\n\n\t\tvar that = this,\n\t\t\tbtnIsLeft = ( event.which === 1 ),\n\n\t\t\t// event.target.nodeName works around a bug in IE 8 with\n\t\t\t// disabled inputs (#7620)\n\t\t\telIsCancel = ( typeof this.options.cancel === \"string\" && event.target.nodeName ?\n\t\t\t\t$( event.target ).closest( this.options.cancel ).length : false );\n\t\tif ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tthis.mouseDelayMet = !this.options.delay;\n\t\tif ( !this.mouseDelayMet ) {\n\t\t\tthis._mouseDelayTimer = setTimeout( function() {\n\t\t\t\tthat.mouseDelayMet = true;\n\t\t\t}, this.options.delay );\n\t\t}\n\n\t\tif ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {\n\t\t\tthis._mouseStarted = ( this._mouseStart( event ) !== false );\n\t\t\tif ( !this._mouseStarted ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\t// Click event may never have fired (Gecko & Opera)\n\t\tif ( true === $.data( event.target, this.widgetName + \".preventClickEvent\" ) ) {\n\t\t\t$.removeData( event.target, this.widgetName + \".preventClickEvent\" );\n\t\t}\n\n\t\t// These delegates are required to keep context\n\t\tthis._mouseMoveDelegate = function( event ) {\n\t\t\treturn that._mouseMove( event );\n\t\t};\n\t\tthis._mouseUpDelegate = function( event ) {\n\t\t\treturn that._mouseUp( event );\n\t\t};\n\n\t\tthis.document\n\t\t\t.on( \"mousemove.\" + this.widgetName, this._mouseMoveDelegate )\n\t\t\t.on( \"mouseup.\" + this.widgetName, this._mouseUpDelegate );\n\n\t\tevent.preventDefault();\n\n\t\tmouseHandled = true;\n\t\treturn true;\n\t},\n\n\t_mouseMove: function( event ) {\n\n\t\t// Only check for mouseups outside the document if you've moved inside the document\n\t\t// at least once. This prevents the firing of mouseup in the case of IE<9, which will\n\t\t// fire a mousemove event if content is placed under the cursor. See #7778\n\t\t// Support: IE <9\n\t\tif ( this._mouseMoved ) {\n\n\t\t\t// IE mouseup check - mouseup happened when mouse was out of window\n\t\t\tif ( $.ui.ie && ( !document.documentMode || document.documentMode < 9 ) &&\n\t\t\t\t\t!event.button ) {\n\t\t\t\treturn this._mouseUp( event );\n\n\t\t\t// Iframe mouseup check - mouseup occurred in another document\n\t\t\t} else if ( !event.which ) {\n\n\t\t\t\t// Support: Safari <=8 - 9\n\t\t\t\t// Safari sets which to 0 if you press any of the following keys\n\t\t\t\t// during a drag (#14461)\n\t\t\t\tif ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||\n\t\t\t\t\t\tevent.originalEvent.metaKey || event.originalEvent.shiftKey ) {\n\t\t\t\t\tthis.ignoreMissingWhich = true;\n\t\t\t\t} else if ( !this.ignoreMissingWhich ) {\n\t\t\t\t\treturn this._mouseUp( event );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( event.which || event.button ) {\n\t\t\tthis._mouseMoved = true;\n\t\t}\n\n\t\tif ( this._mouseStarted ) {\n\t\t\tthis._mouseDrag( event );\n\t\t\treturn event.preventDefault();\n\t\t}\n\n\t\tif ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {\n\t\t\tthis._mouseStarted =\n\t\t\t\t( this._mouseStart( this._mouseDownEvent, event ) !== false );\n\t\t\t( this._mouseStarted ? this._mouseDrag( event ) : this._mouseUp( event ) );\n\t\t}\n\n\t\treturn !this._mouseStarted;\n\t},\n\n\t_mouseUp: function( event ) {\n\t\tthis.document\n\t\t\t.off( \"mousemove.\" + this.widgetName, this._mouseMoveDelegate )\n\t\t\t.off( \"mouseup.\" + this.widgetName, this._mouseUpDelegate );\n\n\t\tif ( this._mouseStarted ) {\n\t\t\tthis._mouseStarted = false;\n\n\t\t\tif ( event.target === this._mouseDownEvent.target ) {\n\t\t\t\t$.data( event.target, this.widgetName + \".preventClickEvent\", true );\n\t\t\t}\n\n\t\t\tthis._mouseStop( event );\n\t\t}\n\n\t\tif ( this._mouseDelayTimer ) {\n\t\t\tclearTimeout( this._mouseDelayTimer );\n\t\t\tdelete this._mouseDelayTimer;\n\t\t}\n\n\t\tthis.ignoreMissingWhich = false;\n\t\tmouseHandled = false;\n\t\tevent.preventDefault();\n\t},\n\n\t_mouseDistanceMet: function( event ) {\n\t\treturn ( Math.max(\n\t\t\t\tMath.abs( this._mouseDownEvent.pageX - event.pageX ),\n\t\t\t\tMath.abs( this._mouseDownEvent.pageY - event.pageY )\n\t\t\t) >= this.options.distance\n\t\t);\n\t},\n\n\t_mouseDelayMet: function( /* event */ ) {\n\t\treturn this.mouseDelayMet;\n\t},\n\n\t// These are placeholder methods, to be overriden by extending plugin\n\t_mouseStart: function( /* event */ ) {},\n\t_mouseDrag: function( /* event */ ) {},\n\t_mouseStop: function( /* event */ ) {},\n\t_mouseCapture: function( /* event */ ) { return true; }\n} );\n\n\n\n\n// $.ui.plugin is deprecated. Use $.widget() extensions instead.\nvar plugin = $.ui.plugin = {\n\tadd: function( module, option, set ) {\n\t\tvar i,\n\t\t\tproto = $.ui[ module ].prototype;\n\t\tfor ( i in set ) {\n\t\t\tproto.plugins[ i ] = proto.plugins[ i ] || [];\n\t\t\tproto.plugins[ i ].push( [ option, set[ i ] ] );\n\t\t}\n\t},\n\tcall: function( instance, name, args, allowDisconnected ) {\n\t\tvar i,\n\t\t\tset = instance.plugins[ name ];\n\n\t\tif ( !set ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||\n\t\t\t\tinstance.element[ 0 ].parentNode.nodeType === 11 ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor ( i = 0; i < set.length; i++ ) {\n\t\t\tif ( instance.options[ set[ i ][ 0 ] ] ) {\n\t\t\t\tset[ i ][ 1 ].apply( instance.element, args );\n\t\t\t}\n\t\t}\n\t}\n};\n\n\n\nvar safeBlur = $.ui.safeBlur = function( element ) {\n\n\t// Support: IE9 - 10 only\n\t// If the <body> is blurred, IE will switch windows, see #9420\n\tif ( element && element.nodeName.toLowerCase() !== \"body\" ) {\n\t\t$( element ).trigger( \"blur\" );\n\t}\n};\n\n\n/*!\n * jQuery UI Draggable 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Draggable\n//>>group: Interactions\n//>>description: Enables dragging functionality for any element.\n//>>docs: http://api.jqueryui.com/draggable/\n//>>demos: http://jqueryui.com/draggable/\n//>>css.structure: ../../themes/base/draggable.css\n\n\n\n$.widget( \"ui.draggable\", $.ui.mouse, {\n\tversion: \"1.12.1\",\n\twidgetEventPrefix: \"drag\",\n\toptions: {\n\t\taddClasses: true,\n\t\tappendTo: \"parent\",\n\t\taxis: false,\n\t\tconnectToSortable: false,\n\t\tcontainment: false,\n\t\tcursor: \"auto\",\n\t\tcursorAt: false,\n\t\tgrid: false,\n\t\thandle: false,\n\t\thelper: \"original\",\n\t\tiframeFix: false,\n\t\topacity: false,\n\t\trefreshPositions: false,\n\t\trevert: false,\n\t\trevertDuration: 500,\n\t\tscope: \"default\",\n\t\tscroll: true,\n\t\tscrollSensitivity: 20,\n\t\tscrollSpeed: 20,\n\t\tsnap: false,\n\t\tsnapMode: \"both\",\n\t\tsnapTolerance: 20,\n\t\tstack: false,\n\t\tzIndex: false,\n\n\t\t// Callbacks\n\t\tdrag: null,\n\t\tstart: null,\n\t\tstop: null\n\t},\n\t_create: function() {\n\n\t\tif ( this.options.helper === \"original\" ) {\n\t\t\tthis._setPositionRelative();\n\t\t}\n\t\tif ( this.options.addClasses ) {\n\t\t\tthis._addClass( \"ui-draggable\" );\n\t\t}\n\t\tthis._setHandleClassName();\n\n\t\tthis._mouseInit();\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tthis._super( key, value );\n\t\tif ( key === \"handle\" ) {\n\t\t\tthis._removeHandleClassName();\n\t\t\tthis._setHandleClassName();\n\t\t}\n\t},\n\n\t_destroy: function() {\n\t\tif ( ( this.helper || this.element ).is( \".ui-draggable-dragging\" ) ) {\n\t\t\tthis.destroyOnClear = true;\n\t\t\treturn;\n\t\t}\n\t\tthis._removeHandleClassName();\n\t\tthis._mouseDestroy();\n\t},\n\n\t_mouseCapture: function( event ) {\n\t\tvar o = this.options;\n\n\t\t// Among others, prevent a drag on a resizable-handle\n\t\tif ( this.helper || o.disabled ||\n\t\t\t\t$( event.target ).closest( \".ui-resizable-handle\" ).length > 0 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t//Quit if we're not on a valid handle\n\t\tthis.handle = this._getHandle( event );\n\t\tif ( !this.handle ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis._blurActiveElement( event );\n\n\t\tthis._blockFrames( o.iframeFix === true ? \"iframe\" : o.iframeFix );\n\n\t\treturn true;\n\n\t},\n\n\t_blockFrames: function( selector ) {\n\t\tthis.iframeBlocks = this.document.find( selector ).map( function() {\n\t\t\tvar iframe = $( this );\n\n\t\t\treturn $( \"<div>\" )\n\t\t\t\t.css( \"position\", \"absolute\" )\n\t\t\t\t.appendTo( iframe.parent() )\n\t\t\t\t.outerWidth( iframe.outerWidth() )\n\t\t\t\t.outerHeight( iframe.outerHeight() )\n\t\t\t\t.offset( iframe.offset() )[ 0 ];\n\t\t} );\n\t},\n\n\t_unblockFrames: function() {\n\t\tif ( this.iframeBlocks ) {\n\t\t\tthis.iframeBlocks.remove();\n\t\t\tdelete this.iframeBlocks;\n\t\t}\n\t},\n\n\t_blurActiveElement: function( event ) {\n\t\tvar activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),\n\t\t\ttarget = $( event.target );\n\n\t\t// Don't blur if the event occurred on an element that is within\n\t\t// the currently focused element\n\t\t// See #10527, #12472\n\t\tif ( target.closest( activeElement ).length ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Blur any element that currently has focus, see #4261\n\t\t$.ui.safeBlur( activeElement );\n\t},\n\n\t_mouseStart: function( event ) {\n\n\t\tvar o = this.options;\n\n\t\t//Create and append the visible helper\n\t\tthis.helper = this._createHelper( event );\n\n\t\tthis._addClass( this.helper, \"ui-draggable-dragging\" );\n\n\t\t//Cache the helper size\n\t\tthis._cacheHelperProportions();\n\n\t\t//If ddmanager is used for droppables, set the global draggable\n\t\tif ( $.ui.ddmanager ) {\n\t\t\t$.ui.ddmanager.current = this;\n\t\t}\n\n\t\t/*\n\t\t * - Position generation -\n\t\t * This block generates everything position related - it's the core of draggables.\n\t\t */\n\n\t\t//Cache the margins of the original element\n\t\tthis._cacheMargins();\n\n\t\t//Store the helper's css position\n\t\tthis.cssPosition = this.helper.css( \"position\" );\n\t\tthis.scrollParent = this.helper.scrollParent( true );\n\t\tthis.offsetParent = this.helper.offsetParent();\n\t\tthis.hasFixedAncestor = this.helper.parents().filter( function() {\n\t\t\t\treturn $( this ).css( \"position\" ) === \"fixed\";\n\t\t\t} ).length > 0;\n\n\t\t//The element's absolute position on the page minus margins\n\t\tthis.positionAbs = this.element.offset();\n\t\tthis._refreshOffsets( event );\n\n\t\t//Generate the original position\n\t\tthis.originalPosition = this.position = this._generatePosition( event, false );\n\t\tthis.originalPageX = event.pageX;\n\t\tthis.originalPageY = event.pageY;\n\n\t\t//Adjust the mouse offset relative to the helper if \"cursorAt\" is supplied\n\t\t( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) );\n\n\t\t//Set a containment if given in the options\n\t\tthis._setContainment();\n\n\t\t//Trigger event + callbacks\n\t\tif ( this._trigger( \"start\", event ) === false ) {\n\t\t\tthis._clear();\n\t\t\treturn false;\n\t\t}\n\n\t\t//Recache the helper size\n\t\tthis._cacheHelperProportions();\n\n\t\t//Prepare the droppable offsets\n\t\tif ( $.ui.ddmanager && !o.dropBehaviour ) {\n\t\t\t$.ui.ddmanager.prepareOffsets( this, event );\n\t\t}\n\n\t\t// Execute the drag once - this causes the helper not to be visible before getting its\n\t\t// correct position\n\t\tthis._mouseDrag( event, true );\n\n\t\t// If the ddmanager is used for droppables, inform the manager that dragging has started\n\t\t// (see #5003)\n\t\tif ( $.ui.ddmanager ) {\n\t\t\t$.ui.ddmanager.dragStart( this, event );\n\t\t}\n\n\t\treturn true;\n\t},\n\n\t_refreshOffsets: function( event ) {\n\t\tthis.offset = {\n\t\t\ttop: this.positionAbs.top - this.margins.top,\n\t\t\tleft: this.positionAbs.left - this.margins.left,\n\t\t\tscroll: false,\n\t\t\tparent: this._getParentOffset(),\n\t\t\trelative: this._getRelativeOffset()\n\t\t};\n\n\t\tthis.offset.click = {\n\t\t\tleft: event.pageX - this.offset.left,\n\t\t\ttop: event.pageY - this.offset.top\n\t\t};\n\t},\n\n\t_mouseDrag: function( event, noPropagation ) {\n\n\t\t// reset any necessary cached properties (see #5009)\n\t\tif ( this.hasFixedAncestor ) {\n\t\t\tthis.offset.parent = this._getParentOffset();\n\t\t}\n\n\t\t//Compute the helpers position\n\t\tthis.position = this._generatePosition( event, true );\n\t\tthis.positionAbs = this._convertPositionTo( \"absolute\" );\n\n\t\t//Call plugins and callbacks and use the resulting position if something is returned\n\t\tif ( !noPropagation ) {\n\t\t\tvar ui = this._uiHash();\n\t\t\tif ( this._trigger( \"drag\", event, ui ) === false ) {\n\t\t\t\tthis._mouseUp( new $.Event( \"mouseup\", event ) );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tthis.position = ui.position;\n\t\t}\n\n\t\tthis.helper[ 0 ].style.left = this.position.left + \"px\";\n\t\tthis.helper[ 0 ].style.top = this.position.top + \"px\";\n\n\t\tif ( $.ui.ddmanager ) {\n\t\t\t$.ui.ddmanager.drag( this, event );\n\t\t}\n\n\t\treturn false;\n\t},\n\n\t_mouseStop: function( event ) {\n\n\t\t//If we are using droppables, inform the manager about the drop\n\t\tvar that = this,\n\t\t\tdropped = false;\n\t\tif ( $.ui.ddmanager && !this.options.dropBehaviour ) {\n\t\t\tdropped = $.ui.ddmanager.drop( this, event );\n\t\t}\n\n\t\t//if a drop comes from outside (a sortable)\n\t\tif ( this.dropped ) {\n\t\t\tdropped = this.dropped;\n\t\t\tthis.dropped = false;\n\t\t}\n\n\t\tif ( ( this.options.revert === \"invalid\" && !dropped ) ||\n\t\t\t\t( this.options.revert === \"valid\" && dropped ) ||\n\t\t\t\tthis.options.revert === true || ( $.isFunction( this.options.revert ) &&\n\t\t\t\tthis.options.revert.call( this.element, dropped ) )\n\t\t) {\n\t\t\t$( this.helper ).animate(\n\t\t\t\tthis.originalPosition,\n\t\t\t\tparseInt( this.options.revertDuration, 10 ),\n\t\t\t\tfunction() {\n\t\t\t\t\tif ( that._trigger( \"stop\", event ) !== false ) {\n\t\t\t\t\t\tthat._clear();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t} else {\n\t\t\tif ( this._trigger( \"stop\", event ) !== false ) {\n\t\t\t\tthis._clear();\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\t_mouseUp: function( event ) {\n\t\tthis._unblockFrames();\n\n\t\t// If the ddmanager is used for droppables, inform the manager that dragging has stopped\n\t\t// (see #5003)\n\t\tif ( $.ui.ddmanager ) {\n\t\t\t$.ui.ddmanager.dragStop( this, event );\n\t\t}\n\n\t\t// Only need to focus if the event occurred on the draggable itself, see #10527\n\t\tif ( this.handleElement.is( event.target ) ) {\n\n\t\t\t// The interaction is over; whether or not the click resulted in a drag,\n\t\t\t// focus the element\n\t\t\tthis.element.trigger( \"focus\" );\n\t\t}\n\n\t\treturn $.ui.mouse.prototype._mouseUp.call( this, event );\n\t},\n\n\tcancel: function() {\n\n\t\tif ( this.helper.is( \".ui-draggable-dragging\" ) ) {\n\t\t\tthis._mouseUp( new $.Event( \"mouseup\", { target: this.element[ 0 ] } ) );\n\t\t} else {\n\t\t\tthis._clear();\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\t_getHandle: function( event ) {\n\t\treturn this.options.handle ?\n\t\t\t!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :\n\t\t\ttrue;\n\t},\n\n\t_setHandleClassName: function() {\n\t\tthis.handleElement = this.options.handle ?\n\t\t\tthis.element.find( this.options.handle ) : this.element;\n\t\tthis._addClass( this.handleElement, \"ui-draggable-handle\" );\n\t},\n\n\t_removeHandleClassName: function() {\n\t\tthis._removeClass( this.handleElement, \"ui-draggable-handle\" );\n\t},\n\n\t_createHelper: function( event ) {\n\n\t\tvar o = this.options,\n\t\t\thelperIsFunction = $.isFunction( o.helper ),\n\t\t\thelper = helperIsFunction ?\n\t\t\t\t$( o.helper.apply( this.element[ 0 ], [ event ] ) ) :\n\t\t\t\t( o.helper === \"clone\" ?\n\t\t\t\t\tthis.element.clone().removeAttr( \"id\" ) :\n\t\t\t\t\tthis.element );\n\n\t\tif ( !helper.parents( \"body\" ).length ) {\n\t\t\thelper.appendTo( ( o.appendTo === \"parent\" ?\n\t\t\t\tthis.element[ 0 ].parentNode :\n\t\t\t\to.appendTo ) );\n\t\t}\n\n\t\t// Http://bugs.jqueryui.com/ticket/9446\n\t\t// a helper function can return the original element\n\t\t// which wouldn't have been set to relative in _create\n\t\tif ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {\n\t\t\tthis._setPositionRelative();\n\t\t}\n\n\t\tif ( helper[ 0 ] !== this.element[ 0 ] &&\n\t\t\t\t!( /(fixed|absolute)/ ).test( helper.css( \"position\" ) ) ) {\n\t\t\thelper.css( \"position\", \"absolute\" );\n\t\t}\n\n\t\treturn helper;\n\n\t},\n\n\t_setPositionRelative: function() {\n\t\tif ( !( /^(?:r|a|f)/ ).test( this.element.css( \"position\" ) ) ) {\n\t\t\tthis.element[ 0 ].style.position = \"relative\";\n\t\t}\n\t},\n\n\t_adjustOffsetFromHelper: function( obj ) {\n\t\tif ( typeof obj === \"string\" ) {\n\t\t\tobj = obj.split( \" \" );\n\t\t}\n\t\tif ( $.isArray( obj ) ) {\n\t\t\tobj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };\n\t\t}\n\t\tif ( \"left\" in obj ) {\n\t\t\tthis.offset.click.left = obj.left + this.margins.left;\n\t\t}\n\t\tif ( \"right\" in obj ) {\n\t\t\tthis.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;\n\t\t}\n\t\tif ( \"top\" in obj ) {\n\t\t\tthis.offset.click.top = obj.top + this.margins.top;\n\t\t}\n\t\tif ( \"bottom\" in obj ) {\n\t\t\tthis.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;\n\t\t}\n\t},\n\n\t_isRootNode: function( element ) {\n\t\treturn ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];\n\t},\n\n\t_getParentOffset: function() {\n\n\t\t//Get the offsetParent and cache its position\n\t\tvar po = this.offsetParent.offset(),\n\t\t\tdocument = this.document[ 0 ];\n\n\t\t// This is a special case where we need to modify a offset calculated on start, since the\n\t\t// following happened:\n\t\t// 1. The position of the helper is absolute, so it's position is calculated based on the\n\t\t// next positioned parent\n\t\t// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't\n\t\t// the document, which means that the scroll is included in the initial calculation of the\n\t\t// offset of the parent, and never recalculated upon drag\n\t\tif ( this.cssPosition === \"absolute\" && this.scrollParent[ 0 ] !== document &&\n\t\t\t\t$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {\n\t\t\tpo.left += this.scrollParent.scrollLeft();\n\t\t\tpo.top += this.scrollParent.scrollTop();\n\t\t}\n\n\t\tif ( this._isRootNode( this.offsetParent[ 0 ] ) ) {\n\t\t\tpo = { top: 0, left: 0 };\n\t\t}\n\n\t\treturn {\n\t\t\ttop: po.top + ( parseInt( this.offsetParent.css( \"borderTopWidth\" ), 10 ) || 0 ),\n\t\t\tleft: po.left + ( parseInt( this.offsetParent.css( \"borderLeftWidth\" ), 10 ) || 0 )\n\t\t};\n\n\t},\n\n\t_getRelativeOffset: function() {\n\t\tif ( this.cssPosition !== \"relative\" ) {\n\t\t\treturn { top: 0, left: 0 };\n\t\t}\n\n\t\tvar p = this.element.position(),\n\t\t\tscrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );\n\n\t\treturn {\n\t\t\ttop: p.top - ( parseInt( this.helper.css( \"top\" ), 10 ) || 0 ) +\n\t\t\t\t( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),\n\t\t\tleft: p.left - ( parseInt( this.helper.css( \"left\" ), 10 ) || 0 ) +\n\t\t\t\t( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )\n\t\t};\n\n\t},\n\n\t_cacheMargins: function() {\n\t\tthis.margins = {\n\t\t\tleft: ( parseInt( this.element.css( \"marginLeft\" ), 10 ) || 0 ),\n\t\t\ttop: ( parseInt( this.element.css( \"marginTop\" ), 10 ) || 0 ),\n\t\t\tright: ( parseInt( this.element.css( \"marginRight\" ), 10 ) || 0 ),\n\t\t\tbottom: ( parseInt( this.element.css( \"marginBottom\" ), 10 ) || 0 )\n\t\t};\n\t},\n\n\t_cacheHelperProportions: function() {\n\t\tthis.helperProportions = {\n\t\t\twidth: this.helper.outerWidth(),\n\t\t\theight: this.helper.outerHeight()\n\t\t};\n\t},\n\n\t_setContainment: function() {\n\n\t\tvar isUserScrollable, c, ce,\n\t\t\to = this.options,\n\t\t\tdocument = this.document[ 0 ];\n\n\t\tthis.relativeContainer = null;\n\n\t\tif ( !o.containment ) {\n\t\t\tthis.containment = null;\n\t\t\treturn;\n\t\t}\n\n\t\tif ( o.containment === \"window\" ) {\n\t\t\tthis.containment = [\n\t\t\t\t$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,\n\t\t\t\t$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,\n\t\t\t\t$( window ).scrollLeft() + $( window ).width() -\n\t\t\t\t\tthis.helperProportions.width - this.margins.left,\n\t\t\t\t$( window ).scrollTop() +\n\t\t\t\t\t( $( window ).height() || document.body.parentNode.scrollHeight ) -\n\t\t\t\t\tthis.helperProportions.height - this.margins.top\n\t\t\t];\n\t\t\treturn;\n\t\t}\n\n\t\tif ( o.containment === \"document\" ) {\n\t\t\tthis.containment = [\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\t$( document ).width() - this.helperProportions.width - this.margins.left,\n\t\t\t\t( $( document ).height() || document.body.parentNode.scrollHeight ) -\n\t\t\t\t\tthis.helperProportions.height - this.margins.top\n\t\t\t];\n\t\t\treturn;\n\t\t}\n\n\t\tif ( o.containment.constructor === Array ) {\n\t\t\tthis.containment = o.containment;\n\t\t\treturn;\n\t\t}\n\n\t\tif ( o.containment === \"parent\" ) {\n\t\t\to.containment = this.helper[ 0 ].parentNode;\n\t\t}\n\n\t\tc = $( o.containment );\n\t\tce = c[ 0 ];\n\n\t\tif ( !ce ) {\n\t\t\treturn;\n\t\t}\n\n\t\tisUserScrollable = /(scroll|auto)/.test( c.css( \"overflow\" ) );\n\n\t\tthis.containment = [\n\t\t\t( parseInt( c.css( \"borderLeftWidth\" ), 10 ) || 0 ) +\n\t\t\t\t( parseInt( c.css( \"paddingLeft\" ), 10 ) || 0 ),\n\t\t\t( parseInt( c.css( \"borderTopWidth\" ), 10 ) || 0 ) +\n\t\t\t\t( parseInt( c.css( \"paddingTop\" ), 10 ) || 0 ),\n\t\t\t( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -\n\t\t\t\t( parseInt( c.css( \"borderRightWidth\" ), 10 ) || 0 ) -\n\t\t\t\t( parseInt( c.css( \"paddingRight\" ), 10 ) || 0 ) -\n\t\t\t\tthis.helperProportions.width -\n\t\t\t\tthis.margins.left -\n\t\t\t\tthis.margins.right,\n\t\t\t( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -\n\t\t\t\t( parseInt( c.css( \"borderBottomWidth\" ), 10 ) || 0 ) -\n\t\t\t\t( parseInt( c.css( \"paddingBottom\" ), 10 ) || 0 ) -\n\t\t\t\tthis.helperProportions.height -\n\t\t\t\tthis.margins.top -\n\t\t\t\tthis.margins.bottom\n\t\t];\n\t\tthis.relativeContainer = c;\n\t},\n\n\t_convertPositionTo: function( d, pos ) {\n\n\t\tif ( !pos ) {\n\t\t\tpos = this.position;\n\t\t}\n\n\t\tvar mod = d === \"absolute\" ? 1 : -1,\n\t\t\tscrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );\n\n\t\treturn {\n\t\t\ttop: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpos.top\t+\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.top * mod +\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.top * mod -\n\t\t\t\t( ( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.offset.scroll.top :\n\t\t\t\t\t( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )\n\t\t\t),\n\t\t\tleft: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpos.left +\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.left * mod +\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.left * mod\t-\n\t\t\t\t( ( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.offset.scroll.left :\n\t\t\t\t\t( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )\n\t\t\t)\n\t\t};\n\n\t},\n\n\t_generatePosition: function( event, constrainPosition ) {\n\n\t\tvar containment, co, top, left,\n\t\t\to = this.options,\n\t\t\tscrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),\n\t\t\tpageX = event.pageX,\n\t\t\tpageY = event.pageY;\n\n\t\t// Cache the scroll\n\t\tif ( !scrollIsRootNode || !this.offset.scroll ) {\n\t\t\tthis.offset.scroll = {\n\t\t\t\ttop: this.scrollParent.scrollTop(),\n\t\t\t\tleft: this.scrollParent.scrollLeft()\n\t\t\t};\n\t\t}\n\n\t\t/*\n\t\t * - Position constraining -\n\t\t * Constrain the position to a mix of grid, containment.\n\t\t */\n\n\t\t// If we are not dragging yet, we won't check for options\n\t\tif ( constrainPosition ) {\n\t\t\tif ( this.containment ) {\n\t\t\t\tif ( this.relativeContainer ) {\n\t\t\t\t\tco = this.relativeContainer.offset();\n\t\t\t\t\tcontainment = [\n\t\t\t\t\t\tthis.containment[ 0 ] + co.left,\n\t\t\t\t\t\tthis.containment[ 1 ] + co.top,\n\t\t\t\t\t\tthis.containment[ 2 ] + co.left,\n\t\t\t\t\t\tthis.containment[ 3 ] + co.top\n\t\t\t\t\t];\n\t\t\t\t} else {\n\t\t\t\t\tcontainment = this.containment;\n\t\t\t\t}\n\n\t\t\t\tif ( event.pageX - this.offset.click.left < containment[ 0 ] ) {\n\t\t\t\t\tpageX = containment[ 0 ] + this.offset.click.left;\n\t\t\t\t}\n\t\t\t\tif ( event.pageY - this.offset.click.top < containment[ 1 ] ) {\n\t\t\t\t\tpageY = containment[ 1 ] + this.offset.click.top;\n\t\t\t\t}\n\t\t\t\tif ( event.pageX - this.offset.click.left > containment[ 2 ] ) {\n\t\t\t\t\tpageX = containment[ 2 ] + this.offset.click.left;\n\t\t\t\t}\n\t\t\t\tif ( event.pageY - this.offset.click.top > containment[ 3 ] ) {\n\t\t\t\t\tpageY = containment[ 3 ] + this.offset.click.top;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( o.grid ) {\n\n\t\t\t\t//Check for grid elements set to 0 to prevent divide by 0 error causing invalid\n\t\t\t\t// argument errors in IE (see ticket #6950)\n\t\t\t\ttop = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY -\n\t\t\t\t\tthis.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY;\n\t\t\t\tpageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] ||\n\t\t\t\t\ttop - this.offset.click.top > containment[ 3 ] ) ?\n\t\t\t\t\t\ttop :\n\t\t\t\t\t\t( ( top - this.offset.click.top >= containment[ 1 ] ) ?\n\t\t\t\t\t\t\ttop - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;\n\n\t\t\t\tleft = o.grid[ 0 ] ? this.originalPageX +\n\t\t\t\t\tMath.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] :\n\t\t\t\t\tthis.originalPageX;\n\t\t\t\tpageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] ||\n\t\t\t\t\tleft - this.offset.click.left > containment[ 2 ] ) ?\n\t\t\t\t\t\tleft :\n\t\t\t\t\t\t( ( left - this.offset.click.left >= containment[ 0 ] ) ?\n\t\t\t\t\t\t\tleft - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left;\n\t\t\t}\n\n\t\t\tif ( o.axis === \"y\" ) {\n\t\t\t\tpageX = this.originalPageX;\n\t\t\t}\n\n\t\t\tif ( o.axis === \"x\" ) {\n\t\t\t\tpageY = this.originalPageY;\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\ttop: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpageY -\n\n\t\t\t\t// Click offset (relative to the element)\n\t\t\t\tthis.offset.click.top -\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.top -\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.top +\n\t\t\t\t( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.offset.scroll.top :\n\t\t\t\t\t( scrollIsRootNode ? 0 : this.offset.scroll.top ) )\n\t\t\t),\n\t\t\tleft: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpageX -\n\n\t\t\t\t// Click offset (relative to the element)\n\t\t\t\tthis.offset.click.left -\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.left -\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.left +\n\t\t\t\t( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.offset.scroll.left :\n\t\t\t\t\t( scrollIsRootNode ? 0 : this.offset.scroll.left ) )\n\t\t\t)\n\t\t};\n\n\t},\n\n\t_clear: function() {\n\t\tthis._removeClass( this.helper, \"ui-draggable-dragging\" );\n\t\tif ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) {\n\t\t\tthis.helper.remove();\n\t\t}\n\t\tthis.helper = null;\n\t\tthis.cancelHelperRemoval = false;\n\t\tif ( this.destroyOnClear ) {\n\t\t\tthis.destroy();\n\t\t}\n\t},\n\n\t// From now on bulk stuff - mainly helpers\n\n\t_trigger: function( type, event, ui ) {\n\t\tui = ui || this._uiHash();\n\t\t$.ui.plugin.call( this, type, [ event, ui, this ], true );\n\n\t\t// Absolute position and offset (see #6884 ) have to be recalculated after plugins\n\t\tif ( /^(drag|start|stop)/.test( type ) ) {\n\t\t\tthis.positionAbs = this._convertPositionTo( \"absolute\" );\n\t\t\tui.offset = this.positionAbs;\n\t\t}\n\t\treturn $.Widget.prototype._trigger.call( this, type, event, ui );\n\t},\n\n\tplugins: {},\n\n\t_uiHash: function() {\n\t\treturn {\n\t\t\thelper: this.helper,\n\t\t\tposition: this.position,\n\t\t\toriginalPosition: this.originalPosition,\n\t\t\toffset: this.positionAbs\n\t\t};\n\t}\n\n} );\n\n$.ui.plugin.add( \"draggable\", \"connectToSortable\", {\n\tstart: function( event, ui, draggable ) {\n\t\tvar uiSortable = $.extend( {}, ui, {\n\t\t\titem: draggable.element\n\t\t} );\n\n\t\tdraggable.sortables = [];\n\t\t$( draggable.options.connectToSortable ).each( function() {\n\t\t\tvar sortable = $( this ).sortable( \"instance\" );\n\n\t\t\tif ( sortable && !sortable.options.disabled ) {\n\t\t\t\tdraggable.sortables.push( sortable );\n\n\t\t\t\t// RefreshPositions is called at drag start to refresh the containerCache\n\t\t\t\t// which is used in drag. This ensures it's initialized and synchronized\n\t\t\t\t// with any changes that might have happened on the page since initialization.\n\t\t\t\tsortable.refreshPositions();\n\t\t\t\tsortable._trigger( \"activate\", event, uiSortable );\n\t\t\t}\n\t\t} );\n\t},\n\tstop: function( event, ui, draggable ) {\n\t\tvar uiSortable = $.extend( {}, ui, {\n\t\t\titem: draggable.element\n\t\t} );\n\n\t\tdraggable.cancelHelperRemoval = false;\n\n\t\t$.each( draggable.sortables, function() {\n\t\t\tvar sortable = this;\n\n\t\t\tif ( sortable.isOver ) {\n\t\t\t\tsortable.isOver = 0;\n\n\t\t\t\t// Allow this sortable to handle removing the helper\n\t\t\t\tdraggable.cancelHelperRemoval = true;\n\t\t\t\tsortable.cancelHelperRemoval = false;\n\n\t\t\t\t// Use _storedCSS To restore properties in the sortable,\n\t\t\t\t// as this also handles revert (#9675) since the draggable\n\t\t\t\t// may have modified them in unexpected ways (#8809)\n\t\t\t\tsortable._storedCSS = {\n\t\t\t\t\tposition: sortable.placeholder.css( \"position\" ),\n\t\t\t\t\ttop: sortable.placeholder.css( \"top\" ),\n\t\t\t\t\tleft: sortable.placeholder.css( \"left\" )\n\t\t\t\t};\n\n\t\t\t\tsortable._mouseStop( event );\n\n\t\t\t\t// Once drag has ended, the sortable should return to using\n\t\t\t\t// its original helper, not the shared helper from draggable\n\t\t\t\tsortable.options.helper = sortable.options._helper;\n\t\t\t} else {\n\n\t\t\t\t// Prevent this Sortable from removing the helper.\n\t\t\t\t// However, don't set the draggable to remove the helper\n\t\t\t\t// either as another connected Sortable may yet handle the removal.\n\t\t\t\tsortable.cancelHelperRemoval = true;\n\n\t\t\t\tsortable._trigger( \"deactivate\", event, uiSortable );\n\t\t\t}\n\t\t} );\n\t},\n\tdrag: function( event, ui, draggable ) {\n\t\t$.each( draggable.sortables, function() {\n\t\t\tvar innermostIntersecting = false,\n\t\t\t\tsortable = this;\n\n\t\t\t// Copy over variables that sortable's _intersectsWith uses\n\t\t\tsortable.positionAbs = draggable.positionAbs;\n\t\t\tsortable.helperProportions = draggable.helperProportions;\n\t\t\tsortable.offset.click = draggable.offset.click;\n\n\t\t\tif ( sortable._intersectsWith( sortable.containerCache ) ) {\n\t\t\t\tinnermostIntersecting = true;\n\n\t\t\t\t$.each( draggable.sortables, function() {\n\n\t\t\t\t\t// Copy over variables that sortable's _intersectsWith uses\n\t\t\t\t\tthis.positionAbs = draggable.positionAbs;\n\t\t\t\t\tthis.helperProportions = draggable.helperProportions;\n\t\t\t\t\tthis.offset.click = draggable.offset.click;\n\n\t\t\t\t\tif ( this !== sortable &&\n\t\t\t\t\t\t\tthis._intersectsWith( this.containerCache ) &&\n\t\t\t\t\t\t\t$.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {\n\t\t\t\t\t\tinnermostIntersecting = false;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn innermostIntersecting;\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tif ( innermostIntersecting ) {\n\n\t\t\t\t// If it intersects, we use a little isOver variable and set it once,\n\t\t\t\t// so that the move-in stuff gets fired only once.\n\t\t\t\tif ( !sortable.isOver ) {\n\t\t\t\t\tsortable.isOver = 1;\n\n\t\t\t\t\t// Store draggable's parent in case we need to reappend to it later.\n\t\t\t\t\tdraggable._parent = ui.helper.parent();\n\n\t\t\t\t\tsortable.currentItem = ui.helper\n\t\t\t\t\t\t.appendTo( sortable.element )\n\t\t\t\t\t\t.data( \"ui-sortable-item\", true );\n\n\t\t\t\t\t// Store helper option to later restore it\n\t\t\t\t\tsortable.options._helper = sortable.options.helper;\n\n\t\t\t\t\tsortable.options.helper = function() {\n\t\t\t\t\t\treturn ui.helper[ 0 ];\n\t\t\t\t\t};\n\n\t\t\t\t\t// Fire the start events of the sortable with our passed browser event,\n\t\t\t\t\t// and our own helper (so it doesn't create a new one)\n\t\t\t\t\tevent.target = sortable.currentItem[ 0 ];\n\t\t\t\t\tsortable._mouseCapture( event, true );\n\t\t\t\t\tsortable._mouseStart( event, true, true );\n\n\t\t\t\t\t// Because the browser event is way off the new appended portlet,\n\t\t\t\t\t// modify necessary variables to reflect the changes\n\t\t\t\t\tsortable.offset.click.top = draggable.offset.click.top;\n\t\t\t\t\tsortable.offset.click.left = draggable.offset.click.left;\n\t\t\t\t\tsortable.offset.parent.left -= draggable.offset.parent.left -\n\t\t\t\t\t\tsortable.offset.parent.left;\n\t\t\t\t\tsortable.offset.parent.top -= draggable.offset.parent.top -\n\t\t\t\t\t\tsortable.offset.parent.top;\n\n\t\t\t\t\tdraggable._trigger( \"toSortable\", event );\n\n\t\t\t\t\t// Inform draggable that the helper is in a valid drop zone,\n\t\t\t\t\t// used solely in the revert option to handle \"valid/invalid\".\n\t\t\t\t\tdraggable.dropped = sortable.element;\n\n\t\t\t\t\t// Need to refreshPositions of all sortables in the case that\n\t\t\t\t\t// adding to one sortable changes the location of the other sortables (#9675)\n\t\t\t\t\t$.each( draggable.sortables, function() {\n\t\t\t\t\t\tthis.refreshPositions();\n\t\t\t\t\t} );\n\n\t\t\t\t\t// Hack so receive/update callbacks work (mostly)\n\t\t\t\t\tdraggable.currentItem = draggable.element;\n\t\t\t\t\tsortable.fromOutside = draggable;\n\t\t\t\t}\n\n\t\t\t\tif ( sortable.currentItem ) {\n\t\t\t\t\tsortable._mouseDrag( event );\n\n\t\t\t\t\t// Copy the sortable's position because the draggable's can potentially reflect\n\t\t\t\t\t// a relative position, while sortable is always absolute, which the dragged\n\t\t\t\t\t// element has now become. (#8809)\n\t\t\t\t\tui.position = sortable.position;\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// If it doesn't intersect with the sortable, and it intersected before,\n\t\t\t\t// we fake the drag stop of the sortable, but make sure it doesn't remove\n\t\t\t\t// the helper by using cancelHelperRemoval.\n\t\t\t\tif ( sortable.isOver ) {\n\n\t\t\t\t\tsortable.isOver = 0;\n\t\t\t\t\tsortable.cancelHelperRemoval = true;\n\n\t\t\t\t\t// Calling sortable's mouseStop would trigger a revert,\n\t\t\t\t\t// so revert must be temporarily false until after mouseStop is called.\n\t\t\t\t\tsortable.options._revert = sortable.options.revert;\n\t\t\t\t\tsortable.options.revert = false;\n\n\t\t\t\t\tsortable._trigger( \"out\", event, sortable._uiHash( sortable ) );\n\t\t\t\t\tsortable._mouseStop( event, true );\n\n\t\t\t\t\t// Restore sortable behaviors that were modfied\n\t\t\t\t\t// when the draggable entered the sortable area (#9481)\n\t\t\t\t\tsortable.options.revert = sortable.options._revert;\n\t\t\t\t\tsortable.options.helper = sortable.options._helper;\n\n\t\t\t\t\tif ( sortable.placeholder ) {\n\t\t\t\t\t\tsortable.placeholder.remove();\n\t\t\t\t\t}\n\n\t\t\t\t\t// Restore and recalculate the draggable's offset considering the sortable\n\t\t\t\t\t// may have modified them in unexpected ways. (#8809, #10669)\n\t\t\t\t\tui.helper.appendTo( draggable._parent );\n\t\t\t\t\tdraggable._refreshOffsets( event );\n\t\t\t\t\tui.position = draggable._generatePosition( event, true );\n\n\t\t\t\t\tdraggable._trigger( \"fromSortable\", event );\n\n\t\t\t\t\t// Inform draggable that the helper is no longer in a valid drop zone\n\t\t\t\t\tdraggable.dropped = false;\n\n\t\t\t\t\t// Need to refreshPositions of all sortables just in case removing\n\t\t\t\t\t// from one sortable changes the location of other sortables (#9675)\n\t\t\t\t\t$.each( draggable.sortables, function() {\n\t\t\t\t\t\tthis.refreshPositions();\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n} );\n\n$.ui.plugin.add( \"draggable\", \"cursor\", {\n\tstart: function( event, ui, instance ) {\n\t\tvar t = $( \"body\" ),\n\t\t\to = instance.options;\n\n\t\tif ( t.css( \"cursor\" ) ) {\n\t\t\to._cursor = t.css( \"cursor\" );\n\t\t}\n\t\tt.css( \"cursor\", o.cursor );\n\t},\n\tstop: function( event, ui, instance ) {\n\t\tvar o = instance.options;\n\t\tif ( o._cursor ) {\n\t\t\t$( \"body\" ).css( \"cursor\", o._cursor );\n\t\t}\n\t}\n} );\n\n$.ui.plugin.add( \"draggable\", \"opacity\", {\n\tstart: function( event, ui, instance ) {\n\t\tvar t = $( ui.helper ),\n\t\t\to = instance.options;\n\t\tif ( t.css( \"opacity\" ) ) {\n\t\t\to._opacity = t.css( \"opacity\" );\n\t\t}\n\t\tt.css( \"opacity\", o.opacity );\n\t},\n\tstop: function( event, ui, instance ) {\n\t\tvar o = instance.options;\n\t\tif ( o._opacity ) {\n\t\t\t$( ui.helper ).css( \"opacity\", o._opacity );\n\t\t}\n\t}\n} );\n\n$.ui.plugin.add( \"draggable\", \"scroll\", {\n\tstart: function( event, ui, i ) {\n\t\tif ( !i.scrollParentNotHidden ) {\n\t\t\ti.scrollParentNotHidden = i.helper.scrollParent( false );\n\t\t}\n\n\t\tif ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] &&\n\t\t\t\ti.scrollParentNotHidden[ 0 ].tagName !== \"HTML\" ) {\n\t\t\ti.overflowOffset = i.scrollParentNotHidden.offset();\n\t\t}\n\t},\n\tdrag: function( event, ui, i  ) {\n\n\t\tvar o = i.options,\n\t\t\tscrolled = false,\n\t\t\tscrollParent = i.scrollParentNotHidden[ 0 ],\n\t\t\tdocument = i.document[ 0 ];\n\n\t\tif ( scrollParent !== document && scrollParent.tagName !== \"HTML\" ) {\n\t\t\tif ( !o.axis || o.axis !== \"x\" ) {\n\t\t\t\tif ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY <\n\t\t\t\t\t\to.scrollSensitivity ) {\n\t\t\t\t\tscrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;\n\t\t\t\t} else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {\n\t\t\t\t\tscrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( !o.axis || o.axis !== \"y\" ) {\n\t\t\t\tif ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX <\n\t\t\t\t\t\to.scrollSensitivity ) {\n\t\t\t\t\tscrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;\n\t\t\t\t} else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {\n\t\t\t\t\tscrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tif ( !o.axis || o.axis !== \"x\" ) {\n\t\t\t\tif ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) {\n\t\t\t\t\tscrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed );\n\t\t\t\t} else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) <\n\t\t\t\t\t\to.scrollSensitivity ) {\n\t\t\t\t\tscrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( !o.axis || o.axis !== \"y\" ) {\n\t\t\t\tif ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) {\n\t\t\t\t\tscrolled = $( document ).scrollLeft(\n\t\t\t\t\t\t$( document ).scrollLeft() - o.scrollSpeed\n\t\t\t\t\t);\n\t\t\t\t} else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) <\n\t\t\t\t\t\to.scrollSensitivity ) {\n\t\t\t\t\tscrolled = $( document ).scrollLeft(\n\t\t\t\t\t\t$( document ).scrollLeft() + o.scrollSpeed\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\tif ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {\n\t\t\t$.ui.ddmanager.prepareOffsets( i, event );\n\t\t}\n\n\t}\n} );\n\n$.ui.plugin.add( \"draggable\", \"snap\", {\n\tstart: function( event, ui, i ) {\n\n\t\tvar o = i.options;\n\n\t\ti.snapElements = [];\n\n\t\t$( o.snap.constructor !== String ? ( o.snap.items || \":data(ui-draggable)\" ) : o.snap )\n\t\t\t.each( function() {\n\t\t\t\tvar $t = $( this ),\n\t\t\t\t\t$o = $t.offset();\n\t\t\t\tif ( this !== i.element[ 0 ] ) {\n\t\t\t\t\ti.snapElements.push( {\n\t\t\t\t\t\titem: this,\n\t\t\t\t\t\twidth: $t.outerWidth(), height: $t.outerHeight(),\n\t\t\t\t\t\ttop: $o.top, left: $o.left\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} );\n\n\t},\n\tdrag: function( event, ui, inst ) {\n\n\t\tvar ts, bs, ls, rs, l, r, t, b, i, first,\n\t\t\to = inst.options,\n\t\t\td = o.snapTolerance,\n\t\t\tx1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,\n\t\t\ty1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;\n\n\t\tfor ( i = inst.snapElements.length - 1; i >= 0; i-- ) {\n\n\t\t\tl = inst.snapElements[ i ].left - inst.margins.left;\n\t\t\tr = l + inst.snapElements[ i ].width;\n\t\t\tt = inst.snapElements[ i ].top - inst.margins.top;\n\t\t\tb = t + inst.snapElements[ i ].height;\n\n\t\t\tif ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||\n\t\t\t\t\t!$.contains( inst.snapElements[ i ].item.ownerDocument,\n\t\t\t\t\tinst.snapElements[ i ].item ) ) {\n\t\t\t\tif ( inst.snapElements[ i ].snapping ) {\n\t\t\t\t\t( inst.options.snap.release &&\n\t\t\t\t\t\tinst.options.snap.release.call(\n\t\t\t\t\t\t\tinst.element,\n\t\t\t\t\t\t\tevent,\n\t\t\t\t\t\t\t$.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } )\n\t\t\t\t\t\t) );\n\t\t\t\t}\n\t\t\t\tinst.snapElements[ i ].snapping = false;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( o.snapMode !== \"inner\" ) {\n\t\t\t\tts = Math.abs( t - y2 ) <= d;\n\t\t\t\tbs = Math.abs( b - y1 ) <= d;\n\t\t\t\tls = Math.abs( l - x2 ) <= d;\n\t\t\t\trs = Math.abs( r - x1 ) <= d;\n\t\t\t\tif ( ts ) {\n\t\t\t\t\tui.position.top = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: t - inst.helperProportions.height,\n\t\t\t\t\t\tleft: 0\n\t\t\t\t\t} ).top;\n\t\t\t\t}\n\t\t\t\tif ( bs ) {\n\t\t\t\t\tui.position.top = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: b,\n\t\t\t\t\t\tleft: 0\n\t\t\t\t\t} ).top;\n\t\t\t\t}\n\t\t\t\tif ( ls ) {\n\t\t\t\t\tui.position.left = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: 0,\n\t\t\t\t\t\tleft: l - inst.helperProportions.width\n\t\t\t\t\t} ).left;\n\t\t\t\t}\n\t\t\t\tif ( rs ) {\n\t\t\t\t\tui.position.left = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: 0,\n\t\t\t\t\t\tleft: r\n\t\t\t\t\t} ).left;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfirst = ( ts || bs || ls || rs );\n\n\t\t\tif ( o.snapMode !== \"outer\" ) {\n\t\t\t\tts = Math.abs( t - y1 ) <= d;\n\t\t\t\tbs = Math.abs( b - y2 ) <= d;\n\t\t\t\tls = Math.abs( l - x1 ) <= d;\n\t\t\t\trs = Math.abs( r - x2 ) <= d;\n\t\t\t\tif ( ts ) {\n\t\t\t\t\tui.position.top = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: t,\n\t\t\t\t\t\tleft: 0\n\t\t\t\t\t} ).top;\n\t\t\t\t}\n\t\t\t\tif ( bs ) {\n\t\t\t\t\tui.position.top = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: b - inst.helperProportions.height,\n\t\t\t\t\t\tleft: 0\n\t\t\t\t\t} ).top;\n\t\t\t\t}\n\t\t\t\tif ( ls ) {\n\t\t\t\t\tui.position.left = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: 0,\n\t\t\t\t\t\tleft: l\n\t\t\t\t\t} ).left;\n\t\t\t\t}\n\t\t\t\tif ( rs ) {\n\t\t\t\t\tui.position.left = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: 0,\n\t\t\t\t\t\tleft: r - inst.helperProportions.width\n\t\t\t\t\t} ).left;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) {\n\t\t\t\t( inst.options.snap.snap &&\n\t\t\t\t\tinst.options.snap.snap.call(\n\t\t\t\t\t\tinst.element,\n\t\t\t\t\t\tevent,\n\t\t\t\t\t\t$.extend( inst._uiHash(), {\n\t\t\t\t\t\t\tsnapItem: inst.snapElements[ i ].item\n\t\t\t\t\t\t} ) ) );\n\t\t\t}\n\t\t\tinst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first );\n\n\t\t}\n\n\t}\n} );\n\n$.ui.plugin.add( \"draggable\", \"stack\", {\n\tstart: function( event, ui, instance ) {\n\t\tvar min,\n\t\t\to = instance.options,\n\t\t\tgroup = $.makeArray( $( o.stack ) ).sort( function( a, b ) {\n\t\t\t\treturn ( parseInt( $( a ).css( \"zIndex\" ), 10 ) || 0 ) -\n\t\t\t\t\t( parseInt( $( b ).css( \"zIndex\" ), 10 ) || 0 );\n\t\t\t} );\n\n\t\tif ( !group.length ) { return; }\n\n\t\tmin = parseInt( $( group[ 0 ] ).css( \"zIndex\" ), 10 ) || 0;\n\t\t$( group ).each( function( i ) {\n\t\t\t$( this ).css( \"zIndex\", min + i );\n\t\t} );\n\t\tthis.css( \"zIndex\", ( min + group.length ) );\n\t}\n} );\n\n$.ui.plugin.add( \"draggable\", \"zIndex\", {\n\tstart: function( event, ui, instance ) {\n\t\tvar t = $( ui.helper ),\n\t\t\to = instance.options;\n\n\t\tif ( t.css( \"zIndex\" ) ) {\n\t\t\to._zIndex = t.css( \"zIndex\" );\n\t\t}\n\t\tt.css( \"zIndex\", o.zIndex );\n\t},\n\tstop: function( event, ui, instance ) {\n\t\tvar o = instance.options;\n\n\t\tif ( o._zIndex ) {\n\t\t\t$( ui.helper ).css( \"zIndex\", o._zIndex );\n\t\t}\n\t}\n} );\n\nvar widgetsDraggable = $.ui.draggable;\n\n\n/*!\n * jQuery UI Resizable 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Resizable\n//>>group: Interactions\n//>>description: Enables resize functionality for any element.\n//>>docs: http://api.jqueryui.com/resizable/\n//>>demos: http://jqueryui.com/resizable/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/resizable.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\n$.widget( \"ui.resizable\", $.ui.mouse, {\n\tversion: \"1.12.1\",\n\twidgetEventPrefix: \"resize\",\n\toptions: {\n\t\talsoResize: false,\n\t\tanimate: false,\n\t\tanimateDuration: \"slow\",\n\t\tanimateEasing: \"swing\",\n\t\taspectRatio: false,\n\t\tautoHide: false,\n\t\tclasses: {\n\t\t\t\"ui-resizable-se\": \"ui-icon ui-icon-gripsmall-diagonal-se\"\n\t\t},\n\t\tcontainment: false,\n\t\tghost: false,\n\t\tgrid: false,\n\t\thandles: \"e,s,se\",\n\t\thelper: false,\n\t\tmaxHeight: null,\n\t\tmaxWidth: null,\n\t\tminHeight: 10,\n\t\tminWidth: 10,\n\n\t\t// See #7960\n\t\tzIndex: 90,\n\n\t\t// Callbacks\n\t\tresize: null,\n\t\tstart: null,\n\t\tstop: null\n\t},\n\n\t_num: function( value ) {\n\t\treturn parseFloat( value ) || 0;\n\t},\n\n\t_isNumber: function( value ) {\n\t\treturn !isNaN( parseFloat( value ) );\n\t},\n\n\t_hasScroll: function( el, a ) {\n\n\t\tif ( $( el ).css( \"overflow\" ) === \"hidden\" ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar scroll = ( a && a === \"left\" ) ? \"scrollLeft\" : \"scrollTop\",\n\t\t\thas = false;\n\n\t\tif ( el[ scroll ] > 0 ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// TODO: determine which cases actually cause this to happen\n\t\t// if the element doesn't have the scroll set, see if it's possible to\n\t\t// set the scroll\n\t\tel[ scroll ] = 1;\n\t\thas = ( el[ scroll ] > 0 );\n\t\tel[ scroll ] = 0;\n\t\treturn has;\n\t},\n\n\t_create: function() {\n\n\t\tvar margins,\n\t\t\to = this.options,\n\t\t\tthat = this;\n\t\tthis._addClass( \"ui-resizable\" );\n\n\t\t$.extend( this, {\n\t\t\t_aspectRatio: !!( o.aspectRatio ),\n\t\t\taspectRatio: o.aspectRatio,\n\t\t\toriginalElement: this.element,\n\t\t\t_proportionallyResizeElements: [],\n\t\t\t_helper: o.helper || o.ghost || o.animate ? o.helper || \"ui-resizable-helper\" : null\n\t\t} );\n\n\t\t// Wrap the element if it cannot hold child nodes\n\t\tif ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {\n\n\t\t\tthis.element.wrap(\n\t\t\t\t$( \"<div class='ui-wrapper' style='overflow: hidden;'></div>\" ).css( {\n\t\t\t\t\tposition: this.element.css( \"position\" ),\n\t\t\t\t\twidth: this.element.outerWidth(),\n\t\t\t\t\theight: this.element.outerHeight(),\n\t\t\t\t\ttop: this.element.css( \"top\" ),\n\t\t\t\t\tleft: this.element.css( \"left\" )\n\t\t\t\t} )\n\t\t\t);\n\n\t\t\tthis.element = this.element.parent().data(\n\t\t\t\t\"ui-resizable\", this.element.resizable( \"instance\" )\n\t\t\t);\n\n\t\t\tthis.elementIsWrapper = true;\n\n\t\t\tmargins = {\n\t\t\t\tmarginTop: this.originalElement.css( \"marginTop\" ),\n\t\t\t\tmarginRight: this.originalElement.css( \"marginRight\" ),\n\t\t\t\tmarginBottom: this.originalElement.css( \"marginBottom\" ),\n\t\t\t\tmarginLeft: this.originalElement.css( \"marginLeft\" )\n\t\t\t};\n\n\t\t\tthis.element.css( margins );\n\t\t\tthis.originalElement.css( \"margin\", 0 );\n\n\t\t\t// support: Safari\n\t\t\t// Prevent Safari textarea resize\n\t\t\tthis.originalResizeStyle = this.originalElement.css( \"resize\" );\n\t\t\tthis.originalElement.css( \"resize\", \"none\" );\n\n\t\t\tthis._proportionallyResizeElements.push( this.originalElement.css( {\n\t\t\t\tposition: \"static\",\n\t\t\t\tzoom: 1,\n\t\t\t\tdisplay: \"block\"\n\t\t\t} ) );\n\n\t\t\t// Support: IE9\n\t\t\t// avoid IE jump (hard set the margin)\n\t\t\tthis.originalElement.css( margins );\n\n\t\t\tthis._proportionallyResize();\n\t\t}\n\n\t\tthis._setupHandles();\n\n\t\tif ( o.autoHide ) {\n\t\t\t$( this.element )\n\t\t\t\t.on( \"mouseenter\", function() {\n\t\t\t\t\tif ( o.disabled ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthat._removeClass( \"ui-resizable-autohide\" );\n\t\t\t\t\tthat._handles.show();\n\t\t\t\t} )\n\t\t\t\t.on( \"mouseleave\", function() {\n\t\t\t\t\tif ( o.disabled ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif ( !that.resizing ) {\n\t\t\t\t\t\tthat._addClass( \"ui-resizable-autohide\" );\n\t\t\t\t\t\tthat._handles.hide();\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t}\n\n\t\tthis._mouseInit();\n\t},\n\n\t_destroy: function() {\n\n\t\tthis._mouseDestroy();\n\n\t\tvar wrapper,\n\t\t\t_destroy = function( exp ) {\n\t\t\t\t$( exp )\n\t\t\t\t\t.removeData( \"resizable\" )\n\t\t\t\t\t.removeData( \"ui-resizable\" )\n\t\t\t\t\t.off( \".resizable\" )\n\t\t\t\t\t.find( \".ui-resizable-handle\" )\n\t\t\t\t\t\t.remove();\n\t\t\t};\n\n\t\t// TODO: Unwrap at same DOM position\n\t\tif ( this.elementIsWrapper ) {\n\t\t\t_destroy( this.element );\n\t\t\twrapper = this.element;\n\t\t\tthis.originalElement.css( {\n\t\t\t\tposition: wrapper.css( \"position\" ),\n\t\t\t\twidth: wrapper.outerWidth(),\n\t\t\t\theight: wrapper.outerHeight(),\n\t\t\t\ttop: wrapper.css( \"top\" ),\n\t\t\t\tleft: wrapper.css( \"left\" )\n\t\t\t} ).insertAfter( wrapper );\n\t\t\twrapper.remove();\n\t\t}\n\n\t\tthis.originalElement.css( \"resize\", this.originalResizeStyle );\n\t\t_destroy( this.originalElement );\n\n\t\treturn this;\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tthis._super( key, value );\n\n\t\tswitch ( key ) {\n\t\tcase \"handles\":\n\t\t\tthis._removeHandles();\n\t\t\tthis._setupHandles();\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t},\n\n\t_setupHandles: function() {\n\t\tvar o = this.options, handle, i, n, hname, axis, that = this;\n\t\tthis.handles = o.handles ||\n\t\t\t( !$( \".ui-resizable-handle\", this.element ).length ?\n\t\t\t\t\"e,s,se\" : {\n\t\t\t\t\tn: \".ui-resizable-n\",\n\t\t\t\t\te: \".ui-resizable-e\",\n\t\t\t\t\ts: \".ui-resizable-s\",\n\t\t\t\t\tw: \".ui-resizable-w\",\n\t\t\t\t\tse: \".ui-resizable-se\",\n\t\t\t\t\tsw: \".ui-resizable-sw\",\n\t\t\t\t\tne: \".ui-resizable-ne\",\n\t\t\t\t\tnw: \".ui-resizable-nw\"\n\t\t\t\t} );\n\n\t\tthis._handles = $();\n\t\tif ( this.handles.constructor === String ) {\n\n\t\t\tif ( this.handles === \"all\" ) {\n\t\t\t\tthis.handles = \"n,e,s,w,se,sw,ne,nw\";\n\t\t\t}\n\n\t\t\tn = this.handles.split( \",\" );\n\t\t\tthis.handles = {};\n\n\t\t\tfor ( i = 0; i < n.length; i++ ) {\n\n\t\t\t\thandle = $.trim( n[ i ] );\n\t\t\t\thname = \"ui-resizable-\" + handle;\n\t\t\t\taxis = $( \"<div>\" );\n\t\t\t\tthis._addClass( axis, \"ui-resizable-handle \" + hname );\n\n\t\t\t\taxis.css( { zIndex: o.zIndex } );\n\n\t\t\t\tthis.handles[ handle ] = \".ui-resizable-\" + handle;\n\t\t\t\tthis.element.append( axis );\n\t\t\t}\n\n\t\t}\n\n\t\tthis._renderAxis = function( target ) {\n\n\t\t\tvar i, axis, padPos, padWrapper;\n\n\t\t\ttarget = target || this.element;\n\n\t\t\tfor ( i in this.handles ) {\n\n\t\t\t\tif ( this.handles[ i ].constructor === String ) {\n\t\t\t\t\tthis.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();\n\t\t\t\t} else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {\n\t\t\t\t\tthis.handles[ i ] = $( this.handles[ i ] );\n\t\t\t\t\tthis._on( this.handles[ i ], { \"mousedown\": that._mouseDown } );\n\t\t\t\t}\n\n\t\t\t\tif ( this.elementIsWrapper &&\n\t\t\t\t\t\tthis.originalElement[ 0 ]\n\t\t\t\t\t\t\t.nodeName\n\t\t\t\t\t\t\t.match( /^(textarea|input|select|button)$/i ) ) {\n\t\t\t\t\taxis = $( this.handles[ i ], this.element );\n\n\t\t\t\t\tpadWrapper = /sw|ne|nw|se|n|s/.test( i ) ?\n\t\t\t\t\t\taxis.outerHeight() :\n\t\t\t\t\t\taxis.outerWidth();\n\n\t\t\t\t\tpadPos = [ \"padding\",\n\t\t\t\t\t\t/ne|nw|n/.test( i ) ? \"Top\" :\n\t\t\t\t\t\t/se|sw|s/.test( i ) ? \"Bottom\" :\n\t\t\t\t\t\t/^e$/.test( i ) ? \"Right\" : \"Left\" ].join( \"\" );\n\n\t\t\t\t\ttarget.css( padPos, padWrapper );\n\n\t\t\t\t\tthis._proportionallyResize();\n\t\t\t\t}\n\n\t\t\t\tthis._handles = this._handles.add( this.handles[ i ] );\n\t\t\t}\n\t\t};\n\n\t\t// TODO: make renderAxis a prototype function\n\t\tthis._renderAxis( this.element );\n\n\t\tthis._handles = this._handles.add( this.element.find( \".ui-resizable-handle\" ) );\n\t\tthis._handles.disableSelection();\n\n\t\tthis._handles.on( \"mouseover\", function() {\n\t\t\tif ( !that.resizing ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\taxis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );\n\t\t\t\t}\n\t\t\t\tthat.axis = axis && axis[ 1 ] ? axis[ 1 ] : \"se\";\n\t\t\t}\n\t\t} );\n\n\t\tif ( o.autoHide ) {\n\t\t\tthis._handles.hide();\n\t\t\tthis._addClass( \"ui-resizable-autohide\" );\n\t\t}\n\t},\n\n\t_removeHandles: function() {\n\t\tthis._handles.remove();\n\t},\n\n\t_mouseCapture: function( event ) {\n\t\tvar i, handle,\n\t\t\tcapture = false;\n\n\t\tfor ( i in this.handles ) {\n\t\t\thandle = $( this.handles[ i ] )[ 0 ];\n\t\t\tif ( handle === event.target || $.contains( handle, event.target ) ) {\n\t\t\t\tcapture = true;\n\t\t\t}\n\t\t}\n\n\t\treturn !this.options.disabled && capture;\n\t},\n\n\t_mouseStart: function( event ) {\n\n\t\tvar curleft, curtop, cursor,\n\t\t\to = this.options,\n\t\t\tel = this.element;\n\n\t\tthis.resizing = true;\n\n\t\tthis._renderProxy();\n\n\t\tcurleft = this._num( this.helper.css( \"left\" ) );\n\t\tcurtop = this._num( this.helper.css( \"top\" ) );\n\n\t\tif ( o.containment ) {\n\t\t\tcurleft += $( o.containment ).scrollLeft() || 0;\n\t\t\tcurtop += $( o.containment ).scrollTop() || 0;\n\t\t}\n\n\t\tthis.offset = this.helper.offset();\n\t\tthis.position = { left: curleft, top: curtop };\n\n\t\tthis.size = this._helper ? {\n\t\t\t\twidth: this.helper.width(),\n\t\t\t\theight: this.helper.height()\n\t\t\t} : {\n\t\t\t\twidth: el.width(),\n\t\t\t\theight: el.height()\n\t\t\t};\n\n\t\tthis.originalSize = this._helper ? {\n\t\t\t\twidth: el.outerWidth(),\n\t\t\t\theight: el.outerHeight()\n\t\t\t} : {\n\t\t\t\twidth: el.width(),\n\t\t\t\theight: el.height()\n\t\t\t};\n\n\t\tthis.sizeDiff = {\n\t\t\twidth: el.outerWidth() - el.width(),\n\t\t\theight: el.outerHeight() - el.height()\n\t\t};\n\n\t\tthis.originalPosition = { left: curleft, top: curtop };\n\t\tthis.originalMousePosition = { left: event.pageX, top: event.pageY };\n\n\t\tthis.aspectRatio = ( typeof o.aspectRatio === \"number\" ) ?\n\t\t\to.aspectRatio :\n\t\t\t( ( this.originalSize.width / this.originalSize.height ) || 1 );\n\n\t\tcursor = $( \".ui-resizable-\" + this.axis ).css( \"cursor\" );\n\t\t$( \"body\" ).css( \"cursor\", cursor === \"auto\" ? this.axis + \"-resize\" : cursor );\n\n\t\tthis._addClass( \"ui-resizable-resizing\" );\n\t\tthis._propagate( \"start\", event );\n\t\treturn true;\n\t},\n\n\t_mouseDrag: function( event ) {\n\n\t\tvar data, props,\n\t\t\tsmp = this.originalMousePosition,\n\t\t\ta = this.axis,\n\t\t\tdx = ( event.pageX - smp.left ) || 0,\n\t\t\tdy = ( event.pageY - smp.top ) || 0,\n\t\t\ttrigger = this._change[ a ];\n\n\t\tthis._updatePrevProperties();\n\n\t\tif ( !trigger ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tdata = trigger.apply( this, [ event, dx, dy ] );\n\n\t\tthis._updateVirtualBoundaries( event.shiftKey );\n\t\tif ( this._aspectRatio || event.shiftKey ) {\n\t\t\tdata = this._updateRatio( data, event );\n\t\t}\n\n\t\tdata = this._respectSize( data, event );\n\n\t\tthis._updateCache( data );\n\n\t\tthis._propagate( \"resize\", event );\n\n\t\tprops = this._applyChanges();\n\n\t\tif ( !this._helper && this._proportionallyResizeElements.length ) {\n\t\t\tthis._proportionallyResize();\n\t\t}\n\n\t\tif ( !$.isEmptyObject( props ) ) {\n\t\t\tthis._updatePrevProperties();\n\t\t\tthis._trigger( \"resize\", event, this.ui() );\n\t\t\tthis._applyChanges();\n\t\t}\n\n\t\treturn false;\n\t},\n\n\t_mouseStop: function( event ) {\n\n\t\tthis.resizing = false;\n\t\tvar pr, ista, soffseth, soffsetw, s, left, top,\n\t\t\to = this.options, that = this;\n\n\t\tif ( this._helper ) {\n\n\t\t\tpr = this._proportionallyResizeElements;\n\t\t\tista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );\n\t\t\tsoffseth = ista && this._hasScroll( pr[ 0 ], \"left\" ) ? 0 : that.sizeDiff.height;\n\t\t\tsoffsetw = ista ? 0 : that.sizeDiff.width;\n\n\t\t\ts = {\n\t\t\t\twidth: ( that.helper.width()  - soffsetw ),\n\t\t\t\theight: ( that.helper.height() - soffseth )\n\t\t\t};\n\t\t\tleft = ( parseFloat( that.element.css( \"left\" ) ) +\n\t\t\t\t( that.position.left - that.originalPosition.left ) ) || null;\n\t\t\ttop = ( parseFloat( that.element.css( \"top\" ) ) +\n\t\t\t\t( that.position.top - that.originalPosition.top ) ) || null;\n\n\t\t\tif ( !o.animate ) {\n\t\t\t\tthis.element.css( $.extend( s, { top: top, left: left } ) );\n\t\t\t}\n\n\t\t\tthat.helper.height( that.size.height );\n\t\t\tthat.helper.width( that.size.width );\n\n\t\t\tif ( this._helper && !o.animate ) {\n\t\t\t\tthis._proportionallyResize();\n\t\t\t}\n\t\t}\n\n\t\t$( \"body\" ).css( \"cursor\", \"auto\" );\n\n\t\tthis._removeClass( \"ui-resizable-resizing\" );\n\n\t\tthis._propagate( \"stop\", event );\n\n\t\tif ( this._helper ) {\n\t\t\tthis.helper.remove();\n\t\t}\n\n\t\treturn false;\n\n\t},\n\n\t_updatePrevProperties: function() {\n\t\tthis.prevPosition = {\n\t\t\ttop: this.position.top,\n\t\t\tleft: this.position.left\n\t\t};\n\t\tthis.prevSize = {\n\t\t\twidth: this.size.width,\n\t\t\theight: this.size.height\n\t\t};\n\t},\n\n\t_applyChanges: function() {\n\t\tvar props = {};\n\n\t\tif ( this.position.top !== this.prevPosition.top ) {\n\t\t\tprops.top = this.position.top + \"px\";\n\t\t}\n\t\tif ( this.position.left !== this.prevPosition.left ) {\n\t\t\tprops.left = this.position.left + \"px\";\n\t\t}\n\t\tif ( this.size.width !== this.prevSize.width ) {\n\t\t\tprops.width = this.size.width + \"px\";\n\t\t}\n\t\tif ( this.size.height !== this.prevSize.height ) {\n\t\t\tprops.height = this.size.height + \"px\";\n\t\t}\n\n\t\tthis.helper.css( props );\n\n\t\treturn props;\n\t},\n\n\t_updateVirtualBoundaries: function( forceAspectRatio ) {\n\t\tvar pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,\n\t\t\to = this.options;\n\n\t\tb = {\n\t\t\tminWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,\n\t\t\tmaxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,\n\t\t\tminHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,\n\t\t\tmaxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity\n\t\t};\n\n\t\tif ( this._aspectRatio || forceAspectRatio ) {\n\t\t\tpMinWidth = b.minHeight * this.aspectRatio;\n\t\t\tpMinHeight = b.minWidth / this.aspectRatio;\n\t\t\tpMaxWidth = b.maxHeight * this.aspectRatio;\n\t\t\tpMaxHeight = b.maxWidth / this.aspectRatio;\n\n\t\t\tif ( pMinWidth > b.minWidth ) {\n\t\t\t\tb.minWidth = pMinWidth;\n\t\t\t}\n\t\t\tif ( pMinHeight > b.minHeight ) {\n\t\t\t\tb.minHeight = pMinHeight;\n\t\t\t}\n\t\t\tif ( pMaxWidth < b.maxWidth ) {\n\t\t\t\tb.maxWidth = pMaxWidth;\n\t\t\t}\n\t\t\tif ( pMaxHeight < b.maxHeight ) {\n\t\t\t\tb.maxHeight = pMaxHeight;\n\t\t\t}\n\t\t}\n\t\tthis._vBoundaries = b;\n\t},\n\n\t_updateCache: function( data ) {\n\t\tthis.offset = this.helper.offset();\n\t\tif ( this._isNumber( data.left ) ) {\n\t\t\tthis.position.left = data.left;\n\t\t}\n\t\tif ( this._isNumber( data.top ) ) {\n\t\t\tthis.position.top = data.top;\n\t\t}\n\t\tif ( this._isNumber( data.height ) ) {\n\t\t\tthis.size.height = data.height;\n\t\t}\n\t\tif ( this._isNumber( data.width ) ) {\n\t\t\tthis.size.width = data.width;\n\t\t}\n\t},\n\n\t_updateRatio: function( data ) {\n\n\t\tvar cpos = this.position,\n\t\t\tcsize = this.size,\n\t\t\ta = this.axis;\n\n\t\tif ( this._isNumber( data.height ) ) {\n\t\t\tdata.width = ( data.height * this.aspectRatio );\n\t\t} else if ( this._isNumber( data.width ) ) {\n\t\t\tdata.height = ( data.width / this.aspectRatio );\n\t\t}\n\n\t\tif ( a === \"sw\" ) {\n\t\t\tdata.left = cpos.left + ( csize.width - data.width );\n\t\t\tdata.top = null;\n\t\t}\n\t\tif ( a === \"nw\" ) {\n\t\t\tdata.top = cpos.top + ( csize.height - data.height );\n\t\t\tdata.left = cpos.left + ( csize.width - data.width );\n\t\t}\n\n\t\treturn data;\n\t},\n\n\t_respectSize: function( data ) {\n\n\t\tvar o = this._vBoundaries,\n\t\t\ta = this.axis,\n\t\t\tismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),\n\t\t\tismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),\n\t\t\tisminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),\n\t\t\tisminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),\n\t\t\tdw = this.originalPosition.left + this.originalSize.width,\n\t\t\tdh = this.originalPosition.top + this.originalSize.height,\n\t\t\tcw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );\n\t\tif ( isminw ) {\n\t\t\tdata.width = o.minWidth;\n\t\t}\n\t\tif ( isminh ) {\n\t\t\tdata.height = o.minHeight;\n\t\t}\n\t\tif ( ismaxw ) {\n\t\t\tdata.width = o.maxWidth;\n\t\t}\n\t\tif ( ismaxh ) {\n\t\t\tdata.height = o.maxHeight;\n\t\t}\n\n\t\tif ( isminw && cw ) {\n\t\t\tdata.left = dw - o.minWidth;\n\t\t}\n\t\tif ( ismaxw && cw ) {\n\t\t\tdata.left = dw - o.maxWidth;\n\t\t}\n\t\tif ( isminh && ch ) {\n\t\t\tdata.top = dh - o.minHeight;\n\t\t}\n\t\tif ( ismaxh && ch ) {\n\t\t\tdata.top = dh - o.maxHeight;\n\t\t}\n\n\t\t// Fixing jump error on top/left - bug #2330\n\t\tif ( !data.width && !data.height && !data.left && data.top ) {\n\t\t\tdata.top = null;\n\t\t} else if ( !data.width && !data.height && !data.top && data.left ) {\n\t\t\tdata.left = null;\n\t\t}\n\n\t\treturn data;\n\t},\n\n\t_getPaddingPlusBorderDimensions: function( element ) {\n\t\tvar i = 0,\n\t\t\twidths = [],\n\t\t\tborders = [\n\t\t\t\telement.css( \"borderTopWidth\" ),\n\t\t\t\telement.css( \"borderRightWidth\" ),\n\t\t\t\telement.css( \"borderBottomWidth\" ),\n\t\t\t\telement.css( \"borderLeftWidth\" )\n\t\t\t],\n\t\t\tpaddings = [\n\t\t\t\telement.css( \"paddingTop\" ),\n\t\t\t\telement.css( \"paddingRight\" ),\n\t\t\t\telement.css( \"paddingBottom\" ),\n\t\t\t\telement.css( \"paddingLeft\" )\n\t\t\t];\n\n\t\tfor ( ; i < 4; i++ ) {\n\t\t\twidths[ i ] = ( parseFloat( borders[ i ] ) || 0 );\n\t\t\twidths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );\n\t\t}\n\n\t\treturn {\n\t\t\theight: widths[ 0 ] + widths[ 2 ],\n\t\t\twidth: widths[ 1 ] + widths[ 3 ]\n\t\t};\n\t},\n\n\t_proportionallyResize: function() {\n\n\t\tif ( !this._proportionallyResizeElements.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar prel,\n\t\t\ti = 0,\n\t\t\telement = this.helper || this.element;\n\n\t\tfor ( ; i < this._proportionallyResizeElements.length; i++ ) {\n\n\t\t\tprel = this._proportionallyResizeElements[ i ];\n\n\t\t\t// TODO: Seems like a bug to cache this.outerDimensions\n\t\t\t// considering that we are in a loop.\n\t\t\tif ( !this.outerDimensions ) {\n\t\t\t\tthis.outerDimensions = this._getPaddingPlusBorderDimensions( prel );\n\t\t\t}\n\n\t\t\tprel.css( {\n\t\t\t\theight: ( element.height() - this.outerDimensions.height ) || 0,\n\t\t\t\twidth: ( element.width() - this.outerDimensions.width ) || 0\n\t\t\t} );\n\n\t\t}\n\n\t},\n\n\t_renderProxy: function() {\n\n\t\tvar el = this.element, o = this.options;\n\t\tthis.elementOffset = el.offset();\n\n\t\tif ( this._helper ) {\n\n\t\t\tthis.helper = this.helper || $( \"<div style='overflow:hidden;'></div>\" );\n\n\t\t\tthis._addClass( this.helper, this._helper );\n\t\t\tthis.helper.css( {\n\t\t\t\twidth: this.element.outerWidth(),\n\t\t\t\theight: this.element.outerHeight(),\n\t\t\t\tposition: \"absolute\",\n\t\t\t\tleft: this.elementOffset.left + \"px\",\n\t\t\t\ttop: this.elementOffset.top + \"px\",\n\t\t\t\tzIndex: ++o.zIndex //TODO: Don't modify option\n\t\t\t} );\n\n\t\t\tthis.helper\n\t\t\t\t.appendTo( \"body\" )\n\t\t\t\t.disableSelection();\n\n\t\t} else {\n\t\t\tthis.helper = this.element;\n\t\t}\n\n\t},\n\n\t_change: {\n\t\te: function( event, dx ) {\n\t\t\treturn { width: this.originalSize.width + dx };\n\t\t},\n\t\tw: function( event, dx ) {\n\t\t\tvar cs = this.originalSize, sp = this.originalPosition;\n\t\t\treturn { left: sp.left + dx, width: cs.width - dx };\n\t\t},\n\t\tn: function( event, dx, dy ) {\n\t\t\tvar cs = this.originalSize, sp = this.originalPosition;\n\t\t\treturn { top: sp.top + dy, height: cs.height - dy };\n\t\t},\n\t\ts: function( event, dx, dy ) {\n\t\t\treturn { height: this.originalSize.height + dy };\n\t\t},\n\t\tse: function( event, dx, dy ) {\n\t\t\treturn $.extend( this._change.s.apply( this, arguments ),\n\t\t\t\tthis._change.e.apply( this, [ event, dx, dy ] ) );\n\t\t},\n\t\tsw: function( event, dx, dy ) {\n\t\t\treturn $.extend( this._change.s.apply( this, arguments ),\n\t\t\t\tthis._change.w.apply( this, [ event, dx, dy ] ) );\n\t\t},\n\t\tne: function( event, dx, dy ) {\n\t\t\treturn $.extend( this._change.n.apply( this, arguments ),\n\t\t\t\tthis._change.e.apply( this, [ event, dx, dy ] ) );\n\t\t},\n\t\tnw: function( event, dx, dy ) {\n\t\t\treturn $.extend( this._change.n.apply( this, arguments ),\n\t\t\t\tthis._change.w.apply( this, [ event, dx, dy ] ) );\n\t\t}\n\t},\n\n\t_propagate: function( n, event ) {\n\t\t$.ui.plugin.call( this, n, [ event, this.ui() ] );\n\t\t( n !== \"resize\" && this._trigger( n, event, this.ui() ) );\n\t},\n\n\tplugins: {},\n\n\tui: function() {\n\t\treturn {\n\t\t\toriginalElement: this.originalElement,\n\t\t\telement: this.element,\n\t\t\thelper: this.helper,\n\t\t\tposition: this.position,\n\t\t\tsize: this.size,\n\t\t\toriginalSize: this.originalSize,\n\t\t\toriginalPosition: this.originalPosition\n\t\t};\n\t}\n\n} );\n\n/*\n * Resizable Extensions\n */\n\n$.ui.plugin.add( \"resizable\", \"animate\", {\n\n\tstop: function( event ) {\n\t\tvar that = $( this ).resizable( \"instance\" ),\n\t\t\to = that.options,\n\t\t\tpr = that._proportionallyResizeElements,\n\t\t\tista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),\n\t\t\tsoffseth = ista && that._hasScroll( pr[ 0 ], \"left\" ) ? 0 : that.sizeDiff.height,\n\t\t\tsoffsetw = ista ? 0 : that.sizeDiff.width,\n\t\t\tstyle = {\n\t\t\t\twidth: ( that.size.width - soffsetw ),\n\t\t\t\theight: ( that.size.height - soffseth )\n\t\t\t},\n\t\t\tleft = ( parseFloat( that.element.css( \"left\" ) ) +\n\t\t\t\t( that.position.left - that.originalPosition.left ) ) || null,\n\t\t\ttop = ( parseFloat( that.element.css( \"top\" ) ) +\n\t\t\t\t( that.position.top - that.originalPosition.top ) ) || null;\n\n\t\tthat.element.animate(\n\t\t\t$.extend( style, top && left ? { top: top, left: left } : {} ), {\n\t\t\t\tduration: o.animateDuration,\n\t\t\t\teasing: o.animateEasing,\n\t\t\t\tstep: function() {\n\n\t\t\t\t\tvar data = {\n\t\t\t\t\t\twidth: parseFloat( that.element.css( \"width\" ) ),\n\t\t\t\t\t\theight: parseFloat( that.element.css( \"height\" ) ),\n\t\t\t\t\t\ttop: parseFloat( that.element.css( \"top\" ) ),\n\t\t\t\t\t\tleft: parseFloat( that.element.css( \"left\" ) )\n\t\t\t\t\t};\n\n\t\t\t\t\tif ( pr && pr.length ) {\n\t\t\t\t\t\t$( pr[ 0 ] ).css( { width: data.width, height: data.height } );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Propagating resize, and updating values for each animation step\n\t\t\t\t\tthat._updateCache( data );\n\t\t\t\t\tthat._propagate( \"resize\", event );\n\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n} );\n\n$.ui.plugin.add( \"resizable\", \"containment\", {\n\n\tstart: function() {\n\t\tvar element, p, co, ch, cw, width, height,\n\t\t\tthat = $( this ).resizable( \"instance\" ),\n\t\t\to = that.options,\n\t\t\tel = that.element,\n\t\t\toc = o.containment,\n\t\t\tce = ( oc instanceof $ ) ?\n\t\t\t\toc.get( 0 ) :\n\t\t\t\t( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;\n\n\t\tif ( !ce ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthat.containerElement = $( ce );\n\n\t\tif ( /document/.test( oc ) || oc === document ) {\n\t\t\tthat.containerOffset = {\n\t\t\t\tleft: 0,\n\t\t\t\ttop: 0\n\t\t\t};\n\t\t\tthat.containerPosition = {\n\t\t\t\tleft: 0,\n\t\t\t\ttop: 0\n\t\t\t};\n\n\t\t\tthat.parentData = {\n\t\t\t\telement: $( document ),\n\t\t\t\tleft: 0,\n\t\t\t\ttop: 0,\n\t\t\t\twidth: $( document ).width(),\n\t\t\t\theight: $( document ).height() || document.body.parentNode.scrollHeight\n\t\t\t};\n\t\t} else {\n\t\t\telement = $( ce );\n\t\t\tp = [];\n\t\t\t$( [ \"Top\", \"Right\", \"Left\", \"Bottom\" ] ).each( function( i, name ) {\n\t\t\t\tp[ i ] = that._num( element.css( \"padding\" + name ) );\n\t\t\t} );\n\n\t\t\tthat.containerOffset = element.offset();\n\t\t\tthat.containerPosition = element.position();\n\t\t\tthat.containerSize = {\n\t\t\t\theight: ( element.innerHeight() - p[ 3 ] ),\n\t\t\t\twidth: ( element.innerWidth() - p[ 1 ] )\n\t\t\t};\n\n\t\t\tco = that.containerOffset;\n\t\t\tch = that.containerSize.height;\n\t\t\tcw = that.containerSize.width;\n\t\t\twidth = ( that._hasScroll ( ce, \"left\" ) ? ce.scrollWidth : cw );\n\t\t\theight = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ;\n\n\t\t\tthat.parentData = {\n\t\t\t\telement: ce,\n\t\t\t\tleft: co.left,\n\t\t\t\ttop: co.top,\n\t\t\t\twidth: width,\n\t\t\t\theight: height\n\t\t\t};\n\t\t}\n\t},\n\n\tresize: function( event ) {\n\t\tvar woset, hoset, isParent, isOffsetRelative,\n\t\t\tthat = $( this ).resizable( \"instance\" ),\n\t\t\to = that.options,\n\t\t\tco = that.containerOffset,\n\t\t\tcp = that.position,\n\t\t\tpRatio = that._aspectRatio || event.shiftKey,\n\t\t\tcop = {\n\t\t\t\ttop: 0,\n\t\t\t\tleft: 0\n\t\t\t},\n\t\t\tce = that.containerElement,\n\t\t\tcontinueResize = true;\n\n\t\tif ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( \"position\" ) ) ) {\n\t\t\tcop = co;\n\t\t}\n\n\t\tif ( cp.left < ( that._helper ? co.left : 0 ) ) {\n\t\t\tthat.size.width = that.size.width +\n\t\t\t\t( that._helper ?\n\t\t\t\t\t( that.position.left - co.left ) :\n\t\t\t\t\t( that.position.left - cop.left ) );\n\n\t\t\tif ( pRatio ) {\n\t\t\t\tthat.size.height = that.size.width / that.aspectRatio;\n\t\t\t\tcontinueResize = false;\n\t\t\t}\n\t\t\tthat.position.left = o.helper ? co.left : 0;\n\t\t}\n\n\t\tif ( cp.top < ( that._helper ? co.top : 0 ) ) {\n\t\t\tthat.size.height = that.size.height +\n\t\t\t\t( that._helper ?\n\t\t\t\t\t( that.position.top - co.top ) :\n\t\t\t\t\tthat.position.top );\n\n\t\t\tif ( pRatio ) {\n\t\t\t\tthat.size.width = that.size.height * that.aspectRatio;\n\t\t\t\tcontinueResize = false;\n\t\t\t}\n\t\t\tthat.position.top = that._helper ? co.top : 0;\n\t\t}\n\n\t\tisParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );\n\t\tisOffsetRelative = /relative|absolute/.test( that.containerElement.css( \"position\" ) );\n\n\t\tif ( isParent && isOffsetRelative ) {\n\t\t\tthat.offset.left = that.parentData.left + that.position.left;\n\t\t\tthat.offset.top = that.parentData.top + that.position.top;\n\t\t} else {\n\t\t\tthat.offset.left = that.element.offset().left;\n\t\t\tthat.offset.top = that.element.offset().top;\n\t\t}\n\n\t\twoset = Math.abs( that.sizeDiff.width +\n\t\t\t( that._helper ?\n\t\t\t\tthat.offset.left - cop.left :\n\t\t\t\t( that.offset.left - co.left ) ) );\n\n\t\thoset = Math.abs( that.sizeDiff.height +\n\t\t\t( that._helper ?\n\t\t\t\tthat.offset.top - cop.top :\n\t\t\t\t( that.offset.top - co.top ) ) );\n\n\t\tif ( woset + that.size.width >= that.parentData.width ) {\n\t\t\tthat.size.width = that.parentData.width - woset;\n\t\t\tif ( pRatio ) {\n\t\t\t\tthat.size.height = that.size.width / that.aspectRatio;\n\t\t\t\tcontinueResize = false;\n\t\t\t}\n\t\t}\n\n\t\tif ( hoset + that.size.height >= that.parentData.height ) {\n\t\t\tthat.size.height = that.parentData.height - hoset;\n\t\t\tif ( pRatio ) {\n\t\t\t\tthat.size.width = that.size.height * that.aspectRatio;\n\t\t\t\tcontinueResize = false;\n\t\t\t}\n\t\t}\n\n\t\tif ( !continueResize ) {\n\t\t\tthat.position.left = that.prevPosition.left;\n\t\t\tthat.position.top = that.prevPosition.top;\n\t\t\tthat.size.width = that.prevSize.width;\n\t\t\tthat.size.height = that.prevSize.height;\n\t\t}\n\t},\n\n\tstop: function() {\n\t\tvar that = $( this ).resizable( \"instance\" ),\n\t\t\to = that.options,\n\t\t\tco = that.containerOffset,\n\t\t\tcop = that.containerPosition,\n\t\t\tce = that.containerElement,\n\t\t\thelper = $( that.helper ),\n\t\t\tho = helper.offset(),\n\t\t\tw = helper.outerWidth() - that.sizeDiff.width,\n\t\t\th = helper.outerHeight() - that.sizeDiff.height;\n\n\t\tif ( that._helper && !o.animate && ( /relative/ ).test( ce.css( \"position\" ) ) ) {\n\t\t\t$( this ).css( {\n\t\t\t\tleft: ho.left - cop.left - co.left,\n\t\t\t\twidth: w,\n\t\t\t\theight: h\n\t\t\t} );\n\t\t}\n\n\t\tif ( that._helper && !o.animate && ( /static/ ).test( ce.css( \"position\" ) ) ) {\n\t\t\t$( this ).css( {\n\t\t\t\tleft: ho.left - cop.left - co.left,\n\t\t\t\twidth: w,\n\t\t\t\theight: h\n\t\t\t} );\n\t\t}\n\t}\n} );\n\n$.ui.plugin.add( \"resizable\", \"alsoResize\", {\n\n\tstart: function() {\n\t\tvar that = $( this ).resizable( \"instance\" ),\n\t\t\to = that.options;\n\n\t\t$( o.alsoResize ).each( function() {\n\t\t\tvar el = $( this );\n\t\t\tel.data( \"ui-resizable-alsoresize\", {\n\t\t\t\twidth: parseFloat( el.width() ), height: parseFloat( el.height() ),\n\t\t\t\tleft: parseFloat( el.css( \"left\" ) ), top: parseFloat( el.css( \"top\" ) )\n\t\t\t} );\n\t\t} );\n\t},\n\n\tresize: function( event, ui ) {\n\t\tvar that = $( this ).resizable( \"instance\" ),\n\t\t\to = that.options,\n\t\t\tos = that.originalSize,\n\t\t\top = that.originalPosition,\n\t\t\tdelta = {\n\t\t\t\theight: ( that.size.height - os.height ) || 0,\n\t\t\t\twidth: ( that.size.width - os.width ) || 0,\n\t\t\t\ttop: ( that.position.top - op.top ) || 0,\n\t\t\t\tleft: ( that.position.left - op.left ) || 0\n\t\t\t};\n\n\t\t\t$( o.alsoResize ).each( function() {\n\t\t\t\tvar el = $( this ), start = $( this ).data( \"ui-resizable-alsoresize\" ), style = {},\n\t\t\t\t\tcss = el.parents( ui.originalElement[ 0 ] ).length ?\n\t\t\t\t\t\t\t[ \"width\", \"height\" ] :\n\t\t\t\t\t\t\t[ \"width\", \"height\", \"top\", \"left\" ];\n\n\t\t\t\t$.each( css, function( i, prop ) {\n\t\t\t\t\tvar sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );\n\t\t\t\t\tif ( sum && sum >= 0 ) {\n\t\t\t\t\t\tstyle[ prop ] = sum || null;\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t\tel.css( style );\n\t\t\t} );\n\t},\n\n\tstop: function() {\n\t\t$( this ).removeData( \"ui-resizable-alsoresize\" );\n\t}\n} );\n\n$.ui.plugin.add( \"resizable\", \"ghost\", {\n\n\tstart: function() {\n\n\t\tvar that = $( this ).resizable( \"instance\" ), cs = that.size;\n\n\t\tthat.ghost = that.originalElement.clone();\n\t\tthat.ghost.css( {\n\t\t\topacity: 0.25,\n\t\t\tdisplay: \"block\",\n\t\t\tposition: \"relative\",\n\t\t\theight: cs.height,\n\t\t\twidth: cs.width,\n\t\t\tmargin: 0,\n\t\t\tleft: 0,\n\t\t\ttop: 0\n\t\t} );\n\n\t\tthat._addClass( that.ghost, \"ui-resizable-ghost\" );\n\n\t\t// DEPRECATED\n\t\t// TODO: remove after 1.12\n\t\tif ( $.uiBackCompat !== false && typeof that.options.ghost === \"string\" ) {\n\n\t\t\t// Ghost option\n\t\t\tthat.ghost.addClass( this.options.ghost );\n\t\t}\n\n\t\tthat.ghost.appendTo( that.helper );\n\n\t},\n\n\tresize: function() {\n\t\tvar that = $( this ).resizable( \"instance\" );\n\t\tif ( that.ghost ) {\n\t\t\tthat.ghost.css( {\n\t\t\t\tposition: \"relative\",\n\t\t\t\theight: that.size.height,\n\t\t\t\twidth: that.size.width\n\t\t\t} );\n\t\t}\n\t},\n\n\tstop: function() {\n\t\tvar that = $( this ).resizable( \"instance\" );\n\t\tif ( that.ghost && that.helper ) {\n\t\t\tthat.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );\n\t\t}\n\t}\n\n} );\n\n$.ui.plugin.add( \"resizable\", \"grid\", {\n\n\tresize: function() {\n\t\tvar outerDimensions,\n\t\t\tthat = $( this ).resizable( \"instance\" ),\n\t\t\to = that.options,\n\t\t\tcs = that.size,\n\t\t\tos = that.originalSize,\n\t\t\top = that.originalPosition,\n\t\t\ta = that.axis,\n\t\t\tgrid = typeof o.grid === \"number\" ? [ o.grid, o.grid ] : o.grid,\n\t\t\tgridX = ( grid[ 0 ] || 1 ),\n\t\t\tgridY = ( grid[ 1 ] || 1 ),\n\t\t\tox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,\n\t\t\toy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,\n\t\t\tnewWidth = os.width + ox,\n\t\t\tnewHeight = os.height + oy,\n\t\t\tisMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),\n\t\t\tisMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),\n\t\t\tisMinWidth = o.minWidth && ( o.minWidth > newWidth ),\n\t\t\tisMinHeight = o.minHeight && ( o.minHeight > newHeight );\n\n\t\to.grid = grid;\n\n\t\tif ( isMinWidth ) {\n\t\t\tnewWidth += gridX;\n\t\t}\n\t\tif ( isMinHeight ) {\n\t\t\tnewHeight += gridY;\n\t\t}\n\t\tif ( isMaxWidth ) {\n\t\t\tnewWidth -= gridX;\n\t\t}\n\t\tif ( isMaxHeight ) {\n\t\t\tnewHeight -= gridY;\n\t\t}\n\n\t\tif ( /^(se|s|e)$/.test( a ) ) {\n\t\t\tthat.size.width = newWidth;\n\t\t\tthat.size.height = newHeight;\n\t\t} else if ( /^(ne)$/.test( a ) ) {\n\t\t\tthat.size.width = newWidth;\n\t\t\tthat.size.height = newHeight;\n\t\t\tthat.position.top = op.top - oy;\n\t\t} else if ( /^(sw)$/.test( a ) ) {\n\t\t\tthat.size.width = newWidth;\n\t\t\tthat.size.height = newHeight;\n\t\t\tthat.position.left = op.left - ox;\n\t\t} else {\n\t\t\tif ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {\n\t\t\t\touterDimensions = that._getPaddingPlusBorderDimensions( this );\n\t\t\t}\n\n\t\t\tif ( newHeight - gridY > 0 ) {\n\t\t\t\tthat.size.height = newHeight;\n\t\t\t\tthat.position.top = op.top - oy;\n\t\t\t} else {\n\t\t\t\tnewHeight = gridY - outerDimensions.height;\n\t\t\t\tthat.size.height = newHeight;\n\t\t\t\tthat.position.top = op.top + os.height - newHeight;\n\t\t\t}\n\t\t\tif ( newWidth - gridX > 0 ) {\n\t\t\t\tthat.size.width = newWidth;\n\t\t\t\tthat.position.left = op.left - ox;\n\t\t\t} else {\n\t\t\t\tnewWidth = gridX - outerDimensions.width;\n\t\t\t\tthat.size.width = newWidth;\n\t\t\t\tthat.position.left = op.left + os.width - newWidth;\n\t\t\t}\n\t\t}\n\t}\n\n} );\n\nvar widgetsResizable = $.ui.resizable;\n\n\n/*!\n * jQuery UI Dialog 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Dialog\n//>>group: Widgets\n//>>description: Displays customizable dialog windows.\n//>>docs: http://api.jqueryui.com/dialog/\n//>>demos: http://jqueryui.com/dialog/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/dialog.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\n$.widget( \"ui.dialog\", {\n\tversion: \"1.12.1\",\n\toptions: {\n\t\tappendTo: \"body\",\n\t\tautoOpen: true,\n\t\tbuttons: [],\n\t\tclasses: {\n\t\t\t\"ui-dialog\": \"ui-corner-all\",\n\t\t\t\"ui-dialog-titlebar\": \"ui-corner-all\"\n\t\t},\n\t\tcloseOnEscape: true,\n\t\tcloseText: \"Close\",\n\t\tdraggable: true,\n\t\thide: null,\n\t\theight: \"auto\",\n\t\tmaxHeight: null,\n\t\tmaxWidth: null,\n\t\tminHeight: 150,\n\t\tminWidth: 150,\n\t\tmodal: false,\n\t\tposition: {\n\t\t\tmy: \"center\",\n\t\t\tat: \"center\",\n\t\t\tof: window,\n\t\t\tcollision: \"fit\",\n\n\t\t\t// Ensure the titlebar is always visible\n\t\t\tusing: function( pos ) {\n\t\t\t\tvar topOffset = $( this ).css( pos ).offset().top;\n\t\t\t\tif ( topOffset < 0 ) {\n\t\t\t\t\t$( this ).css( \"top\", pos.top - topOffset );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tresizable: true,\n\t\tshow: null,\n\t\ttitle: null,\n\t\twidth: 300,\n\n\t\t// Callbacks\n\t\tbeforeClose: null,\n\t\tclose: null,\n\t\tdrag: null,\n\t\tdragStart: null,\n\t\tdragStop: null,\n\t\tfocus: null,\n\t\topen: null,\n\t\tresize: null,\n\t\tresizeStart: null,\n\t\tresizeStop: null\n\t},\n\n\tsizeRelatedOptions: {\n\t\tbuttons: true,\n\t\theight: true,\n\t\tmaxHeight: true,\n\t\tmaxWidth: true,\n\t\tminHeight: true,\n\t\tminWidth: true,\n\t\twidth: true\n\t},\n\n\tresizableRelatedOptions: {\n\t\tmaxHeight: true,\n\t\tmaxWidth: true,\n\t\tminHeight: true,\n\t\tminWidth: true\n\t},\n\n\t_create: function() {\n\t\tthis.originalCss = {\n\t\t\tdisplay: this.element[ 0 ].style.display,\n\t\t\twidth: this.element[ 0 ].style.width,\n\t\t\tminHeight: this.element[ 0 ].style.minHeight,\n\t\t\tmaxHeight: this.element[ 0 ].style.maxHeight,\n\t\t\theight: this.element[ 0 ].style.height\n\t\t};\n\t\tthis.originalPosition = {\n\t\t\tparent: this.element.parent(),\n\t\t\tindex: this.element.parent().children().index( this.element )\n\t\t};\n\t\tthis.originalTitle = this.element.attr( \"title\" );\n\t\tif ( this.options.title == null && this.originalTitle != null ) {\n\t\t\tthis.options.title = this.originalTitle;\n\t\t}\n\n\t\t// Dialogs can't be disabled\n\t\tif ( this.options.disabled ) {\n\t\t\tthis.options.disabled = false;\n\t\t}\n\n\t\tthis._createWrapper();\n\n\t\tthis.element\n\t\t\t.show()\n\t\t\t.removeAttr( \"title\" )\n\t\t\t.appendTo( this.uiDialog );\n\n\t\tthis._addClass( \"ui-dialog-content\", \"ui-widget-content\" );\n\n\t\tthis._createTitlebar();\n\t\tthis._createButtonPane();\n\n\t\tif ( this.options.draggable && $.fn.draggable ) {\n\t\t\tthis._makeDraggable();\n\t\t}\n\t\tif ( this.options.resizable && $.fn.resizable ) {\n\t\t\tthis._makeResizable();\n\t\t}\n\n\t\tthis._isOpen = false;\n\n\t\tthis._trackFocus();\n\t},\n\n\t_init: function() {\n\t\tif ( this.options.autoOpen ) {\n\t\t\tthis.open();\n\t\t}\n\t},\n\n\t_appendTo: function() {\n\t\tvar element = this.options.appendTo;\n\t\tif ( element && ( element.jquery || element.nodeType ) ) {\n\t\t\treturn $( element );\n\t\t}\n\t\treturn this.document.find( element || \"body\" ).eq( 0 );\n\t},\n\n\t_destroy: function() {\n\t\tvar next,\n\t\t\toriginalPosition = this.originalPosition;\n\n\t\tthis._untrackInstance();\n\t\tthis._destroyOverlay();\n\n\t\tthis.element\n\t\t\t.removeUniqueId()\n\t\t\t.css( this.originalCss )\n\n\t\t\t// Without detaching first, the following becomes really slow\n\t\t\t.detach();\n\n\t\tthis.uiDialog.remove();\n\n\t\tif ( this.originalTitle ) {\n\t\t\tthis.element.attr( \"title\", this.originalTitle );\n\t\t}\n\n\t\tnext = originalPosition.parent.children().eq( originalPosition.index );\n\n\t\t// Don't try to place the dialog next to itself (#8613)\n\t\tif ( next.length && next[ 0 ] !== this.element[ 0 ] ) {\n\t\t\tnext.before( this.element );\n\t\t} else {\n\t\t\toriginalPosition.parent.append( this.element );\n\t\t}\n\t},\n\n\twidget: function() {\n\t\treturn this.uiDialog;\n\t},\n\n\tdisable: $.noop,\n\tenable: $.noop,\n\n\tclose: function( event ) {\n\t\tvar that = this;\n\n\t\tif ( !this._isOpen || this._trigger( \"beforeClose\", event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._isOpen = false;\n\t\tthis._focusedElement = null;\n\t\tthis._destroyOverlay();\n\t\tthis._untrackInstance();\n\n\t\tif ( !this.opener.filter( \":focusable\" ).trigger( \"focus\" ).length ) {\n\n\t\t\t// Hiding a focused element doesn't trigger blur in WebKit\n\t\t\t// so in case we have nothing to focus on, explicitly blur the active element\n\t\t\t// https://bugs.webkit.org/show_bug.cgi?id=47182\n\t\t\t$.ui.safeBlur( $.ui.safeActiveElement( this.document[ 0 ] ) );\n\t\t}\n\n\t\tthis._hide( this.uiDialog, this.options.hide, function() {\n\t\t\tthat._trigger( \"close\", event );\n\t\t} );\n\t},\n\n\tisOpen: function() {\n\t\treturn this._isOpen;\n\t},\n\n\tmoveToTop: function() {\n\t\tthis._moveToTop();\n\t},\n\n\t_moveToTop: function( event, silent ) {\n\t\tvar moved = false,\n\t\t\tzIndices = this.uiDialog.siblings( \".ui-front:visible\" ).map( function() {\n\t\t\t\treturn +$( this ).css( \"z-index\" );\n\t\t\t} ).get(),\n\t\t\tzIndexMax = Math.max.apply( null, zIndices );\n\n\t\tif ( zIndexMax >= +this.uiDialog.css( \"z-index\" ) ) {\n\t\t\tthis.uiDialog.css( \"z-index\", zIndexMax + 1 );\n\t\t\tmoved = true;\n\t\t}\n\n\t\tif ( moved && !silent ) {\n\t\t\tthis._trigger( \"focus\", event );\n\t\t}\n\t\treturn moved;\n\t},\n\n\topen: function() {\n\t\tvar that = this;\n\t\tif ( this._isOpen ) {\n\t\t\tif ( this._moveToTop() ) {\n\t\t\t\tthis._focusTabbable();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tthis._isOpen = true;\n\t\tthis.opener = $( $.ui.safeActiveElement( this.document[ 0 ] ) );\n\n\t\tthis._size();\n\t\tthis._position();\n\t\tthis._createOverlay();\n\t\tthis._moveToTop( null, true );\n\n\t\t// Ensure the overlay is moved to the top with the dialog, but only when\n\t\t// opening. The overlay shouldn't move after the dialog is open so that\n\t\t// modeless dialogs opened after the modal dialog stack properly.\n\t\tif ( this.overlay ) {\n\t\t\tthis.overlay.css( \"z-index\", this.uiDialog.css( \"z-index\" ) - 1 );\n\t\t}\n\n\t\tthis._show( this.uiDialog, this.options.show, function() {\n\t\t\tthat._focusTabbable();\n\t\t\tthat._trigger( \"focus\" );\n\t\t} );\n\n\t\t// Track the dialog immediately upon openening in case a focus event\n\t\t// somehow occurs outside of the dialog before an element inside the\n\t\t// dialog is focused (#10152)\n\t\tthis._makeFocusTarget();\n\n\t\tthis._trigger( \"open\" );\n\t},\n\n\t_focusTabbable: function() {\n\n\t\t// Set focus to the first match:\n\t\t// 1. An element that was focused previously\n\t\t// 2. First element inside the dialog matching [autofocus]\n\t\t// 3. Tabbable element inside the content element\n\t\t// 4. Tabbable element inside the buttonpane\n\t\t// 5. The close button\n\t\t// 6. The dialog itself\n\t\tvar hasFocus = this._focusedElement;\n\t\tif ( !hasFocus ) {\n\t\t\thasFocus = this.element.find( \"[autofocus]\" );\n\t\t}\n\t\tif ( !hasFocus.length ) {\n\t\t\thasFocus = this.element.find( \":tabbable\" );\n\t\t}\n\t\tif ( !hasFocus.length ) {\n\t\t\thasFocus = this.uiDialogButtonPane.find( \":tabbable\" );\n\t\t}\n\t\tif ( !hasFocus.length ) {\n\t\t\thasFocus = this.uiDialogTitlebarClose.filter( \":tabbable\" );\n\t\t}\n\t\tif ( !hasFocus.length ) {\n\t\t\thasFocus = this.uiDialog;\n\t\t}\n\t\thasFocus.eq( 0 ).trigger( \"focus\" );\n\t},\n\n\t_keepFocus: function( event ) {\n\t\tfunction checkFocus() {\n\t\t\tvar activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),\n\t\t\t\tisActive = this.uiDialog[ 0 ] === activeElement ||\n\t\t\t\t\t$.contains( this.uiDialog[ 0 ], activeElement );\n\t\t\tif ( !isActive ) {\n\t\t\t\tthis._focusTabbable();\n\t\t\t}\n\t\t}\n\t\tevent.preventDefault();\n\t\tcheckFocus.call( this );\n\n\t\t// support: IE\n\t\t// IE <= 8 doesn't prevent moving focus even with event.preventDefault()\n\t\t// so we check again later\n\t\tthis._delay( checkFocus );\n\t},\n\n\t_createWrapper: function() {\n\t\tthis.uiDialog = $( \"<div>\" )\n\t\t\t.hide()\n\t\t\t.attr( {\n\n\t\t\t\t// Setting tabIndex makes the div focusable\n\t\t\t\ttabIndex: -1,\n\t\t\t\trole: \"dialog\"\n\t\t\t} )\n\t\t\t.appendTo( this._appendTo() );\n\n\t\tthis._addClass( this.uiDialog, \"ui-dialog\", \"ui-widget ui-widget-content ui-front\" );\n\t\tthis._on( this.uiDialog, {\n\t\t\tkeydown: function( event ) {\n\t\t\t\tif ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&\n\t\t\t\t\t\tevent.keyCode === $.ui.keyCode.ESCAPE ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tthis.close( event );\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Prevent tabbing out of dialogs\n\t\t\t\tif ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tvar tabbables = this.uiDialog.find( \":tabbable\" ),\n\t\t\t\t\tfirst = tabbables.filter( \":first\" ),\n\t\t\t\t\tlast = tabbables.filter( \":last\" );\n\n\t\t\t\tif ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) &&\n\t\t\t\t\t\t!event.shiftKey ) {\n\t\t\t\t\tthis._delay( function() {\n\t\t\t\t\t\tfirst.trigger( \"focus\" );\n\t\t\t\t\t} );\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t} else if ( ( event.target === first[ 0 ] ||\n\t\t\t\t\t\tevent.target === this.uiDialog[ 0 ] ) && event.shiftKey ) {\n\t\t\t\t\tthis._delay( function() {\n\t\t\t\t\t\tlast.trigger( \"focus\" );\n\t\t\t\t\t} );\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t},\n\t\t\tmousedown: function( event ) {\n\t\t\t\tif ( this._moveToTop( event ) ) {\n\t\t\t\t\tthis._focusTabbable();\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\n\t\t// We assume that any existing aria-describedby attribute means\n\t\t// that the dialog content is marked up properly\n\t\t// otherwise we brute force the content as the description\n\t\tif ( !this.element.find( \"[aria-describedby]\" ).length ) {\n\t\t\tthis.uiDialog.attr( {\n\t\t\t\t\"aria-describedby\": this.element.uniqueId().attr( \"id\" )\n\t\t\t} );\n\t\t}\n\t},\n\n\t_createTitlebar: function() {\n\t\tvar uiDialogTitle;\n\n\t\tthis.uiDialogTitlebar = $( \"<div>\" );\n\t\tthis._addClass( this.uiDialogTitlebar,\n\t\t\t\"ui-dialog-titlebar\", \"ui-widget-header ui-helper-clearfix\" );\n\t\tthis._on( this.uiDialogTitlebar, {\n\t\t\tmousedown: function( event ) {\n\n\t\t\t\t// Don't prevent click on close button (#8838)\n\t\t\t\t// Focusing a dialog that is partially scrolled out of view\n\t\t\t\t// causes the browser to scroll it into view, preventing the click event\n\t\t\t\tif ( !$( event.target ).closest( \".ui-dialog-titlebar-close\" ) ) {\n\n\t\t\t\t\t// Dialog isn't getting focus when dragging (#8063)\n\t\t\t\t\tthis.uiDialog.trigger( \"focus\" );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\n\t\t// Support: IE\n\t\t// Use type=\"button\" to prevent enter keypresses in textboxes from closing the\n\t\t// dialog in IE (#9312)\n\t\tthis.uiDialogTitlebarClose = $( \"<button type='button'></button>\" )\n\t\t\t.button( {\n\t\t\t\tlabel: $( \"<a>\" ).text( this.options.closeText ).html(),\n\t\t\t\ticon: \"ui-icon-closethick\",\n\t\t\t\tshowLabel: false\n\t\t\t} )\n\t\t\t.appendTo( this.uiDialogTitlebar );\n\n\t\tthis._addClass( this.uiDialogTitlebarClose, \"ui-dialog-titlebar-close\" );\n\t\tthis._on( this.uiDialogTitlebarClose, {\n\t\t\tclick: function( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tthis.close( event );\n\t\t\t}\n\t\t} );\n\n\t\tuiDialogTitle = $( \"<span>\" ).uniqueId().prependTo( this.uiDialogTitlebar );\n\t\tthis._addClass( uiDialogTitle, \"ui-dialog-title\" );\n\t\tthis._title( uiDialogTitle );\n\n\t\tthis.uiDialogTitlebar.prependTo( this.uiDialog );\n\n\t\tthis.uiDialog.attr( {\n\t\t\t\"aria-labelledby\": uiDialogTitle.attr( \"id\" )\n\t\t} );\n\t},\n\n\t_title: function( title ) {\n\t\tif ( this.options.title ) {\n\t\t\ttitle.text( this.options.title );\n\t\t} else {\n\t\t\ttitle.html( \"&#160;\" );\n\t\t}\n\t},\n\n\t_createButtonPane: function() {\n\t\tthis.uiDialogButtonPane = $( \"<div>\" );\n\t\tthis._addClass( this.uiDialogButtonPane, \"ui-dialog-buttonpane\",\n\t\t\t\"ui-widget-content ui-helper-clearfix\" );\n\n\t\tthis.uiButtonSet = $( \"<div>\" )\n\t\t\t.appendTo( this.uiDialogButtonPane );\n\t\tthis._addClass( this.uiButtonSet, \"ui-dialog-buttonset\" );\n\n\t\tthis._createButtons();\n\t},\n\n\t_createButtons: function() {\n\t\tvar that = this,\n\t\t\tbuttons = this.options.buttons;\n\n\t\t// If we already have a button pane, remove it\n\t\tthis.uiDialogButtonPane.remove();\n\t\tthis.uiButtonSet.empty();\n\n\t\tif ( $.isEmptyObject( buttons ) || ( $.isArray( buttons ) && !buttons.length ) ) {\n\t\t\tthis._removeClass( this.uiDialog, \"ui-dialog-buttons\" );\n\t\t\treturn;\n\t\t}\n\n\t\t$.each( buttons, function( name, props ) {\n\t\t\tvar click, buttonOptions;\n\t\t\tprops = $.isFunction( props ) ?\n\t\t\t\t{ click: props, text: name } :\n\t\t\t\tprops;\n\n\t\t\t// Default to a non-submitting button\n\t\t\tprops = $.extend( { type: \"button\" }, props );\n\n\t\t\t// Change the context for the click callback to be the main element\n\t\t\tclick = props.click;\n\t\t\tbuttonOptions = {\n\t\t\t\ticon: props.icon,\n\t\t\t\ticonPosition: props.iconPosition,\n\t\t\t\tshowLabel: props.showLabel,\n\n\t\t\t\t// Deprecated options\n\t\t\t\ticons: props.icons,\n\t\t\t\ttext: props.text\n\t\t\t};\n\n\t\t\tdelete props.click;\n\t\t\tdelete props.icon;\n\t\t\tdelete props.iconPosition;\n\t\t\tdelete props.showLabel;\n\n\t\t\t// Deprecated options\n\t\t\tdelete props.icons;\n\t\t\tif ( typeof props.text === \"boolean\" ) {\n\t\t\t\tdelete props.text;\n\t\t\t}\n\n\t\t\t$( \"<button></button>\", props )\n\t\t\t\t.button( buttonOptions )\n\t\t\t\t.appendTo( that.uiButtonSet )\n\t\t\t\t.on( \"click\", function() {\n\t\t\t\t\tclick.apply( that.element[ 0 ], arguments );\n\t\t\t\t} );\n\t\t} );\n\t\tthis._addClass( this.uiDialog, \"ui-dialog-buttons\" );\n\t\tthis.uiDialogButtonPane.appendTo( this.uiDialog );\n\t},\n\n\t_makeDraggable: function() {\n\t\tvar that = this,\n\t\t\toptions = this.options;\n\n\t\tfunction filteredUi( ui ) {\n\t\t\treturn {\n\t\t\t\tposition: ui.position,\n\t\t\t\toffset: ui.offset\n\t\t\t};\n\t\t}\n\n\t\tthis.uiDialog.draggable( {\n\t\t\tcancel: \".ui-dialog-content, .ui-dialog-titlebar-close\",\n\t\t\thandle: \".ui-dialog-titlebar\",\n\t\t\tcontainment: \"document\",\n\t\t\tstart: function( event, ui ) {\n\t\t\t\tthat._addClass( $( this ), \"ui-dialog-dragging\" );\n\t\t\t\tthat._blockFrames();\n\t\t\t\tthat._trigger( \"dragStart\", event, filteredUi( ui ) );\n\t\t\t},\n\t\t\tdrag: function( event, ui ) {\n\t\t\t\tthat._trigger( \"drag\", event, filteredUi( ui ) );\n\t\t\t},\n\t\t\tstop: function( event, ui ) {\n\t\t\t\tvar left = ui.offset.left - that.document.scrollLeft(),\n\t\t\t\t\ttop = ui.offset.top - that.document.scrollTop();\n\n\t\t\t\toptions.position = {\n\t\t\t\t\tmy: \"left top\",\n\t\t\t\t\tat: \"left\" + ( left >= 0 ? \"+\" : \"\" ) + left + \" \" +\n\t\t\t\t\t\t\"top\" + ( top >= 0 ? \"+\" : \"\" ) + top,\n\t\t\t\t\tof: that.window\n\t\t\t\t};\n\t\t\t\tthat._removeClass( $( this ), \"ui-dialog-dragging\" );\n\t\t\t\tthat._unblockFrames();\n\t\t\t\tthat._trigger( \"dragStop\", event, filteredUi( ui ) );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_makeResizable: function() {\n\t\tvar that = this,\n\t\t\toptions = this.options,\n\t\t\thandles = options.resizable,\n\n\t\t\t// .ui-resizable has position: relative defined in the stylesheet\n\t\t\t// but dialogs have to use absolute or fixed positioning\n\t\t\tposition = this.uiDialog.css( \"position\" ),\n\t\t\tresizeHandles = typeof handles === \"string\" ?\n\t\t\t\thandles :\n\t\t\t\t\"n,e,s,w,se,sw,ne,nw\";\n\n\t\tfunction filteredUi( ui ) {\n\t\t\treturn {\n\t\t\t\toriginalPosition: ui.originalPosition,\n\t\t\t\toriginalSize: ui.originalSize,\n\t\t\t\tposition: ui.position,\n\t\t\t\tsize: ui.size\n\t\t\t};\n\t\t}\n\n\t\tthis.uiDialog.resizable( {\n\t\t\tcancel: \".ui-dialog-content\",\n\t\t\tcontainment: \"document\",\n\t\t\talsoResize: this.element,\n\t\t\tmaxWidth: options.maxWidth,\n\t\t\tmaxHeight: options.maxHeight,\n\t\t\tminWidth: options.minWidth,\n\t\t\tminHeight: this._minHeight(),\n\t\t\thandles: resizeHandles,\n\t\t\tstart: function( event, ui ) {\n\t\t\t\tthat._addClass( $( this ), \"ui-dialog-resizing\" );\n\t\t\t\tthat._blockFrames();\n\t\t\t\tthat._trigger( \"resizeStart\", event, filteredUi( ui ) );\n\t\t\t},\n\t\t\tresize: function( event, ui ) {\n\t\t\t\tthat._trigger( \"resize\", event, filteredUi( ui ) );\n\t\t\t},\n\t\t\tstop: function( event, ui ) {\n\t\t\t\tvar offset = that.uiDialog.offset(),\n\t\t\t\t\tleft = offset.left - that.document.scrollLeft(),\n\t\t\t\t\ttop = offset.top - that.document.scrollTop();\n\n\t\t\t\toptions.height = that.uiDialog.height();\n\t\t\t\toptions.width = that.uiDialog.width();\n\t\t\t\toptions.position = {\n\t\t\t\t\tmy: \"left top\",\n\t\t\t\t\tat: \"left\" + ( left >= 0 ? \"+\" : \"\" ) + left + \" \" +\n\t\t\t\t\t\t\"top\" + ( top >= 0 ? \"+\" : \"\" ) + top,\n\t\t\t\t\tof: that.window\n\t\t\t\t};\n\t\t\t\tthat._removeClass( $( this ), \"ui-dialog-resizing\" );\n\t\t\t\tthat._unblockFrames();\n\t\t\t\tthat._trigger( \"resizeStop\", event, filteredUi( ui ) );\n\t\t\t}\n\t\t} )\n\t\t\t.css( \"position\", position );\n\t},\n\n\t_trackFocus: function() {\n\t\tthis._on( this.widget(), {\n\t\t\tfocusin: function( event ) {\n\t\t\t\tthis._makeFocusTarget();\n\t\t\t\tthis._focusedElement = $( event.target );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_makeFocusTarget: function() {\n\t\tthis._untrackInstance();\n\t\tthis._trackingInstances().unshift( this );\n\t},\n\n\t_untrackInstance: function() {\n\t\tvar instances = this._trackingInstances(),\n\t\t\texists = $.inArray( this, instances );\n\t\tif ( exists !== -1 ) {\n\t\t\tinstances.splice( exists, 1 );\n\t\t}\n\t},\n\n\t_trackingInstances: function() {\n\t\tvar instances = this.document.data( \"ui-dialog-instances\" );\n\t\tif ( !instances ) {\n\t\t\tinstances = [];\n\t\t\tthis.document.data( \"ui-dialog-instances\", instances );\n\t\t}\n\t\treturn instances;\n\t},\n\n\t_minHeight: function() {\n\t\tvar options = this.options;\n\n\t\treturn options.height === \"auto\" ?\n\t\t\toptions.minHeight :\n\t\t\tMath.min( options.minHeight, options.height );\n\t},\n\n\t_position: function() {\n\n\t\t// Need to show the dialog to get the actual offset in the position plugin\n\t\tvar isVisible = this.uiDialog.is( \":visible\" );\n\t\tif ( !isVisible ) {\n\t\t\tthis.uiDialog.show();\n\t\t}\n\t\tthis.uiDialog.position( this.options.position );\n\t\tif ( !isVisible ) {\n\t\t\tthis.uiDialog.hide();\n\t\t}\n\t},\n\n\t_setOptions: function( options ) {\n\t\tvar that = this,\n\t\t\tresize = false,\n\t\t\tresizableOptions = {};\n\n\t\t$.each( options, function( key, value ) {\n\t\t\tthat._setOption( key, value );\n\n\t\t\tif ( key in that.sizeRelatedOptions ) {\n\t\t\t\tresize = true;\n\t\t\t}\n\t\t\tif ( key in that.resizableRelatedOptions ) {\n\t\t\t\tresizableOptions[ key ] = value;\n\t\t\t}\n\t\t} );\n\n\t\tif ( resize ) {\n\t\t\tthis._size();\n\t\t\tthis._position();\n\t\t}\n\t\tif ( this.uiDialog.is( \":data(ui-resizable)\" ) ) {\n\t\t\tthis.uiDialog.resizable( \"option\", resizableOptions );\n\t\t}\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tvar isDraggable, isResizable,\n\t\t\tuiDialog = this.uiDialog;\n\n\t\tif ( key === \"disabled\" ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._super( key, value );\n\n\t\tif ( key === \"appendTo\" ) {\n\t\t\tthis.uiDialog.appendTo( this._appendTo() );\n\t\t}\n\n\t\tif ( key === \"buttons\" ) {\n\t\t\tthis._createButtons();\n\t\t}\n\n\t\tif ( key === \"closeText\" ) {\n\t\t\tthis.uiDialogTitlebarClose.button( {\n\n\t\t\t\t// Ensure that we always pass a string\n\t\t\t\tlabel: $( \"<a>\" ).text( \"\" + this.options.closeText ).html()\n\t\t\t} );\n\t\t}\n\n\t\tif ( key === \"draggable\" ) {\n\t\t\tisDraggable = uiDialog.is( \":data(ui-draggable)\" );\n\t\t\tif ( isDraggable && !value ) {\n\t\t\t\tuiDialog.draggable( \"destroy\" );\n\t\t\t}\n\n\t\t\tif ( !isDraggable && value ) {\n\t\t\t\tthis._makeDraggable();\n\t\t\t}\n\t\t}\n\n\t\tif ( key === \"position\" ) {\n\t\t\tthis._position();\n\t\t}\n\n\t\tif ( key === \"resizable\" ) {\n\n\t\t\t// currently resizable, becoming non-resizable\n\t\t\tisResizable = uiDialog.is( \":data(ui-resizable)\" );\n\t\t\tif ( isResizable && !value ) {\n\t\t\t\tuiDialog.resizable( \"destroy\" );\n\t\t\t}\n\n\t\t\t// Currently resizable, changing handles\n\t\t\tif ( isResizable && typeof value === \"string\" ) {\n\t\t\t\tuiDialog.resizable( \"option\", \"handles\", value );\n\t\t\t}\n\n\t\t\t// Currently non-resizable, becoming resizable\n\t\t\tif ( !isResizable && value !== false ) {\n\t\t\t\tthis._makeResizable();\n\t\t\t}\n\t\t}\n\n\t\tif ( key === \"title\" ) {\n\t\t\tthis._title( this.uiDialogTitlebar.find( \".ui-dialog-title\" ) );\n\t\t}\n\t},\n\n\t_size: function() {\n\n\t\t// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content\n\t\t// divs will both have width and height set, so we need to reset them\n\t\tvar nonContentHeight, minContentHeight, maxContentHeight,\n\t\t\toptions = this.options;\n\n\t\t// Reset content sizing\n\t\tthis.element.show().css( {\n\t\t\twidth: \"auto\",\n\t\t\tminHeight: 0,\n\t\t\tmaxHeight: \"none\",\n\t\t\theight: 0\n\t\t} );\n\n\t\tif ( options.minWidth > options.width ) {\n\t\t\toptions.width = options.minWidth;\n\t\t}\n\n\t\t// Reset wrapper sizing\n\t\t// determine the height of all the non-content elements\n\t\tnonContentHeight = this.uiDialog.css( {\n\t\t\theight: \"auto\",\n\t\t\twidth: options.width\n\t\t} )\n\t\t\t.outerHeight();\n\t\tminContentHeight = Math.max( 0, options.minHeight - nonContentHeight );\n\t\tmaxContentHeight = typeof options.maxHeight === \"number\" ?\n\t\t\tMath.max( 0, options.maxHeight - nonContentHeight ) :\n\t\t\t\"none\";\n\n\t\tif ( options.height === \"auto\" ) {\n\t\t\tthis.element.css( {\n\t\t\t\tminHeight: minContentHeight,\n\t\t\t\tmaxHeight: maxContentHeight,\n\t\t\t\theight: \"auto\"\n\t\t\t} );\n\t\t} else {\n\t\t\tthis.element.height( Math.max( 0, options.height - nonContentHeight ) );\n\t\t}\n\n\t\tif ( this.uiDialog.is( \":data(ui-resizable)\" ) ) {\n\t\t\tthis.uiDialog.resizable( \"option\", \"minHeight\", this._minHeight() );\n\t\t}\n\t},\n\n\t_blockFrames: function() {\n\t\tthis.iframeBlocks = this.document.find( \"iframe\" ).map( function() {\n\t\t\tvar iframe = $( this );\n\n\t\t\treturn $( \"<div>\" )\n\t\t\t\t.css( {\n\t\t\t\t\tposition: \"absolute\",\n\t\t\t\t\twidth: iframe.outerWidth(),\n\t\t\t\t\theight: iframe.outerHeight()\n\t\t\t\t} )\n\t\t\t\t.appendTo( iframe.parent() )\n\t\t\t\t.offset( iframe.offset() )[ 0 ];\n\t\t} );\n\t},\n\n\t_unblockFrames: function() {\n\t\tif ( this.iframeBlocks ) {\n\t\t\tthis.iframeBlocks.remove();\n\t\t\tdelete this.iframeBlocks;\n\t\t}\n\t},\n\n\t_allowInteraction: function( event ) {\n\t\tif ( $( event.target ).closest( \".ui-dialog\" ).length ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// TODO: Remove hack when datepicker implements\n\t\t// the .ui-front logic (#8989)\n\t\treturn !!$( event.target ).closest( \".ui-datepicker\" ).length;\n\t},\n\n\t_createOverlay: function() {\n\t\tif ( !this.options.modal ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// We use a delay in case the overlay is created from an\n\t\t// event that we're going to be cancelling (#2804)\n\t\tvar isOpening = true;\n\t\tthis._delay( function() {\n\t\t\tisOpening = false;\n\t\t} );\n\n\t\tif ( !this.document.data( \"ui-dialog-overlays\" ) ) {\n\n\t\t\t// Prevent use of anchors and inputs\n\t\t\t// Using _on() for an event handler shared across many instances is\n\t\t\t// safe because the dialogs stack and must be closed in reverse order\n\t\t\tthis._on( this.document, {\n\t\t\t\tfocusin: function( event ) {\n\t\t\t\t\tif ( isOpening ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !this._allowInteraction( event ) ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\tthis._trackingInstances()[ 0 ]._focusTabbable();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\tthis.overlay = $( \"<div>\" )\n\t\t\t.appendTo( this._appendTo() );\n\n\t\tthis._addClass( this.overlay, null, \"ui-widget-overlay ui-front\" );\n\t\tthis._on( this.overlay, {\n\t\t\tmousedown: \"_keepFocus\"\n\t\t} );\n\t\tthis.document.data( \"ui-dialog-overlays\",\n\t\t\t( this.document.data( \"ui-dialog-overlays\" ) || 0 ) + 1 );\n\t},\n\n\t_destroyOverlay: function() {\n\t\tif ( !this.options.modal ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.overlay ) {\n\t\t\tvar overlays = this.document.data( \"ui-dialog-overlays\" ) - 1;\n\n\t\t\tif ( !overlays ) {\n\t\t\t\tthis._off( this.document, \"focusin\" );\n\t\t\t\tthis.document.removeData( \"ui-dialog-overlays\" );\n\t\t\t} else {\n\t\t\t\tthis.document.data( \"ui-dialog-overlays\", overlays );\n\t\t\t}\n\n\t\t\tthis.overlay.remove();\n\t\t\tthis.overlay = null;\n\t\t}\n\t}\n} );\n\n// DEPRECATED\n// TODO: switch return back to widget declaration at top of file when this is removed\nif ( $.uiBackCompat !== false ) {\n\n\t// Backcompat for dialogClass option\n\t$.widget( \"ui.dialog\", $.ui.dialog, {\n\t\toptions: {\n\t\t\tdialogClass: \"\"\n\t\t},\n\t\t_createWrapper: function() {\n\t\t\tthis._super();\n\t\t\tthis.uiDialog.addClass( this.options.dialogClass );\n\t\t},\n\t\t_setOption: function( key, value ) {\n\t\t\tif ( key === \"dialogClass\" ) {\n\t\t\t\tthis.uiDialog\n\t\t\t\t\t.removeClass( this.options.dialogClass )\n\t\t\t\t\t.addClass( value );\n\t\t\t}\n\t\t\tthis._superApply( arguments );\n\t\t}\n\t} );\n}\n\nvar widgetsDialog = $.ui.dialog;\n\n\n/*!\n * jQuery UI Droppable 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Droppable\n//>>group: Interactions\n//>>description: Enables drop targets for draggable elements.\n//>>docs: http://api.jqueryui.com/droppable/\n//>>demos: http://jqueryui.com/droppable/\n\n\n\n$.widget( \"ui.droppable\", {\n\tversion: \"1.12.1\",\n\twidgetEventPrefix: \"drop\",\n\toptions: {\n\t\taccept: \"*\",\n\t\taddClasses: true,\n\t\tgreedy: false,\n\t\tscope: \"default\",\n\t\ttolerance: \"intersect\",\n\n\t\t// Callbacks\n\t\tactivate: null,\n\t\tdeactivate: null,\n\t\tdrop: null,\n\t\tout: null,\n\t\tover: null\n\t},\n\t_create: function() {\n\n\t\tvar proportions,\n\t\t\to = this.options,\n\t\t\taccept = o.accept;\n\n\t\tthis.isover = false;\n\t\tthis.isout = true;\n\n\t\tthis.accept = $.isFunction( accept ) ? accept : function( d ) {\n\t\t\treturn d.is( accept );\n\t\t};\n\n\t\tthis.proportions = function( /* valueToWrite */ ) {\n\t\t\tif ( arguments.length ) {\n\n\t\t\t\t// Store the droppable's proportions\n\t\t\t\tproportions = arguments[ 0 ];\n\t\t\t} else {\n\n\t\t\t\t// Retrieve or derive the droppable's proportions\n\t\t\t\treturn proportions ?\n\t\t\t\t\tproportions :\n\t\t\t\t\tproportions = {\n\t\t\t\t\t\twidth: this.element[ 0 ].offsetWidth,\n\t\t\t\t\t\theight: this.element[ 0 ].offsetHeight\n\t\t\t\t\t};\n\t\t\t}\n\t\t};\n\n\t\tthis._addToManager( o.scope );\n\n\t\to.addClasses && this._addClass( \"ui-droppable\" );\n\n\t},\n\n\t_addToManager: function( scope ) {\n\n\t\t// Add the reference and positions to the manager\n\t\t$.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];\n\t\t$.ui.ddmanager.droppables[ scope ].push( this );\n\t},\n\n\t_splice: function( drop ) {\n\t\tvar i = 0;\n\t\tfor ( ; i < drop.length; i++ ) {\n\t\t\tif ( drop[ i ] === this ) {\n\t\t\t\tdrop.splice( i, 1 );\n\t\t\t}\n\t\t}\n\t},\n\n\t_destroy: function() {\n\t\tvar drop = $.ui.ddmanager.droppables[ this.options.scope ];\n\n\t\tthis._splice( drop );\n\t},\n\n\t_setOption: function( key, value ) {\n\n\t\tif ( key === \"accept\" ) {\n\t\t\tthis.accept = $.isFunction( value ) ? value : function( d ) {\n\t\t\t\treturn d.is( value );\n\t\t\t};\n\t\t} else if ( key === \"scope\" ) {\n\t\t\tvar drop = $.ui.ddmanager.droppables[ this.options.scope ];\n\n\t\t\tthis._splice( drop );\n\t\t\tthis._addToManager( value );\n\t\t}\n\n\t\tthis._super( key, value );\n\t},\n\n\t_activate: function( event ) {\n\t\tvar draggable = $.ui.ddmanager.current;\n\n\t\tthis._addActiveClass();\n\t\tif ( draggable ) {\n\t\t\tthis._trigger( \"activate\", event, this.ui( draggable ) );\n\t\t}\n\t},\n\n\t_deactivate: function( event ) {\n\t\tvar draggable = $.ui.ddmanager.current;\n\n\t\tthis._removeActiveClass();\n\t\tif ( draggable ) {\n\t\t\tthis._trigger( \"deactivate\", event, this.ui( draggable ) );\n\t\t}\n\t},\n\n\t_over: function( event ) {\n\n\t\tvar draggable = $.ui.ddmanager.current;\n\n\t\t// Bail if draggable and droppable are same element\n\t\tif ( !draggable || ( draggable.currentItem ||\n\t\t\t\tdraggable.element )[ 0 ] === this.element[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||\n\t\t\t\tdraggable.element ) ) ) {\n\t\t\tthis._addHoverClass();\n\t\t\tthis._trigger( \"over\", event, this.ui( draggable ) );\n\t\t}\n\n\t},\n\n\t_out: function( event ) {\n\n\t\tvar draggable = $.ui.ddmanager.current;\n\n\t\t// Bail if draggable and droppable are same element\n\t\tif ( !draggable || ( draggable.currentItem ||\n\t\t\t\tdraggable.element )[ 0 ] === this.element[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||\n\t\t\t\tdraggable.element ) ) ) {\n\t\t\tthis._removeHoverClass();\n\t\t\tthis._trigger( \"out\", event, this.ui( draggable ) );\n\t\t}\n\n\t},\n\n\t_drop: function( event, custom ) {\n\n\t\tvar draggable = custom || $.ui.ddmanager.current,\n\t\t\tchildrenIntersection = false;\n\n\t\t// Bail if draggable and droppable are same element\n\t\tif ( !draggable || ( draggable.currentItem ||\n\t\t\t\tdraggable.element )[ 0 ] === this.element[ 0 ] ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.element\n\t\t\t.find( \":data(ui-droppable)\" )\n\t\t\t.not( \".ui-draggable-dragging\" )\n\t\t\t.each( function() {\n\t\t\t\tvar inst = $( this ).droppable( \"instance\" );\n\t\t\t\tif (\n\t\t\t\t\tinst.options.greedy &&\n\t\t\t\t\t!inst.options.disabled &&\n\t\t\t\t\tinst.options.scope === draggable.options.scope &&\n\t\t\t\t\tinst.accept.call(\n\t\t\t\t\t\tinst.element[ 0 ], ( draggable.currentItem || draggable.element )\n\t\t\t\t\t) &&\n\t\t\t\t\tintersect(\n\t\t\t\t\t\tdraggable,\n\t\t\t\t\t\t$.extend( inst, { offset: inst.element.offset() } ),\n\t\t\t\t\t\tinst.options.tolerance, event\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\tchildrenIntersection = true;\n\t\t\t\t\treturn false; }\n\t\t\t} );\n\t\tif ( childrenIntersection ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( this.accept.call( this.element[ 0 ],\n\t\t\t\t( draggable.currentItem || draggable.element ) ) ) {\n\t\t\tthis._removeActiveClass();\n\t\t\tthis._removeHoverClass();\n\n\t\t\tthis._trigger( \"drop\", event, this.ui( draggable ) );\n\t\t\treturn this.element;\n\t\t}\n\n\t\treturn false;\n\n\t},\n\n\tui: function( c ) {\n\t\treturn {\n\t\t\tdraggable: ( c.currentItem || c.element ),\n\t\t\thelper: c.helper,\n\t\t\tposition: c.position,\n\t\t\toffset: c.positionAbs\n\t\t};\n\t},\n\n\t// Extension points just to make backcompat sane and avoid duplicating logic\n\t// TODO: Remove in 1.13 along with call to it below\n\t_addHoverClass: function() {\n\t\tthis._addClass( \"ui-droppable-hover\" );\n\t},\n\n\t_removeHoverClass: function() {\n\t\tthis._removeClass( \"ui-droppable-hover\" );\n\t},\n\n\t_addActiveClass: function() {\n\t\tthis._addClass( \"ui-droppable-active\" );\n\t},\n\n\t_removeActiveClass: function() {\n\t\tthis._removeClass( \"ui-droppable-active\" );\n\t}\n} );\n\nvar intersect = $.ui.intersect = ( function() {\n\tfunction isOverAxis( x, reference, size ) {\n\t\treturn ( x >= reference ) && ( x < ( reference + size ) );\n\t}\n\n\treturn function( draggable, droppable, toleranceMode, event ) {\n\n\t\tif ( !droppable.offset ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar x1 = ( draggable.positionAbs ||\n\t\t\t\tdraggable.position.absolute ).left + draggable.margins.left,\n\t\t\ty1 = ( draggable.positionAbs ||\n\t\t\t\tdraggable.position.absolute ).top + draggable.margins.top,\n\t\t\tx2 = x1 + draggable.helperProportions.width,\n\t\t\ty2 = y1 + draggable.helperProportions.height,\n\t\t\tl = droppable.offset.left,\n\t\t\tt = droppable.offset.top,\n\t\t\tr = l + droppable.proportions().width,\n\t\t\tb = t + droppable.proportions().height;\n\n\t\tswitch ( toleranceMode ) {\n\t\tcase \"fit\":\n\t\t\treturn ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );\n\t\tcase \"intersect\":\n\t\t\treturn ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half\n\t\t\t\tx2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half\n\t\t\t\tt < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half\n\t\t\t\ty2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half\n\t\tcase \"pointer\":\n\t\t\treturn isOverAxis( event.pageY, t, droppable.proportions().height ) &&\n\t\t\t\tisOverAxis( event.pageX, l, droppable.proportions().width );\n\t\tcase \"touch\":\n\t\t\treturn (\n\t\t\t\t( y1 >= t && y1 <= b ) || // Top edge touching\n\t\t\t\t( y2 >= t && y2 <= b ) || // Bottom edge touching\n\t\t\t\t( y1 < t && y2 > b ) // Surrounded vertically\n\t\t\t) && (\n\t\t\t\t( x1 >= l && x1 <= r ) || // Left edge touching\n\t\t\t\t( x2 >= l && x2 <= r ) || // Right edge touching\n\t\t\t\t( x1 < l && x2 > r ) // Surrounded horizontally\n\t\t\t);\n\t\tdefault:\n\t\t\treturn false;\n\t\t}\n\t};\n} )();\n\n/*\n\tThis manager tracks offsets of draggables and droppables\n*/\n$.ui.ddmanager = {\n\tcurrent: null,\n\tdroppables: { \"default\": [] },\n\tprepareOffsets: function( t, event ) {\n\n\t\tvar i, j,\n\t\t\tm = $.ui.ddmanager.droppables[ t.options.scope ] || [],\n\t\t\ttype = event ? event.type : null, // workaround for #2317\n\t\t\tlist = ( t.currentItem || t.element ).find( \":data(ui-droppable)\" ).addBack();\n\n\t\tdroppablesLoop: for ( i = 0; i < m.length; i++ ) {\n\n\t\t\t// No disabled and non-accepted\n\t\t\tif ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ],\n\t\t\t\t\t( t.currentItem || t.element ) ) ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Filter out elements in the current dragged item\n\t\t\tfor ( j = 0; j < list.length; j++ ) {\n\t\t\t\tif ( list[ j ] === m[ i ].element[ 0 ] ) {\n\t\t\t\t\tm[ i ].proportions().height = 0;\n\t\t\t\t\tcontinue droppablesLoop;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tm[ i ].visible = m[ i ].element.css( \"display\" ) !== \"none\";\n\t\t\tif ( !m[ i ].visible ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Activate the droppable if used directly from draggables\n\t\t\tif ( type === \"mousedown\" ) {\n\t\t\t\tm[ i ]._activate.call( m[ i ], event );\n\t\t\t}\n\n\t\t\tm[ i ].offset = m[ i ].element.offset();\n\t\t\tm[ i ].proportions( {\n\t\t\t\twidth: m[ i ].element[ 0 ].offsetWidth,\n\t\t\t\theight: m[ i ].element[ 0 ].offsetHeight\n\t\t\t} );\n\n\t\t}\n\n\t},\n\tdrop: function( draggable, event ) {\n\n\t\tvar dropped = false;\n\n\t\t// Create a copy of the droppables in case the list changes during the drop (#9116)\n\t\t$.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {\n\n\t\t\tif ( !this.options ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ( !this.options.disabled && this.visible &&\n\t\t\t\t\tintersect( draggable, this, this.options.tolerance, event ) ) {\n\t\t\t\tdropped = this._drop.call( this, event ) || dropped;\n\t\t\t}\n\n\t\t\tif ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ],\n\t\t\t\t\t( draggable.currentItem || draggable.element ) ) ) {\n\t\t\t\tthis.isout = true;\n\t\t\t\tthis.isover = false;\n\t\t\t\tthis._deactivate.call( this, event );\n\t\t\t}\n\n\t\t} );\n\t\treturn dropped;\n\n\t},\n\tdragStart: function( draggable, event ) {\n\n\t\t// Listen for scrolling so that if the dragging causes scrolling the position of the\n\t\t// droppables can be recalculated (see #5003)\n\t\tdraggable.element.parentsUntil( \"body\" ).on( \"scroll.droppable\", function() {\n\t\t\tif ( !draggable.options.refreshPositions ) {\n\t\t\t\t$.ui.ddmanager.prepareOffsets( draggable, event );\n\t\t\t}\n\t\t} );\n\t},\n\tdrag: function( draggable, event ) {\n\n\t\t// If you have a highly dynamic page, you might try this option. It renders positions\n\t\t// every time you move the mouse.\n\t\tif ( draggable.options.refreshPositions ) {\n\t\t\t$.ui.ddmanager.prepareOffsets( draggable, event );\n\t\t}\n\n\t\t// Run through all droppables and check their positions based on specific tolerance options\n\t\t$.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {\n\n\t\t\tif ( this.options.disabled || this.greedyChild || !this.visible ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar parentInstance, scope, parent,\n\t\t\t\tintersects = intersect( draggable, this, this.options.tolerance, event ),\n\t\t\t\tc = !intersects && this.isover ?\n\t\t\t\t\t\"isout\" :\n\t\t\t\t\t( intersects && !this.isover ? \"isover\" : null );\n\t\t\tif ( !c ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( this.options.greedy ) {\n\n\t\t\t\t// find droppable parents with same scope\n\t\t\t\tscope = this.options.scope;\n\t\t\t\tparent = this.element.parents( \":data(ui-droppable)\" ).filter( function() {\n\t\t\t\t\treturn $( this ).droppable( \"instance\" ).options.scope === scope;\n\t\t\t\t} );\n\n\t\t\t\tif ( parent.length ) {\n\t\t\t\t\tparentInstance = $( parent[ 0 ] ).droppable( \"instance\" );\n\t\t\t\t\tparentInstance.greedyChild = ( c === \"isover\" );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// We just moved into a greedy child\n\t\t\tif ( parentInstance && c === \"isover\" ) {\n\t\t\t\tparentInstance.isover = false;\n\t\t\t\tparentInstance.isout = true;\n\t\t\t\tparentInstance._out.call( parentInstance, event );\n\t\t\t}\n\n\t\t\tthis[ c ] = true;\n\t\t\tthis[ c === \"isout\" ? \"isover\" : \"isout\" ] = false;\n\t\t\tthis[ c === \"isover\" ? \"_over\" : \"_out\" ].call( this, event );\n\n\t\t\t// We just moved out of a greedy child\n\t\t\tif ( parentInstance && c === \"isout\" ) {\n\t\t\t\tparentInstance.isout = false;\n\t\t\t\tparentInstance.isover = true;\n\t\t\t\tparentInstance._over.call( parentInstance, event );\n\t\t\t}\n\t\t} );\n\n\t},\n\tdragStop: function( draggable, event ) {\n\t\tdraggable.element.parentsUntil( \"body\" ).off( \"scroll.droppable\" );\n\n\t\t// Call prepareOffsets one final time since IE does not fire return scroll events when\n\t\t// overflow was caused by drag (see #5003)\n\t\tif ( !draggable.options.refreshPositions ) {\n\t\t\t$.ui.ddmanager.prepareOffsets( draggable, event );\n\t\t}\n\t}\n};\n\n// DEPRECATED\n// TODO: switch return back to widget declaration at top of file when this is removed\nif ( $.uiBackCompat !== false ) {\n\n\t// Backcompat for activeClass and hoverClass options\n\t$.widget( \"ui.droppable\", $.ui.droppable, {\n\t\toptions: {\n\t\t\thoverClass: false,\n\t\t\tactiveClass: false\n\t\t},\n\t\t_addActiveClass: function() {\n\t\t\tthis._super();\n\t\t\tif ( this.options.activeClass ) {\n\t\t\t\tthis.element.addClass( this.options.activeClass );\n\t\t\t}\n\t\t},\n\t\t_removeActiveClass: function() {\n\t\t\tthis._super();\n\t\t\tif ( this.options.activeClass ) {\n\t\t\t\tthis.element.removeClass( this.options.activeClass );\n\t\t\t}\n\t\t},\n\t\t_addHoverClass: function() {\n\t\t\tthis._super();\n\t\t\tif ( this.options.hoverClass ) {\n\t\t\t\tthis.element.addClass( this.options.hoverClass );\n\t\t\t}\n\t\t},\n\t\t_removeHoverClass: function() {\n\t\t\tthis._super();\n\t\t\tif ( this.options.hoverClass ) {\n\t\t\t\tthis.element.removeClass( this.options.hoverClass );\n\t\t\t}\n\t\t}\n\t} );\n}\n\nvar widgetsDroppable = $.ui.droppable;\n\n\n/*!\n * jQuery UI Progressbar 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Progressbar\n//>>group: Widgets\n// jscs:disable maximumLineLength\n//>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators.\n// jscs:enable maximumLineLength\n//>>docs: http://api.jqueryui.com/progressbar/\n//>>demos: http://jqueryui.com/progressbar/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/progressbar.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\nvar widgetsProgressbar = $.widget( \"ui.progressbar\", {\n\tversion: \"1.12.1\",\n\toptions: {\n\t\tclasses: {\n\t\t\t\"ui-progressbar\": \"ui-corner-all\",\n\t\t\t\"ui-progressbar-value\": \"ui-corner-left\",\n\t\t\t\"ui-progressbar-complete\": \"ui-corner-right\"\n\t\t},\n\t\tmax: 100,\n\t\tvalue: 0,\n\n\t\tchange: null,\n\t\tcomplete: null\n\t},\n\n\tmin: 0,\n\n\t_create: function() {\n\n\t\t// Constrain initial value\n\t\tthis.oldValue = this.options.value = this._constrainedValue();\n\n\t\tthis.element.attr( {\n\n\t\t\t// Only set static values; aria-valuenow and aria-valuemax are\n\t\t\t// set inside _refreshValue()\n\t\t\trole: \"progressbar\",\n\t\t\t\"aria-valuemin\": this.min\n\t\t} );\n\t\tthis._addClass( \"ui-progressbar\", \"ui-widget ui-widget-content\" );\n\n\t\tthis.valueDiv = $( \"<div>\" ).appendTo( this.element );\n\t\tthis._addClass( this.valueDiv, \"ui-progressbar-value\", \"ui-widget-header\" );\n\t\tthis._refreshValue();\n\t},\n\n\t_destroy: function() {\n\t\tthis.element.removeAttr( \"role aria-valuemin aria-valuemax aria-valuenow\" );\n\n\t\tthis.valueDiv.remove();\n\t},\n\n\tvalue: function( newValue ) {\n\t\tif ( newValue === undefined ) {\n\t\t\treturn this.options.value;\n\t\t}\n\n\t\tthis.options.value = this._constrainedValue( newValue );\n\t\tthis._refreshValue();\n\t},\n\n\t_constrainedValue: function( newValue ) {\n\t\tif ( newValue === undefined ) {\n\t\t\tnewValue = this.options.value;\n\t\t}\n\n\t\tthis.indeterminate = newValue === false;\n\n\t\t// Sanitize value\n\t\tif ( typeof newValue !== \"number\" ) {\n\t\t\tnewValue = 0;\n\t\t}\n\n\t\treturn this.indeterminate ? false :\n\t\t\tMath.min( this.options.max, Math.max( this.min, newValue ) );\n\t},\n\n\t_setOptions: function( options ) {\n\n\t\t// Ensure \"value\" option is set after other values (like max)\n\t\tvar value = options.value;\n\t\tdelete options.value;\n\n\t\tthis._super( options );\n\n\t\tthis.options.value = this._constrainedValue( value );\n\t\tthis._refreshValue();\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"max\" ) {\n\n\t\t\t// Don't allow a max less than min\n\t\t\tvalue = Math.max( this.min, value );\n\t\t}\n\t\tthis._super( key, value );\n\t},\n\n\t_setOptionDisabled: function( value ) {\n\t\tthis._super( value );\n\n\t\tthis.element.attr( \"aria-disabled\", value );\n\t\tthis._toggleClass( null, \"ui-state-disabled\", !!value );\n\t},\n\n\t_percentage: function() {\n\t\treturn this.indeterminate ?\n\t\t\t100 :\n\t\t\t100 * ( this.options.value - this.min ) / ( this.options.max - this.min );\n\t},\n\n\t_refreshValue: function() {\n\t\tvar value = this.options.value,\n\t\t\tpercentage = this._percentage();\n\n\t\tthis.valueDiv\n\t\t\t.toggle( this.indeterminate || value > this.min )\n\t\t\t.width( percentage.toFixed( 0 ) + \"%\" );\n\n\t\tthis\n\t\t\t._toggleClass( this.valueDiv, \"ui-progressbar-complete\", null,\n\t\t\t\tvalue === this.options.max )\n\t\t\t._toggleClass( \"ui-progressbar-indeterminate\", null, this.indeterminate );\n\n\t\tif ( this.indeterminate ) {\n\t\t\tthis.element.removeAttr( \"aria-valuenow\" );\n\t\t\tif ( !this.overlayDiv ) {\n\t\t\t\tthis.overlayDiv = $( \"<div>\" ).appendTo( this.valueDiv );\n\t\t\t\tthis._addClass( this.overlayDiv, \"ui-progressbar-overlay\" );\n\t\t\t}\n\t\t} else {\n\t\t\tthis.element.attr( {\n\t\t\t\t\"aria-valuemax\": this.options.max,\n\t\t\t\t\"aria-valuenow\": value\n\t\t\t} );\n\t\t\tif ( this.overlayDiv ) {\n\t\t\t\tthis.overlayDiv.remove();\n\t\t\t\tthis.overlayDiv = null;\n\t\t\t}\n\t\t}\n\n\t\tif ( this.oldValue !== value ) {\n\t\t\tthis.oldValue = value;\n\t\t\tthis._trigger( \"change\" );\n\t\t}\n\t\tif ( value === this.options.max ) {\n\t\t\tthis._trigger( \"complete\" );\n\t\t}\n\t}\n} );\n\n\n/*!\n * jQuery UI Selectable 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Selectable\n//>>group: Interactions\n//>>description: Allows groups of elements to be selected with the mouse.\n//>>docs: http://api.jqueryui.com/selectable/\n//>>demos: http://jqueryui.com/selectable/\n//>>css.structure: ../../themes/base/selectable.css\n\n\n\nvar widgetsSelectable = $.widget( \"ui.selectable\", $.ui.mouse, {\n\tversion: \"1.12.1\",\n\toptions: {\n\t\tappendTo: \"body\",\n\t\tautoRefresh: true,\n\t\tdistance: 0,\n\t\tfilter: \"*\",\n\t\ttolerance: \"touch\",\n\n\t\t// Callbacks\n\t\tselected: null,\n\t\tselecting: null,\n\t\tstart: null,\n\t\tstop: null,\n\t\tunselected: null,\n\t\tunselecting: null\n\t},\n\t_create: function() {\n\t\tvar that = this;\n\n\t\tthis._addClass( \"ui-selectable\" );\n\n\t\tthis.dragged = false;\n\n\t\t// Cache selectee children based on filter\n\t\tthis.refresh = function() {\n\t\t\tthat.elementPos = $( that.element[ 0 ] ).offset();\n\t\t\tthat.selectees = $( that.options.filter, that.element[ 0 ] );\n\t\t\tthat._addClass( that.selectees, \"ui-selectee\" );\n\t\t\tthat.selectees.each( function() {\n\t\t\t\tvar $this = $( this ),\n\t\t\t\t\tselecteeOffset = $this.offset(),\n\t\t\t\t\tpos = {\n\t\t\t\t\t\tleft: selecteeOffset.left - that.elementPos.left,\n\t\t\t\t\t\ttop: selecteeOffset.top - that.elementPos.top\n\t\t\t\t\t};\n\t\t\t\t$.data( this, \"selectable-item\", {\n\t\t\t\t\telement: this,\n\t\t\t\t\t$element: $this,\n\t\t\t\t\tleft: pos.left,\n\t\t\t\t\ttop: pos.top,\n\t\t\t\t\tright: pos.left + $this.outerWidth(),\n\t\t\t\t\tbottom: pos.top + $this.outerHeight(),\n\t\t\t\t\tstartselected: false,\n\t\t\t\t\tselected: $this.hasClass( \"ui-selected\" ),\n\t\t\t\t\tselecting: $this.hasClass( \"ui-selecting\" ),\n\t\t\t\t\tunselecting: $this.hasClass( \"ui-unselecting\" )\n\t\t\t\t} );\n\t\t\t} );\n\t\t};\n\t\tthis.refresh();\n\n\t\tthis._mouseInit();\n\n\t\tthis.helper = $( \"<div>\" );\n\t\tthis._addClass( this.helper, \"ui-selectable-helper\" );\n\t},\n\n\t_destroy: function() {\n\t\tthis.selectees.removeData( \"selectable-item\" );\n\t\tthis._mouseDestroy();\n\t},\n\n\t_mouseStart: function( event ) {\n\t\tvar that = this,\n\t\t\toptions = this.options;\n\n\t\tthis.opos = [ event.pageX, event.pageY ];\n\t\tthis.elementPos = $( this.element[ 0 ] ).offset();\n\n\t\tif ( this.options.disabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.selectees = $( options.filter, this.element[ 0 ] );\n\n\t\tthis._trigger( \"start\", event );\n\n\t\t$( options.appendTo ).append( this.helper );\n\n\t\t// position helper (lasso)\n\t\tthis.helper.css( {\n\t\t\t\"left\": event.pageX,\n\t\t\t\"top\": event.pageY,\n\t\t\t\"width\": 0,\n\t\t\t\"height\": 0\n\t\t} );\n\n\t\tif ( options.autoRefresh ) {\n\t\t\tthis.refresh();\n\t\t}\n\n\t\tthis.selectees.filter( \".ui-selected\" ).each( function() {\n\t\t\tvar selectee = $.data( this, \"selectable-item\" );\n\t\t\tselectee.startselected = true;\n\t\t\tif ( !event.metaKey && !event.ctrlKey ) {\n\t\t\t\tthat._removeClass( selectee.$element, \"ui-selected\" );\n\t\t\t\tselectee.selected = false;\n\t\t\t\tthat._addClass( selectee.$element, \"ui-unselecting\" );\n\t\t\t\tselectee.unselecting = true;\n\n\t\t\t\t// selectable UNSELECTING callback\n\t\t\t\tthat._trigger( \"unselecting\", event, {\n\t\t\t\t\tunselecting: selectee.element\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\n\t\t$( event.target ).parents().addBack().each( function() {\n\t\t\tvar doSelect,\n\t\t\t\tselectee = $.data( this, \"selectable-item\" );\n\t\t\tif ( selectee ) {\n\t\t\t\tdoSelect = ( !event.metaKey && !event.ctrlKey ) ||\n\t\t\t\t\t!selectee.$element.hasClass( \"ui-selected\" );\n\t\t\t\tthat._removeClass( selectee.$element, doSelect ? \"ui-unselecting\" : \"ui-selected\" )\n\t\t\t\t\t._addClass( selectee.$element, doSelect ? \"ui-selecting\" : \"ui-unselecting\" );\n\t\t\t\tselectee.unselecting = !doSelect;\n\t\t\t\tselectee.selecting = doSelect;\n\t\t\t\tselectee.selected = doSelect;\n\n\t\t\t\t// selectable (UN)SELECTING callback\n\t\t\t\tif ( doSelect ) {\n\t\t\t\t\tthat._trigger( \"selecting\", event, {\n\t\t\t\t\t\tselecting: selectee.element\n\t\t\t\t\t} );\n\t\t\t\t} else {\n\t\t\t\t\tthat._trigger( \"unselecting\", event, {\n\t\t\t\t\t\tunselecting: selectee.element\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} );\n\n\t},\n\n\t_mouseDrag: function( event ) {\n\n\t\tthis.dragged = true;\n\n\t\tif ( this.options.disabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar tmp,\n\t\t\tthat = this,\n\t\t\toptions = this.options,\n\t\t\tx1 = this.opos[ 0 ],\n\t\t\ty1 = this.opos[ 1 ],\n\t\t\tx2 = event.pageX,\n\t\t\ty2 = event.pageY;\n\n\t\tif ( x1 > x2 ) { tmp = x2; x2 = x1; x1 = tmp; }\n\t\tif ( y1 > y2 ) { tmp = y2; y2 = y1; y1 = tmp; }\n\t\tthis.helper.css( { left: x1, top: y1, width: x2 - x1, height: y2 - y1 } );\n\n\t\tthis.selectees.each( function() {\n\t\t\tvar selectee = $.data( this, \"selectable-item\" ),\n\t\t\t\thit = false,\n\t\t\t\toffset = {};\n\n\t\t\t//prevent helper from being selected if appendTo: selectable\n\t\t\tif ( !selectee || selectee.element === that.element[ 0 ] ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\toffset.left   = selectee.left   + that.elementPos.left;\n\t\t\toffset.right  = selectee.right  + that.elementPos.left;\n\t\t\toffset.top    = selectee.top    + that.elementPos.top;\n\t\t\toffset.bottom = selectee.bottom + that.elementPos.top;\n\n\t\t\tif ( options.tolerance === \"touch\" ) {\n\t\t\t\thit = ( !( offset.left > x2 || offset.right < x1 || offset.top > y2 ||\n                    offset.bottom < y1 ) );\n\t\t\t} else if ( options.tolerance === \"fit\" ) {\n\t\t\t\thit = ( offset.left > x1 && offset.right < x2 && offset.top > y1 &&\n                    offset.bottom < y2 );\n\t\t\t}\n\n\t\t\tif ( hit ) {\n\n\t\t\t\t// SELECT\n\t\t\t\tif ( selectee.selected ) {\n\t\t\t\t\tthat._removeClass( selectee.$element, \"ui-selected\" );\n\t\t\t\t\tselectee.selected = false;\n\t\t\t\t}\n\t\t\t\tif ( selectee.unselecting ) {\n\t\t\t\t\tthat._removeClass( selectee.$element, \"ui-unselecting\" );\n\t\t\t\t\tselectee.unselecting = false;\n\t\t\t\t}\n\t\t\t\tif ( !selectee.selecting ) {\n\t\t\t\t\tthat._addClass( selectee.$element, \"ui-selecting\" );\n\t\t\t\t\tselectee.selecting = true;\n\n\t\t\t\t\t// selectable SELECTING callback\n\t\t\t\t\tthat._trigger( \"selecting\", event, {\n\t\t\t\t\t\tselecting: selectee.element\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// UNSELECT\n\t\t\t\tif ( selectee.selecting ) {\n\t\t\t\t\tif ( ( event.metaKey || event.ctrlKey ) && selectee.startselected ) {\n\t\t\t\t\t\tthat._removeClass( selectee.$element, \"ui-selecting\" );\n\t\t\t\t\t\tselectee.selecting = false;\n\t\t\t\t\t\tthat._addClass( selectee.$element, \"ui-selected\" );\n\t\t\t\t\t\tselectee.selected = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthat._removeClass( selectee.$element, \"ui-selecting\" );\n\t\t\t\t\t\tselectee.selecting = false;\n\t\t\t\t\t\tif ( selectee.startselected ) {\n\t\t\t\t\t\t\tthat._addClass( selectee.$element, \"ui-unselecting\" );\n\t\t\t\t\t\t\tselectee.unselecting = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// selectable UNSELECTING callback\n\t\t\t\t\t\tthat._trigger( \"unselecting\", event, {\n\t\t\t\t\t\t\tunselecting: selectee.element\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( selectee.selected ) {\n\t\t\t\t\tif ( !event.metaKey && !event.ctrlKey && !selectee.startselected ) {\n\t\t\t\t\t\tthat._removeClass( selectee.$element, \"ui-selected\" );\n\t\t\t\t\t\tselectee.selected = false;\n\n\t\t\t\t\t\tthat._addClass( selectee.$element, \"ui-unselecting\" );\n\t\t\t\t\t\tselectee.unselecting = true;\n\n\t\t\t\t\t\t// selectable UNSELECTING callback\n\t\t\t\t\t\tthat._trigger( \"unselecting\", event, {\n\t\t\t\t\t\t\tunselecting: selectee.element\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\n\t\treturn false;\n\t},\n\n\t_mouseStop: function( event ) {\n\t\tvar that = this;\n\n\t\tthis.dragged = false;\n\n\t\t$( \".ui-unselecting\", this.element[ 0 ] ).each( function() {\n\t\t\tvar selectee = $.data( this, \"selectable-item\" );\n\t\t\tthat._removeClass( selectee.$element, \"ui-unselecting\" );\n\t\t\tselectee.unselecting = false;\n\t\t\tselectee.startselected = false;\n\t\t\tthat._trigger( \"unselected\", event, {\n\t\t\t\tunselected: selectee.element\n\t\t\t} );\n\t\t} );\n\t\t$( \".ui-selecting\", this.element[ 0 ] ).each( function() {\n\t\t\tvar selectee = $.data( this, \"selectable-item\" );\n\t\t\tthat._removeClass( selectee.$element, \"ui-selecting\" )\n\t\t\t\t._addClass( selectee.$element, \"ui-selected\" );\n\t\t\tselectee.selecting = false;\n\t\t\tselectee.selected = true;\n\t\t\tselectee.startselected = true;\n\t\t\tthat._trigger( \"selected\", event, {\n\t\t\t\tselected: selectee.element\n\t\t\t} );\n\t\t} );\n\t\tthis._trigger( \"stop\", event );\n\n\t\tthis.helper.remove();\n\n\t\treturn false;\n\t}\n\n} );\n\n\n/*!\n * jQuery UI Selectmenu 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Selectmenu\n//>>group: Widgets\n// jscs:disable maximumLineLength\n//>>description: Duplicates and extends the functionality of a native HTML select element, allowing it to be customizable in behavior and appearance far beyond the limitations of a native select.\n// jscs:enable maximumLineLength\n//>>docs: http://api.jqueryui.com/selectmenu/\n//>>demos: http://jqueryui.com/selectmenu/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\nvar widgetsSelectmenu = $.widget( \"ui.selectmenu\", [ $.ui.formResetMixin, {\n\tversion: \"1.12.1\",\n\tdefaultElement: \"<select>\",\n\toptions: {\n\t\tappendTo: null,\n\t\tclasses: {\n\t\t\t\"ui-selectmenu-button-open\": \"ui-corner-top\",\n\t\t\t\"ui-selectmenu-button-closed\": \"ui-corner-all\"\n\t\t},\n\t\tdisabled: null,\n\t\ticons: {\n\t\t\tbutton: \"ui-icon-triangle-1-s\"\n\t\t},\n\t\tposition: {\n\t\t\tmy: \"left top\",\n\t\t\tat: \"left bottom\",\n\t\t\tcollision: \"none\"\n\t\t},\n\t\twidth: false,\n\n\t\t// Callbacks\n\t\tchange: null,\n\t\tclose: null,\n\t\tfocus: null,\n\t\topen: null,\n\t\tselect: null\n\t},\n\n\t_create: function() {\n\t\tvar selectmenuId = this.element.uniqueId().attr( \"id\" );\n\t\tthis.ids = {\n\t\t\telement: selectmenuId,\n\t\t\tbutton: selectmenuId + \"-button\",\n\t\t\tmenu: selectmenuId + \"-menu\"\n\t\t};\n\n\t\tthis._drawButton();\n\t\tthis._drawMenu();\n\t\tthis._bindFormResetHandler();\n\n\t\tthis._rendered = false;\n\t\tthis.menuItems = $();\n\t},\n\n\t_drawButton: function() {\n\t\tvar icon,\n\t\t\tthat = this,\n\t\t\titem = this._parseOption(\n\t\t\t\tthis.element.find( \"option:selected\" ),\n\t\t\t\tthis.element[ 0 ].selectedIndex\n\t\t\t);\n\n\t\t// Associate existing label with the new button\n\t\tthis.labels = this.element.labels().attr( \"for\", this.ids.button );\n\t\tthis._on( this.labels, {\n\t\t\tclick: function( event ) {\n\t\t\t\tthis.button.focus();\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t} );\n\n\t\t// Hide original select element\n\t\tthis.element.hide();\n\n\t\t// Create button\n\t\tthis.button = $( \"<span>\", {\n\t\t\ttabindex: this.options.disabled ? -1 : 0,\n\t\t\tid: this.ids.button,\n\t\t\trole: \"combobox\",\n\t\t\t\"aria-expanded\": \"false\",\n\t\t\t\"aria-autocomplete\": \"list\",\n\t\t\t\"aria-owns\": this.ids.menu,\n\t\t\t\"aria-haspopup\": \"true\",\n\t\t\ttitle: this.element.attr( \"title\" )\n\t\t} )\n\t\t\t.insertAfter( this.element );\n\n\t\tthis._addClass( this.button, \"ui-selectmenu-button ui-selectmenu-button-closed\",\n\t\t\t\"ui-button ui-widget\" );\n\n\t\ticon = $( \"<span>\" ).appendTo( this.button );\n\t\tthis._addClass( icon, \"ui-selectmenu-icon\", \"ui-icon \" + this.options.icons.button );\n\t\tthis.buttonItem = this._renderButtonItem( item )\n\t\t\t.appendTo( this.button );\n\n\t\tif ( this.options.width !== false ) {\n\t\t\tthis._resizeButton();\n\t\t}\n\n\t\tthis._on( this.button, this._buttonEvents );\n\t\tthis.button.one( \"focusin\", function() {\n\n\t\t\t// Delay rendering the menu items until the button receives focus.\n\t\t\t// The menu may have already been rendered via a programmatic open.\n\t\t\tif ( !that._rendered ) {\n\t\t\t\tthat._refreshMenu();\n\t\t\t}\n\t\t} );\n\t},\n\n\t_drawMenu: function() {\n\t\tvar that = this;\n\n\t\t// Create menu\n\t\tthis.menu = $( \"<ul>\", {\n\t\t\t\"aria-hidden\": \"true\",\n\t\t\t\"aria-labelledby\": this.ids.button,\n\t\t\tid: this.ids.menu\n\t\t} );\n\n\t\t// Wrap menu\n\t\tthis.menuWrap = $( \"<div>\" ).append( this.menu );\n\t\tthis._addClass( this.menuWrap, \"ui-selectmenu-menu\", \"ui-front\" );\n\t\tthis.menuWrap.appendTo( this._appendTo() );\n\n\t\t// Initialize menu widget\n\t\tthis.menuInstance = this.menu\n\t\t\t.menu( {\n\t\t\t\tclasses: {\n\t\t\t\t\t\"ui-menu\": \"ui-corner-bottom\"\n\t\t\t\t},\n\t\t\t\trole: \"listbox\",\n\t\t\t\tselect: function( event, ui ) {\n\t\t\t\t\tevent.preventDefault();\n\n\t\t\t\t\t// Support: IE8\n\t\t\t\t\t// If the item was selected via a click, the text selection\n\t\t\t\t\t// will be destroyed in IE\n\t\t\t\t\tthat._setSelection();\n\n\t\t\t\t\tthat._select( ui.item.data( \"ui-selectmenu-item\" ), event );\n\t\t\t\t},\n\t\t\t\tfocus: function( event, ui ) {\n\t\t\t\t\tvar item = ui.item.data( \"ui-selectmenu-item\" );\n\n\t\t\t\t\t// Prevent inital focus from firing and check if its a newly focused item\n\t\t\t\t\tif ( that.focusIndex != null && item.index !== that.focusIndex ) {\n\t\t\t\t\t\tthat._trigger( \"focus\", event, { item: item } );\n\t\t\t\t\t\tif ( !that.isOpen ) {\n\t\t\t\t\t\t\tthat._select( item, event );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthat.focusIndex = item.index;\n\n\t\t\t\t\tthat.button.attr( \"aria-activedescendant\",\n\t\t\t\t\t\tthat.menuItems.eq( item.index ).attr( \"id\" ) );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.menu( \"instance\" );\n\n\t\t// Don't close the menu on mouseleave\n\t\tthis.menuInstance._off( this.menu, \"mouseleave\" );\n\n\t\t// Cancel the menu's collapseAll on document click\n\t\tthis.menuInstance._closeOnDocumentClick = function() {\n\t\t\treturn false;\n\t\t};\n\n\t\t// Selects often contain empty items, but never contain dividers\n\t\tthis.menuInstance._isDivider = function() {\n\t\t\treturn false;\n\t\t};\n\t},\n\n\trefresh: function() {\n\t\tthis._refreshMenu();\n\t\tthis.buttonItem.replaceWith(\n\t\t\tthis.buttonItem = this._renderButtonItem(\n\n\t\t\t\t// Fall back to an empty object in case there are no options\n\t\t\t\tthis._getSelectedItem().data( \"ui-selectmenu-item\" ) || {}\n\t\t\t)\n\t\t);\n\t\tif ( this.options.width === null ) {\n\t\t\tthis._resizeButton();\n\t\t}\n\t},\n\n\t_refreshMenu: function() {\n\t\tvar item,\n\t\t\toptions = this.element.find( \"option\" );\n\n\t\tthis.menu.empty();\n\n\t\tthis._parseOptions( options );\n\t\tthis._renderMenu( this.menu, this.items );\n\n\t\tthis.menuInstance.refresh();\n\t\tthis.menuItems = this.menu.find( \"li\" )\n\t\t\t.not( \".ui-selectmenu-optgroup\" )\n\t\t\t\t.find( \".ui-menu-item-wrapper\" );\n\n\t\tthis._rendered = true;\n\n\t\tif ( !options.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\titem = this._getSelectedItem();\n\n\t\t// Update the menu to have the correct item focused\n\t\tthis.menuInstance.focus( null, item );\n\t\tthis._setAria( item.data( \"ui-selectmenu-item\" ) );\n\n\t\t// Set disabled state\n\t\tthis._setOption( \"disabled\", this.element.prop( \"disabled\" ) );\n\t},\n\n\topen: function( event ) {\n\t\tif ( this.options.disabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If this is the first time the menu is being opened, render the items\n\t\tif ( !this._rendered ) {\n\t\t\tthis._refreshMenu();\n\t\t} else {\n\n\t\t\t// Menu clears focus on close, reset focus to selected item\n\t\t\tthis._removeClass( this.menu.find( \".ui-state-active\" ), null, \"ui-state-active\" );\n\t\t\tthis.menuInstance.focus( null, this._getSelectedItem() );\n\t\t}\n\n\t\t// If there are no options, don't open the menu\n\t\tif ( !this.menuItems.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.isOpen = true;\n\t\tthis._toggleAttr();\n\t\tthis._resizeMenu();\n\t\tthis._position();\n\n\t\tthis._on( this.document, this._documentClick );\n\n\t\tthis._trigger( \"open\", event );\n\t},\n\n\t_position: function() {\n\t\tthis.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );\n\t},\n\n\tclose: function( event ) {\n\t\tif ( !this.isOpen ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.isOpen = false;\n\t\tthis._toggleAttr();\n\n\t\tthis.range = null;\n\t\tthis._off( this.document );\n\n\t\tthis._trigger( \"close\", event );\n\t},\n\n\twidget: function() {\n\t\treturn this.button;\n\t},\n\n\tmenuWidget: function() {\n\t\treturn this.menu;\n\t},\n\n\t_renderButtonItem: function( item ) {\n\t\tvar buttonItem = $( \"<span>\" );\n\n\t\tthis._setText( buttonItem, item.label );\n\t\tthis._addClass( buttonItem, \"ui-selectmenu-text\" );\n\n\t\treturn buttonItem;\n\t},\n\n\t_renderMenu: function( ul, items ) {\n\t\tvar that = this,\n\t\t\tcurrentOptgroup = \"\";\n\n\t\t$.each( items, function( index, item ) {\n\t\t\tvar li;\n\n\t\t\tif ( item.optgroup !== currentOptgroup ) {\n\t\t\t\tli = $( \"<li>\", {\n\t\t\t\t\ttext: item.optgroup\n\t\t\t\t} );\n\t\t\t\tthat._addClass( li, \"ui-selectmenu-optgroup\", \"ui-menu-divider\" +\n\t\t\t\t\t( item.element.parent( \"optgroup\" ).prop( \"disabled\" ) ?\n\t\t\t\t\t\t\" ui-state-disabled\" :\n\t\t\t\t\t\t\"\" ) );\n\n\t\t\t\tli.appendTo( ul );\n\n\t\t\t\tcurrentOptgroup = item.optgroup;\n\t\t\t}\n\n\t\t\tthat._renderItemData( ul, item );\n\t\t} );\n\t},\n\n\t_renderItemData: function( ul, item ) {\n\t\treturn this._renderItem( ul, item ).data( \"ui-selectmenu-item\", item );\n\t},\n\n\t_renderItem: function( ul, item ) {\n\t\tvar li = $( \"<li>\" ),\n\t\t\twrapper = $( \"<div>\", {\n\t\t\t\ttitle: item.element.attr( \"title\" )\n\t\t\t} );\n\n\t\tif ( item.disabled ) {\n\t\t\tthis._addClass( li, null, \"ui-state-disabled\" );\n\t\t}\n\t\tthis._setText( wrapper, item.label );\n\n\t\treturn li.append( wrapper ).appendTo( ul );\n\t},\n\n\t_setText: function( element, value ) {\n\t\tif ( value ) {\n\t\t\telement.text( value );\n\t\t} else {\n\t\t\telement.html( \"&#160;\" );\n\t\t}\n\t},\n\n\t_move: function( direction, event ) {\n\t\tvar item, next,\n\t\t\tfilter = \".ui-menu-item\";\n\n\t\tif ( this.isOpen ) {\n\t\t\titem = this.menuItems.eq( this.focusIndex ).parent( \"li\" );\n\t\t} else {\n\t\t\titem = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( \"li\" );\n\t\t\tfilter += \":not(.ui-state-disabled)\";\n\t\t}\n\n\t\tif ( direction === \"first\" || direction === \"last\" ) {\n\t\t\tnext = item[ direction === \"first\" ? \"prevAll\" : \"nextAll\" ]( filter ).eq( -1 );\n\t\t} else {\n\t\t\tnext = item[ direction + \"All\" ]( filter ).eq( 0 );\n\t\t}\n\n\t\tif ( next.length ) {\n\t\t\tthis.menuInstance.focus( event, next );\n\t\t}\n\t},\n\n\t_getSelectedItem: function() {\n\t\treturn this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( \"li\" );\n\t},\n\n\t_toggle: function( event ) {\n\t\tthis[ this.isOpen ? \"close\" : \"open\" ]( event );\n\t},\n\n\t_setSelection: function() {\n\t\tvar selection;\n\n\t\tif ( !this.range ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( window.getSelection ) {\n\t\t\tselection = window.getSelection();\n\t\t\tselection.removeAllRanges();\n\t\t\tselection.addRange( this.range );\n\n\t\t// Support: IE8\n\t\t} else {\n\t\t\tthis.range.select();\n\t\t}\n\n\t\t// Support: IE\n\t\t// Setting the text selection kills the button focus in IE, but\n\t\t// restoring the focus doesn't kill the selection.\n\t\tthis.button.focus();\n\t},\n\n\t_documentClick: {\n\t\tmousedown: function( event ) {\n\t\t\tif ( !this.isOpen ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( !$( event.target ).closest( \".ui-selectmenu-menu, #\" +\n\t\t\t\t\t$.ui.escapeSelector( this.ids.button ) ).length ) {\n\t\t\t\tthis.close( event );\n\t\t\t}\n\t\t}\n\t},\n\n\t_buttonEvents: {\n\n\t\t// Prevent text selection from being reset when interacting with the selectmenu (#10144)\n\t\tmousedown: function() {\n\t\t\tvar selection;\n\n\t\t\tif ( window.getSelection ) {\n\t\t\t\tselection = window.getSelection();\n\t\t\t\tif ( selection.rangeCount ) {\n\t\t\t\t\tthis.range = selection.getRangeAt( 0 );\n\t\t\t\t}\n\n\t\t\t// Support: IE8\n\t\t\t} else {\n\t\t\t\tthis.range = document.selection.createRange();\n\t\t\t}\n\t\t},\n\n\t\tclick: function( event ) {\n\t\t\tthis._setSelection();\n\t\t\tthis._toggle( event );\n\t\t},\n\n\t\tkeydown: function( event ) {\n\t\t\tvar preventDefault = true;\n\t\t\tswitch ( event.keyCode ) {\n\t\t\tcase $.ui.keyCode.TAB:\n\t\t\tcase $.ui.keyCode.ESCAPE:\n\t\t\t\tthis.close( event );\n\t\t\t\tpreventDefault = false;\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.ENTER:\n\t\t\t\tif ( this.isOpen ) {\n\t\t\t\t\tthis._selectFocusedItem( event );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.UP:\n\t\t\t\tif ( event.altKey ) {\n\t\t\t\t\tthis._toggle( event );\n\t\t\t\t} else {\n\t\t\t\t\tthis._move( \"prev\", event );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.DOWN:\n\t\t\t\tif ( event.altKey ) {\n\t\t\t\t\tthis._toggle( event );\n\t\t\t\t} else {\n\t\t\t\t\tthis._move( \"next\", event );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.SPACE:\n\t\t\t\tif ( this.isOpen ) {\n\t\t\t\t\tthis._selectFocusedItem( event );\n\t\t\t\t} else {\n\t\t\t\t\tthis._toggle( event );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.LEFT:\n\t\t\t\tthis._move( \"prev\", event );\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.RIGHT:\n\t\t\t\tthis._move( \"next\", event );\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.HOME:\n\t\t\tcase $.ui.keyCode.PAGE_UP:\n\t\t\t\tthis._move( \"first\", event );\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.END:\n\t\t\tcase $.ui.keyCode.PAGE_DOWN:\n\t\t\t\tthis._move( \"last\", event );\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthis.menu.trigger( event );\n\t\t\t\tpreventDefault = false;\n\t\t\t}\n\n\t\t\tif ( preventDefault ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\t},\n\n\t_selectFocusedItem: function( event ) {\n\t\tvar item = this.menuItems.eq( this.focusIndex ).parent( \"li\" );\n\t\tif ( !item.hasClass( \"ui-state-disabled\" ) ) {\n\t\t\tthis._select( item.data( \"ui-selectmenu-item\" ), event );\n\t\t}\n\t},\n\n\t_select: function( item, event ) {\n\t\tvar oldIndex = this.element[ 0 ].selectedIndex;\n\n\t\t// Change native select element\n\t\tthis.element[ 0 ].selectedIndex = item.index;\n\t\tthis.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) );\n\t\tthis._setAria( item );\n\t\tthis._trigger( \"select\", event, { item: item } );\n\n\t\tif ( item.index !== oldIndex ) {\n\t\t\tthis._trigger( \"change\", event, { item: item } );\n\t\t}\n\n\t\tthis.close( event );\n\t},\n\n\t_setAria: function( item ) {\n\t\tvar id = this.menuItems.eq( item.index ).attr( \"id\" );\n\n\t\tthis.button.attr( {\n\t\t\t\"aria-labelledby\": id,\n\t\t\t\"aria-activedescendant\": id\n\t\t} );\n\t\tthis.menu.attr( \"aria-activedescendant\", id );\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"icons\" ) {\n\t\t\tvar icon = this.button.find( \"span.ui-icon\" );\n\t\t\tthis._removeClass( icon, null, this.options.icons.button )\n\t\t\t\t._addClass( icon, null, value.button );\n\t\t}\n\n\t\tthis._super( key, value );\n\n\t\tif ( key === \"appendTo\" ) {\n\t\t\tthis.menuWrap.appendTo( this._appendTo() );\n\t\t}\n\n\t\tif ( key === \"width\" ) {\n\t\t\tthis._resizeButton();\n\t\t}\n\t},\n\n\t_setOptionDisabled: function( value ) {\n\t\tthis._super( value );\n\n\t\tthis.menuInstance.option( \"disabled\", value );\n\t\tthis.button.attr( \"aria-disabled\", value );\n\t\tthis._toggleClass( this.button, null, \"ui-state-disabled\", value );\n\n\t\tthis.element.prop( \"disabled\", value );\n\t\tif ( value ) {\n\t\t\tthis.button.attr( \"tabindex\", -1 );\n\t\t\tthis.close();\n\t\t} else {\n\t\t\tthis.button.attr( \"tabindex\", 0 );\n\t\t}\n\t},\n\n\t_appendTo: function() {\n\t\tvar element = this.options.appendTo;\n\n\t\tif ( element ) {\n\t\t\telement = element.jquery || element.nodeType ?\n\t\t\t\t$( element ) :\n\t\t\t\tthis.document.find( element ).eq( 0 );\n\t\t}\n\n\t\tif ( !element || !element[ 0 ] ) {\n\t\t\telement = this.element.closest( \".ui-front, dialog\" );\n\t\t}\n\n\t\tif ( !element.length ) {\n\t\t\telement = this.document[ 0 ].body;\n\t\t}\n\n\t\treturn element;\n\t},\n\n\t_toggleAttr: function() {\n\t\tthis.button.attr( \"aria-expanded\", this.isOpen );\n\n\t\t// We can't use two _toggleClass() calls here, because we need to make sure\n\t\t// we always remove classes first and add them second, otherwise if both classes have the\n\t\t// same theme class, it will be removed after we add it.\n\t\tthis._removeClass( this.button, \"ui-selectmenu-button-\" +\n\t\t\t( this.isOpen ? \"closed\" : \"open\" ) )\n\t\t\t._addClass( this.button, \"ui-selectmenu-button-\" +\n\t\t\t\t( this.isOpen ? \"open\" : \"closed\" ) )\n\t\t\t._toggleClass( this.menuWrap, \"ui-selectmenu-open\", null, this.isOpen );\n\n\t\tthis.menu.attr( \"aria-hidden\", !this.isOpen );\n\t},\n\n\t_resizeButton: function() {\n\t\tvar width = this.options.width;\n\n\t\t// For `width: false`, just remove inline style and stop\n\t\tif ( width === false ) {\n\t\t\tthis.button.css( \"width\", \"\" );\n\t\t\treturn;\n\t\t}\n\n\t\t// For `width: null`, match the width of the original element\n\t\tif ( width === null ) {\n\t\t\twidth = this.element.show().outerWidth();\n\t\t\tthis.element.hide();\n\t\t}\n\n\t\tthis.button.outerWidth( width );\n\t},\n\n\t_resizeMenu: function() {\n\t\tthis.menu.outerWidth( Math.max(\n\t\t\tthis.button.outerWidth(),\n\n\t\t\t// Support: IE10\n\t\t\t// IE10 wraps long text (possibly a rounding bug)\n\t\t\t// so we add 1px to avoid the wrapping\n\t\t\tthis.menu.width( \"\" ).outerWidth() + 1\n\t\t) );\n\t},\n\n\t_getCreateOptions: function() {\n\t\tvar options = this._super();\n\n\t\toptions.disabled = this.element.prop( \"disabled\" );\n\n\t\treturn options;\n\t},\n\n\t_parseOptions: function( options ) {\n\t\tvar that = this,\n\t\t\tdata = [];\n\t\toptions.each( function( index, item ) {\n\t\t\tdata.push( that._parseOption( $( item ), index ) );\n\t\t} );\n\t\tthis.items = data;\n\t},\n\n\t_parseOption: function( option, index ) {\n\t\tvar optgroup = option.parent( \"optgroup\" );\n\n\t\treturn {\n\t\t\telement: option,\n\t\t\tindex: index,\n\t\t\tvalue: option.val(),\n\t\t\tlabel: option.text(),\n\t\t\toptgroup: optgroup.attr( \"label\" ) || \"\",\n\t\t\tdisabled: optgroup.prop( \"disabled\" ) || option.prop( \"disabled\" )\n\t\t};\n\t},\n\n\t_destroy: function() {\n\t\tthis._unbindFormResetHandler();\n\t\tthis.menuWrap.remove();\n\t\tthis.button.remove();\n\t\tthis.element.show();\n\t\tthis.element.removeUniqueId();\n\t\tthis.labels.attr( \"for\", this.ids.element );\n\t}\n} ] );\n\n\n/*!\n * jQuery UI Slider 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Slider\n//>>group: Widgets\n//>>description: Displays a flexible slider with ranges and accessibility via keyboard.\n//>>docs: http://api.jqueryui.com/slider/\n//>>demos: http://jqueryui.com/slider/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/slider.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\nvar widgetsSlider = $.widget( \"ui.slider\", $.ui.mouse, {\n\tversion: \"1.12.1\",\n\twidgetEventPrefix: \"slide\",\n\n\toptions: {\n\t\tanimate: false,\n\t\tclasses: {\n\t\t\t\"ui-slider\": \"ui-corner-all\",\n\t\t\t\"ui-slider-handle\": \"ui-corner-all\",\n\n\t\t\t// Note: ui-widget-header isn't the most fittingly semantic framework class for this\n\t\t\t// element, but worked best visually with a variety of themes\n\t\t\t\"ui-slider-range\": \"ui-corner-all ui-widget-header\"\n\t\t},\n\t\tdistance: 0,\n\t\tmax: 100,\n\t\tmin: 0,\n\t\torientation: \"horizontal\",\n\t\trange: false,\n\t\tstep: 1,\n\t\tvalue: 0,\n\t\tvalues: null,\n\n\t\t// Callbacks\n\t\tchange: null,\n\t\tslide: null,\n\t\tstart: null,\n\t\tstop: null\n\t},\n\n\t// Number of pages in a slider\n\t// (how many times can you page up/down to go through the whole range)\n\tnumPages: 5,\n\n\t_create: function() {\n\t\tthis._keySliding = false;\n\t\tthis._mouseSliding = false;\n\t\tthis._animateOff = true;\n\t\tthis._handleIndex = null;\n\t\tthis._detectOrientation();\n\t\tthis._mouseInit();\n\t\tthis._calculateNewMax();\n\n\t\tthis._addClass( \"ui-slider ui-slider-\" + this.orientation,\n\t\t\t\"ui-widget ui-widget-content\" );\n\n\t\tthis._refresh();\n\n\t\tthis._animateOff = false;\n\t},\n\n\t_refresh: function() {\n\t\tthis._createRange();\n\t\tthis._createHandles();\n\t\tthis._setupEvents();\n\t\tthis._refreshValue();\n\t},\n\n\t_createHandles: function() {\n\t\tvar i, handleCount,\n\t\t\toptions = this.options,\n\t\t\texistingHandles = this.element.find( \".ui-slider-handle\" ),\n\t\t\thandle = \"<span tabindex='0'></span>\",\n\t\t\thandles = [];\n\n\t\thandleCount = ( options.values && options.values.length ) || 1;\n\n\t\tif ( existingHandles.length > handleCount ) {\n\t\t\texistingHandles.slice( handleCount ).remove();\n\t\t\texistingHandles = existingHandles.slice( 0, handleCount );\n\t\t}\n\n\t\tfor ( i = existingHandles.length; i < handleCount; i++ ) {\n\t\t\thandles.push( handle );\n\t\t}\n\n\t\tthis.handles = existingHandles.add( $( handles.join( \"\" ) ).appendTo( this.element ) );\n\n\t\tthis._addClass( this.handles, \"ui-slider-handle\", \"ui-state-default\" );\n\n\t\tthis.handle = this.handles.eq( 0 );\n\n\t\tthis.handles.each( function( i ) {\n\t\t\t$( this )\n\t\t\t\t.data( \"ui-slider-handle-index\", i )\n\t\t\t\t.attr( \"tabIndex\", 0 );\n\t\t} );\n\t},\n\n\t_createRange: function() {\n\t\tvar options = this.options;\n\n\t\tif ( options.range ) {\n\t\t\tif ( options.range === true ) {\n\t\t\t\tif ( !options.values ) {\n\t\t\t\t\toptions.values = [ this._valueMin(), this._valueMin() ];\n\t\t\t\t} else if ( options.values.length && options.values.length !== 2 ) {\n\t\t\t\t\toptions.values = [ options.values[ 0 ], options.values[ 0 ] ];\n\t\t\t\t} else if ( $.isArray( options.values ) ) {\n\t\t\t\t\toptions.values = options.values.slice( 0 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( !this.range || !this.range.length ) {\n\t\t\t\tthis.range = $( \"<div>\" )\n\t\t\t\t\t.appendTo( this.element );\n\n\t\t\t\tthis._addClass( this.range, \"ui-slider-range\" );\n\t\t\t} else {\n\t\t\t\tthis._removeClass( this.range, \"ui-slider-range-min ui-slider-range-max\" );\n\n\t\t\t\t// Handle range switching from true to min/max\n\t\t\t\tthis.range.css( {\n\t\t\t\t\t\"left\": \"\",\n\t\t\t\t\t\"bottom\": \"\"\n\t\t\t\t} );\n\t\t\t}\n\t\t\tif ( options.range === \"min\" || options.range === \"max\" ) {\n\t\t\t\tthis._addClass( this.range, \"ui-slider-range-\" + options.range );\n\t\t\t}\n\t\t} else {\n\t\t\tif ( this.range ) {\n\t\t\t\tthis.range.remove();\n\t\t\t}\n\t\t\tthis.range = null;\n\t\t}\n\t},\n\n\t_setupEvents: function() {\n\t\tthis._off( this.handles );\n\t\tthis._on( this.handles, this._handleEvents );\n\t\tthis._hoverable( this.handles );\n\t\tthis._focusable( this.handles );\n\t},\n\n\t_destroy: function() {\n\t\tthis.handles.remove();\n\t\tif ( this.range ) {\n\t\t\tthis.range.remove();\n\t\t}\n\n\t\tthis._mouseDestroy();\n\t},\n\n\t_mouseCapture: function( event ) {\n\t\tvar position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,\n\t\t\tthat = this,\n\t\t\to = this.options;\n\n\t\tif ( o.disabled ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.elementSize = {\n\t\t\twidth: this.element.outerWidth(),\n\t\t\theight: this.element.outerHeight()\n\t\t};\n\t\tthis.elementOffset = this.element.offset();\n\n\t\tposition = { x: event.pageX, y: event.pageY };\n\t\tnormValue = this._normValueFromMouse( position );\n\t\tdistance = this._valueMax() - this._valueMin() + 1;\n\t\tthis.handles.each( function( i ) {\n\t\t\tvar thisDistance = Math.abs( normValue - that.values( i ) );\n\t\t\tif ( ( distance > thisDistance ) ||\n\t\t\t\t( distance === thisDistance &&\n\t\t\t\t\t( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) {\n\t\t\t\tdistance = thisDistance;\n\t\t\t\tclosestHandle = $( this );\n\t\t\t\tindex = i;\n\t\t\t}\n\t\t} );\n\n\t\tallowed = this._start( event, index );\n\t\tif ( allowed === false ) {\n\t\t\treturn false;\n\t\t}\n\t\tthis._mouseSliding = true;\n\n\t\tthis._handleIndex = index;\n\n\t\tthis._addClass( closestHandle, null, \"ui-state-active\" );\n\t\tclosestHandle.trigger( \"focus\" );\n\n\t\toffset = closestHandle.offset();\n\t\tmouseOverHandle = !$( event.target ).parents().addBack().is( \".ui-slider-handle\" );\n\t\tthis._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {\n\t\t\tleft: event.pageX - offset.left - ( closestHandle.width() / 2 ),\n\t\t\ttop: event.pageY - offset.top -\n\t\t\t\t( closestHandle.height() / 2 ) -\n\t\t\t\t( parseInt( closestHandle.css( \"borderTopWidth\" ), 10 ) || 0 ) -\n\t\t\t\t( parseInt( closestHandle.css( \"borderBottomWidth\" ), 10 ) || 0 ) +\n\t\t\t\t( parseInt( closestHandle.css( \"marginTop\" ), 10 ) || 0 )\n\t\t};\n\n\t\tif ( !this.handles.hasClass( \"ui-state-hover\" ) ) {\n\t\t\tthis._slide( event, index, normValue );\n\t\t}\n\t\tthis._animateOff = true;\n\t\treturn true;\n\t},\n\n\t_mouseStart: function() {\n\t\treturn true;\n\t},\n\n\t_mouseDrag: function( event ) {\n\t\tvar position = { x: event.pageX, y: event.pageY },\n\t\t\tnormValue = this._normValueFromMouse( position );\n\n\t\tthis._slide( event, this._handleIndex, normValue );\n\n\t\treturn false;\n\t},\n\n\t_mouseStop: function( event ) {\n\t\tthis._removeClass( this.handles, null, \"ui-state-active\" );\n\t\tthis._mouseSliding = false;\n\n\t\tthis._stop( event, this._handleIndex );\n\t\tthis._change( event, this._handleIndex );\n\n\t\tthis._handleIndex = null;\n\t\tthis._clickOffset = null;\n\t\tthis._animateOff = false;\n\n\t\treturn false;\n\t},\n\n\t_detectOrientation: function() {\n\t\tthis.orientation = ( this.options.orientation === \"vertical\" ) ? \"vertical\" : \"horizontal\";\n\t},\n\n\t_normValueFromMouse: function( position ) {\n\t\tvar pixelTotal,\n\t\t\tpixelMouse,\n\t\t\tpercentMouse,\n\t\t\tvalueTotal,\n\t\t\tvalueMouse;\n\n\t\tif ( this.orientation === \"horizontal\" ) {\n\t\t\tpixelTotal = this.elementSize.width;\n\t\t\tpixelMouse = position.x - this.elementOffset.left -\n\t\t\t\t( this._clickOffset ? this._clickOffset.left : 0 );\n\t\t} else {\n\t\t\tpixelTotal = this.elementSize.height;\n\t\t\tpixelMouse = position.y - this.elementOffset.top -\n\t\t\t\t( this._clickOffset ? this._clickOffset.top : 0 );\n\t\t}\n\n\t\tpercentMouse = ( pixelMouse / pixelTotal );\n\t\tif ( percentMouse > 1 ) {\n\t\t\tpercentMouse = 1;\n\t\t}\n\t\tif ( percentMouse < 0 ) {\n\t\t\tpercentMouse = 0;\n\t\t}\n\t\tif ( this.orientation === \"vertical\" ) {\n\t\t\tpercentMouse = 1 - percentMouse;\n\t\t}\n\n\t\tvalueTotal = this._valueMax() - this._valueMin();\n\t\tvalueMouse = this._valueMin() + percentMouse * valueTotal;\n\n\t\treturn this._trimAlignValue( valueMouse );\n\t},\n\n\t_uiHash: function( index, value, values ) {\n\t\tvar uiHash = {\n\t\t\thandle: this.handles[ index ],\n\t\t\thandleIndex: index,\n\t\t\tvalue: value !== undefined ? value : this.value()\n\t\t};\n\n\t\tif ( this._hasMultipleValues() ) {\n\t\t\tuiHash.value = value !== undefined ? value : this.values( index );\n\t\t\tuiHash.values = values || this.values();\n\t\t}\n\n\t\treturn uiHash;\n\t},\n\n\t_hasMultipleValues: function() {\n\t\treturn this.options.values && this.options.values.length;\n\t},\n\n\t_start: function( event, index ) {\n\t\treturn this._trigger( \"start\", event, this._uiHash( index ) );\n\t},\n\n\t_slide: function( event, index, newVal ) {\n\t\tvar allowed, otherVal,\n\t\t\tcurrentValue = this.value(),\n\t\t\tnewValues = this.values();\n\n\t\tif ( this._hasMultipleValues() ) {\n\t\t\totherVal = this.values( index ? 0 : 1 );\n\t\t\tcurrentValue = this.values( index );\n\n\t\t\tif ( this.options.values.length === 2 && this.options.range === true ) {\n\t\t\t\tnewVal =  index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal );\n\t\t\t}\n\n\t\t\tnewValues[ index ] = newVal;\n\t\t}\n\n\t\tif ( newVal === currentValue ) {\n\t\t\treturn;\n\t\t}\n\n\t\tallowed = this._trigger( \"slide\", event, this._uiHash( index, newVal, newValues ) );\n\n\t\t// A slide can be canceled by returning false from the slide callback\n\t\tif ( allowed === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this._hasMultipleValues() ) {\n\t\t\tthis.values( index, newVal );\n\t\t} else {\n\t\t\tthis.value( newVal );\n\t\t}\n\t},\n\n\t_stop: function( event, index ) {\n\t\tthis._trigger( \"stop\", event, this._uiHash( index ) );\n\t},\n\n\t_change: function( event, index ) {\n\t\tif ( !this._keySliding && !this._mouseSliding ) {\n\n\t\t\t//store the last changed value index for reference when handles overlap\n\t\t\tthis._lastChangedValue = index;\n\t\t\tthis._trigger( \"change\", event, this._uiHash( index ) );\n\t\t}\n\t},\n\n\tvalue: function( newValue ) {\n\t\tif ( arguments.length ) {\n\t\t\tthis.options.value = this._trimAlignValue( newValue );\n\t\t\tthis._refreshValue();\n\t\t\tthis._change( null, 0 );\n\t\t\treturn;\n\t\t}\n\n\t\treturn this._value();\n\t},\n\n\tvalues: function( index, newValue ) {\n\t\tvar vals,\n\t\t\tnewValues,\n\t\t\ti;\n\n\t\tif ( arguments.length > 1 ) {\n\t\t\tthis.options.values[ index ] = this._trimAlignValue( newValue );\n\t\t\tthis._refreshValue();\n\t\t\tthis._change( null, index );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( arguments.length ) {\n\t\t\tif ( $.isArray( arguments[ 0 ] ) ) {\n\t\t\t\tvals = this.options.values;\n\t\t\t\tnewValues = arguments[ 0 ];\n\t\t\t\tfor ( i = 0; i < vals.length; i += 1 ) {\n\t\t\t\t\tvals[ i ] = this._trimAlignValue( newValues[ i ] );\n\t\t\t\t\tthis._change( null, i );\n\t\t\t\t}\n\t\t\t\tthis._refreshValue();\n\t\t\t} else {\n\t\t\t\tif ( this._hasMultipleValues() ) {\n\t\t\t\t\treturn this._values( index );\n\t\t\t\t} else {\n\t\t\t\t\treturn this.value();\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\treturn this._values();\n\t\t}\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tvar i,\n\t\t\tvalsLength = 0;\n\n\t\tif ( key === \"range\" && this.options.range === true ) {\n\t\t\tif ( value === \"min\" ) {\n\t\t\t\tthis.options.value = this._values( 0 );\n\t\t\t\tthis.options.values = null;\n\t\t\t} else if ( value === \"max\" ) {\n\t\t\t\tthis.options.value = this._values( this.options.values.length - 1 );\n\t\t\t\tthis.options.values = null;\n\t\t\t}\n\t\t}\n\n\t\tif ( $.isArray( this.options.values ) ) {\n\t\t\tvalsLength = this.options.values.length;\n\t\t}\n\n\t\tthis._super( key, value );\n\n\t\tswitch ( key ) {\n\t\t\tcase \"orientation\":\n\t\t\t\tthis._detectOrientation();\n\t\t\t\tthis._removeClass( \"ui-slider-horizontal ui-slider-vertical\" )\n\t\t\t\t\t._addClass( \"ui-slider-\" + this.orientation );\n\t\t\t\tthis._refreshValue();\n\t\t\t\tif ( this.options.range ) {\n\t\t\t\t\tthis._refreshRange( value );\n\t\t\t\t}\n\n\t\t\t\t// Reset positioning from previous orientation\n\t\t\t\tthis.handles.css( value === \"horizontal\" ? \"bottom\" : \"left\", \"\" );\n\t\t\t\tbreak;\n\t\t\tcase \"value\":\n\t\t\t\tthis._animateOff = true;\n\t\t\t\tthis._refreshValue();\n\t\t\t\tthis._change( null, 0 );\n\t\t\t\tthis._animateOff = false;\n\t\t\t\tbreak;\n\t\t\tcase \"values\":\n\t\t\t\tthis._animateOff = true;\n\t\t\t\tthis._refreshValue();\n\n\t\t\t\t// Start from the last handle to prevent unreachable handles (#9046)\n\t\t\t\tfor ( i = valsLength - 1; i >= 0; i-- ) {\n\t\t\t\t\tthis._change( null, i );\n\t\t\t\t}\n\t\t\t\tthis._animateOff = false;\n\t\t\t\tbreak;\n\t\t\tcase \"step\":\n\t\t\tcase \"min\":\n\t\t\tcase \"max\":\n\t\t\t\tthis._animateOff = true;\n\t\t\t\tthis._calculateNewMax();\n\t\t\t\tthis._refreshValue();\n\t\t\t\tthis._animateOff = false;\n\t\t\t\tbreak;\n\t\t\tcase \"range\":\n\t\t\t\tthis._animateOff = true;\n\t\t\t\tthis._refresh();\n\t\t\t\tthis._animateOff = false;\n\t\t\t\tbreak;\n\t\t}\n\t},\n\n\t_setOptionDisabled: function( value ) {\n\t\tthis._super( value );\n\n\t\tthis._toggleClass( null, \"ui-state-disabled\", !!value );\n\t},\n\n\t//internal value getter\n\t// _value() returns value trimmed by min and max, aligned by step\n\t_value: function() {\n\t\tvar val = this.options.value;\n\t\tval = this._trimAlignValue( val );\n\n\t\treturn val;\n\t},\n\n\t//internal values getter\n\t// _values() returns array of values trimmed by min and max, aligned by step\n\t// _values( index ) returns single value trimmed by min and max, aligned by step\n\t_values: function( index ) {\n\t\tvar val,\n\t\t\tvals,\n\t\t\ti;\n\n\t\tif ( arguments.length ) {\n\t\t\tval = this.options.values[ index ];\n\t\t\tval = this._trimAlignValue( val );\n\n\t\t\treturn val;\n\t\t} else if ( this._hasMultipleValues() ) {\n\n\t\t\t// .slice() creates a copy of the array\n\t\t\t// this copy gets trimmed by min and max and then returned\n\t\t\tvals = this.options.values.slice();\n\t\t\tfor ( i = 0; i < vals.length; i += 1 ) {\n\t\t\t\tvals[ i ] = this._trimAlignValue( vals[ i ] );\n\t\t\t}\n\n\t\t\treturn vals;\n\t\t} else {\n\t\t\treturn [];\n\t\t}\n\t},\n\n\t// Returns the step-aligned value that val is closest to, between (inclusive) min and max\n\t_trimAlignValue: function( val ) {\n\t\tif ( val <= this._valueMin() ) {\n\t\t\treturn this._valueMin();\n\t\t}\n\t\tif ( val >= this._valueMax() ) {\n\t\t\treturn this._valueMax();\n\t\t}\n\t\tvar step = ( this.options.step > 0 ) ? this.options.step : 1,\n\t\t\tvalModStep = ( val - this._valueMin() ) % step,\n\t\t\talignValue = val - valModStep;\n\n\t\tif ( Math.abs( valModStep ) * 2 >= step ) {\n\t\t\talignValue += ( valModStep > 0 ) ? step : ( -step );\n\t\t}\n\n\t\t// Since JavaScript has problems with large floats, round\n\t\t// the final value to 5 digits after the decimal point (see #4124)\n\t\treturn parseFloat( alignValue.toFixed( 5 ) );\n\t},\n\n\t_calculateNewMax: function() {\n\t\tvar max = this.options.max,\n\t\t\tmin = this._valueMin(),\n\t\t\tstep = this.options.step,\n\t\t\taboveMin = Math.round( ( max - min ) / step ) * step;\n\t\tmax = aboveMin + min;\n\t\tif ( max > this.options.max ) {\n\n\t\t\t//If max is not divisible by step, rounding off may increase its value\n\t\t\tmax -= step;\n\t\t}\n\t\tthis.max = parseFloat( max.toFixed( this._precision() ) );\n\t},\n\n\t_precision: function() {\n\t\tvar precision = this._precisionOf( this.options.step );\n\t\tif ( this.options.min !== null ) {\n\t\t\tprecision = Math.max( precision, this._precisionOf( this.options.min ) );\n\t\t}\n\t\treturn precision;\n\t},\n\n\t_precisionOf: function( num ) {\n\t\tvar str = num.toString(),\n\t\t\tdecimal = str.indexOf( \".\" );\n\t\treturn decimal === -1 ? 0 : str.length - decimal - 1;\n\t},\n\n\t_valueMin: function() {\n\t\treturn this.options.min;\n\t},\n\n\t_valueMax: function() {\n\t\treturn this.max;\n\t},\n\n\t_refreshRange: function( orientation ) {\n\t\tif ( orientation === \"vertical\" ) {\n\t\t\tthis.range.css( { \"width\": \"\", \"left\": \"\" } );\n\t\t}\n\t\tif ( orientation === \"horizontal\" ) {\n\t\t\tthis.range.css( { \"height\": \"\", \"bottom\": \"\" } );\n\t\t}\n\t},\n\n\t_refreshValue: function() {\n\t\tvar lastValPercent, valPercent, value, valueMin, valueMax,\n\t\t\toRange = this.options.range,\n\t\t\to = this.options,\n\t\t\tthat = this,\n\t\t\tanimate = ( !this._animateOff ) ? o.animate : false,\n\t\t\t_set = {};\n\n\t\tif ( this._hasMultipleValues() ) {\n\t\t\tthis.handles.each( function( i ) {\n\t\t\t\tvalPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() -\n\t\t\t\t\tthat._valueMin() ) * 100;\n\t\t\t\t_set[ that.orientation === \"horizontal\" ? \"left\" : \"bottom\" ] = valPercent + \"%\";\n\t\t\t\t$( this ).stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( _set, o.animate );\n\t\t\t\tif ( that.options.range === true ) {\n\t\t\t\t\tif ( that.orientation === \"horizontal\" ) {\n\t\t\t\t\t\tif ( i === 0 ) {\n\t\t\t\t\t\t\tthat.range.stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( {\n\t\t\t\t\t\t\t\tleft: valPercent + \"%\"\n\t\t\t\t\t\t\t}, o.animate );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( i === 1 ) {\n\t\t\t\t\t\t\tthat.range[ animate ? \"animate\" : \"css\" ]( {\n\t\t\t\t\t\t\t\twidth: ( valPercent - lastValPercent ) + \"%\"\n\t\t\t\t\t\t\t}, {\n\t\t\t\t\t\t\t\tqueue: false,\n\t\t\t\t\t\t\t\tduration: o.animate\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( i === 0 ) {\n\t\t\t\t\t\t\tthat.range.stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( {\n\t\t\t\t\t\t\t\tbottom: ( valPercent ) + \"%\"\n\t\t\t\t\t\t\t}, o.animate );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( i === 1 ) {\n\t\t\t\t\t\t\tthat.range[ animate ? \"animate\" : \"css\" ]( {\n\t\t\t\t\t\t\t\theight: ( valPercent - lastValPercent ) + \"%\"\n\t\t\t\t\t\t\t}, {\n\t\t\t\t\t\t\t\tqueue: false,\n\t\t\t\t\t\t\t\tduration: o.animate\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlastValPercent = valPercent;\n\t\t\t} );\n\t\t} else {\n\t\t\tvalue = this.value();\n\t\t\tvalueMin = this._valueMin();\n\t\t\tvalueMax = this._valueMax();\n\t\t\tvalPercent = ( valueMax !== valueMin ) ?\n\t\t\t\t\t( value - valueMin ) / ( valueMax - valueMin ) * 100 :\n\t\t\t\t\t0;\n\t\t\t_set[ this.orientation === \"horizontal\" ? \"left\" : \"bottom\" ] = valPercent + \"%\";\n\t\t\tthis.handle.stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( _set, o.animate );\n\n\t\t\tif ( oRange === \"min\" && this.orientation === \"horizontal\" ) {\n\t\t\t\tthis.range.stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( {\n\t\t\t\t\twidth: valPercent + \"%\"\n\t\t\t\t}, o.animate );\n\t\t\t}\n\t\t\tif ( oRange === \"max\" && this.orientation === \"horizontal\" ) {\n\t\t\t\tthis.range.stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( {\n\t\t\t\t\twidth: ( 100 - valPercent ) + \"%\"\n\t\t\t\t}, o.animate );\n\t\t\t}\n\t\t\tif ( oRange === \"min\" && this.orientation === \"vertical\" ) {\n\t\t\t\tthis.range.stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( {\n\t\t\t\t\theight: valPercent + \"%\"\n\t\t\t\t}, o.animate );\n\t\t\t}\n\t\t\tif ( oRange === \"max\" && this.orientation === \"vertical\" ) {\n\t\t\t\tthis.range.stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( {\n\t\t\t\t\theight: ( 100 - valPercent ) + \"%\"\n\t\t\t\t}, o.animate );\n\t\t\t}\n\t\t}\n\t},\n\n\t_handleEvents: {\n\t\tkeydown: function( event ) {\n\t\t\tvar allowed, curVal, newVal, step,\n\t\t\t\tindex = $( event.target ).data( \"ui-slider-handle-index\" );\n\n\t\t\tswitch ( event.keyCode ) {\n\t\t\t\tcase $.ui.keyCode.HOME:\n\t\t\t\tcase $.ui.keyCode.END:\n\t\t\t\tcase $.ui.keyCode.PAGE_UP:\n\t\t\t\tcase $.ui.keyCode.PAGE_DOWN:\n\t\t\t\tcase $.ui.keyCode.UP:\n\t\t\t\tcase $.ui.keyCode.RIGHT:\n\t\t\t\tcase $.ui.keyCode.DOWN:\n\t\t\t\tcase $.ui.keyCode.LEFT:\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tif ( !this._keySliding ) {\n\t\t\t\t\t\tthis._keySliding = true;\n\t\t\t\t\t\tthis._addClass( $( event.target ), null, \"ui-state-active\" );\n\t\t\t\t\t\tallowed = this._start( event, index );\n\t\t\t\t\t\tif ( allowed === false ) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tstep = this.options.step;\n\t\t\tif ( this._hasMultipleValues() ) {\n\t\t\t\tcurVal = newVal = this.values( index );\n\t\t\t} else {\n\t\t\t\tcurVal = newVal = this.value();\n\t\t\t}\n\n\t\t\tswitch ( event.keyCode ) {\n\t\t\t\tcase $.ui.keyCode.HOME:\n\t\t\t\t\tnewVal = this._valueMin();\n\t\t\t\t\tbreak;\n\t\t\t\tcase $.ui.keyCode.END:\n\t\t\t\t\tnewVal = this._valueMax();\n\t\t\t\t\tbreak;\n\t\t\t\tcase $.ui.keyCode.PAGE_UP:\n\t\t\t\t\tnewVal = this._trimAlignValue(\n\t\t\t\t\t\tcurVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\tcase $.ui.keyCode.PAGE_DOWN:\n\t\t\t\t\tnewVal = this._trimAlignValue(\n\t\t\t\t\t\tcurVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) );\n\t\t\t\t\tbreak;\n\t\t\t\tcase $.ui.keyCode.UP:\n\t\t\t\tcase $.ui.keyCode.RIGHT:\n\t\t\t\t\tif ( curVal === this._valueMax() ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tnewVal = this._trimAlignValue( curVal + step );\n\t\t\t\t\tbreak;\n\t\t\t\tcase $.ui.keyCode.DOWN:\n\t\t\t\tcase $.ui.keyCode.LEFT:\n\t\t\t\t\tif ( curVal === this._valueMin() ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tnewVal = this._trimAlignValue( curVal - step );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tthis._slide( event, index, newVal );\n\t\t},\n\t\tkeyup: function( event ) {\n\t\t\tvar index = $( event.target ).data( \"ui-slider-handle-index\" );\n\n\t\t\tif ( this._keySliding ) {\n\t\t\t\tthis._keySliding = false;\n\t\t\t\tthis._stop( event, index );\n\t\t\t\tthis._change( event, index );\n\t\t\t\tthis._removeClass( $( event.target ), null, \"ui-state-active\" );\n\t\t\t}\n\t\t}\n\t}\n} );\n\n\n/*!\n * jQuery UI Sortable 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Sortable\n//>>group: Interactions\n//>>description: Enables items in a list to be sorted using the mouse.\n//>>docs: http://api.jqueryui.com/sortable/\n//>>demos: http://jqueryui.com/sortable/\n//>>css.structure: ../../themes/base/sortable.css\n\n\n\nvar widgetsSortable = $.widget( \"ui.sortable\", $.ui.mouse, {\n\tversion: \"1.12.1\",\n\twidgetEventPrefix: \"sort\",\n\tready: false,\n\toptions: {\n\t\tappendTo: \"parent\",\n\t\taxis: false,\n\t\tconnectWith: false,\n\t\tcontainment: false,\n\t\tcursor: \"auto\",\n\t\tcursorAt: false,\n\t\tdropOnEmpty: true,\n\t\tforcePlaceholderSize: false,\n\t\tforceHelperSize: false,\n\t\tgrid: false,\n\t\thandle: false,\n\t\thelper: \"original\",\n\t\titems: \"> *\",\n\t\topacity: false,\n\t\tplaceholder: false,\n\t\trevert: false,\n\t\tscroll: true,\n\t\tscrollSensitivity: 20,\n\t\tscrollSpeed: 20,\n\t\tscope: \"default\",\n\t\ttolerance: \"intersect\",\n\t\tzIndex: 1000,\n\n\t\t// Callbacks\n\t\tactivate: null,\n\t\tbeforeStop: null,\n\t\tchange: null,\n\t\tdeactivate: null,\n\t\tout: null,\n\t\tover: null,\n\t\treceive: null,\n\t\tremove: null,\n\t\tsort: null,\n\t\tstart: null,\n\t\tstop: null,\n\t\tupdate: null\n\t},\n\n\t_isOverAxis: function( x, reference, size ) {\n\t\treturn ( x >= reference ) && ( x < ( reference + size ) );\n\t},\n\n\t_isFloating: function( item ) {\n\t\treturn ( /left|right/ ).test( item.css( \"float\" ) ) ||\n\t\t\t( /inline|table-cell/ ).test( item.css( \"display\" ) );\n\t},\n\n\t_create: function() {\n\t\tthis.containerCache = {};\n\t\tthis._addClass( \"ui-sortable\" );\n\n\t\t//Get the items\n\t\tthis.refresh();\n\n\t\t//Let's determine the parent's offset\n\t\tthis.offset = this.element.offset();\n\n\t\t//Initialize mouse events for interaction\n\t\tthis._mouseInit();\n\n\t\tthis._setHandleClassName();\n\n\t\t//We're ready to go\n\t\tthis.ready = true;\n\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tthis._super( key, value );\n\n\t\tif ( key === \"handle\" ) {\n\t\t\tthis._setHandleClassName();\n\t\t}\n\t},\n\n\t_setHandleClassName: function() {\n\t\tvar that = this;\n\t\tthis._removeClass( this.element.find( \".ui-sortable-handle\" ), \"ui-sortable-handle\" );\n\t\t$.each( this.items, function() {\n\t\t\tthat._addClass(\n\t\t\t\tthis.instance.options.handle ?\n\t\t\t\t\tthis.item.find( this.instance.options.handle ) :\n\t\t\t\t\tthis.item,\n\t\t\t\t\"ui-sortable-handle\"\n\t\t\t);\n\t\t} );\n\t},\n\n\t_destroy: function() {\n\t\tthis._mouseDestroy();\n\n\t\tfor ( var i = this.items.length - 1; i >= 0; i-- ) {\n\t\t\tthis.items[ i ].item.removeData( this.widgetName + \"-item\" );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_mouseCapture: function( event, overrideHandle ) {\n\t\tvar currentItem = null,\n\t\t\tvalidHandle = false,\n\t\t\tthat = this;\n\n\t\tif ( this.reverting ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( this.options.disabled || this.options.type === \"static\" ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t//We have to refresh the items data once first\n\t\tthis._refreshItems( event );\n\n\t\t//Find out if the clicked node (or one of its parents) is a actual item in this.items\n\t\t$( event.target ).parents().each( function() {\n\t\t\tif ( $.data( this, that.widgetName + \"-item\" ) === that ) {\n\t\t\t\tcurrentItem = $( this );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} );\n\t\tif ( $.data( event.target, that.widgetName + \"-item\" ) === that ) {\n\t\t\tcurrentItem = $( event.target );\n\t\t}\n\n\t\tif ( !currentItem ) {\n\t\t\treturn false;\n\t\t}\n\t\tif ( this.options.handle && !overrideHandle ) {\n\t\t\t$( this.options.handle, currentItem ).find( \"*\" ).addBack().each( function() {\n\t\t\t\tif ( this === event.target ) {\n\t\t\t\t\tvalidHandle = true;\n\t\t\t\t}\n\t\t\t} );\n\t\t\tif ( !validHandle ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tthis.currentItem = currentItem;\n\t\tthis._removeCurrentsFromItems();\n\t\treturn true;\n\n\t},\n\n\t_mouseStart: function( event, overrideHandle, noActivation ) {\n\n\t\tvar i, body,\n\t\t\to = this.options;\n\n\t\tthis.currentContainer = this;\n\n\t\t//We only need to call refreshPositions, because the refreshItems call has been moved to\n\t\t// mouseCapture\n\t\tthis.refreshPositions();\n\n\t\t//Create and append the visible helper\n\t\tthis.helper = this._createHelper( event );\n\n\t\t//Cache the helper size\n\t\tthis._cacheHelperProportions();\n\n\t\t/*\n\t\t * - Position generation -\n\t\t * This block generates everything position related - it's the core of draggables.\n\t\t */\n\n\t\t//Cache the margins of the original element\n\t\tthis._cacheMargins();\n\n\t\t//Get the next scrolling parent\n\t\tthis.scrollParent = this.helper.scrollParent();\n\n\t\t//The element's absolute position on the page minus margins\n\t\tthis.offset = this.currentItem.offset();\n\t\tthis.offset = {\n\t\t\ttop: this.offset.top - this.margins.top,\n\t\t\tleft: this.offset.left - this.margins.left\n\t\t};\n\n\t\t$.extend( this.offset, {\n\t\t\tclick: { //Where the click happened, relative to the element\n\t\t\t\tleft: event.pageX - this.offset.left,\n\t\t\t\ttop: event.pageY - this.offset.top\n\t\t\t},\n\t\t\tparent: this._getParentOffset(),\n\n\t\t\t// This is a relative to absolute position minus the actual position calculation -\n\t\t\t// only used for relative positioned helper\n\t\t\trelative: this._getRelativeOffset()\n\t\t} );\n\n\t\t// Only after we got the offset, we can change the helper's position to absolute\n\t\t// TODO: Still need to figure out a way to make relative sorting possible\n\t\tthis.helper.css( \"position\", \"absolute\" );\n\t\tthis.cssPosition = this.helper.css( \"position\" );\n\n\t\t//Generate the original position\n\t\tthis.originalPosition = this._generatePosition( event );\n\t\tthis.originalPageX = event.pageX;\n\t\tthis.originalPageY = event.pageY;\n\n\t\t//Adjust the mouse offset relative to the helper if \"cursorAt\" is supplied\n\t\t( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) );\n\n\t\t//Cache the former DOM position\n\t\tthis.domPosition = {\n\t\t\tprev: this.currentItem.prev()[ 0 ],\n\t\t\tparent: this.currentItem.parent()[ 0 ]\n\t\t};\n\n\t\t// If the helper is not the original, hide the original so it's not playing any role during\n\t\t// the drag, won't cause anything bad this way\n\t\tif ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {\n\t\t\tthis.currentItem.hide();\n\t\t}\n\n\t\t//Create the placeholder\n\t\tthis._createPlaceholder();\n\n\t\t//Set a containment if given in the options\n\t\tif ( o.containment ) {\n\t\t\tthis._setContainment();\n\t\t}\n\n\t\tif ( o.cursor && o.cursor !== \"auto\" ) { // cursor option\n\t\t\tbody = this.document.find( \"body\" );\n\n\t\t\t// Support: IE\n\t\t\tthis.storedCursor = body.css( \"cursor\" );\n\t\t\tbody.css( \"cursor\", o.cursor );\n\n\t\t\tthis.storedStylesheet =\n\t\t\t\t$( \"<style>*{ cursor: \" + o.cursor + \" !important; }</style>\" ).appendTo( body );\n\t\t}\n\n\t\tif ( o.opacity ) { // opacity option\n\t\t\tif ( this.helper.css( \"opacity\" ) ) {\n\t\t\t\tthis._storedOpacity = this.helper.css( \"opacity\" );\n\t\t\t}\n\t\t\tthis.helper.css( \"opacity\", o.opacity );\n\t\t}\n\n\t\tif ( o.zIndex ) { // zIndex option\n\t\t\tif ( this.helper.css( \"zIndex\" ) ) {\n\t\t\t\tthis._storedZIndex = this.helper.css( \"zIndex\" );\n\t\t\t}\n\t\t\tthis.helper.css( \"zIndex\", o.zIndex );\n\t\t}\n\n\t\t//Prepare scrolling\n\t\tif ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&\n\t\t\t\tthis.scrollParent[ 0 ].tagName !== \"HTML\" ) {\n\t\t\tthis.overflowOffset = this.scrollParent.offset();\n\t\t}\n\n\t\t//Call callbacks\n\t\tthis._trigger( \"start\", event, this._uiHash() );\n\n\t\t//Recache the helper size\n\t\tif ( !this._preserveHelperProportions ) {\n\t\t\tthis._cacheHelperProportions();\n\t\t}\n\n\t\t//Post \"activate\" events to possible containers\n\t\tif ( !noActivation ) {\n\t\t\tfor ( i = this.containers.length - 1; i >= 0; i-- ) {\n\t\t\t\tthis.containers[ i ]._trigger( \"activate\", event, this._uiHash( this ) );\n\t\t\t}\n\t\t}\n\n\t\t//Prepare possible droppables\n\t\tif ( $.ui.ddmanager ) {\n\t\t\t$.ui.ddmanager.current = this;\n\t\t}\n\n\t\tif ( $.ui.ddmanager && !o.dropBehaviour ) {\n\t\t\t$.ui.ddmanager.prepareOffsets( this, event );\n\t\t}\n\n\t\tthis.dragging = true;\n\n\t\tthis._addClass( this.helper, \"ui-sortable-helper\" );\n\n\t\t// Execute the drag once - this causes the helper not to be visiblebefore getting its\n\t\t// correct position\n\t\tthis._mouseDrag( event );\n\t\treturn true;\n\n\t},\n\n\t_mouseDrag: function( event ) {\n\t\tvar i, item, itemElement, intersection,\n\t\t\to = this.options,\n\t\t\tscrolled = false;\n\n\t\t//Compute the helpers position\n\t\tthis.position = this._generatePosition( event );\n\t\tthis.positionAbs = this._convertPositionTo( \"absolute\" );\n\n\t\tif ( !this.lastPositionAbs ) {\n\t\t\tthis.lastPositionAbs = this.positionAbs;\n\t\t}\n\n\t\t//Do scrolling\n\t\tif ( this.options.scroll ) {\n\t\t\tif ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&\n\t\t\t\t\tthis.scrollParent[ 0 ].tagName !== \"HTML\" ) {\n\n\t\t\t\tif ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) -\n\t\t\t\t\t\tevent.pageY < o.scrollSensitivity ) {\n\t\t\t\t\tthis.scrollParent[ 0 ].scrollTop =\n\t\t\t\t\t\tscrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed;\n\t\t\t\t} else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) {\n\t\t\t\t\tthis.scrollParent[ 0 ].scrollTop =\n\t\t\t\t\t\tscrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed;\n\t\t\t\t}\n\n\t\t\t\tif ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) -\n\t\t\t\t\t\tevent.pageX < o.scrollSensitivity ) {\n\t\t\t\t\tthis.scrollParent[ 0 ].scrollLeft = scrolled =\n\t\t\t\t\t\tthis.scrollParent[ 0 ].scrollLeft + o.scrollSpeed;\n\t\t\t\t} else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) {\n\t\t\t\t\tthis.scrollParent[ 0 ].scrollLeft = scrolled =\n\t\t\t\t\t\tthis.scrollParent[ 0 ].scrollLeft - o.scrollSpeed;\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tif ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) {\n\t\t\t\t\tscrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed );\n\t\t\t\t} else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) <\n\t\t\t\t\t\to.scrollSensitivity ) {\n\t\t\t\t\tscrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed );\n\t\t\t\t}\n\n\t\t\t\tif ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) {\n\t\t\t\t\tscrolled = this.document.scrollLeft(\n\t\t\t\t\t\tthis.document.scrollLeft() - o.scrollSpeed\n\t\t\t\t\t);\n\t\t\t\t} else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) <\n\t\t\t\t\t\to.scrollSensitivity ) {\n\t\t\t\t\tscrolled = this.document.scrollLeft(\n\t\t\t\t\t\tthis.document.scrollLeft() + o.scrollSpeed\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {\n\t\t\t\t$.ui.ddmanager.prepareOffsets( this, event );\n\t\t\t}\n\t\t}\n\n\t\t//Regenerate the absolute position used for position checks\n\t\tthis.positionAbs = this._convertPositionTo( \"absolute\" );\n\n\t\t//Set the helper position\n\t\tif ( !this.options.axis || this.options.axis !== \"y\" ) {\n\t\t\tthis.helper[ 0 ].style.left = this.position.left + \"px\";\n\t\t}\n\t\tif ( !this.options.axis || this.options.axis !== \"x\" ) {\n\t\t\tthis.helper[ 0 ].style.top = this.position.top + \"px\";\n\t\t}\n\n\t\t//Rearrange\n\t\tfor ( i = this.items.length - 1; i >= 0; i-- ) {\n\n\t\t\t//Cache variables and intersection, continue if no intersection\n\t\t\titem = this.items[ i ];\n\t\t\titemElement = item.item[ 0 ];\n\t\t\tintersection = this._intersectsWithPointer( item );\n\t\t\tif ( !intersection ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Only put the placeholder inside the current Container, skip all\n\t\t\t// items from other containers. This works because when moving\n\t\t\t// an item from one container to another the\n\t\t\t// currentContainer is switched before the placeholder is moved.\n\t\t\t//\n\t\t\t// Without this, moving items in \"sub-sortables\" can cause\n\t\t\t// the placeholder to jitter between the outer and inner container.\n\t\t\tif ( item.instance !== this.currentContainer ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Cannot intersect with itself\n\t\t\t// no useless actions that have been done before\n\t\t\t// no action if the item moved is the parent of the item checked\n\t\t\tif ( itemElement !== this.currentItem[ 0 ] &&\n\t\t\t\tthis.placeholder[ intersection === 1 ? \"next\" : \"prev\" ]()[ 0 ] !== itemElement &&\n\t\t\t\t!$.contains( this.placeholder[ 0 ], itemElement ) &&\n\t\t\t\t( this.options.type === \"semi-dynamic\" ?\n\t\t\t\t\t!$.contains( this.element[ 0 ], itemElement ) :\n\t\t\t\t\ttrue\n\t\t\t\t)\n\t\t\t) {\n\n\t\t\t\tthis.direction = intersection === 1 ? \"down\" : \"up\";\n\n\t\t\t\tif ( this.options.tolerance === \"pointer\" || this._intersectsWithSides( item ) ) {\n\t\t\t\t\tthis._rearrange( event, item );\n\t\t\t\t} else {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tthis._trigger( \"change\", event, this._uiHash() );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t//Post events to containers\n\t\tthis._contactContainers( event );\n\n\t\t//Interconnect with droppables\n\t\tif ( $.ui.ddmanager ) {\n\t\t\t$.ui.ddmanager.drag( this, event );\n\t\t}\n\n\t\t//Call callbacks\n\t\tthis._trigger( \"sort\", event, this._uiHash() );\n\n\t\tthis.lastPositionAbs = this.positionAbs;\n\t\treturn false;\n\n\t},\n\n\t_mouseStop: function( event, noPropagation ) {\n\n\t\tif ( !event ) {\n\t\t\treturn;\n\t\t}\n\n\t\t//If we are using droppables, inform the manager about the drop\n\t\tif ( $.ui.ddmanager && !this.options.dropBehaviour ) {\n\t\t\t$.ui.ddmanager.drop( this, event );\n\t\t}\n\n\t\tif ( this.options.revert ) {\n\t\t\tvar that = this,\n\t\t\t\tcur = this.placeholder.offset(),\n\t\t\t\taxis = this.options.axis,\n\t\t\t\tanimation = {};\n\n\t\t\tif ( !axis || axis === \"x\" ) {\n\t\t\t\tanimation.left = cur.left - this.offset.parent.left - this.margins.left +\n\t\t\t\t\t( this.offsetParent[ 0 ] === this.document[ 0 ].body ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tthis.offsetParent[ 0 ].scrollLeft\n\t\t\t\t\t);\n\t\t\t}\n\t\t\tif ( !axis || axis === \"y\" ) {\n\t\t\t\tanimation.top = cur.top - this.offset.parent.top - this.margins.top +\n\t\t\t\t\t( this.offsetParent[ 0 ] === this.document[ 0 ].body ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tthis.offsetParent[ 0 ].scrollTop\n\t\t\t\t\t);\n\t\t\t}\n\t\t\tthis.reverting = true;\n\t\t\t$( this.helper ).animate(\n\t\t\t\tanimation,\n\t\t\t\tparseInt( this.options.revert, 10 ) || 500,\n\t\t\t\tfunction() {\n\t\t\t\t\tthat._clear( event );\n\t\t\t\t}\n\t\t\t);\n\t\t} else {\n\t\t\tthis._clear( event, noPropagation );\n\t\t}\n\n\t\treturn false;\n\n\t},\n\n\tcancel: function() {\n\n\t\tif ( this.dragging ) {\n\n\t\t\tthis._mouseUp( new $.Event( \"mouseup\", { target: null } ) );\n\n\t\t\tif ( this.options.helper === \"original\" ) {\n\t\t\t\tthis.currentItem.css( this._storedCSS );\n\t\t\t\tthis._removeClass( this.currentItem, \"ui-sortable-helper\" );\n\t\t\t} else {\n\t\t\t\tthis.currentItem.show();\n\t\t\t}\n\n\t\t\t//Post deactivating events to containers\n\t\t\tfor ( var i = this.containers.length - 1; i >= 0; i-- ) {\n\t\t\t\tthis.containers[ i ]._trigger( \"deactivate\", null, this._uiHash( this ) );\n\t\t\t\tif ( this.containers[ i ].containerCache.over ) {\n\t\t\t\t\tthis.containers[ i ]._trigger( \"out\", null, this._uiHash( this ) );\n\t\t\t\t\tthis.containers[ i ].containerCache.over = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\tif ( this.placeholder ) {\n\n\t\t\t//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,\n\t\t\t// it unbinds ALL events from the original node!\n\t\t\tif ( this.placeholder[ 0 ].parentNode ) {\n\t\t\t\tthis.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );\n\t\t\t}\n\t\t\tif ( this.options.helper !== \"original\" && this.helper &&\n\t\t\t\t\tthis.helper[ 0 ].parentNode ) {\n\t\t\t\tthis.helper.remove();\n\t\t\t}\n\n\t\t\t$.extend( this, {\n\t\t\t\thelper: null,\n\t\t\t\tdragging: false,\n\t\t\t\treverting: false,\n\t\t\t\t_noFinalSort: null\n\t\t\t} );\n\n\t\t\tif ( this.domPosition.prev ) {\n\t\t\t\t$( this.domPosition.prev ).after( this.currentItem );\n\t\t\t} else {\n\t\t\t\t$( this.domPosition.parent ).prepend( this.currentItem );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tserialize: function( o ) {\n\n\t\tvar items = this._getItemsAsjQuery( o && o.connected ),\n\t\t\tstr = [];\n\t\to = o || {};\n\n\t\t$( items ).each( function() {\n\t\t\tvar res = ( $( o.item || this ).attr( o.attribute || \"id\" ) || \"\" )\n\t\t\t\t.match( o.expression || ( /(.+)[\\-=_](.+)/ ) );\n\t\t\tif ( res ) {\n\t\t\t\tstr.push(\n\t\t\t\t\t( o.key || res[ 1 ] + \"[]\" ) +\n\t\t\t\t\t\"=\" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) );\n\t\t\t}\n\t\t} );\n\n\t\tif ( !str.length && o.key ) {\n\t\t\tstr.push( o.key + \"=\" );\n\t\t}\n\n\t\treturn str.join( \"&\" );\n\n\t},\n\n\ttoArray: function( o ) {\n\n\t\tvar items = this._getItemsAsjQuery( o && o.connected ),\n\t\t\tret = [];\n\n\t\to = o || {};\n\n\t\titems.each( function() {\n\t\t\tret.push( $( o.item || this ).attr( o.attribute || \"id\" ) || \"\" );\n\t\t} );\n\t\treturn ret;\n\n\t},\n\n\t/* Be careful with the following core functions */\n\t_intersectsWith: function( item ) {\n\n\t\tvar x1 = this.positionAbs.left,\n\t\t\tx2 = x1 + this.helperProportions.width,\n\t\t\ty1 = this.positionAbs.top,\n\t\t\ty2 = y1 + this.helperProportions.height,\n\t\t\tl = item.left,\n\t\t\tr = l + item.width,\n\t\t\tt = item.top,\n\t\t\tb = t + item.height,\n\t\t\tdyClick = this.offset.click.top,\n\t\t\tdxClick = this.offset.click.left,\n\t\t\tisOverElementHeight = ( this.options.axis === \"x\" ) || ( ( y1 + dyClick ) > t &&\n\t\t\t\t( y1 + dyClick ) < b ),\n\t\t\tisOverElementWidth = ( this.options.axis === \"y\" ) || ( ( x1 + dxClick ) > l &&\n\t\t\t\t( x1 + dxClick ) < r ),\n\t\t\tisOverElement = isOverElementHeight && isOverElementWidth;\n\n\t\tif ( this.options.tolerance === \"pointer\" ||\n\t\t\tthis.options.forcePointerForContainers ||\n\t\t\t( this.options.tolerance !== \"pointer\" &&\n\t\t\t\tthis.helperProportions[ this.floating ? \"width\" : \"height\" ] >\n\t\t\t\titem[ this.floating ? \"width\" : \"height\" ] )\n\t\t) {\n\t\t\treturn isOverElement;\n\t\t} else {\n\n\t\t\treturn ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half\n\t\t\t\tx2 - ( this.helperProportions.width / 2 ) < r && // Left Half\n\t\t\t\tt < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half\n\t\t\t\ty2 - ( this.helperProportions.height / 2 ) < b ); // Top Half\n\n\t\t}\n\t},\n\n\t_intersectsWithPointer: function( item ) {\n\t\tvar verticalDirection, horizontalDirection,\n\t\t\tisOverElementHeight = ( this.options.axis === \"x\" ) ||\n\t\t\t\tthis._isOverAxis(\n\t\t\t\t\tthis.positionAbs.top + this.offset.click.top, item.top, item.height ),\n\t\t\tisOverElementWidth = ( this.options.axis === \"y\" ) ||\n\t\t\t\tthis._isOverAxis(\n\t\t\t\t\tthis.positionAbs.left + this.offset.click.left, item.left, item.width ),\n\t\t\tisOverElement = isOverElementHeight && isOverElementWidth;\n\n\t\tif ( !isOverElement ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tverticalDirection = this._getDragVerticalDirection();\n\t\thorizontalDirection = this._getDragHorizontalDirection();\n\n\t\treturn this.floating ?\n\t\t\t( ( horizontalDirection === \"right\" || verticalDirection === \"down\" ) ? 2 : 1 )\n\t\t\t: ( verticalDirection && ( verticalDirection === \"down\" ? 2 : 1 ) );\n\n\t},\n\n\t_intersectsWithSides: function( item ) {\n\n\t\tvar isOverBottomHalf = this._isOverAxis( this.positionAbs.top +\n\t\t\t\tthis.offset.click.top, item.top + ( item.height / 2 ), item.height ),\n\t\t\tisOverRightHalf = this._isOverAxis( this.positionAbs.left +\n\t\t\t\tthis.offset.click.left, item.left + ( item.width / 2 ), item.width ),\n\t\t\tverticalDirection = this._getDragVerticalDirection(),\n\t\t\thorizontalDirection = this._getDragHorizontalDirection();\n\n\t\tif ( this.floating && horizontalDirection ) {\n\t\t\treturn ( ( horizontalDirection === \"right\" && isOverRightHalf ) ||\n\t\t\t\t( horizontalDirection === \"left\" && !isOverRightHalf ) );\n\t\t} else {\n\t\t\treturn verticalDirection && ( ( verticalDirection === \"down\" && isOverBottomHalf ) ||\n\t\t\t\t( verticalDirection === \"up\" && !isOverBottomHalf ) );\n\t\t}\n\n\t},\n\n\t_getDragVerticalDirection: function() {\n\t\tvar delta = this.positionAbs.top - this.lastPositionAbs.top;\n\t\treturn delta !== 0 && ( delta > 0 ? \"down\" : \"up\" );\n\t},\n\n\t_getDragHorizontalDirection: function() {\n\t\tvar delta = this.positionAbs.left - this.lastPositionAbs.left;\n\t\treturn delta !== 0 && ( delta > 0 ? \"right\" : \"left\" );\n\t},\n\n\trefresh: function( event ) {\n\t\tthis._refreshItems( event );\n\t\tthis._setHandleClassName();\n\t\tthis.refreshPositions();\n\t\treturn this;\n\t},\n\n\t_connectWith: function() {\n\t\tvar options = this.options;\n\t\treturn options.connectWith.constructor === String ?\n\t\t\t[ options.connectWith ] :\n\t\t\toptions.connectWith;\n\t},\n\n\t_getItemsAsjQuery: function( connected ) {\n\n\t\tvar i, j, cur, inst,\n\t\t\titems = [],\n\t\t\tqueries = [],\n\t\t\tconnectWith = this._connectWith();\n\n\t\tif ( connectWith && connected ) {\n\t\t\tfor ( i = connectWith.length - 1; i >= 0; i-- ) {\n\t\t\t\tcur = $( connectWith[ i ], this.document[ 0 ] );\n\t\t\t\tfor ( j = cur.length - 1; j >= 0; j-- ) {\n\t\t\t\t\tinst = $.data( cur[ j ], this.widgetFullName );\n\t\t\t\t\tif ( inst && inst !== this && !inst.options.disabled ) {\n\t\t\t\t\t\tqueries.push( [ $.isFunction( inst.options.items ) ?\n\t\t\t\t\t\t\tinst.options.items.call( inst.element ) :\n\t\t\t\t\t\t\t$( inst.options.items, inst.element )\n\t\t\t\t\t\t\t\t.not( \".ui-sortable-helper\" )\n\t\t\t\t\t\t\t\t.not( \".ui-sortable-placeholder\" ), inst ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tqueries.push( [ $.isFunction( this.options.items ) ?\n\t\t\tthis.options.items\n\t\t\t\t.call( this.element, null, { options: this.options, item: this.currentItem } ) :\n\t\t\t$( this.options.items, this.element )\n\t\t\t\t.not( \".ui-sortable-helper\" )\n\t\t\t\t.not( \".ui-sortable-placeholder\" ), this ] );\n\n\t\tfunction addItems() {\n\t\t\titems.push( this );\n\t\t}\n\t\tfor ( i = queries.length - 1; i >= 0; i-- ) {\n\t\t\tqueries[ i ][ 0 ].each( addItems );\n\t\t}\n\n\t\treturn $( items );\n\n\t},\n\n\t_removeCurrentsFromItems: function() {\n\n\t\tvar list = this.currentItem.find( \":data(\" + this.widgetName + \"-item)\" );\n\n\t\tthis.items = $.grep( this.items, function( item ) {\n\t\t\tfor ( var j = 0; j < list.length; j++ ) {\n\t\t\t\tif ( list[ j ] === item.item[ 0 ] ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} );\n\n\t},\n\n\t_refreshItems: function( event ) {\n\n\t\tthis.items = [];\n\t\tthis.containers = [ this ];\n\n\t\tvar i, j, cur, inst, targetData, _queries, item, queriesLength,\n\t\t\titems = this.items,\n\t\t\tqueries = [ [ $.isFunction( this.options.items ) ?\n\t\t\t\tthis.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) :\n\t\t\t\t$( this.options.items, this.element ), this ] ],\n\t\t\tconnectWith = this._connectWith();\n\n\t\t//Shouldn't be run the first time through due to massive slow-down\n\t\tif ( connectWith && this.ready ) {\n\t\t\tfor ( i = connectWith.length - 1; i >= 0; i-- ) {\n\t\t\t\tcur = $( connectWith[ i ], this.document[ 0 ] );\n\t\t\t\tfor ( j = cur.length - 1; j >= 0; j-- ) {\n\t\t\t\t\tinst = $.data( cur[ j ], this.widgetFullName );\n\t\t\t\t\tif ( inst && inst !== this && !inst.options.disabled ) {\n\t\t\t\t\t\tqueries.push( [ $.isFunction( inst.options.items ) ?\n\t\t\t\t\t\t\tinst.options.items\n\t\t\t\t\t\t\t\t.call( inst.element[ 0 ], event, { item: this.currentItem } ) :\n\t\t\t\t\t\t\t$( inst.options.items, inst.element ), inst ] );\n\t\t\t\t\t\tthis.containers.push( inst );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor ( i = queries.length - 1; i >= 0; i-- ) {\n\t\t\ttargetData = queries[ i ][ 1 ];\n\t\t\t_queries = queries[ i ][ 0 ];\n\n\t\t\tfor ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) {\n\t\t\t\titem = $( _queries[ j ] );\n\n\t\t\t\t// Data for target checking (mouse manager)\n\t\t\t\titem.data( this.widgetName + \"-item\", targetData );\n\n\t\t\t\titems.push( {\n\t\t\t\t\titem: item,\n\t\t\t\t\tinstance: targetData,\n\t\t\t\t\twidth: 0, height: 0,\n\t\t\t\t\tleft: 0, top: 0\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\n\t},\n\n\trefreshPositions: function( fast ) {\n\n\t\t// Determine whether items are being displayed horizontally\n\t\tthis.floating = this.items.length ?\n\t\t\tthis.options.axis === \"x\" || this._isFloating( this.items[ 0 ].item ) :\n\t\t\tfalse;\n\n\t\t//This has to be redone because due to the item being moved out/into the offsetParent,\n\t\t// the offsetParent's position will change\n\t\tif ( this.offsetParent && this.helper ) {\n\t\t\tthis.offset.parent = this._getParentOffset();\n\t\t}\n\n\t\tvar i, item, t, p;\n\n\t\tfor ( i = this.items.length - 1; i >= 0; i-- ) {\n\t\t\titem = this.items[ i ];\n\n\t\t\t//We ignore calculating positions of all connected containers when we're not over them\n\t\t\tif ( item.instance !== this.currentContainer && this.currentContainer &&\n\t\t\t\t\titem.item[ 0 ] !== this.currentItem[ 0 ] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tt = this.options.toleranceElement ?\n\t\t\t\t$( this.options.toleranceElement, item.item ) :\n\t\t\t\titem.item;\n\n\t\t\tif ( !fast ) {\n\t\t\t\titem.width = t.outerWidth();\n\t\t\t\titem.height = t.outerHeight();\n\t\t\t}\n\n\t\t\tp = t.offset();\n\t\t\titem.left = p.left;\n\t\t\titem.top = p.top;\n\t\t}\n\n\t\tif ( this.options.custom && this.options.custom.refreshContainers ) {\n\t\t\tthis.options.custom.refreshContainers.call( this );\n\t\t} else {\n\t\t\tfor ( i = this.containers.length - 1; i >= 0; i-- ) {\n\t\t\t\tp = this.containers[ i ].element.offset();\n\t\t\t\tthis.containers[ i ].containerCache.left = p.left;\n\t\t\t\tthis.containers[ i ].containerCache.top = p.top;\n\t\t\t\tthis.containers[ i ].containerCache.width =\n\t\t\t\t\tthis.containers[ i ].element.outerWidth();\n\t\t\t\tthis.containers[ i ].containerCache.height =\n\t\t\t\t\tthis.containers[ i ].element.outerHeight();\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_createPlaceholder: function( that ) {\n\t\tthat = that || this;\n\t\tvar className,\n\t\t\to = that.options;\n\n\t\tif ( !o.placeholder || o.placeholder.constructor === String ) {\n\t\t\tclassName = o.placeholder;\n\t\t\to.placeholder = {\n\t\t\t\telement: function() {\n\n\t\t\t\t\tvar nodeName = that.currentItem[ 0 ].nodeName.toLowerCase(),\n\t\t\t\t\t\telement = $( \"<\" + nodeName + \">\", that.document[ 0 ] );\n\n\t\t\t\t\t\tthat._addClass( element, \"ui-sortable-placeholder\",\n\t\t\t\t\t\t\t\tclassName || that.currentItem[ 0 ].className )\n\t\t\t\t\t\t\t._removeClass( element, \"ui-sortable-helper\" );\n\n\t\t\t\t\tif ( nodeName === \"tbody\" ) {\n\t\t\t\t\t\tthat._createTrPlaceholder(\n\t\t\t\t\t\t\tthat.currentItem.find( \"tr\" ).eq( 0 ),\n\t\t\t\t\t\t\t$( \"<tr>\", that.document[ 0 ] ).appendTo( element )\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if ( nodeName === \"tr\" ) {\n\t\t\t\t\t\tthat._createTrPlaceholder( that.currentItem, element );\n\t\t\t\t\t} else if ( nodeName === \"img\" ) {\n\t\t\t\t\t\telement.attr( \"src\", that.currentItem.attr( \"src\" ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !className ) {\n\t\t\t\t\t\telement.css( \"visibility\", \"hidden\" );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn element;\n\t\t\t\t},\n\t\t\t\tupdate: function( container, p ) {\n\n\t\t\t\t\t// 1. If a className is set as 'placeholder option, we don't force sizes -\n\t\t\t\t\t// the class is responsible for that\n\t\t\t\t\t// 2. The option 'forcePlaceholderSize can be enabled to force it even if a\n\t\t\t\t\t// class name is specified\n\t\t\t\t\tif ( className && !o.forcePlaceholderSize ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t//If the element doesn't have a actual height by itself (without styles coming\n\t\t\t\t\t// from a stylesheet), it receives the inline height from the dragged item\n\t\t\t\t\tif ( !p.height() ) {\n\t\t\t\t\t\tp.height(\n\t\t\t\t\t\t\tthat.currentItem.innerHeight() -\n\t\t\t\t\t\t\tparseInt( that.currentItem.css( \"paddingTop\" ) || 0, 10 ) -\n\t\t\t\t\t\t\tparseInt( that.currentItem.css( \"paddingBottom\" ) || 0, 10 ) );\n\t\t\t\t\t}\n\t\t\t\t\tif ( !p.width() ) {\n\t\t\t\t\t\tp.width(\n\t\t\t\t\t\t\tthat.currentItem.innerWidth() -\n\t\t\t\t\t\t\tparseInt( that.currentItem.css( \"paddingLeft\" ) || 0, 10 ) -\n\t\t\t\t\t\t\tparseInt( that.currentItem.css( \"paddingRight\" ) || 0, 10 ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\t//Create the placeholder\n\t\tthat.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) );\n\n\t\t//Append it after the actual current item\n\t\tthat.currentItem.after( that.placeholder );\n\n\t\t//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)\n\t\to.placeholder.update( that, that.placeholder );\n\n\t},\n\n\t_createTrPlaceholder: function( sourceTr, targetTr ) {\n\t\tvar that = this;\n\n\t\tsourceTr.children().each( function() {\n\t\t\t$( \"<td>&#160;</td>\", that.document[ 0 ] )\n\t\t\t\t.attr( \"colspan\", $( this ).attr( \"colspan\" ) || 1 )\n\t\t\t\t.appendTo( targetTr );\n\t\t} );\n\t},\n\n\t_contactContainers: function( event ) {\n\t\tvar i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom,\n\t\t\tfloating, axis,\n\t\t\tinnermostContainer = null,\n\t\t\tinnermostIndex = null;\n\n\t\t// Get innermost container that intersects with item\n\t\tfor ( i = this.containers.length - 1; i >= 0; i-- ) {\n\n\t\t\t// Never consider a container that's located within the item itself\n\t\t\tif ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( this._intersectsWith( this.containers[ i ].containerCache ) ) {\n\n\t\t\t\t// If we've already found a container and it's more \"inner\" than this, then continue\n\t\t\t\tif ( innermostContainer &&\n\t\t\t\t\t\t$.contains(\n\t\t\t\t\t\t\tthis.containers[ i ].element[ 0 ],\n\t\t\t\t\t\t\tinnermostContainer.element[ 0 ] ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tinnermostContainer = this.containers[ i ];\n\t\t\t\tinnermostIndex = i;\n\n\t\t\t} else {\n\n\t\t\t\t// container doesn't intersect. trigger \"out\" event if necessary\n\t\t\t\tif ( this.containers[ i ].containerCache.over ) {\n\t\t\t\t\tthis.containers[ i ]._trigger( \"out\", event, this._uiHash( this ) );\n\t\t\t\t\tthis.containers[ i ].containerCache.over = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\t// If no intersecting containers found, return\n\t\tif ( !innermostContainer ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Move the item into the container if it's not there already\n\t\tif ( this.containers.length === 1 ) {\n\t\t\tif ( !this.containers[ innermostIndex ].containerCache.over ) {\n\t\t\t\tthis.containers[ innermostIndex ]._trigger( \"over\", event, this._uiHash( this ) );\n\t\t\t\tthis.containers[ innermostIndex ].containerCache.over = 1;\n\t\t\t}\n\t\t} else {\n\n\t\t\t// When entering a new container, we will find the item with the least distance and\n\t\t\t// append our item near it\n\t\t\tdist = 10000;\n\t\t\titemWithLeastDistance = null;\n\t\t\tfloating = innermostContainer.floating || this._isFloating( this.currentItem );\n\t\t\tposProperty = floating ? \"left\" : \"top\";\n\t\t\tsizeProperty = floating ? \"width\" : \"height\";\n\t\t\taxis = floating ? \"pageX\" : \"pageY\";\n\n\t\t\tfor ( j = this.items.length - 1; j >= 0; j-- ) {\n\t\t\t\tif ( !$.contains(\n\t\t\t\t\t\tthis.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] )\n\t\t\t\t) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tcur = this.items[ j ].item.offset()[ posProperty ];\n\t\t\t\tnearBottom = false;\n\t\t\t\tif ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {\n\t\t\t\t\tnearBottom = true;\n\t\t\t\t}\n\n\t\t\t\tif ( Math.abs( event[ axis ] - cur ) < dist ) {\n\t\t\t\t\tdist = Math.abs( event[ axis ] - cur );\n\t\t\t\t\titemWithLeastDistance = this.items[ j ];\n\t\t\t\t\tthis.direction = nearBottom ? \"up\" : \"down\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//Check if dropOnEmpty is enabled\n\t\t\tif ( !itemWithLeastDistance && !this.options.dropOnEmpty ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( this.currentContainer === this.containers[ innermostIndex ] ) {\n\t\t\t\tif ( !this.currentContainer.containerCache.over ) {\n\t\t\t\t\tthis.containers[ innermostIndex ]._trigger( \"over\", event, this._uiHash() );\n\t\t\t\t\tthis.currentContainer.containerCache.over = 1;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\titemWithLeastDistance ?\n\t\t\t\tthis._rearrange( event, itemWithLeastDistance, null, true ) :\n\t\t\t\tthis._rearrange( event, null, this.containers[ innermostIndex ].element, true );\n\t\t\tthis._trigger( \"change\", event, this._uiHash() );\n\t\t\tthis.containers[ innermostIndex ]._trigger( \"change\", event, this._uiHash( this ) );\n\t\t\tthis.currentContainer = this.containers[ innermostIndex ];\n\n\t\t\t//Update the placeholder\n\t\t\tthis.options.placeholder.update( this.currentContainer, this.placeholder );\n\n\t\t\tthis.containers[ innermostIndex ]._trigger( \"over\", event, this._uiHash( this ) );\n\t\t\tthis.containers[ innermostIndex ].containerCache.over = 1;\n\t\t}\n\n\t},\n\n\t_createHelper: function( event ) {\n\n\t\tvar o = this.options,\n\t\t\thelper = $.isFunction( o.helper ) ?\n\t\t\t\t$( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) :\n\t\t\t\t( o.helper === \"clone\" ? this.currentItem.clone() : this.currentItem );\n\n\t\t//Add the helper to the DOM if that didn't happen already\n\t\tif ( !helper.parents( \"body\" ).length ) {\n\t\t\t$( o.appendTo !== \"parent\" ?\n\t\t\t\to.appendTo :\n\t\t\t\tthis.currentItem[ 0 ].parentNode )[ 0 ].appendChild( helper[ 0 ] );\n\t\t}\n\n\t\tif ( helper[ 0 ] === this.currentItem[ 0 ] ) {\n\t\t\tthis._storedCSS = {\n\t\t\t\twidth: this.currentItem[ 0 ].style.width,\n\t\t\t\theight: this.currentItem[ 0 ].style.height,\n\t\t\t\tposition: this.currentItem.css( \"position\" ),\n\t\t\t\ttop: this.currentItem.css( \"top\" ),\n\t\t\t\tleft: this.currentItem.css( \"left\" )\n\t\t\t};\n\t\t}\n\n\t\tif ( !helper[ 0 ].style.width || o.forceHelperSize ) {\n\t\t\thelper.width( this.currentItem.width() );\n\t\t}\n\t\tif ( !helper[ 0 ].style.height || o.forceHelperSize ) {\n\t\t\thelper.height( this.currentItem.height() );\n\t\t}\n\n\t\treturn helper;\n\n\t},\n\n\t_adjustOffsetFromHelper: function( obj ) {\n\t\tif ( typeof obj === \"string\" ) {\n\t\t\tobj = obj.split( \" \" );\n\t\t}\n\t\tif ( $.isArray( obj ) ) {\n\t\t\tobj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };\n\t\t}\n\t\tif ( \"left\" in obj ) {\n\t\t\tthis.offset.click.left = obj.left + this.margins.left;\n\t\t}\n\t\tif ( \"right\" in obj ) {\n\t\t\tthis.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;\n\t\t}\n\t\tif ( \"top\" in obj ) {\n\t\t\tthis.offset.click.top = obj.top + this.margins.top;\n\t\t}\n\t\tif ( \"bottom\" in obj ) {\n\t\t\tthis.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;\n\t\t}\n\t},\n\n\t_getParentOffset: function() {\n\n\t\t//Get the offsetParent and cache its position\n\t\tthis.offsetParent = this.helper.offsetParent();\n\t\tvar po = this.offsetParent.offset();\n\n\t\t// This is a special case where we need to modify a offset calculated on start, since the\n\t\t// following happened:\n\t\t// 1. The position of the helper is absolute, so it's position is calculated based on the\n\t\t// next positioned parent\n\t\t// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't\n\t\t// the document, which means that the scroll is included in the initial calculation of the\n\t\t// offset of the parent, and never recalculated upon drag\n\t\tif ( this.cssPosition === \"absolute\" && this.scrollParent[ 0 ] !== this.document[ 0 ] &&\n\t\t\t\t$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {\n\t\t\tpo.left += this.scrollParent.scrollLeft();\n\t\t\tpo.top += this.scrollParent.scrollTop();\n\t\t}\n\n\t\t// This needs to be actually done for all browsers, since pageX/pageY includes this\n\t\t// information with an ugly IE fix\n\t\tif ( this.offsetParent[ 0 ] === this.document[ 0 ].body ||\n\t\t\t\t( this.offsetParent[ 0 ].tagName &&\n\t\t\t\tthis.offsetParent[ 0 ].tagName.toLowerCase() === \"html\" && $.ui.ie ) ) {\n\t\t\tpo = { top: 0, left: 0 };\n\t\t}\n\n\t\treturn {\n\t\t\ttop: po.top + ( parseInt( this.offsetParent.css( \"borderTopWidth\" ), 10 ) || 0 ),\n\t\t\tleft: po.left + ( parseInt( this.offsetParent.css( \"borderLeftWidth\" ), 10 ) || 0 )\n\t\t};\n\n\t},\n\n\t_getRelativeOffset: function() {\n\n\t\tif ( this.cssPosition === \"relative\" ) {\n\t\t\tvar p = this.currentItem.position();\n\t\t\treturn {\n\t\t\t\ttop: p.top - ( parseInt( this.helper.css( \"top\" ), 10 ) || 0 ) +\n\t\t\t\t\tthis.scrollParent.scrollTop(),\n\t\t\t\tleft: p.left - ( parseInt( this.helper.css( \"left\" ), 10 ) || 0 ) +\n\t\t\t\t\tthis.scrollParent.scrollLeft()\n\t\t\t};\n\t\t} else {\n\t\t\treturn { top: 0, left: 0 };\n\t\t}\n\n\t},\n\n\t_cacheMargins: function() {\n\t\tthis.margins = {\n\t\t\tleft: ( parseInt( this.currentItem.css( \"marginLeft\" ), 10 ) || 0 ),\n\t\t\ttop: ( parseInt( this.currentItem.css( \"marginTop\" ), 10 ) || 0 )\n\t\t};\n\t},\n\n\t_cacheHelperProportions: function() {\n\t\tthis.helperProportions = {\n\t\t\twidth: this.helper.outerWidth(),\n\t\t\theight: this.helper.outerHeight()\n\t\t};\n\t},\n\n\t_setContainment: function() {\n\n\t\tvar ce, co, over,\n\t\t\to = this.options;\n\t\tif ( o.containment === \"parent\" ) {\n\t\t\to.containment = this.helper[ 0 ].parentNode;\n\t\t}\n\t\tif ( o.containment === \"document\" || o.containment === \"window\" ) {\n\t\t\tthis.containment = [\n\t\t\t\t0 - this.offset.relative.left - this.offset.parent.left,\n\t\t\t\t0 - this.offset.relative.top - this.offset.parent.top,\n\t\t\t\to.containment === \"document\" ?\n\t\t\t\t\tthis.document.width() :\n\t\t\t\t\tthis.window.width() - this.helperProportions.width - this.margins.left,\n\t\t\t\t( o.containment === \"document\" ?\n\t\t\t\t\t( this.document.height() || document.body.parentNode.scrollHeight ) :\n\t\t\t\t\tthis.window.height() || this.document[ 0 ].body.parentNode.scrollHeight\n\t\t\t\t) - this.helperProportions.height - this.margins.top\n\t\t\t];\n\t\t}\n\n\t\tif ( !( /^(document|window|parent)$/ ).test( o.containment ) ) {\n\t\t\tce = $( o.containment )[ 0 ];\n\t\t\tco = $( o.containment ).offset();\n\t\t\tover = ( $( ce ).css( \"overflow\" ) !== \"hidden\" );\n\n\t\t\tthis.containment = [\n\t\t\t\tco.left + ( parseInt( $( ce ).css( \"borderLeftWidth\" ), 10 ) || 0 ) +\n\t\t\t\t\t( parseInt( $( ce ).css( \"paddingLeft\" ), 10 ) || 0 ) - this.margins.left,\n\t\t\t\tco.top + ( parseInt( $( ce ).css( \"borderTopWidth\" ), 10 ) || 0 ) +\n\t\t\t\t\t( parseInt( $( ce ).css( \"paddingTop\" ), 10 ) || 0 ) - this.margins.top,\n\t\t\t\tco.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -\n\t\t\t\t\t( parseInt( $( ce ).css( \"borderLeftWidth\" ), 10 ) || 0 ) -\n\t\t\t\t\t( parseInt( $( ce ).css( \"paddingRight\" ), 10 ) || 0 ) -\n\t\t\t\t\tthis.helperProportions.width - this.margins.left,\n\t\t\t\tco.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -\n\t\t\t\t\t( parseInt( $( ce ).css( \"borderTopWidth\" ), 10 ) || 0 ) -\n\t\t\t\t\t( parseInt( $( ce ).css( \"paddingBottom\" ), 10 ) || 0 ) -\n\t\t\t\t\tthis.helperProportions.height - this.margins.top\n\t\t\t];\n\t\t}\n\n\t},\n\n\t_convertPositionTo: function( d, pos ) {\n\n\t\tif ( !pos ) {\n\t\t\tpos = this.position;\n\t\t}\n\t\tvar mod = d === \"absolute\" ? 1 : -1,\n\t\t\tscroll = this.cssPosition === \"absolute\" &&\n\t\t\t\t!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&\n\t\t\t\t$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?\n\t\t\t\t\tthis.offsetParent :\n\t\t\t\t\tthis.scrollParent,\n\t\t\tscrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );\n\n\t\treturn {\n\t\t\ttop: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpos.top\t+\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.top * mod +\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.top * mod -\n\t\t\t\t( ( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.scrollParent.scrollTop() :\n\t\t\t\t\t( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod )\n\t\t\t),\n\t\t\tleft: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpos.left +\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.left * mod +\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.left * mod\t-\n\t\t\t\t( ( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :\n\t\t\t\t\tscroll.scrollLeft() ) * mod )\n\t\t\t)\n\t\t};\n\n\t},\n\n\t_generatePosition: function( event ) {\n\n\t\tvar top, left,\n\t\t\to = this.options,\n\t\t\tpageX = event.pageX,\n\t\t\tpageY = event.pageY,\n\t\t\tscroll = this.cssPosition === \"absolute\" &&\n\t\t\t\t!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&\n\t\t\t\t$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?\n\t\t\t\t\tthis.offsetParent :\n\t\t\t\t\tthis.scrollParent,\n\t\t\t\tscrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );\n\n\t\t// This is another very weird special case that only happens for relative elements:\n\t\t// 1. If the css position is relative\n\t\t// 2. and the scroll parent is the document or similar to the offset parent\n\t\t// we have to refresh the relative offset during the scroll so there are no jumps\n\t\tif ( this.cssPosition === \"relative\" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&\n\t\t\t\tthis.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) {\n\t\t\tthis.offset.relative = this._getRelativeOffset();\n\t\t}\n\n\t\t/*\n\t\t * - Position constraining -\n\t\t * Constrain the position to a mix of grid, containment.\n\t\t */\n\n\t\tif ( this.originalPosition ) { //If we are not dragging yet, we won't check for options\n\n\t\t\tif ( this.containment ) {\n\t\t\t\tif ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) {\n\t\t\t\t\tpageX = this.containment[ 0 ] + this.offset.click.left;\n\t\t\t\t}\n\t\t\t\tif ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) {\n\t\t\t\t\tpageY = this.containment[ 1 ] + this.offset.click.top;\n\t\t\t\t}\n\t\t\t\tif ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) {\n\t\t\t\t\tpageX = this.containment[ 2 ] + this.offset.click.left;\n\t\t\t\t}\n\t\t\t\tif ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) {\n\t\t\t\t\tpageY = this.containment[ 3 ] + this.offset.click.top;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( o.grid ) {\n\t\t\t\ttop = this.originalPageY + Math.round( ( pageY - this.originalPageY ) /\n\t\t\t\t\to.grid[ 1 ] ) * o.grid[ 1 ];\n\t\t\t\tpageY = this.containment ?\n\t\t\t\t\t( ( top - this.offset.click.top >= this.containment[ 1 ] &&\n\t\t\t\t\t\ttop - this.offset.click.top <= this.containment[ 3 ] ) ?\n\t\t\t\t\t\t\ttop :\n\t\t\t\t\t\t\t( ( top - this.offset.click.top >= this.containment[ 1 ] ) ?\n\t\t\t\t\t\t\t\ttop - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) :\n\t\t\t\t\t\t\t\ttop;\n\n\t\t\t\tleft = this.originalPageX + Math.round( ( pageX - this.originalPageX ) /\n\t\t\t\t\to.grid[ 0 ] ) * o.grid[ 0 ];\n\t\t\t\tpageX = this.containment ?\n\t\t\t\t\t( ( left - this.offset.click.left >= this.containment[ 0 ] &&\n\t\t\t\t\t\tleft - this.offset.click.left <= this.containment[ 2 ] ) ?\n\t\t\t\t\t\t\tleft :\n\t\t\t\t\t\t\t( ( left - this.offset.click.left >= this.containment[ 0 ] ) ?\n\t\t\t\t\t\t\t\tleft - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) :\n\t\t\t\t\t\t\t\tleft;\n\t\t\t}\n\n\t\t}\n\n\t\treturn {\n\t\t\ttop: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpageY -\n\n\t\t\t\t// Click offset (relative to the element)\n\t\t\t\tthis.offset.click.top -\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.top -\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.top +\n\t\t\t\t( ( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.scrollParent.scrollTop() :\n\t\t\t\t\t( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) )\n\t\t\t),\n\t\t\tleft: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpageX -\n\n\t\t\t\t// Click offset (relative to the element)\n\t\t\t\tthis.offset.click.left -\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.left -\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.left +\n\t\t\t\t( ( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.scrollParent.scrollLeft() :\n\t\t\t\t\tscrollIsRootNode ? 0 : scroll.scrollLeft() ) )\n\t\t\t)\n\t\t};\n\n\t},\n\n\t_rearrange: function( event, i, a, hardRefresh ) {\n\n\t\ta ? a[ 0 ].appendChild( this.placeholder[ 0 ] ) :\n\t\t\ti.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ],\n\t\t\t\t( this.direction === \"down\" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) );\n\n\t\t//Various things done here to improve the performance:\n\t\t// 1. we create a setTimeout, that calls refreshPositions\n\t\t// 2. on the instance, we have a counter variable, that get's higher after every append\n\t\t// 3. on the local scope, we copy the counter variable, and check in the timeout,\n\t\t// if it's still the same\n\t\t// 4. this lets only the last addition to the timeout stack through\n\t\tthis.counter = this.counter ? ++this.counter : 1;\n\t\tvar counter = this.counter;\n\n\t\tthis._delay( function() {\n\t\t\tif ( counter === this.counter ) {\n\n\t\t\t\t//Precompute after each DOM insertion, NOT on mousemove\n\t\t\t\tthis.refreshPositions( !hardRefresh );\n\t\t\t}\n\t\t} );\n\n\t},\n\n\t_clear: function( event, noPropagation ) {\n\n\t\tthis.reverting = false;\n\n\t\t// We delay all events that have to be triggered to after the point where the placeholder\n\t\t// has been removed and everything else normalized again\n\t\tvar i,\n\t\t\tdelayedTriggers = [];\n\n\t\t// We first have to update the dom position of the actual currentItem\n\t\t// Note: don't do it if the current item is already removed (by a user), or it gets\n\t\t// reappended (see #4088)\n\t\tif ( !this._noFinalSort && this.currentItem.parent().length ) {\n\t\t\tthis.placeholder.before( this.currentItem );\n\t\t}\n\t\tthis._noFinalSort = null;\n\n\t\tif ( this.helper[ 0 ] === this.currentItem[ 0 ] ) {\n\t\t\tfor ( i in this._storedCSS ) {\n\t\t\t\tif ( this._storedCSS[ i ] === \"auto\" || this._storedCSS[ i ] === \"static\" ) {\n\t\t\t\t\tthis._storedCSS[ i ] = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.currentItem.css( this._storedCSS );\n\t\t\tthis._removeClass( this.currentItem, \"ui-sortable-helper\" );\n\t\t} else {\n\t\t\tthis.currentItem.show();\n\t\t}\n\n\t\tif ( this.fromOutside && !noPropagation ) {\n\t\t\tdelayedTriggers.push( function( event ) {\n\t\t\t\tthis._trigger( \"receive\", event, this._uiHash( this.fromOutside ) );\n\t\t\t} );\n\t\t}\n\t\tif ( ( this.fromOutside ||\n\t\t\t\tthis.domPosition.prev !==\n\t\t\t\tthis.currentItem.prev().not( \".ui-sortable-helper\" )[ 0 ] ||\n\t\t\t\tthis.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) {\n\n\t\t\t// Trigger update callback if the DOM position has changed\n\t\t\tdelayedTriggers.push( function( event ) {\n\t\t\t\tthis._trigger( \"update\", event, this._uiHash() );\n\t\t\t} );\n\t\t}\n\n\t\t// Check if the items Container has Changed and trigger appropriate\n\t\t// events.\n\t\tif ( this !== this.currentContainer ) {\n\t\t\tif ( !noPropagation ) {\n\t\t\t\tdelayedTriggers.push( function( event ) {\n\t\t\t\t\tthis._trigger( \"remove\", event, this._uiHash() );\n\t\t\t\t} );\n\t\t\t\tdelayedTriggers.push( ( function( c ) {\n\t\t\t\t\treturn function( event ) {\n\t\t\t\t\t\tc._trigger( \"receive\", event, this._uiHash( this ) );\n\t\t\t\t\t};\n\t\t\t\t} ).call( this, this.currentContainer ) );\n\t\t\t\tdelayedTriggers.push( ( function( c ) {\n\t\t\t\t\treturn function( event ) {\n\t\t\t\t\t\tc._trigger( \"update\", event, this._uiHash( this ) );\n\t\t\t\t\t};\n\t\t\t\t} ).call( this, this.currentContainer ) );\n\t\t\t}\n\t\t}\n\n\t\t//Post events to containers\n\t\tfunction delayEvent( type, instance, container ) {\n\t\t\treturn function( event ) {\n\t\t\t\tcontainer._trigger( type, event, instance._uiHash( instance ) );\n\t\t\t};\n\t\t}\n\t\tfor ( i = this.containers.length - 1; i >= 0; i-- ) {\n\t\t\tif ( !noPropagation ) {\n\t\t\t\tdelayedTriggers.push( delayEvent( \"deactivate\", this, this.containers[ i ] ) );\n\t\t\t}\n\t\t\tif ( this.containers[ i ].containerCache.over ) {\n\t\t\t\tdelayedTriggers.push( delayEvent( \"out\", this, this.containers[ i ] ) );\n\t\t\t\tthis.containers[ i ].containerCache.over = 0;\n\t\t\t}\n\t\t}\n\n\t\t//Do what was originally in plugins\n\t\tif ( this.storedCursor ) {\n\t\t\tthis.document.find( \"body\" ).css( \"cursor\", this.storedCursor );\n\t\t\tthis.storedStylesheet.remove();\n\t\t}\n\t\tif ( this._storedOpacity ) {\n\t\t\tthis.helper.css( \"opacity\", this._storedOpacity );\n\t\t}\n\t\tif ( this._storedZIndex ) {\n\t\t\tthis.helper.css( \"zIndex\", this._storedZIndex === \"auto\" ? \"\" : this._storedZIndex );\n\t\t}\n\n\t\tthis.dragging = false;\n\n\t\tif ( !noPropagation ) {\n\t\t\tthis._trigger( \"beforeStop\", event, this._uiHash() );\n\t\t}\n\n\t\t//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,\n\t\t// it unbinds ALL events from the original node!\n\t\tthis.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );\n\n\t\tif ( !this.cancelHelperRemoval ) {\n\t\t\tif ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {\n\t\t\t\tthis.helper.remove();\n\t\t\t}\n\t\t\tthis.helper = null;\n\t\t}\n\n\t\tif ( !noPropagation ) {\n\t\t\tfor ( i = 0; i < delayedTriggers.length; i++ ) {\n\n\t\t\t\t// Trigger all delayed events\n\t\t\t\tdelayedTriggers[ i ].call( this, event );\n\t\t\t}\n\t\t\tthis._trigger( \"stop\", event, this._uiHash() );\n\t\t}\n\n\t\tthis.fromOutside = false;\n\t\treturn !this.cancelHelperRemoval;\n\n\t},\n\n\t_trigger: function() {\n\t\tif ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) {\n\t\t\tthis.cancel();\n\t\t}\n\t},\n\n\t_uiHash: function( _inst ) {\n\t\tvar inst = _inst || this;\n\t\treturn {\n\t\t\thelper: inst.helper,\n\t\t\tplaceholder: inst.placeholder || $( [] ),\n\t\t\tposition: inst.position,\n\t\t\toriginalPosition: inst.originalPosition,\n\t\t\toffset: inst.positionAbs,\n\t\t\titem: inst.currentItem,\n\t\t\tsender: _inst ? _inst.element : null\n\t\t};\n\t}\n\n} );\n\n\n/*!\n * jQuery UI Spinner 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Spinner\n//>>group: Widgets\n//>>description: Displays buttons to easily input numbers via the keyboard or mouse.\n//>>docs: http://api.jqueryui.com/spinner/\n//>>demos: http://jqueryui.com/spinner/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/spinner.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\nfunction spinnerModifer( fn ) {\n\treturn function() {\n\t\tvar previous = this.element.val();\n\t\tfn.apply( this, arguments );\n\t\tthis._refresh();\n\t\tif ( previous !== this.element.val() ) {\n\t\t\tthis._trigger( \"change\" );\n\t\t}\n\t};\n}\n\n$.widget( \"ui.spinner\", {\n\tversion: \"1.12.1\",\n\tdefaultElement: \"<input>\",\n\twidgetEventPrefix: \"spin\",\n\toptions: {\n\t\tclasses: {\n\t\t\t\"ui-spinner\": \"ui-corner-all\",\n\t\t\t\"ui-spinner-down\": \"ui-corner-br\",\n\t\t\t\"ui-spinner-up\": \"ui-corner-tr\"\n\t\t},\n\t\tculture: null,\n\t\ticons: {\n\t\t\tdown: \"ui-icon-triangle-1-s\",\n\t\t\tup: \"ui-icon-triangle-1-n\"\n\t\t},\n\t\tincremental: true,\n\t\tmax: null,\n\t\tmin: null,\n\t\tnumberFormat: null,\n\t\tpage: 10,\n\t\tstep: 1,\n\n\t\tchange: null,\n\t\tspin: null,\n\t\tstart: null,\n\t\tstop: null\n\t},\n\n\t_create: function() {\n\n\t\t// handle string values that need to be parsed\n\t\tthis._setOption( \"max\", this.options.max );\n\t\tthis._setOption( \"min\", this.options.min );\n\t\tthis._setOption( \"step\", this.options.step );\n\n\t\t// Only format if there is a value, prevents the field from being marked\n\t\t// as invalid in Firefox, see #9573.\n\t\tif ( this.value() !== \"\" ) {\n\n\t\t\t// Format the value, but don't constrain.\n\t\t\tthis._value( this.element.val(), true );\n\t\t}\n\n\t\tthis._draw();\n\t\tthis._on( this._events );\n\t\tthis._refresh();\n\n\t\t// Turning off autocomplete prevents the browser from remembering the\n\t\t// value when navigating through history, so we re-enable autocomplete\n\t\t// if the page is unloaded before the widget is destroyed. #7790\n\t\tthis._on( this.window, {\n\t\t\tbeforeunload: function() {\n\t\t\t\tthis.element.removeAttr( \"autocomplete\" );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_getCreateOptions: function() {\n\t\tvar options = this._super();\n\t\tvar element = this.element;\n\n\t\t$.each( [ \"min\", \"max\", \"step\" ], function( i, option ) {\n\t\t\tvar value = element.attr( option );\n\t\t\tif ( value != null && value.length ) {\n\t\t\t\toptions[ option ] = value;\n\t\t\t}\n\t\t} );\n\n\t\treturn options;\n\t},\n\n\t_events: {\n\t\tkeydown: function( event ) {\n\t\t\tif ( this._start( event ) && this._keydown( event ) ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t},\n\t\tkeyup: \"_stop\",\n\t\tfocus: function() {\n\t\t\tthis.previous = this.element.val();\n\t\t},\n\t\tblur: function( event ) {\n\t\t\tif ( this.cancelBlur ) {\n\t\t\t\tdelete this.cancelBlur;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._stop();\n\t\t\tthis._refresh();\n\t\t\tif ( this.previous !== this.element.val() ) {\n\t\t\t\tthis._trigger( \"change\", event );\n\t\t\t}\n\t\t},\n\t\tmousewheel: function( event, delta ) {\n\t\t\tif ( !delta ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ( !this.spinning && !this._start( event ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tthis._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event );\n\t\t\tclearTimeout( this.mousewheelTimer );\n\t\t\tthis.mousewheelTimer = this._delay( function() {\n\t\t\t\tif ( this.spinning ) {\n\t\t\t\t\tthis._stop( event );\n\t\t\t\t}\n\t\t\t}, 100 );\n\t\t\tevent.preventDefault();\n\t\t},\n\t\t\"mousedown .ui-spinner-button\": function( event ) {\n\t\t\tvar previous;\n\n\t\t\t// We never want the buttons to have focus; whenever the user is\n\t\t\t// interacting with the spinner, the focus should be on the input.\n\t\t\t// If the input is focused then this.previous is properly set from\n\t\t\t// when the input first received focus. If the input is not focused\n\t\t\t// then we need to set this.previous based on the value before spinning.\n\t\t\tprevious = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] ) ?\n\t\t\t\tthis.previous : this.element.val();\n\t\t\tfunction checkFocus() {\n\t\t\t\tvar isActive = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] );\n\t\t\t\tif ( !isActive ) {\n\t\t\t\t\tthis.element.trigger( \"focus\" );\n\t\t\t\t\tthis.previous = previous;\n\n\t\t\t\t\t// support: IE\n\t\t\t\t\t// IE sets focus asynchronously, so we need to check if focus\n\t\t\t\t\t// moved off of the input because the user clicked on the button.\n\t\t\t\t\tthis._delay( function() {\n\t\t\t\t\t\tthis.previous = previous;\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Ensure focus is on (or stays on) the text field\n\t\t\tevent.preventDefault();\n\t\t\tcheckFocus.call( this );\n\n\t\t\t// Support: IE\n\t\t\t// IE doesn't prevent moving focus even with event.preventDefault()\n\t\t\t// so we set a flag to know when we should ignore the blur event\n\t\t\t// and check (again) if focus moved off of the input.\n\t\t\tthis.cancelBlur = true;\n\t\t\tthis._delay( function() {\n\t\t\t\tdelete this.cancelBlur;\n\t\t\t\tcheckFocus.call( this );\n\t\t\t} );\n\n\t\t\tif ( this._start( event ) === false ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._repeat( null, $( event.currentTarget )\n\t\t\t\t.hasClass( \"ui-spinner-up\" ) ? 1 : -1, event );\n\t\t},\n\t\t\"mouseup .ui-spinner-button\": \"_stop\",\n\t\t\"mouseenter .ui-spinner-button\": function( event ) {\n\n\t\t\t// button will add ui-state-active if mouse was down while mouseleave and kept down\n\t\t\tif ( !$( event.currentTarget ).hasClass( \"ui-state-active\" ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( this._start( event ) === false ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tthis._repeat( null, $( event.currentTarget )\n\t\t\t\t.hasClass( \"ui-spinner-up\" ) ? 1 : -1, event );\n\t\t},\n\n\t\t// TODO: do we really want to consider this a stop?\n\t\t// shouldn't we just stop the repeater and wait until mouseup before\n\t\t// we trigger the stop event?\n\t\t\"mouseleave .ui-spinner-button\": \"_stop\"\n\t},\n\n\t// Support mobile enhanced option and make backcompat more sane\n\t_enhance: function() {\n\t\tthis.uiSpinner = this.element\n\t\t\t.attr( \"autocomplete\", \"off\" )\n\t\t\t.wrap( \"<span>\" )\n\t\t\t.parent()\n\n\t\t\t\t// Add buttons\n\t\t\t\t.append(\n\t\t\t\t\t\"<a></a><a></a>\"\n\t\t\t\t);\n\t},\n\n\t_draw: function() {\n\t\tthis._enhance();\n\n\t\tthis._addClass( this.uiSpinner, \"ui-spinner\", \"ui-widget ui-widget-content\" );\n\t\tthis._addClass( \"ui-spinner-input\" );\n\n\t\tthis.element.attr( \"role\", \"spinbutton\" );\n\n\t\t// Button bindings\n\t\tthis.buttons = this.uiSpinner.children( \"a\" )\n\t\t\t.attr( \"tabIndex\", -1 )\n\t\t\t.attr( \"aria-hidden\", true )\n\t\t\t.button( {\n\t\t\t\tclasses: {\n\t\t\t\t\t\"ui-button\": \"\"\n\t\t\t\t}\n\t\t\t} );\n\n\t\t// TODO: Right now button does not support classes this is already updated in button PR\n\t\tthis._removeClass( this.buttons, \"ui-corner-all\" );\n\n\t\tthis._addClass( this.buttons.first(), \"ui-spinner-button ui-spinner-up\" );\n\t\tthis._addClass( this.buttons.last(), \"ui-spinner-button ui-spinner-down\" );\n\t\tthis.buttons.first().button( {\n\t\t\t\"icon\": this.options.icons.up,\n\t\t\t\"showLabel\": false\n\t\t} );\n\t\tthis.buttons.last().button( {\n\t\t\t\"icon\": this.options.icons.down,\n\t\t\t\"showLabel\": false\n\t\t} );\n\n\t\t// IE 6 doesn't understand height: 50% for the buttons\n\t\t// unless the wrapper has an explicit height\n\t\tif ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) &&\n\t\t\t\tthis.uiSpinner.height() > 0 ) {\n\t\t\tthis.uiSpinner.height( this.uiSpinner.height() );\n\t\t}\n\t},\n\n\t_keydown: function( event ) {\n\t\tvar options = this.options,\n\t\t\tkeyCode = $.ui.keyCode;\n\n\t\tswitch ( event.keyCode ) {\n\t\tcase keyCode.UP:\n\t\t\tthis._repeat( null, 1, event );\n\t\t\treturn true;\n\t\tcase keyCode.DOWN:\n\t\t\tthis._repeat( null, -1, event );\n\t\t\treturn true;\n\t\tcase keyCode.PAGE_UP:\n\t\t\tthis._repeat( null, options.page, event );\n\t\t\treturn true;\n\t\tcase keyCode.PAGE_DOWN:\n\t\t\tthis._repeat( null, -options.page, event );\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t},\n\n\t_start: function( event ) {\n\t\tif ( !this.spinning && this._trigger( \"start\", event ) === false ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( !this.counter ) {\n\t\t\tthis.counter = 1;\n\t\t}\n\t\tthis.spinning = true;\n\t\treturn true;\n\t},\n\n\t_repeat: function( i, steps, event ) {\n\t\ti = i || 500;\n\n\t\tclearTimeout( this.timer );\n\t\tthis.timer = this._delay( function() {\n\t\t\tthis._repeat( 40, steps, event );\n\t\t}, i );\n\n\t\tthis._spin( steps * this.options.step, event );\n\t},\n\n\t_spin: function( step, event ) {\n\t\tvar value = this.value() || 0;\n\n\t\tif ( !this.counter ) {\n\t\t\tthis.counter = 1;\n\t\t}\n\n\t\tvalue = this._adjustValue( value + step * this._increment( this.counter ) );\n\n\t\tif ( !this.spinning || this._trigger( \"spin\", event, { value: value } ) !== false ) {\n\t\t\tthis._value( value );\n\t\t\tthis.counter++;\n\t\t}\n\t},\n\n\t_increment: function( i ) {\n\t\tvar incremental = this.options.incremental;\n\n\t\tif ( incremental ) {\n\t\t\treturn $.isFunction( incremental ) ?\n\t\t\t\tincremental( i ) :\n\t\t\t\tMath.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );\n\t\t}\n\n\t\treturn 1;\n\t},\n\n\t_precision: function() {\n\t\tvar precision = this._precisionOf( this.options.step );\n\t\tif ( this.options.min !== null ) {\n\t\t\tprecision = Math.max( precision, this._precisionOf( this.options.min ) );\n\t\t}\n\t\treturn precision;\n\t},\n\n\t_precisionOf: function( num ) {\n\t\tvar str = num.toString(),\n\t\t\tdecimal = str.indexOf( \".\" );\n\t\treturn decimal === -1 ? 0 : str.length - decimal - 1;\n\t},\n\n\t_adjustValue: function( value ) {\n\t\tvar base, aboveMin,\n\t\t\toptions = this.options;\n\n\t\t// Make sure we're at a valid step\n\t\t// - find out where we are relative to the base (min or 0)\n\t\tbase = options.min !== null ? options.min : 0;\n\t\taboveMin = value - base;\n\n\t\t// - round to the nearest step\n\t\taboveMin = Math.round( aboveMin / options.step ) * options.step;\n\n\t\t// - rounding is based on 0, so adjust back to our base\n\t\tvalue = base + aboveMin;\n\n\t\t// Fix precision from bad JS floating point math\n\t\tvalue = parseFloat( value.toFixed( this._precision() ) );\n\n\t\t// Clamp the value\n\t\tif ( options.max !== null && value > options.max ) {\n\t\t\treturn options.max;\n\t\t}\n\t\tif ( options.min !== null && value < options.min ) {\n\t\t\treturn options.min;\n\t\t}\n\n\t\treturn value;\n\t},\n\n\t_stop: function( event ) {\n\t\tif ( !this.spinning ) {\n\t\t\treturn;\n\t\t}\n\n\t\tclearTimeout( this.timer );\n\t\tclearTimeout( this.mousewheelTimer );\n\t\tthis.counter = 0;\n\t\tthis.spinning = false;\n\t\tthis._trigger( \"stop\", event );\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tvar prevValue, first, last;\n\n\t\tif ( key === \"culture\" || key === \"numberFormat\" ) {\n\t\t\tprevValue = this._parse( this.element.val() );\n\t\t\tthis.options[ key ] = value;\n\t\t\tthis.element.val( this._format( prevValue ) );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( key === \"max\" || key === \"min\" || key === \"step\" ) {\n\t\t\tif ( typeof value === \"string\" ) {\n\t\t\t\tvalue = this._parse( value );\n\t\t\t}\n\t\t}\n\t\tif ( key === \"icons\" ) {\n\t\t\tfirst = this.buttons.first().find( \".ui-icon\" );\n\t\t\tthis._removeClass( first, null, this.options.icons.up );\n\t\t\tthis._addClass( first, null, value.up );\n\t\t\tlast = this.buttons.last().find( \".ui-icon\" );\n\t\t\tthis._removeClass( last, null, this.options.icons.down );\n\t\t\tthis._addClass( last, null, value.down );\n\t\t}\n\n\t\tthis._super( key, value );\n\t},\n\n\t_setOptionDisabled: function( value ) {\n\t\tthis._super( value );\n\n\t\tthis._toggleClass( this.uiSpinner, null, \"ui-state-disabled\", !!value );\n\t\tthis.element.prop( \"disabled\", !!value );\n\t\tthis.buttons.button( value ? \"disable\" : \"enable\" );\n\t},\n\n\t_setOptions: spinnerModifer( function( options ) {\n\t\tthis._super( options );\n\t} ),\n\n\t_parse: function( val ) {\n\t\tif ( typeof val === \"string\" && val !== \"\" ) {\n\t\t\tval = window.Globalize && this.options.numberFormat ?\n\t\t\t\tGlobalize.parseFloat( val, 10, this.options.culture ) : +val;\n\t\t}\n\t\treturn val === \"\" || isNaN( val ) ? null : val;\n\t},\n\n\t_format: function( value ) {\n\t\tif ( value === \"\" ) {\n\t\t\treturn \"\";\n\t\t}\n\t\treturn window.Globalize && this.options.numberFormat ?\n\t\t\tGlobalize.format( value, this.options.numberFormat, this.options.culture ) :\n\t\t\tvalue;\n\t},\n\n\t_refresh: function() {\n\t\tthis.element.attr( {\n\t\t\t\"aria-valuemin\": this.options.min,\n\t\t\t\"aria-valuemax\": this.options.max,\n\n\t\t\t// TODO: what should we do with values that can't be parsed?\n\t\t\t\"aria-valuenow\": this._parse( this.element.val() )\n\t\t} );\n\t},\n\n\tisValid: function() {\n\t\tvar value = this.value();\n\n\t\t// Null is invalid\n\t\tif ( value === null ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// If value gets adjusted, it's invalid\n\t\treturn value === this._adjustValue( value );\n\t},\n\n\t// Update the value without triggering change\n\t_value: function( value, allowAny ) {\n\t\tvar parsed;\n\t\tif ( value !== \"\" ) {\n\t\t\tparsed = this._parse( value );\n\t\t\tif ( parsed !== null ) {\n\t\t\t\tif ( !allowAny ) {\n\t\t\t\t\tparsed = this._adjustValue( parsed );\n\t\t\t\t}\n\t\t\t\tvalue = this._format( parsed );\n\t\t\t}\n\t\t}\n\t\tthis.element.val( value );\n\t\tthis._refresh();\n\t},\n\n\t_destroy: function() {\n\t\tthis.element\n\t\t\t.prop( \"disabled\", false )\n\t\t\t.removeAttr( \"autocomplete role aria-valuemin aria-valuemax aria-valuenow\" );\n\n\t\tthis.uiSpinner.replaceWith( this.element );\n\t},\n\n\tstepUp: spinnerModifer( function( steps ) {\n\t\tthis._stepUp( steps );\n\t} ),\n\t_stepUp: function( steps ) {\n\t\tif ( this._start() ) {\n\t\t\tthis._spin( ( steps || 1 ) * this.options.step );\n\t\t\tthis._stop();\n\t\t}\n\t},\n\n\tstepDown: spinnerModifer( function( steps ) {\n\t\tthis._stepDown( steps );\n\t} ),\n\t_stepDown: function( steps ) {\n\t\tif ( this._start() ) {\n\t\t\tthis._spin( ( steps || 1 ) * -this.options.step );\n\t\t\tthis._stop();\n\t\t}\n\t},\n\n\tpageUp: spinnerModifer( function( pages ) {\n\t\tthis._stepUp( ( pages || 1 ) * this.options.page );\n\t} ),\n\n\tpageDown: spinnerModifer( function( pages ) {\n\t\tthis._stepDown( ( pages || 1 ) * this.options.page );\n\t} ),\n\n\tvalue: function( newVal ) {\n\t\tif ( !arguments.length ) {\n\t\t\treturn this._parse( this.element.val() );\n\t\t}\n\t\tspinnerModifer( this._value ).call( this, newVal );\n\t},\n\n\twidget: function() {\n\t\treturn this.uiSpinner;\n\t}\n} );\n\n// DEPRECATED\n// TODO: switch return back to widget declaration at top of file when this is removed\nif ( $.uiBackCompat !== false ) {\n\n\t// Backcompat for spinner html extension points\n\t$.widget( \"ui.spinner\", $.ui.spinner, {\n\t\t_enhance: function() {\n\t\t\tthis.uiSpinner = this.element\n\t\t\t\t.attr( \"autocomplete\", \"off\" )\n\t\t\t\t.wrap( this._uiSpinnerHtml() )\n\t\t\t\t.parent()\n\n\t\t\t\t\t// Add buttons\n\t\t\t\t\t.append( this._buttonHtml() );\n\t\t},\n\t\t_uiSpinnerHtml: function() {\n\t\t\treturn \"<span>\";\n\t\t},\n\n\t\t_buttonHtml: function() {\n\t\t\treturn \"<a></a><a></a>\";\n\t\t}\n\t} );\n}\n\nvar widgetsSpinner = $.ui.spinner;\n\n\n/*!\n * jQuery UI Tabs 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Tabs\n//>>group: Widgets\n//>>description: Transforms a set of container elements into a tab structure.\n//>>docs: http://api.jqueryui.com/tabs/\n//>>demos: http://jqueryui.com/tabs/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/tabs.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\n$.widget( \"ui.tabs\", {\n\tversion: \"1.12.1\",\n\tdelay: 300,\n\toptions: {\n\t\tactive: null,\n\t\tclasses: {\n\t\t\t\"ui-tabs\": \"ui-corner-all\",\n\t\t\t\"ui-tabs-nav\": \"ui-corner-all\",\n\t\t\t\"ui-tabs-panel\": \"ui-corner-bottom\",\n\t\t\t\"ui-tabs-tab\": \"ui-corner-top\"\n\t\t},\n\t\tcollapsible: false,\n\t\tevent: \"click\",\n\t\theightStyle: \"content\",\n\t\thide: null,\n\t\tshow: null,\n\n\t\t// Callbacks\n\t\tactivate: null,\n\t\tbeforeActivate: null,\n\t\tbeforeLoad: null,\n\t\tload: null\n\t},\n\n\t_isLocal: ( function() {\n\t\tvar rhash = /#.*$/;\n\n\t\treturn function( anchor ) {\n\t\t\tvar anchorUrl, locationUrl;\n\n\t\t\tanchorUrl = anchor.href.replace( rhash, \"\" );\n\t\t\tlocationUrl = location.href.replace( rhash, \"\" );\n\n\t\t\t// Decoding may throw an error if the URL isn't UTF-8 (#9518)\n\t\t\ttry {\n\t\t\t\tanchorUrl = decodeURIComponent( anchorUrl );\n\t\t\t} catch ( error ) {}\n\t\t\ttry {\n\t\t\t\tlocationUrl = decodeURIComponent( locationUrl );\n\t\t\t} catch ( error ) {}\n\n\t\t\treturn anchor.hash.length > 1 && anchorUrl === locationUrl;\n\t\t};\n\t} )(),\n\n\t_create: function() {\n\t\tvar that = this,\n\t\t\toptions = this.options;\n\n\t\tthis.running = false;\n\n\t\tthis._addClass( \"ui-tabs\", \"ui-widget ui-widget-content\" );\n\t\tthis._toggleClass( \"ui-tabs-collapsible\", null, options.collapsible );\n\n\t\tthis._processTabs();\n\t\toptions.active = this._initialActive();\n\n\t\t// Take disabling tabs via class attribute from HTML\n\t\t// into account and update option properly.\n\t\tif ( $.isArray( options.disabled ) ) {\n\t\t\toptions.disabled = $.unique( options.disabled.concat(\n\t\t\t\t$.map( this.tabs.filter( \".ui-state-disabled\" ), function( li ) {\n\t\t\t\t\treturn that.tabs.index( li );\n\t\t\t\t} )\n\t\t\t) ).sort();\n\t\t}\n\n\t\t// Check for length avoids error when initializing empty list\n\t\tif ( this.options.active !== false && this.anchors.length ) {\n\t\t\tthis.active = this._findActive( options.active );\n\t\t} else {\n\t\t\tthis.active = $();\n\t\t}\n\n\t\tthis._refresh();\n\n\t\tif ( this.active.length ) {\n\t\t\tthis.load( options.active );\n\t\t}\n\t},\n\n\t_initialActive: function() {\n\t\tvar active = this.options.active,\n\t\t\tcollapsible = this.options.collapsible,\n\t\t\tlocationHash = location.hash.substring( 1 );\n\n\t\tif ( active === null ) {\n\n\t\t\t// check the fragment identifier in the URL\n\t\t\tif ( locationHash ) {\n\t\t\t\tthis.tabs.each( function( i, tab ) {\n\t\t\t\t\tif ( $( tab ).attr( \"aria-controls\" ) === locationHash ) {\n\t\t\t\t\t\tactive = i;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\t// Check for a tab marked active via a class\n\t\t\tif ( active === null ) {\n\t\t\t\tactive = this.tabs.index( this.tabs.filter( \".ui-tabs-active\" ) );\n\t\t\t}\n\n\t\t\t// No active tab, set to false\n\t\t\tif ( active === null || active === -1 ) {\n\t\t\t\tactive = this.tabs.length ? 0 : false;\n\t\t\t}\n\t\t}\n\n\t\t// Handle numbers: negative, out of range\n\t\tif ( active !== false ) {\n\t\t\tactive = this.tabs.index( this.tabs.eq( active ) );\n\t\t\tif ( active === -1 ) {\n\t\t\t\tactive = collapsible ? false : 0;\n\t\t\t}\n\t\t}\n\n\t\t// Don't allow collapsible: false and active: false\n\t\tif ( !collapsible && active === false && this.anchors.length ) {\n\t\t\tactive = 0;\n\t\t}\n\n\t\treturn active;\n\t},\n\n\t_getCreateEventData: function() {\n\t\treturn {\n\t\t\ttab: this.active,\n\t\t\tpanel: !this.active.length ? $() : this._getPanelForTab( this.active )\n\t\t};\n\t},\n\n\t_tabKeydown: function( event ) {\n\t\tvar focusedTab = $( $.ui.safeActiveElement( this.document[ 0 ] ) ).closest( \"li\" ),\n\t\t\tselectedIndex = this.tabs.index( focusedTab ),\n\t\t\tgoingForward = true;\n\n\t\tif ( this._handlePageNav( event ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tswitch ( event.keyCode ) {\n\t\tcase $.ui.keyCode.RIGHT:\n\t\tcase $.ui.keyCode.DOWN:\n\t\t\tselectedIndex++;\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.UP:\n\t\tcase $.ui.keyCode.LEFT:\n\t\t\tgoingForward = false;\n\t\t\tselectedIndex--;\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.END:\n\t\t\tselectedIndex = this.anchors.length - 1;\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.HOME:\n\t\t\tselectedIndex = 0;\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.SPACE:\n\n\t\t\t// Activate only, no collapsing\n\t\t\tevent.preventDefault();\n\t\t\tclearTimeout( this.activating );\n\t\t\tthis._activate( selectedIndex );\n\t\t\treturn;\n\t\tcase $.ui.keyCode.ENTER:\n\n\t\t\t// Toggle (cancel delayed activation, allow collapsing)\n\t\t\tevent.preventDefault();\n\t\t\tclearTimeout( this.activating );\n\n\t\t\t// Determine if we should collapse or activate\n\t\t\tthis._activate( selectedIndex === this.options.active ? false : selectedIndex );\n\t\t\treturn;\n\t\tdefault:\n\t\t\treturn;\n\t\t}\n\n\t\t// Focus the appropriate tab, based on which key was pressed\n\t\tevent.preventDefault();\n\t\tclearTimeout( this.activating );\n\t\tselectedIndex = this._focusNextTab( selectedIndex, goingForward );\n\n\t\t// Navigating with control/command key will prevent automatic activation\n\t\tif ( !event.ctrlKey && !event.metaKey ) {\n\n\t\t\t// Update aria-selected immediately so that AT think the tab is already selected.\n\t\t\t// Otherwise AT may confuse the user by stating that they need to activate the tab,\n\t\t\t// but the tab will already be activated by the time the announcement finishes.\n\t\t\tfocusedTab.attr( \"aria-selected\", \"false\" );\n\t\t\tthis.tabs.eq( selectedIndex ).attr( \"aria-selected\", \"true\" );\n\n\t\t\tthis.activating = this._delay( function() {\n\t\t\t\tthis.option( \"active\", selectedIndex );\n\t\t\t}, this.delay );\n\t\t}\n\t},\n\n\t_panelKeydown: function( event ) {\n\t\tif ( this._handlePageNav( event ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Ctrl+up moves focus to the current tab\n\t\tif ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {\n\t\t\tevent.preventDefault();\n\t\t\tthis.active.trigger( \"focus\" );\n\t\t}\n\t},\n\n\t// Alt+page up/down moves focus to the previous/next tab (and activates)\n\t_handlePageNav: function( event ) {\n\t\tif ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {\n\t\t\tthis._activate( this._focusNextTab( this.options.active - 1, false ) );\n\t\t\treturn true;\n\t\t}\n\t\tif ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {\n\t\t\tthis._activate( this._focusNextTab( this.options.active + 1, true ) );\n\t\t\treturn true;\n\t\t}\n\t},\n\n\t_findNextTab: function( index, goingForward ) {\n\t\tvar lastTabIndex = this.tabs.length - 1;\n\n\t\tfunction constrain() {\n\t\t\tif ( index > lastTabIndex ) {\n\t\t\t\tindex = 0;\n\t\t\t}\n\t\t\tif ( index < 0 ) {\n\t\t\t\tindex = lastTabIndex;\n\t\t\t}\n\t\t\treturn index;\n\t\t}\n\n\t\twhile ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {\n\t\t\tindex = goingForward ? index + 1 : index - 1;\n\t\t}\n\n\t\treturn index;\n\t},\n\n\t_focusNextTab: function( index, goingForward ) {\n\t\tindex = this._findNextTab( index, goingForward );\n\t\tthis.tabs.eq( index ).trigger( \"focus\" );\n\t\treturn index;\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"active\" ) {\n\n\t\t\t// _activate() will handle invalid values and update this.options\n\t\t\tthis._activate( value );\n\t\t\treturn;\n\t\t}\n\n\t\tthis._super( key, value );\n\n\t\tif ( key === \"collapsible\" ) {\n\t\t\tthis._toggleClass( \"ui-tabs-collapsible\", null, value );\n\n\t\t\t// Setting collapsible: false while collapsed; open first panel\n\t\t\tif ( !value && this.options.active === false ) {\n\t\t\t\tthis._activate( 0 );\n\t\t\t}\n\t\t}\n\n\t\tif ( key === \"event\" ) {\n\t\t\tthis._setupEvents( value );\n\t\t}\n\n\t\tif ( key === \"heightStyle\" ) {\n\t\t\tthis._setupHeightStyle( value );\n\t\t}\n\t},\n\n\t_sanitizeSelector: function( hash ) {\n\t\treturn hash ? hash.replace( /[!\"$%&'()*+,.\\/:;<=>?@\\[\\]\\^`{|}~]/g, \"\\\\$&\" ) : \"\";\n\t},\n\n\trefresh: function() {\n\t\tvar options = this.options,\n\t\t\tlis = this.tablist.children( \":has(a[href])\" );\n\n\t\t// Get disabled tabs from class attribute from HTML\n\t\t// this will get converted to a boolean if needed in _refresh()\n\t\toptions.disabled = $.map( lis.filter( \".ui-state-disabled\" ), function( tab ) {\n\t\t\treturn lis.index( tab );\n\t\t} );\n\n\t\tthis._processTabs();\n\n\t\t// Was collapsed or no tabs\n\t\tif ( options.active === false || !this.anchors.length ) {\n\t\t\toptions.active = false;\n\t\t\tthis.active = $();\n\n\t\t// was active, but active tab is gone\n\t\t} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {\n\n\t\t\t// all remaining tabs are disabled\n\t\t\tif ( this.tabs.length === options.disabled.length ) {\n\t\t\t\toptions.active = false;\n\t\t\t\tthis.active = $();\n\n\t\t\t// activate previous tab\n\t\t\t} else {\n\t\t\t\tthis._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );\n\t\t\t}\n\n\t\t// was active, active tab still exists\n\t\t} else {\n\n\t\t\t// make sure active index is correct\n\t\t\toptions.active = this.tabs.index( this.active );\n\t\t}\n\n\t\tthis._refresh();\n\t},\n\n\t_refresh: function() {\n\t\tthis._setOptionDisabled( this.options.disabled );\n\t\tthis._setupEvents( this.options.event );\n\t\tthis._setupHeightStyle( this.options.heightStyle );\n\n\t\tthis.tabs.not( this.active ).attr( {\n\t\t\t\"aria-selected\": \"false\",\n\t\t\t\"aria-expanded\": \"false\",\n\t\t\ttabIndex: -1\n\t\t} );\n\t\tthis.panels.not( this._getPanelForTab( this.active ) )\n\t\t\t.hide()\n\t\t\t.attr( {\n\t\t\t\t\"aria-hidden\": \"true\"\n\t\t\t} );\n\n\t\t// Make sure one tab is in the tab order\n\t\tif ( !this.active.length ) {\n\t\t\tthis.tabs.eq( 0 ).attr( \"tabIndex\", 0 );\n\t\t} else {\n\t\t\tthis.active\n\t\t\t\t.attr( {\n\t\t\t\t\t\"aria-selected\": \"true\",\n\t\t\t\t\t\"aria-expanded\": \"true\",\n\t\t\t\t\ttabIndex: 0\n\t\t\t\t} );\n\t\t\tthis._addClass( this.active, \"ui-tabs-active\", \"ui-state-active\" );\n\t\t\tthis._getPanelForTab( this.active )\n\t\t\t\t.show()\n\t\t\t\t.attr( {\n\t\t\t\t\t\"aria-hidden\": \"false\"\n\t\t\t\t} );\n\t\t}\n\t},\n\n\t_processTabs: function() {\n\t\tvar that = this,\n\t\t\tprevTabs = this.tabs,\n\t\t\tprevAnchors = this.anchors,\n\t\t\tprevPanels = this.panels;\n\n\t\tthis.tablist = this._getList().attr( \"role\", \"tablist\" );\n\t\tthis._addClass( this.tablist, \"ui-tabs-nav\",\n\t\t\t\"ui-helper-reset ui-helper-clearfix ui-widget-header\" );\n\n\t\t// Prevent users from focusing disabled tabs via click\n\t\tthis.tablist\n\t\t\t.on( \"mousedown\" + this.eventNamespace, \"> li\", function( event ) {\n\t\t\t\tif ( $( this ).is( \".ui-state-disabled\" ) ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t} )\n\n\t\t\t// Support: IE <9\n\t\t\t// Preventing the default action in mousedown doesn't prevent IE\n\t\t\t// from focusing the element, so if the anchor gets focused, blur.\n\t\t\t// We don't have to worry about focusing the previously focused\n\t\t\t// element since clicking on a non-focusable element should focus\n\t\t\t// the body anyway.\n\t\t\t.on( \"focus\" + this.eventNamespace, \".ui-tabs-anchor\", function() {\n\t\t\t\tif ( $( this ).closest( \"li\" ).is( \".ui-state-disabled\" ) ) {\n\t\t\t\t\tthis.blur();\n\t\t\t\t}\n\t\t\t} );\n\n\t\tthis.tabs = this.tablist.find( \"> li:has(a[href])\" )\n\t\t\t.attr( {\n\t\t\t\trole: \"tab\",\n\t\t\t\ttabIndex: -1\n\t\t\t} );\n\t\tthis._addClass( this.tabs, \"ui-tabs-tab\", \"ui-state-default\" );\n\n\t\tthis.anchors = this.tabs.map( function() {\n\t\t\treturn $( \"a\", this )[ 0 ];\n\t\t} )\n\t\t\t.attr( {\n\t\t\t\trole: \"presentation\",\n\t\t\t\ttabIndex: -1\n\t\t\t} );\n\t\tthis._addClass( this.anchors, \"ui-tabs-anchor\" );\n\n\t\tthis.panels = $();\n\n\t\tthis.anchors.each( function( i, anchor ) {\n\t\t\tvar selector, panel, panelId,\n\t\t\t\tanchorId = $( anchor ).uniqueId().attr( \"id\" ),\n\t\t\t\ttab = $( anchor ).closest( \"li\" ),\n\t\t\t\toriginalAriaControls = tab.attr( \"aria-controls\" );\n\n\t\t\t// Inline tab\n\t\t\tif ( that._isLocal( anchor ) ) {\n\t\t\t\tselector = anchor.hash;\n\t\t\t\tpanelId = selector.substring( 1 );\n\t\t\t\tpanel = that.element.find( that._sanitizeSelector( selector ) );\n\n\t\t\t// remote tab\n\t\t\t} else {\n\n\t\t\t\t// If the tab doesn't already have aria-controls,\n\t\t\t\t// generate an id by using a throw-away element\n\t\t\t\tpanelId = tab.attr( \"aria-controls\" ) || $( {} ).uniqueId()[ 0 ].id;\n\t\t\t\tselector = \"#\" + panelId;\n\t\t\t\tpanel = that.element.find( selector );\n\t\t\t\tif ( !panel.length ) {\n\t\t\t\t\tpanel = that._createPanel( panelId );\n\t\t\t\t\tpanel.insertAfter( that.panels[ i - 1 ] || that.tablist );\n\t\t\t\t}\n\t\t\t\tpanel.attr( \"aria-live\", \"polite\" );\n\t\t\t}\n\n\t\t\tif ( panel.length ) {\n\t\t\t\tthat.panels = that.panels.add( panel );\n\t\t\t}\n\t\t\tif ( originalAriaControls ) {\n\t\t\t\ttab.data( \"ui-tabs-aria-controls\", originalAriaControls );\n\t\t\t}\n\t\t\ttab.attr( {\n\t\t\t\t\"aria-controls\": panelId,\n\t\t\t\t\"aria-labelledby\": anchorId\n\t\t\t} );\n\t\t\tpanel.attr( \"aria-labelledby\", anchorId );\n\t\t} );\n\n\t\tthis.panels.attr( \"role\", \"tabpanel\" );\n\t\tthis._addClass( this.panels, \"ui-tabs-panel\", \"ui-widget-content\" );\n\n\t\t// Avoid memory leaks (#10056)\n\t\tif ( prevTabs ) {\n\t\t\tthis._off( prevTabs.not( this.tabs ) );\n\t\t\tthis._off( prevAnchors.not( this.anchors ) );\n\t\t\tthis._off( prevPanels.not( this.panels ) );\n\t\t}\n\t},\n\n\t// Allow overriding how to find the list for rare usage scenarios (#7715)\n\t_getList: function() {\n\t\treturn this.tablist || this.element.find( \"ol, ul\" ).eq( 0 );\n\t},\n\n\t_createPanel: function( id ) {\n\t\treturn $( \"<div>\" )\n\t\t\t.attr( \"id\", id )\n\t\t\t.data( \"ui-tabs-destroy\", true );\n\t},\n\n\t_setOptionDisabled: function( disabled ) {\n\t\tvar currentItem, li, i;\n\n\t\tif ( $.isArray( disabled ) ) {\n\t\t\tif ( !disabled.length ) {\n\t\t\t\tdisabled = false;\n\t\t\t} else if ( disabled.length === this.anchors.length ) {\n\t\t\t\tdisabled = true;\n\t\t\t}\n\t\t}\n\n\t\t// Disable tabs\n\t\tfor ( i = 0; ( li = this.tabs[ i ] ); i++ ) {\n\t\t\tcurrentItem = $( li );\n\t\t\tif ( disabled === true || $.inArray( i, disabled ) !== -1 ) {\n\t\t\t\tcurrentItem.attr( \"aria-disabled\", \"true\" );\n\t\t\t\tthis._addClass( currentItem, null, \"ui-state-disabled\" );\n\t\t\t} else {\n\t\t\t\tcurrentItem.removeAttr( \"aria-disabled\" );\n\t\t\t\tthis._removeClass( currentItem, null, \"ui-state-disabled\" );\n\t\t\t}\n\t\t}\n\n\t\tthis.options.disabled = disabled;\n\n\t\tthis._toggleClass( this.widget(), this.widgetFullName + \"-disabled\", null,\n\t\t\tdisabled === true );\n\t},\n\n\t_setupEvents: function( event ) {\n\t\tvar events = {};\n\t\tif ( event ) {\n\t\t\t$.each( event.split( \" \" ), function( index, eventName ) {\n\t\t\t\tevents[ eventName ] = \"_eventHandler\";\n\t\t\t} );\n\t\t}\n\n\t\tthis._off( this.anchors.add( this.tabs ).add( this.panels ) );\n\n\t\t// Always prevent the default action, even when disabled\n\t\tthis._on( true, this.anchors, {\n\t\t\tclick: function( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t} );\n\t\tthis._on( this.anchors, events );\n\t\tthis._on( this.tabs, { keydown: \"_tabKeydown\" } );\n\t\tthis._on( this.panels, { keydown: \"_panelKeydown\" } );\n\n\t\tthis._focusable( this.tabs );\n\t\tthis._hoverable( this.tabs );\n\t},\n\n\t_setupHeightStyle: function( heightStyle ) {\n\t\tvar maxHeight,\n\t\t\tparent = this.element.parent();\n\n\t\tif ( heightStyle === \"fill\" ) {\n\t\t\tmaxHeight = parent.height();\n\t\t\tmaxHeight -= this.element.outerHeight() - this.element.height();\n\n\t\t\tthis.element.siblings( \":visible\" ).each( function() {\n\t\t\t\tvar elem = $( this ),\n\t\t\t\t\tposition = elem.css( \"position\" );\n\n\t\t\t\tif ( position === \"absolute\" || position === \"fixed\" ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tmaxHeight -= elem.outerHeight( true );\n\t\t\t} );\n\n\t\t\tthis.element.children().not( this.panels ).each( function() {\n\t\t\t\tmaxHeight -= $( this ).outerHeight( true );\n\t\t\t} );\n\n\t\t\tthis.panels.each( function() {\n\t\t\t\t$( this ).height( Math.max( 0, maxHeight -\n\t\t\t\t\t$( this ).innerHeight() + $( this ).height() ) );\n\t\t\t} )\n\t\t\t\t.css( \"overflow\", \"auto\" );\n\t\t} else if ( heightStyle === \"auto\" ) {\n\t\t\tmaxHeight = 0;\n\t\t\tthis.panels.each( function() {\n\t\t\t\tmaxHeight = Math.max( maxHeight, $( this ).height( \"\" ).height() );\n\t\t\t} ).height( maxHeight );\n\t\t}\n\t},\n\n\t_eventHandler: function( event ) {\n\t\tvar options = this.options,\n\t\t\tactive = this.active,\n\t\t\tanchor = $( event.currentTarget ),\n\t\t\ttab = anchor.closest( \"li\" ),\n\t\t\tclickedIsActive = tab[ 0 ] === active[ 0 ],\n\t\t\tcollapsing = clickedIsActive && options.collapsible,\n\t\t\ttoShow = collapsing ? $() : this._getPanelForTab( tab ),\n\t\t\ttoHide = !active.length ? $() : this._getPanelForTab( active ),\n\t\t\teventData = {\n\t\t\t\toldTab: active,\n\t\t\t\toldPanel: toHide,\n\t\t\t\tnewTab: collapsing ? $() : tab,\n\t\t\t\tnewPanel: toShow\n\t\t\t};\n\n\t\tevent.preventDefault();\n\n\t\tif ( tab.hasClass( \"ui-state-disabled\" ) ||\n\n\t\t\t\t// tab is already loading\n\t\t\t\ttab.hasClass( \"ui-tabs-loading\" ) ||\n\n\t\t\t\t// can't switch durning an animation\n\t\t\t\tthis.running ||\n\n\t\t\t\t// click on active header, but not collapsible\n\t\t\t\t( clickedIsActive && !options.collapsible ) ||\n\n\t\t\t\t// allow canceling activation\n\t\t\t\t( this._trigger( \"beforeActivate\", event, eventData ) === false ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\toptions.active = collapsing ? false : this.tabs.index( tab );\n\n\t\tthis.active = clickedIsActive ? $() : tab;\n\t\tif ( this.xhr ) {\n\t\t\tthis.xhr.abort();\n\t\t}\n\n\t\tif ( !toHide.length && !toShow.length ) {\n\t\t\t$.error( \"jQuery UI Tabs: Mismatching fragment identifier.\" );\n\t\t}\n\n\t\tif ( toShow.length ) {\n\t\t\tthis.load( this.tabs.index( tab ), event );\n\t\t}\n\t\tthis._toggle( event, eventData );\n\t},\n\n\t// Handles show/hide for selecting tabs\n\t_toggle: function( event, eventData ) {\n\t\tvar that = this,\n\t\t\ttoShow = eventData.newPanel,\n\t\t\ttoHide = eventData.oldPanel;\n\n\t\tthis.running = true;\n\n\t\tfunction complete() {\n\t\t\tthat.running = false;\n\t\t\tthat._trigger( \"activate\", event, eventData );\n\t\t}\n\n\t\tfunction show() {\n\t\t\tthat._addClass( eventData.newTab.closest( \"li\" ), \"ui-tabs-active\", \"ui-state-active\" );\n\n\t\t\tif ( toShow.length && that.options.show ) {\n\t\t\t\tthat._show( toShow, that.options.show, complete );\n\t\t\t} else {\n\t\t\t\ttoShow.show();\n\t\t\t\tcomplete();\n\t\t\t}\n\t\t}\n\n\t\t// Start out by hiding, then showing, then completing\n\t\tif ( toHide.length && this.options.hide ) {\n\t\t\tthis._hide( toHide, this.options.hide, function() {\n\t\t\t\tthat._removeClass( eventData.oldTab.closest( \"li\" ),\n\t\t\t\t\t\"ui-tabs-active\", \"ui-state-active\" );\n\t\t\t\tshow();\n\t\t\t} );\n\t\t} else {\n\t\t\tthis._removeClass( eventData.oldTab.closest( \"li\" ),\n\t\t\t\t\"ui-tabs-active\", \"ui-state-active\" );\n\t\t\ttoHide.hide();\n\t\t\tshow();\n\t\t}\n\n\t\ttoHide.attr( \"aria-hidden\", \"true\" );\n\t\teventData.oldTab.attr( {\n\t\t\t\"aria-selected\": \"false\",\n\t\t\t\"aria-expanded\": \"false\"\n\t\t} );\n\n\t\t// If we're switching tabs, remove the old tab from the tab order.\n\t\t// If we're opening from collapsed state, remove the previous tab from the tab order.\n\t\t// If we're collapsing, then keep the collapsing tab in the tab order.\n\t\tif ( toShow.length && toHide.length ) {\n\t\t\teventData.oldTab.attr( \"tabIndex\", -1 );\n\t\t} else if ( toShow.length ) {\n\t\t\tthis.tabs.filter( function() {\n\t\t\t\treturn $( this ).attr( \"tabIndex\" ) === 0;\n\t\t\t} )\n\t\t\t\t.attr( \"tabIndex\", -1 );\n\t\t}\n\n\t\ttoShow.attr( \"aria-hidden\", \"false\" );\n\t\teventData.newTab.attr( {\n\t\t\t\"aria-selected\": \"true\",\n\t\t\t\"aria-expanded\": \"true\",\n\t\t\ttabIndex: 0\n\t\t} );\n\t},\n\n\t_activate: function( index ) {\n\t\tvar anchor,\n\t\t\tactive = this._findActive( index );\n\n\t\t// Trying to activate the already active panel\n\t\tif ( active[ 0 ] === this.active[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Trying to collapse, simulate a click on the current active header\n\t\tif ( !active.length ) {\n\t\t\tactive = this.active;\n\t\t}\n\n\t\tanchor = active.find( \".ui-tabs-anchor\" )[ 0 ];\n\t\tthis._eventHandler( {\n\t\t\ttarget: anchor,\n\t\t\tcurrentTarget: anchor,\n\t\t\tpreventDefault: $.noop\n\t\t} );\n\t},\n\n\t_findActive: function( index ) {\n\t\treturn index === false ? $() : this.tabs.eq( index );\n\t},\n\n\t_getIndex: function( index ) {\n\n\t\t// meta-function to give users option to provide a href string instead of a numerical index.\n\t\tif ( typeof index === \"string\" ) {\n\t\t\tindex = this.anchors.index( this.anchors.filter( \"[href$='\" +\n\t\t\t\t$.ui.escapeSelector( index ) + \"']\" ) );\n\t\t}\n\n\t\treturn index;\n\t},\n\n\t_destroy: function() {\n\t\tif ( this.xhr ) {\n\t\t\tthis.xhr.abort();\n\t\t}\n\n\t\tthis.tablist\n\t\t\t.removeAttr( \"role\" )\n\t\t\t.off( this.eventNamespace );\n\n\t\tthis.anchors\n\t\t\t.removeAttr( \"role tabIndex\" )\n\t\t\t.removeUniqueId();\n\n\t\tthis.tabs.add( this.panels ).each( function() {\n\t\t\tif ( $.data( this, \"ui-tabs-destroy\" ) ) {\n\t\t\t\t$( this ).remove();\n\t\t\t} else {\n\t\t\t\t$( this ).removeAttr( \"role tabIndex \" +\n\t\t\t\t\t\"aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded\" );\n\t\t\t}\n\t\t} );\n\n\t\tthis.tabs.each( function() {\n\t\t\tvar li = $( this ),\n\t\t\t\tprev = li.data( \"ui-tabs-aria-controls\" );\n\t\t\tif ( prev ) {\n\t\t\t\tli\n\t\t\t\t\t.attr( \"aria-controls\", prev )\n\t\t\t\t\t.removeData( \"ui-tabs-aria-controls\" );\n\t\t\t} else {\n\t\t\t\tli.removeAttr( \"aria-controls\" );\n\t\t\t}\n\t\t} );\n\n\t\tthis.panels.show();\n\n\t\tif ( this.options.heightStyle !== \"content\" ) {\n\t\t\tthis.panels.css( \"height\", \"\" );\n\t\t}\n\t},\n\n\tenable: function( index ) {\n\t\tvar disabled = this.options.disabled;\n\t\tif ( disabled === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( index === undefined ) {\n\t\t\tdisabled = false;\n\t\t} else {\n\t\t\tindex = this._getIndex( index );\n\t\t\tif ( $.isArray( disabled ) ) {\n\t\t\t\tdisabled = $.map( disabled, function( num ) {\n\t\t\t\t\treturn num !== index ? num : null;\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\tdisabled = $.map( this.tabs, function( li, num ) {\n\t\t\t\t\treturn num !== index ? num : null;\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t\tthis._setOptionDisabled( disabled );\n\t},\n\n\tdisable: function( index ) {\n\t\tvar disabled = this.options.disabled;\n\t\tif ( disabled === true ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( index === undefined ) {\n\t\t\tdisabled = true;\n\t\t} else {\n\t\t\tindex = this._getIndex( index );\n\t\t\tif ( $.inArray( index, disabled ) !== -1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ( $.isArray( disabled ) ) {\n\t\t\t\tdisabled = $.merge( [ index ], disabled ).sort();\n\t\t\t} else {\n\t\t\t\tdisabled = [ index ];\n\t\t\t}\n\t\t}\n\t\tthis._setOptionDisabled( disabled );\n\t},\n\n\tload: function( index, event ) {\n\t\tindex = this._getIndex( index );\n\t\tvar that = this,\n\t\t\ttab = this.tabs.eq( index ),\n\t\t\tanchor = tab.find( \".ui-tabs-anchor\" ),\n\t\t\tpanel = this._getPanelForTab( tab ),\n\t\t\teventData = {\n\t\t\t\ttab: tab,\n\t\t\t\tpanel: panel\n\t\t\t},\n\t\t\tcomplete = function( jqXHR, status ) {\n\t\t\t\tif ( status === \"abort\" ) {\n\t\t\t\t\tthat.panels.stop( false, true );\n\t\t\t\t}\n\n\t\t\t\tthat._removeClass( tab, \"ui-tabs-loading\" );\n\t\t\t\tpanel.removeAttr( \"aria-busy\" );\n\n\t\t\t\tif ( jqXHR === that.xhr ) {\n\t\t\t\t\tdelete that.xhr;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Not remote\n\t\tif ( this._isLocal( anchor[ 0 ] ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );\n\n\t\t// Support: jQuery <1.8\n\t\t// jQuery <1.8 returns false if the request is canceled in beforeSend,\n\t\t// but as of 1.8, $.ajax() always returns a jqXHR object.\n\t\tif ( this.xhr && this.xhr.statusText !== \"canceled\" ) {\n\t\t\tthis._addClass( tab, \"ui-tabs-loading\" );\n\t\t\tpanel.attr( \"aria-busy\", \"true\" );\n\n\t\t\tthis.xhr\n\t\t\t\t.done( function( response, status, jqXHR ) {\n\n\t\t\t\t\t// support: jQuery <1.8\n\t\t\t\t\t// http://bugs.jquery.com/ticket/11778\n\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\tpanel.html( response );\n\t\t\t\t\t\tthat._trigger( \"load\", event, eventData );\n\n\t\t\t\t\t\tcomplete( jqXHR, status );\n\t\t\t\t\t}, 1 );\n\t\t\t\t} )\n\t\t\t\t.fail( function( jqXHR, status ) {\n\n\t\t\t\t\t// support: jQuery <1.8\n\t\t\t\t\t// http://bugs.jquery.com/ticket/11778\n\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\tcomplete( jqXHR, status );\n\t\t\t\t\t}, 1 );\n\t\t\t\t} );\n\t\t}\n\t},\n\n\t_ajaxSettings: function( anchor, event, eventData ) {\n\t\tvar that = this;\n\t\treturn {\n\n\t\t\t// Support: IE <11 only\n\t\t\t// Strip any hash that exists to prevent errors with the Ajax request\n\t\t\turl: anchor.attr( \"href\" ).replace( /#.*$/, \"\" ),\n\t\t\tbeforeSend: function( jqXHR, settings ) {\n\t\t\t\treturn that._trigger( \"beforeLoad\", event,\n\t\t\t\t\t$.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );\n\t\t\t}\n\t\t};\n\t},\n\n\t_getPanelForTab: function( tab ) {\n\t\tvar id = $( tab ).attr( \"aria-controls\" );\n\t\treturn this.element.find( this._sanitizeSelector( \"#\" + id ) );\n\t}\n} );\n\n// DEPRECATED\n// TODO: Switch return back to widget declaration at top of file when this is removed\nif ( $.uiBackCompat !== false ) {\n\n\t// Backcompat for ui-tab class (now ui-tabs-tab)\n\t$.widget( \"ui.tabs\", $.ui.tabs, {\n\t\t_processTabs: function() {\n\t\t\tthis._superApply( arguments );\n\t\t\tthis._addClass( this.tabs, \"ui-tab\" );\n\t\t}\n\t} );\n}\n\nvar widgetsTabs = $.ui.tabs;\n\n\n/*!\n * jQuery UI Tooltip 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Tooltip\n//>>group: Widgets\n//>>description: Shows additional information for any element on hover or focus.\n//>>docs: http://api.jqueryui.com/tooltip/\n//>>demos: http://jqueryui.com/tooltip/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/tooltip.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\n$.widget( \"ui.tooltip\", {\n\tversion: \"1.12.1\",\n\toptions: {\n\t\tclasses: {\n\t\t\t\"ui-tooltip\": \"ui-corner-all ui-widget-shadow\"\n\t\t},\n\t\tcontent: function() {\n\n\t\t\t// support: IE<9, Opera in jQuery <1.7\n\t\t\t// .text() can't accept undefined, so coerce to a string\n\t\t\tvar title = $( this ).attr( \"title\" ) || \"\";\n\n\t\t\t// Escape title, since we're going from an attribute to raw HTML\n\t\t\treturn $( \"<a>\" ).text( title ).html();\n\t\t},\n\t\thide: true,\n\n\t\t// Disabled elements have inconsistent behavior across browsers (#8661)\n\t\titems: \"[title]:not([disabled])\",\n\t\tposition: {\n\t\t\tmy: \"left top+15\",\n\t\t\tat: \"left bottom\",\n\t\t\tcollision: \"flipfit flip\"\n\t\t},\n\t\tshow: true,\n\t\ttrack: false,\n\n\t\t// Callbacks\n\t\tclose: null,\n\t\topen: null\n\t},\n\n\t_addDescribedBy: function( elem, id ) {\n\t\tvar describedby = ( elem.attr( \"aria-describedby\" ) || \"\" ).split( /\\s+/ );\n\t\tdescribedby.push( id );\n\t\telem\n\t\t\t.data( \"ui-tooltip-id\", id )\n\t\t\t.attr( \"aria-describedby\", $.trim( describedby.join( \" \" ) ) );\n\t},\n\n\t_removeDescribedBy: function( elem ) {\n\t\tvar id = elem.data( \"ui-tooltip-id\" ),\n\t\t\tdescribedby = ( elem.attr( \"aria-describedby\" ) || \"\" ).split( /\\s+/ ),\n\t\t\tindex = $.inArray( id, describedby );\n\n\t\tif ( index !== -1 ) {\n\t\t\tdescribedby.splice( index, 1 );\n\t\t}\n\n\t\telem.removeData( \"ui-tooltip-id\" );\n\t\tdescribedby = $.trim( describedby.join( \" \" ) );\n\t\tif ( describedby ) {\n\t\t\telem.attr( \"aria-describedby\", describedby );\n\t\t} else {\n\t\t\telem.removeAttr( \"aria-describedby\" );\n\t\t}\n\t},\n\n\t_create: function() {\n\t\tthis._on( {\n\t\t\tmouseover: \"open\",\n\t\t\tfocusin: \"open\"\n\t\t} );\n\n\t\t// IDs of generated tooltips, needed for destroy\n\t\tthis.tooltips = {};\n\n\t\t// IDs of parent tooltips where we removed the title attribute\n\t\tthis.parents = {};\n\n\t\t// Append the aria-live region so tooltips announce correctly\n\t\tthis.liveRegion = $( \"<div>\" )\n\t\t\t.attr( {\n\t\t\t\trole: \"log\",\n\t\t\t\t\"aria-live\": \"assertive\",\n\t\t\t\t\"aria-relevant\": \"additions\"\n\t\t\t} )\n\t\t\t.appendTo( this.document[ 0 ].body );\n\t\tthis._addClass( this.liveRegion, null, \"ui-helper-hidden-accessible\" );\n\n\t\tthis.disabledTitles = $( [] );\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tvar that = this;\n\n\t\tthis._super( key, value );\n\n\t\tif ( key === \"content\" ) {\n\t\t\t$.each( this.tooltips, function( id, tooltipData ) {\n\t\t\t\tthat._updateContent( tooltipData.element );\n\t\t\t} );\n\t\t}\n\t},\n\n\t_setOptionDisabled: function( value ) {\n\t\tthis[ value ? \"_disable\" : \"_enable\" ]();\n\t},\n\n\t_disable: function() {\n\t\tvar that = this;\n\n\t\t// Close open tooltips\n\t\t$.each( this.tooltips, function( id, tooltipData ) {\n\t\t\tvar event = $.Event( \"blur\" );\n\t\t\tevent.target = event.currentTarget = tooltipData.element[ 0 ];\n\t\t\tthat.close( event, true );\n\t\t} );\n\n\t\t// Remove title attributes to prevent native tooltips\n\t\tthis.disabledTitles = this.disabledTitles.add(\n\t\t\tthis.element.find( this.options.items ).addBack()\n\t\t\t\t.filter( function() {\n\t\t\t\t\tvar element = $( this );\n\t\t\t\t\tif ( element.is( \"[title]\" ) ) {\n\t\t\t\t\t\treturn element\n\t\t\t\t\t\t\t.data( \"ui-tooltip-title\", element.attr( \"title\" ) )\n\t\t\t\t\t\t\t.removeAttr( \"title\" );\n\t\t\t\t\t}\n\t\t\t\t} )\n\t\t);\n\t},\n\n\t_enable: function() {\n\n\t\t// restore title attributes\n\t\tthis.disabledTitles.each( function() {\n\t\t\tvar element = $( this );\n\t\t\tif ( element.data( \"ui-tooltip-title\" ) ) {\n\t\t\t\telement.attr( \"title\", element.data( \"ui-tooltip-title\" ) );\n\t\t\t}\n\t\t} );\n\t\tthis.disabledTitles = $( [] );\n\t},\n\n\topen: function( event ) {\n\t\tvar that = this,\n\t\t\ttarget = $( event ? event.target : this.element )\n\n\t\t\t\t// we need closest here due to mouseover bubbling,\n\t\t\t\t// but always pointing at the same event target\n\t\t\t\t.closest( this.options.items );\n\n\t\t// No element to show a tooltip for or the tooltip is already open\n\t\tif ( !target.length || target.data( \"ui-tooltip-id\" ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( target.attr( \"title\" ) ) {\n\t\t\ttarget.data( \"ui-tooltip-title\", target.attr( \"title\" ) );\n\t\t}\n\n\t\ttarget.data( \"ui-tooltip-open\", true );\n\n\t\t// Kill parent tooltips, custom or native, for hover\n\t\tif ( event && event.type === \"mouseover\" ) {\n\t\t\ttarget.parents().each( function() {\n\t\t\t\tvar parent = $( this ),\n\t\t\t\t\tblurEvent;\n\t\t\t\tif ( parent.data( \"ui-tooltip-open\" ) ) {\n\t\t\t\t\tblurEvent = $.Event( \"blur\" );\n\t\t\t\t\tblurEvent.target = blurEvent.currentTarget = this;\n\t\t\t\t\tthat.close( blurEvent, true );\n\t\t\t\t}\n\t\t\t\tif ( parent.attr( \"title\" ) ) {\n\t\t\t\t\tparent.uniqueId();\n\t\t\t\t\tthat.parents[ this.id ] = {\n\t\t\t\t\t\telement: this,\n\t\t\t\t\t\ttitle: parent.attr( \"title\" )\n\t\t\t\t\t};\n\t\t\t\t\tparent.attr( \"title\", \"\" );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\tthis._registerCloseHandlers( event, target );\n\t\tthis._updateContent( target, event );\n\t},\n\n\t_updateContent: function( target, event ) {\n\t\tvar content,\n\t\t\tcontentOption = this.options.content,\n\t\t\tthat = this,\n\t\t\teventType = event ? event.type : null;\n\n\t\tif ( typeof contentOption === \"string\" || contentOption.nodeType ||\n\t\t\t\tcontentOption.jquery ) {\n\t\t\treturn this._open( event, target, contentOption );\n\t\t}\n\n\t\tcontent = contentOption.call( target[ 0 ], function( response ) {\n\n\t\t\t// IE may instantly serve a cached response for ajax requests\n\t\t\t// delay this call to _open so the other call to _open runs first\n\t\t\tthat._delay( function() {\n\n\t\t\t\t// Ignore async response if tooltip was closed already\n\t\t\t\tif ( !target.data( \"ui-tooltip-open\" ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// JQuery creates a special event for focusin when it doesn't\n\t\t\t\t// exist natively. To improve performance, the native event\n\t\t\t\t// object is reused and the type is changed. Therefore, we can't\n\t\t\t\t// rely on the type being correct after the event finished\n\t\t\t\t// bubbling, so we set it back to the previous value. (#8740)\n\t\t\t\tif ( event ) {\n\t\t\t\t\tevent.type = eventType;\n\t\t\t\t}\n\t\t\t\tthis._open( event, target, response );\n\t\t\t} );\n\t\t} );\n\t\tif ( content ) {\n\t\t\tthis._open( event, target, content );\n\t\t}\n\t},\n\n\t_open: function( event, target, content ) {\n\t\tvar tooltipData, tooltip, delayedShow, a11yContent,\n\t\t\tpositionOption = $.extend( {}, this.options.position );\n\n\t\tif ( !content ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Content can be updated multiple times. If the tooltip already\n\t\t// exists, then just update the content and bail.\n\t\ttooltipData = this._find( target );\n\t\tif ( tooltipData ) {\n\t\t\ttooltipData.tooltip.find( \".ui-tooltip-content\" ).html( content );\n\t\t\treturn;\n\t\t}\n\n\t\t// If we have a title, clear it to prevent the native tooltip\n\t\t// we have to check first to avoid defining a title if none exists\n\t\t// (we don't want to cause an element to start matching [title])\n\t\t//\n\t\t// We use removeAttr only for key events, to allow IE to export the correct\n\t\t// accessible attributes. For mouse events, set to empty string to avoid\n\t\t// native tooltip showing up (happens only when removing inside mouseover).\n\t\tif ( target.is( \"[title]\" ) ) {\n\t\t\tif ( event && event.type === \"mouseover\" ) {\n\t\t\t\ttarget.attr( \"title\", \"\" );\n\t\t\t} else {\n\t\t\t\ttarget.removeAttr( \"title\" );\n\t\t\t}\n\t\t}\n\n\t\ttooltipData = this._tooltip( target );\n\t\ttooltip = tooltipData.tooltip;\n\t\tthis._addDescribedBy( target, tooltip.attr( \"id\" ) );\n\t\ttooltip.find( \".ui-tooltip-content\" ).html( content );\n\n\t\t// Support: Voiceover on OS X, JAWS on IE <= 9\n\t\t// JAWS announces deletions even when aria-relevant=\"additions\"\n\t\t// Voiceover will sometimes re-read the entire log region's contents from the beginning\n\t\tthis.liveRegion.children().hide();\n\t\ta11yContent = $( \"<div>\" ).html( tooltip.find( \".ui-tooltip-content\" ).html() );\n\t\ta11yContent.removeAttr( \"name\" ).find( \"[name]\" ).removeAttr( \"name\" );\n\t\ta11yContent.removeAttr( \"id\" ).find( \"[id]\" ).removeAttr( \"id\" );\n\t\ta11yContent.appendTo( this.liveRegion );\n\n\t\tfunction position( event ) {\n\t\t\tpositionOption.of = event;\n\t\t\tif ( tooltip.is( \":hidden\" ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttooltip.position( positionOption );\n\t\t}\n\t\tif ( this.options.track && event && /^mouse/.test( event.type ) ) {\n\t\t\tthis._on( this.document, {\n\t\t\t\tmousemove: position\n\t\t\t} );\n\n\t\t\t// trigger once to override element-relative positioning\n\t\t\tposition( event );\n\t\t} else {\n\t\t\ttooltip.position( $.extend( {\n\t\t\t\tof: target\n\t\t\t}, this.options.position ) );\n\t\t}\n\n\t\ttooltip.hide();\n\n\t\tthis._show( tooltip, this.options.show );\n\n\t\t// Handle tracking tooltips that are shown with a delay (#8644). As soon\n\t\t// as the tooltip is visible, position the tooltip using the most recent\n\t\t// event.\n\t\t// Adds the check to add the timers only when both delay and track options are set (#14682)\n\t\tif ( this.options.track && this.options.show && this.options.show.delay ) {\n\t\t\tdelayedShow = this.delayedShow = setInterval( function() {\n\t\t\t\tif ( tooltip.is( \":visible\" ) ) {\n\t\t\t\t\tposition( positionOption.of );\n\t\t\t\t\tclearInterval( delayedShow );\n\t\t\t\t}\n\t\t\t}, $.fx.interval );\n\t\t}\n\n\t\tthis._trigger( \"open\", event, { tooltip: tooltip } );\n\t},\n\n\t_registerCloseHandlers: function( event, target ) {\n\t\tvar events = {\n\t\t\tkeyup: function( event ) {\n\t\t\t\tif ( event.keyCode === $.ui.keyCode.ESCAPE ) {\n\t\t\t\t\tvar fakeEvent = $.Event( event );\n\t\t\t\t\tfakeEvent.currentTarget = target[ 0 ];\n\t\t\t\t\tthis.close( fakeEvent, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t// Only bind remove handler for delegated targets. Non-delegated\n\t\t// tooltips will handle this in destroy.\n\t\tif ( target[ 0 ] !== this.element[ 0 ] ) {\n\t\t\tevents.remove = function() {\n\t\t\t\tthis._removeTooltip( this._find( target ).tooltip );\n\t\t\t};\n\t\t}\n\n\t\tif ( !event || event.type === \"mouseover\" ) {\n\t\t\tevents.mouseleave = \"close\";\n\t\t}\n\t\tif ( !event || event.type === \"focusin\" ) {\n\t\t\tevents.focusout = \"close\";\n\t\t}\n\t\tthis._on( true, target, events );\n\t},\n\n\tclose: function( event ) {\n\t\tvar tooltip,\n\t\t\tthat = this,\n\t\t\ttarget = $( event ? event.currentTarget : this.element ),\n\t\t\ttooltipData = this._find( target );\n\n\t\t// The tooltip may already be closed\n\t\tif ( !tooltipData ) {\n\n\t\t\t// We set ui-tooltip-open immediately upon open (in open()), but only set the\n\t\t\t// additional data once there's actually content to show (in _open()). So even if the\n\t\t\t// tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in\n\t\t\t// the period between open() and _open().\n\t\t\ttarget.removeData( \"ui-tooltip-open\" );\n\t\t\treturn;\n\t\t}\n\n\t\ttooltip = tooltipData.tooltip;\n\n\t\t// Disabling closes the tooltip, so we need to track when we're closing\n\t\t// to avoid an infinite loop in case the tooltip becomes disabled on close\n\t\tif ( tooltipData.closing ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Clear the interval for delayed tracking tooltips\n\t\tclearInterval( this.delayedShow );\n\n\t\t// Only set title if we had one before (see comment in _open())\n\t\t// If the title attribute has changed since open(), don't restore\n\t\tif ( target.data( \"ui-tooltip-title\" ) && !target.attr( \"title\" ) ) {\n\t\t\ttarget.attr( \"title\", target.data( \"ui-tooltip-title\" ) );\n\t\t}\n\n\t\tthis._removeDescribedBy( target );\n\n\t\ttooltipData.hiding = true;\n\t\ttooltip.stop( true );\n\t\tthis._hide( tooltip, this.options.hide, function() {\n\t\t\tthat._removeTooltip( $( this ) );\n\t\t} );\n\n\t\ttarget.removeData( \"ui-tooltip-open\" );\n\t\tthis._off( target, \"mouseleave focusout keyup\" );\n\n\t\t// Remove 'remove' binding only on delegated targets\n\t\tif ( target[ 0 ] !== this.element[ 0 ] ) {\n\t\t\tthis._off( target, \"remove\" );\n\t\t}\n\t\tthis._off( this.document, \"mousemove\" );\n\n\t\tif ( event && event.type === \"mouseleave\" ) {\n\t\t\t$.each( this.parents, function( id, parent ) {\n\t\t\t\t$( parent.element ).attr( \"title\", parent.title );\n\t\t\t\tdelete that.parents[ id ];\n\t\t\t} );\n\t\t}\n\n\t\ttooltipData.closing = true;\n\t\tthis._trigger( \"close\", event, { tooltip: tooltip } );\n\t\tif ( !tooltipData.hiding ) {\n\t\t\ttooltipData.closing = false;\n\t\t}\n\t},\n\n\t_tooltip: function( element ) {\n\t\tvar tooltip = $( \"<div>\" ).attr( \"role\", \"tooltip\" ),\n\t\t\tcontent = $( \"<div>\" ).appendTo( tooltip ),\n\t\t\tid = tooltip.uniqueId().attr( \"id\" );\n\n\t\tthis._addClass( content, \"ui-tooltip-content\" );\n\t\tthis._addClass( tooltip, \"ui-tooltip\", \"ui-widget ui-widget-content\" );\n\n\t\ttooltip.appendTo( this._appendTo( element ) );\n\n\t\treturn this.tooltips[ id ] = {\n\t\t\telement: element,\n\t\t\ttooltip: tooltip\n\t\t};\n\t},\n\n\t_find: function( target ) {\n\t\tvar id = target.data( \"ui-tooltip-id\" );\n\t\treturn id ? this.tooltips[ id ] : null;\n\t},\n\n\t_removeTooltip: function( tooltip ) {\n\t\ttooltip.remove();\n\t\tdelete this.tooltips[ tooltip.attr( \"id\" ) ];\n\t},\n\n\t_appendTo: function( target ) {\n\t\tvar element = target.closest( \".ui-front, dialog\" );\n\n\t\tif ( !element.length ) {\n\t\t\telement = this.document[ 0 ].body;\n\t\t}\n\n\t\treturn element;\n\t},\n\n\t_destroy: function() {\n\t\tvar that = this;\n\n\t\t// Close open tooltips\n\t\t$.each( this.tooltips, function( id, tooltipData ) {\n\n\t\t\t// Delegate to close method to handle common cleanup\n\t\t\tvar event = $.Event( \"blur\" ),\n\t\t\t\telement = tooltipData.element;\n\t\t\tevent.target = event.currentTarget = element[ 0 ];\n\t\t\tthat.close( event, true );\n\n\t\t\t// Remove immediately; destroying an open tooltip doesn't use the\n\t\t\t// hide animation\n\t\t\t$( \"#\" + id ).remove();\n\n\t\t\t// Restore the title\n\t\t\tif ( element.data( \"ui-tooltip-title\" ) ) {\n\n\t\t\t\t// If the title attribute has changed since open(), don't restore\n\t\t\t\tif ( !element.attr( \"title\" ) ) {\n\t\t\t\t\telement.attr( \"title\", element.data( \"ui-tooltip-title\" ) );\n\t\t\t\t}\n\t\t\t\telement.removeData( \"ui-tooltip-title\" );\n\t\t\t}\n\t\t} );\n\t\tthis.liveRegion.remove();\n\t}\n} );\n\n// DEPRECATED\n// TODO: Switch return back to widget declaration at top of file when this is removed\nif ( $.uiBackCompat !== false ) {\n\n\t// Backcompat for tooltipClass option\n\t$.widget( \"ui.tooltip\", $.ui.tooltip, {\n\t\toptions: {\n\t\t\ttooltipClass: null\n\t\t},\n\t\t_tooltip: function() {\n\t\t\tvar tooltipData = this._superApply( arguments );\n\t\t\tif ( this.options.tooltipClass ) {\n\t\t\t\ttooltipData.tooltip.addClass( this.options.tooltipClass );\n\t\t\t}\n\t\t\treturn tooltipData;\n\t\t}\n\t} );\n}\n\nvar widgetsTooltip = $.ui.tooltip;\n\n\n\n\n}));"
  },
  {
    "path": "lib/jquery.fancytree.filter.js",
    "content": "/*!\n * jquery.fancytree.filter.js\n *\n * Remove or highlight tree nodes, based on a filter.\n * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/)\n *\n * Copyright (c) 2008-2017, Martin Wendt (http://wwWendt.de)\n *\n * Released under the MIT license\n * https://github.com/mar10/fancytree/wiki/LicenseInfo\n *\n * @version @VERSION\n * @date @DATE\n */\n\n;(function( factory ) {\n\tif ( typeof define === \"function\" && define.amd ) {\n\t\t// AMD. Register as an anonymous module.\n\t\tdefine( [ \"jquery\", \"./jquery.fancytree\" ], factory );\n\t} else if ( typeof module === \"object\" && module.exports ) {\n\t\t// Node/CommonJS\n\t\trequire(\"./jquery.fancytree\");\n\t\tmodule.exports = factory(require(\"jquery\"));\n\t} else {\n\t\t// Browser globals\n\t\tfactory( jQuery );\n\t}\n\n}( function( $ ) {\n\n\"use strict\";\n\n\n/*******************************************************************************\n * Private functions and variables\n */\n\nvar KeyNoData = \"__not_found__\",\n\tescapeHtml = $.ui.fancytree.escapeHtml;\n\nfunction _escapeRegex(str){\n\t/*jshint regexdash:true */\n\treturn (str + \"\").replace(/([.?*+\\^\\$\\[\\]\\\\(){}|-])/g, \"\\\\$1\");\n}\n\nfunction extractHtmlText(s){\n\tif( s.indexOf(\">\") >= 0 ) {\n\t\treturn $(\"<div/>\").html(s).text();\n\t}\n\treturn s;\n}\n\n$.ui.fancytree._FancytreeClass.prototype._applyFilterImpl = function(filter, branchMode, _opts){\n\tvar match, statusNode, re, reHighlight, temp,\n\t\tcount = 0,\n\t\ttreeOpts = this.options,\n\t\tescapeTitles = treeOpts.escapeTitles,\n\t\tprevAutoCollapse = treeOpts.autoCollapse,\n\t\topts = $.extend({}, treeOpts.filter, _opts),\n\t\thideMode = opts.mode === \"hide\",\n\t\tleavesOnly = !!opts.leavesOnly && !branchMode;\n\n\t// Default to 'match title substring (not case sensitive)'\n\tif(typeof filter === \"string\"){\n\t\tif( filter === \"\" ) {\n\t\t\tthis.warn(\"Fancytree passing an empty string as a filter is handled as clearFilter().\");\n\t\t\tthis.clearFilter();\n\t\t\treturn;\n\t\t}\n\t\tif( opts.fuzzy ) {\n\t\t\t// See https://codereview.stackexchange.com/questions/23899/faster-javascript-fuzzy-string-matching-function/23905#23905\n\t\t\t// and http://www.quora.com/How-is-the-fuzzy-search-algorithm-in-Sublime-Text-designed\n\t\t\t// and http://www.dustindiaz.com/autocomplete-fuzzy-matching\n\t\t\tmatch = filter.split(\"\").reduce(function(a, b) {\n\t\t\t\treturn a + \"[^\" + b + \"]*\" + b;\n\t\t\t});\n\t\t} else {\n\t\t\tmatch = _escapeRegex(filter); // make sure a '.' is treated literally\n\t\t}\n\t\tre = new RegExp(\".*\" + match + \".*\", \"i\");\n\t\treHighlight = new RegExp(_escapeRegex(filter), \"gi\");\n\t\tfilter = function(node){\n\t\t\tvar text = escapeTitles ? node.title : extractHtmlText(node.title),\n\t\t\t\tres = !!re.test(text);\n\n\t\t\tif( res && opts.highlight ) {\n\t\t\t\tif( escapeTitles ) {\n\t\t\t\t\t// #740: we must not apply the marks to escaped entity names, e.g. `&quot;`\n\t\t\t\t\t// Use some exotic characters to mark matches:\n\t\t\t\t\ttemp = text.replace(reHighlight, function(s){\n\t\t\t\t\t\treturn \"\\uFFF7\" + s + \"\\uFFF8\";\n\t\t\t\t\t});\n\t\t\t\t\t// now we can escape the title...\n\t\t\t\t\tnode.titleWithHighlight = escapeHtml(temp)\n\t\t\t\t\t\t// ... and finally insert the desired `<mark>` tags\n\t\t\t\t\t\t.replace(/\\uFFF7/g, \"<mark>\")\n\t\t\t\t\t\t.replace(/\\uFFF8/g, \"</mark>\");\n\t\t\t\t} else {\n\t\t\t\t\tnode.titleWithHighlight = text.replace(reHighlight, function(s){\n\t\t\t\t\t\treturn \"<mark>\" + s + \"</mark>\";\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t// node.debug(\"filter\", escapeTitles, text, node.titleWithHighlight);\n\t\t\t}\n\t\t\treturn res;\n\t\t};\n\t}\n\n\tthis.enableFilter = true;\n\tthis.lastFilterArgs = arguments;\n\n\tthis.$div.addClass(\"fancytree-ext-filter\");\n\tif( hideMode ){\n\t\tthis.$div.addClass(\"fancytree-ext-filter-hide\");\n\t} else {\n\t\tthis.$div.addClass(\"fancytree-ext-filter-dimm\");\n\t}\n\tthis.$div.toggleClass(\"fancytree-ext-filter-hide-expanders\", !!opts.hideExpanders);\n\t// Reset current filter\n\tthis.visit(function(node){\n\t\tdelete node.match;\n\t\tdelete node.titleWithHighlight;\n\t\tnode.subMatchCount = 0;\n\t});\n\tstatusNode = this.getRootNode()._findDirectChild(KeyNoData);\n\tif( statusNode ) {\n\t\tstatusNode.remove();\n\t}\n\n\t// Adjust node.hide, .match, and .subMatchCount properties\n\ttreeOpts.autoCollapse = false;  // #528\n\n\tthis.visit(function(node){\n\t\tif ( leavesOnly && node.children != null ) {\n\t\t\treturn;\n\t\t}\n\t\tvar res = filter(node),\n\t\t\tmatchedByBranch = false;\n\n\t\tif( res === \"skip\" ) {\n\t\t\tnode.visit(function(c){\n\t\t\t\tc.match = false;\n\t\t\t}, true);\n\t\t\treturn \"skip\";\n\t\t}\n\t\tif( !res && (branchMode || res === \"branch\") && node.parent.match ) {\n\t\t\tres = true;\n\t\t\tmatchedByBranch = true;\n\t\t}\n\t\tif( res ) {\n\t\t\tcount++;\n\t\t\tnode.match = true;\n\t\t\tnode.visitParents(function(p){\n\t\t\t\tp.subMatchCount += 1;\n\t\t\t\t// Expand match (unless this is no real match, but only a node in a matched branch)\n\t\t\t\tif( opts.autoExpand && !matchedByBranch && !p.expanded ) {\n\t\t\t\t\tp.setExpanded(true, {noAnimation: true, noEvents: true, scrollIntoView: false});\n\t\t\t\t\tp._filterAutoExpanded = true;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\ttreeOpts.autoCollapse = prevAutoCollapse;\n\n\tif( count === 0 && opts.nodata && hideMode ) {\n\t\tstatusNode = opts.nodata;\n\t\tif( $.isFunction(statusNode) ) {\n\t\t\tstatusNode = statusNode();\n\t\t}\n\t\tif( statusNode === true ) {\n\t\t\tstatusNode = {};\n\t\t} else if( typeof statusNode === \"string\" ) {\n\t\t\tstatusNode = { title: statusNode };\n\t\t}\n\t\tstatusNode = $.extend({\n\t\t\tstatusNodeType: \"nodata\",\n\t\t\tkey: KeyNoData,\n\t\t\ttitle: this.options.strings.noData\n\t\t}, statusNode);\n\n\t\tthis.getRootNode().addNode(statusNode).match = true;\n\t}\n\t// Redraw whole tree\n\tthis.render();\n\treturn count;\n};\n\n/**\n * [ext-filter] Dimm or hide nodes.\n *\n * @param {function | string} filter\n * @param {boolean} [opts={autoExpand: false, leavesOnly: false}]\n * @returns {integer} count\n * @alias Fancytree#filterNodes\n * @requires jquery.fancytree.filter.js\n */\n$.ui.fancytree._FancytreeClass.prototype.filterNodes = function(filter, opts) {\n\tif( typeof opts === \"boolean\" ) {\n\t\topts = { leavesOnly: opts };\n\t\tthis.warn(\"Fancytree.filterNodes() leavesOnly option is deprecated since 2.9.0 / 2015-04-19. Use opts.leavesOnly instead.\");\n\t}\n\treturn this._applyFilterImpl(filter, false, opts);\n};\n\n/**\n * @deprecated\n */\n$.ui.fancytree._FancytreeClass.prototype.applyFilter = function(filter){\n\tthis.warn(\"Fancytree.applyFilter() is deprecated since 2.1.0 / 2014-05-29. Use .filterNodes() instead.\");\n\treturn this.filterNodes.apply(this, arguments);\n};\n\n/**\n * [ext-filter] Dimm or hide whole branches.\n *\n * @param {function | string} filter\n * @param {boolean} [opts={autoExpand: false}]\n * @returns {integer} count\n * @alias Fancytree#filterBranches\n * @requires jquery.fancytree.filter.js\n */\n$.ui.fancytree._FancytreeClass.prototype.filterBranches = function(filter, opts){\n\treturn this._applyFilterImpl(filter, true, opts);\n};\n\n\n/**\n * [ext-filter] Reset the filter.\n *\n * @alias Fancytree#clearFilter\n * @requires jquery.fancytree.filter.js\n */\n$.ui.fancytree._FancytreeClass.prototype.clearFilter = function(){\n\tvar $title,\n\t\tstatusNode = this.getRootNode()._findDirectChild(KeyNoData),\n\t\tescapeTitles = this.options.escapeTitles,\n\t\tenhanceTitle = this.options.enhanceTitle;\n\n\tif( statusNode ) {\n\t\tstatusNode.remove();\n\t}\n\tthis.visit(function(node){\n\t\tif( node.match && node.span ) {  // #491, #601\n\t\t\t$title = $(node.span).find(\">span.fancytree-title\");\n\t\t\tif( escapeTitles ) {\n\t\t\t\t$title.text(node.title);\n\t\t\t} else {\n\t\t\t\t$title.html(node.title);\n\t\t\t}\n\t\t\tif( enhanceTitle ) {\n\t\t\t\tenhanceTitle({type: \"enhanceTitle\"}, {node: node, $title: $title});\n\t\t\t}\n\t\t}\n\t\tdelete node.match;\n\t\tdelete node.subMatchCount;\n\t\tdelete node.titleWithHighlight;\n\t\tif ( node.$subMatchBadge ) {\n\t\t\tnode.$subMatchBadge.remove();\n\t\t\tdelete node.$subMatchBadge;\n\t\t}\n\t\tif( node._filterAutoExpanded && node.expanded ) {\n\t\t\tnode.setExpanded(false, {noAnimation: true, noEvents: true, scrollIntoView: false});\n\t\t}\n\t\tdelete node._filterAutoExpanded;\n\t});\n\tthis.enableFilter = false;\n\tthis.lastFilterArgs = null;\n\tthis.$div.removeClass(\"fancytree-ext-filter fancytree-ext-filter-dimm fancytree-ext-filter-hide\");\n\tthis.render();\n};\n\n\n/**\n * [ext-filter] Return true if a filter is currently applied.\n *\n * @returns {Boolean}\n * @alias Fancytree#isFilterActive\n * @requires jquery.fancytree.filter.js\n * @since 2.13\n */\n$.ui.fancytree._FancytreeClass.prototype.isFilterActive = function(){\n\treturn !!this.enableFilter;\n};\n\n\n/**\n * [ext-filter] Return true if this node is matched by current filter (or no filter is active).\n *\n * @returns {Boolean}\n * @alias FancytreeNode#isMatched\n * @requires jquery.fancytree.filter.js\n * @since 2.13\n */\n$.ui.fancytree._FancytreeNodeClass.prototype.isMatched = function(){\n\treturn !(this.tree.enableFilter && !this.match);\n};\n\n\n/*******************************************************************************\n * Extension code\n */\n$.ui.fancytree.registerExtension({\n\tname: \"filter\",\n\tversion: \"@VERSION\",\n\t// Default options for this extension.\n\toptions: {\n\t\tautoApply: true,   // Re-apply last filter if lazy data is loaded\n\t\tautoExpand: false, // Expand all branches that contain matches while filtered\n\t\tcounter: true,     // Show a badge with number of matching child nodes near parent icons\n\t\tfuzzy: false,      // Match single characters in order, e.g. 'fb' will match 'FooBar'\n\t\thideExpandedCounter: true,  // Hide counter badge if parent is expanded\n\t\thideExpanders: false,       // Hide expanders if all child nodes are hidden by filter\n\t\thighlight: true,   // Highlight matches by wrapping inside <mark> tags\n\t\tleavesOnly: false, // Match end nodes only\n\t\tnodata: true,      // Display a 'no data' status node if result is empty\n\t\tmode: \"dimm\"       // Grayout unmatched nodes (pass \"hide\" to remove unmatched node instead)\n\t},\n\tnodeLoadChildren: function(ctx, source) {\n\t\treturn this._superApply(arguments).done(function() {\n\t\t\tif( ctx.tree.enableFilter && ctx.tree.lastFilterArgs && ctx.options.filter.autoApply ) {\n\t\t\t\tctx.tree._applyFilterImpl.apply(ctx.tree, ctx.tree.lastFilterArgs);\n\t\t\t}\n\t\t});\n\t},\n\tnodeSetExpanded: function(ctx, flag, callOpts) {\n\t\tdelete ctx.node._filterAutoExpanded;\n\t\t// Make sure counter badge is displayed again, when node is beeing collapsed\n\t\tif( !flag && ctx.options.filter.hideExpandedCounter && ctx.node.$subMatchBadge ) {\n\t\t\tctx.node.$subMatchBadge.show();\n\t\t}\n\t\treturn this._superApply(arguments);\n\t},\n\tnodeRenderStatus: function(ctx) {\n\t\t// Set classes for current status\n\t\tvar res,\n\t\t\tnode = ctx.node,\n\t\t\ttree = ctx.tree,\n\t\t\topts = ctx.options.filter,\n\t\t\t$title = $(node.span).find(\"span.fancytree-title\"),\n\t\t\t$span = $(node[tree.statusClassPropName]),\n\t\t\tenhanceTitle = ctx.options.enhanceTitle,\n\t\t\tescapeTitles = ctx.options.escapeTitles;\n\n\t\tres = this._super(ctx);\n\t\t// nothing to do, if node was not yet rendered\n\t\tif( !$span.length || !tree.enableFilter ) {\n\t\t\treturn res;\n\t\t}\n\t\t$span\n\t\t\t.toggleClass(\"fancytree-match\", !!node.match)\n\t\t\t.toggleClass(\"fancytree-submatch\", !!node.subMatchCount)\n\t\t\t.toggleClass(\"fancytree-hide\", !(node.match || node.subMatchCount));\n\t\t// Add/update counter badge\n\t\tif( opts.counter && node.subMatchCount && (!node.isExpanded() || !opts.hideExpandedCounter) ) {\n\t\t\tif( !node.$subMatchBadge ) {\n\t\t\t\tnode.$subMatchBadge = $(\"<span class='fancytree-childcounter'/>\");\n\t\t\t\t$(\"span.fancytree-icon, span.fancytree-custom-icon\", node.span).append(node.$subMatchBadge);\n\t\t\t}\n\t\t\tnode.$subMatchBadge.show().text(node.subMatchCount);\n\t\t} else if ( node.$subMatchBadge ) {\n\t\t\tnode.$subMatchBadge.hide();\n\t\t}\n\t\t// node.debug(\"nodeRenderStatus\", node.titleWithHighlight, node.title)\n\t\t// #601: also chek for $title.length, because we don't need to render\n\t\t// if node.span is null (i.e. not rendered)\n\t\tif( node.span && (!node.isEditing || !node.isEditing.call(node)) ) {\n\t\t\tif( node.titleWithHighlight ) {\n\t\t\t\t$title.html(node.titleWithHighlight);\n\t\t\t} else if ( escapeTitles ) {\n\t\t\t\t$title.text(node.title);\n\t\t\t} else {\n\t\t\t\t$title.html(node.title);\n\t\t\t}\n\t\t\tif( enhanceTitle ) {\n\t\t\t\tenhanceTitle({type: \"enhanceTitle\"}, {node: node, $title: $title});\n\t\t\t}\n\t\t}\n\t\treturn res;\n\t}\n});\n// Value returned by `require('jquery.fancytree..')`\nreturn $.ui.fancytree;\n}));  // End of closure\n"
  },
  {
    "path": "lib/jquery.fancytree.js",
    "content": "/*!\n * jquery.fancytree.js\n * Tree view control with support for lazy loading and much more.\n * https://github.com/mar10/fancytree/\n *\n * Copyright (c) 2008-2017, Martin Wendt (http://wwWendt.de)\n * Released under the MIT license\n * https://github.com/mar10/fancytree/wiki/LicenseInfo\n *\n * @version @VERSION\n * @date @DATE\n */\n\n/** Core Fancytree module.\n */\n\n\n// Start of local namespace\n;(function($, window, document, undefined) {\n\"use strict\";\n\n// prevent duplicate loading\nif ( $.ui && $.ui.fancytree ) {\n\t$.ui.fancytree.warn(\"Fancytree: ignored duplicate include\");\n\treturn;\n}\n\n\n/* *****************************************************************************\n * Private functions and variables\n */\n\nvar i, attr,\n\tFT = null, // initialized below\n\tTEST_IMG = new RegExp(/\\.|\\//),  // strings are considered image urls if they conatin '.' or '/'\n\tREX_HTML = /[&<>\"'\\/]/g,\n\tREX_TOOLTIP = /[<>\"'\\/]/g,\n\tRECURSIVE_REQUEST_ERROR = \"$recursive_request\",\n\tENTITY_MAP = {\"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\", \"\\\"\": \"&quot;\", \"'\": \"&#39;\", \"/\": \"&#x2F;\"},\n\tIGNORE_KEYCODES = { 16: true, 17: true, 18: true },\n\tSPECIAL_KEYCODES = {\n\t\t8: \"backspace\", 9: \"tab\", 10: \"return\", 13: \"return\",\n\t\t// 16: null, 17: null, 18: null, // ignore shift, ctrl, alt\n\t\t19: \"pause\", 20: \"capslock\", 27: \"esc\", 32: \"space\", 33: \"pageup\",\n\t\t34: \"pagedown\", 35: \"end\", 36: \"home\", 37: \"left\", 38: \"up\",\n\t\t39: \"right\", 40: \"down\", 45: \"insert\", 46: \"del\", 59: \";\", 61: \"=\",\n\t\t96: \"0\", 97: \"1\", 98: \"2\", 99: \"3\", 100: \"4\", 101: \"5\", 102: \"6\",\n\t\t103: \"7\", 104: \"8\", 105: \"9\", 106: \"*\", 107: \"+\", 109: \"-\", 110: \".\",\n\t\t111: \"/\", 112: \"f1\", 113: \"f2\", 114: \"f3\", 115: \"f4\", 116: \"f5\",\n\t\t117: \"f6\", 118: \"f7\", 119: \"f8\", 120: \"f9\", 121: \"f10\", 122: \"f11\",\n\t\t123: \"f12\", 144: \"numlock\", 145: \"scroll\", 173: \"-\", 186: \";\", 187: \"=\",\n\t\t188: \",\", 189: \"-\", 190: \".\", 191: \"/\", 192: \"`\", 219: \"[\", 220: \"\\\\\",\n\t\t221: \"]\", 222: \"'\"},\n\tMOUSE_BUTTONS = { 0: \"\", 1: \"left\", 2: \"middle\", 3: \"right\" },\n\t// Boolean attributes that can be set with equivalent class names in the LI tags\n\tCLASS_ATTRS = \"active expanded focus folder hideCheckbox lazy selected unselectable\".split(\" \"),\n\tCLASS_ATTR_MAP = {},\n\t// Top-level Fancytree node attributes, that can be set by dict\n\tNODE_ATTRS = \"expanded extraClasses folder hideCheckbox icon key lazy refKey selected statusNodeType title tooltip unselectable\".split(\" \"),\n\tNODE_ATTR_MAP = {},\n\t// Mapping of lowercase -> real name (because HTML5 data-... attribute only supports lowercase)\n\tNODE_ATTR_LOWERCASE_MAP = {},\n\t// Attribute names that should NOT be added to node.data\n\tNONE_NODE_DATA_MAP = {\"active\": true, \"children\": true, \"data\": true, \"focus\": true};\n\nfor(i=0; i<CLASS_ATTRS.length; i++){ CLASS_ATTR_MAP[CLASS_ATTRS[i]] = true; }\nfor(i=0; i<NODE_ATTRS.length; i++) {\n\tattr = NODE_ATTRS[i];\n\tNODE_ATTR_MAP[attr] = true;\n\tif( attr !== attr.toLowerCase() ) {\n\t\tNODE_ATTR_LOWERCASE_MAP[attr.toLowerCase()] = attr;\n\t}\n}\n\n\nfunction _assert(cond, msg){\n\t// TODO: see qunit.js extractStacktrace()\n\tif(!cond){\n\t\tmsg = msg ? \": \" + msg : \"\";\n\t\t// consoleApply(\"assert\", [!!cond, msg]);\n\t\t$.error(\"Fancytree assertion failed\" + msg);\n\t}\n}\n\n_assert($.ui, \"Fancytree requires jQuery UI (http://jqueryui.com)\");\n\nfunction consoleApply(method, args){\n\tvar i, s,\n\t\tfn = window.console ? window.console[method] : null;\n\n\tif(fn){\n\t\ttry{\n\t\t\tfn.apply(window.console, args);\n\t\t} catch(e) {\n\t\t\t// IE 8?\n\t\t\ts = \"\";\n\t\t\tfor( i=0; i<args.length; i++ ) {\n\t\t\t\ts += args[i];\n\t\t\t}\n\t\t\tfn(s);\n\t\t}\n\t}\n}\n\n/*Return true if x is a FancytreeNode.*/\nfunction _isNode(x){\n\treturn !!(x.tree && x.statusNodeType !== undefined);\n}\n\n/** Return true if dotted version string is equal or higher than requested version.\n *\n * See http://jsfiddle.net/mar10/FjSAN/\n */\nfunction isVersionAtLeast(dottedVersion, major, minor, patch){\n\tvar i, v, t,\n\t\tverParts = $.map($.trim(dottedVersion).split(\".\"), function(e){ return parseInt(e, 10); }),\n\t\ttestParts = $.map(Array.prototype.slice.call(arguments, 1), function(e){ return parseInt(e, 10); });\n\n\tfor( i = 0; i < testParts.length; i++ ){\n\t\tv = verParts[i] || 0;\n\t\tt = testParts[i] || 0;\n\t\tif( v !== t ){\n\t\t\treturn ( v > t );\n\t\t}\n\t}\n\treturn true;\n}\n\n/** Return a wrapper that calls sub.methodName() and exposes\n *  this             : tree\n *  this._local      : tree.ext.EXTNAME\n *  this._super      : base.methodName.call()\n *  this._superApply : base.methodName.apply()\n */\nfunction _makeVirtualFunction(methodName, tree, base, extension, extName){\n\t// $.ui.fancytree.debug(\"_makeVirtualFunction\", methodName, tree, base, extension, extName);\n\t// if(rexTestSuper && !rexTestSuper.test(func)){\n\t//     // extension.methodName() doesn't call _super(), so no wrapper required\n\t//     return func;\n\t// }\n\t// Use an immediate function as closure\n\tvar proxy = (function(){\n\t\tvar prevFunc = tree[methodName],      // org. tree method or prev. proxy\n\t\t\tbaseFunc = extension[methodName], //\n\t\t\t_local = tree.ext[extName],\n\t\t\t_super = function(){\n\t\t\t\treturn prevFunc.apply(tree, arguments);\n\t\t\t},\n\t\t\t_superApply = function(args){\n\t\t\t\treturn prevFunc.apply(tree, args);\n\t\t\t};\n\n\t\t// Return the wrapper function\n\t\treturn function(){\n\t\t\tvar prevLocal = tree._local,\n\t\t\t\tprevSuper = tree._super,\n\t\t\t\tprevSuperApply = tree._superApply;\n\n\t\t\ttry{\n\t\t\t\ttree._local = _local;\n\t\t\t\ttree._super = _super;\n\t\t\t\ttree._superApply = _superApply;\n\t\t\t\treturn  baseFunc.apply(tree, arguments);\n\t\t\t}finally{\n\t\t\t\ttree._local = prevLocal;\n\t\t\t\ttree._super = prevSuper;\n\t\t\t\ttree._superApply = prevSuperApply;\n\t\t\t}\n\t\t};\n\t})(); // end of Immediate Function\n\treturn proxy;\n}\n\n/**\n * Subclass `base` by creating proxy functions\n */\nfunction _subclassObject(tree, base, extension, extName){\n\t// $.ui.fancytree.debug(\"_subclassObject\", tree, base, extension, extName);\n\tfor(var attrName in extension){\n\t\tif(typeof extension[attrName] === \"function\"){\n\t\t\tif(typeof tree[attrName] === \"function\"){\n\t\t\t\t// override existing method\n\t\t\t\ttree[attrName] = _makeVirtualFunction(attrName, tree, base, extension, extName);\n\t\t\t}else if(attrName.charAt(0) === \"_\"){\n\t\t\t\t// Create private methods in tree.ext.EXTENSION namespace\n\t\t\t\ttree.ext[extName][attrName] = _makeVirtualFunction(attrName, tree, base, extension, extName);\n\t\t\t}else{\n\t\t\t\t$.error(\"Could not override tree.\" + attrName + \". Use prefix '_' to create tree.\" + extName + \"._\" + attrName);\n\t\t\t}\n\t\t}else{\n\t\t\t// Create member variables in tree.ext.EXTENSION namespace\n\t\t\tif(attrName !== \"options\"){\n\t\t\t\ttree.ext[extName][attrName] = extension[attrName];\n\t\t\t}\n\t\t}\n\t}\n}\n\n\nfunction _getResolvedPromise(context, argArray){\n\tif(context === undefined){\n\t\treturn $.Deferred(function(){this.resolve();}).promise();\n\t}else{\n\t\treturn $.Deferred(function(){this.resolveWith(context, argArray);}).promise();\n\t}\n}\n\n\nfunction _getRejectedPromise(context, argArray){\n\tif(context === undefined){\n\t\treturn $.Deferred(function(){this.reject();}).promise();\n\t}else{\n\t\treturn $.Deferred(function(){this.rejectWith(context, argArray);}).promise();\n\t}\n}\n\n\nfunction _makeResolveFunc(deferred, context){\n\treturn function(){\n\t\tdeferred.resolveWith(context);\n\t};\n}\n\n\nfunction _getElementDataAsDict($el){\n\t// Evaluate 'data-NAME' attributes with special treatment for 'data-json'.\n\tvar d = $.extend({}, $el.data()),\n\t\tjson = d.json;\n\n\tdelete d.fancytree; // added to container by widget factory (old jQuery UI)\n\tdelete d.uiFancytree; // added to container by widget factory\n\n\tif( json ) {\n\t\tdelete d.json;\n\t\t// <li data-json='...'> is already returned as object (http://api.jquery.com/data/#data-html5)\n\t\td = $.extend(d, json);\n\t}\n\treturn d;\n}\n\n\nfunction _escapeHtml(s){\n\treturn (\"\" + s).replace(REX_HTML, function(s) {\n\t\treturn ENTITY_MAP[s];\n\t});\n}\n\n\nfunction _escapeTooltip(s){\n\treturn (\"\" + s).replace(REX_TOOLTIP, function(s) {\n\t\treturn ENTITY_MAP[s];\n\t});\n}\n\n\n// TODO: use currying\nfunction _makeNodeTitleMatcher(s){\n\ts = s.toLowerCase();\n\treturn function(node){\n\t\treturn node.title.toLowerCase().indexOf(s) >= 0;\n\t};\n}\n\n\nfunction _makeNodeTitleStartMatcher(s){\n\tvar reMatch = new RegExp(\"^\" + s, \"i\");\n\treturn function(node){\n\t\treturn reMatch.test(node.title);\n\t};\n}\n\n\n/* *****************************************************************************\n * FancytreeNode\n */\n\n\n/**\n * Creates a new FancytreeNode\n *\n * @class FancytreeNode\n * @classdesc A FancytreeNode represents the hierarchical data model and operations.\n *\n * @param {FancytreeNode} parent\n * @param {NodeData} obj\n *\n * @property {Fancytree} tree The tree instance\n * @property {FancytreeNode} parent The parent node\n * @property {string} key Node id (must be unique inside the tree)\n * @property {string} title Display name (may contain HTML)\n * @property {object} data Contains all extra data that was passed on node creation\n * @property {FancytreeNode[] | null | undefined} children Array of child nodes.<br>\n *     For lazy nodes, null or undefined means 'not yet loaded'. Use an empty array\n *     to define a node that has no children.\n * @property {boolean} expanded Use isExpanded(), setExpanded() to access this property.\n * @property {string} extraClasses Additional CSS classes, added to the node's `&lt;span>`.<br>\n *     Note: use `node.add/remove/toggleClass()` to modify.\n * @property {boolean} folder Folder nodes have different default icons and click behavior.<br>\n *     Note: Also non-folders may have children.\n * @property {string} statusNodeType null for standard nodes. Otherwise type of special system node: 'error', 'loading', 'nodata', or 'paging'.\n * @property {boolean} lazy True if this node is loaded on demand, i.e. on first expansion.\n * @property {boolean} selected Use isSelected(), setSelected() to access this property.\n * @property {string} tooltip Alternative description used as hover popup\n */\nfunction FancytreeNode(parent, obj){\n\tvar i, l, name, cl;\n\n\tthis.parent = parent;\n\tthis.tree = parent.tree;\n\tthis.ul = null;\n\tthis.li = null;  // <li id='key' ftnode=this> tag\n\tthis.statusNodeType = null; // if this is a temp. node to display the status of its parent\n\tthis._isLoading = false;    // if this node itself is loading\n\tthis._error = null;         // {message: '...'} if a load error occurred\n\tthis.data = {};\n\n\t// TODO: merge this code with node.toDict()\n\t// copy attributes from obj object\n\tfor(i=0, l=NODE_ATTRS.length; i<l; i++){\n\t\tname = NODE_ATTRS[i];\n\t\tthis[name] = obj[name];\n\t}\n\t// node.data += obj.data\n\tif(obj.data){\n\t\t$.extend(this.data, obj.data);\n\t}\n\t// copy all other attributes to this.data.NAME\n\tfor(name in obj){\n\t\tif(!NODE_ATTR_MAP[name] && !$.isFunction(obj[name]) && !NONE_NODE_DATA_MAP[name]){\n\t\t\t// node.data.NAME = obj.NAME\n\t\t\tthis.data[name] = obj[name];\n\t\t}\n\t}\n\n\t// Fix missing key\n\tif( this.key == null ){ // test for null OR undefined\n\t\tif( this.tree.options.defaultKey ) {\n\t\t\tthis.key = this.tree.options.defaultKey(this);\n\t\t\t_assert(this.key, \"defaultKey() must return a unique key\");\n\t\t} else {\n\t\t\tthis.key = \"_\" + (FT._nextNodeKey++);\n\t\t}\n\t} else {\n\t\tthis.key = \"\" + this.key; // Convert to string (#217)\n\t}\n\n\t// Fix tree.activeNode\n\t// TODO: not elegant: we use obj.active as marker to set tree.activeNode\n\t// when loading from a dictionary.\n\tif(obj.active){\n\t\t_assert(this.tree.activeNode === null, \"only one active node allowed\");\n\t\tthis.tree.activeNode = this;\n\t}\n\tif( obj.selected ){ // #186\n\t\tthis.tree.lastSelectedNode = this;\n\t}\n\t// TODO: handle obj.focus = true\n\t// Create child nodes\n\tcl = obj.children;\n\tif( cl ){\n\t\tif( cl.length ){\n\t\t\tthis._setChildren(cl);\n\t\t} else {\n\t\t\t// if an empty array was passed for a lazy node, keep it, in order to mark it 'loaded'\n\t\t\tthis.children = this.lazy ? [] : null;\n\t\t}\n\t} else {\n\t\tthis.children = null;\n\t}\n\t// Add to key/ref map (except for root node)\n//\tif( parent ) {\n\tthis.tree._callHook(\"treeRegisterNode\", this.tree, true, this);\n//\t}\n}\n\n\nFancytreeNode.prototype = /** @lends FancytreeNode# */{\n\t/* Return the direct child FancytreeNode with a given key, index. */\n\t_findDirectChild: function(ptr){\n\t\tvar i, l,\n\t\t\tcl = this.children;\n\n\t\tif(cl){\n\t\t\tif(typeof ptr === \"string\"){\n\t\t\t\tfor(i=0, l=cl.length; i<l; i++){\n\t\t\t\t\tif(cl[i].key === ptr){\n\t\t\t\t\t\treturn cl[i];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}else if(typeof ptr === \"number\"){\n\t\t\t\treturn this.children[ptr];\n\t\t\t}else if(ptr.parent === this){\n\t\t\t\treturn ptr;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t},\n\t// TODO: activate()\n\t// TODO: activateSilently()\n\t/* Internal helper called in recursive addChildren sequence.*/\n\t_setChildren: function(children){\n\t\t_assert(children && (!this.children || this.children.length === 0), \"only init supported\");\n\t\tthis.children = [];\n\t\tfor(var i=0, l=children.length; i<l; i++){\n\t\t\tthis.children.push(new FancytreeNode(this, children[i]));\n\t\t}\n\t},\n\t/**\n\t * Append (or insert) a list of child nodes.\n\t *\n\t * @param {NodeData[]} children array of child node definitions (also single child accepted)\n\t * @param {FancytreeNode | string | Integer} [insertBefore] child node (or key or index of such).\n\t *     If omitted, the new children are appended.\n\t * @returns {FancytreeNode} first child added\n\t *\n\t * @see FancytreeNode#applyPatch\n\t */\n\taddChildren: function(children, insertBefore){\n\t\tvar i, l, pos,\n\t\t\torigFirstChild = this.getFirstChild(),\n\t\t\torigLastChild = this.getLastChild(),\n\t\t\tfirstNode = null,\n\t\t\tnodeList = [];\n\n\t\tif($.isPlainObject(children) ){\n\t\t\tchildren = [children];\n\t\t}\n\t\tif(!this.children){\n\t\t\tthis.children = [];\n\t\t}\n\t\tfor(i=0, l=children.length; i<l; i++){\n\t\t\tnodeList.push(new FancytreeNode(this, children[i]));\n\t\t}\n\t\tfirstNode = nodeList[0];\n\t\tif(insertBefore == null){\n\t\t\tthis.children = this.children.concat(nodeList);\n\t\t}else{\n\t\t\tinsertBefore = this._findDirectChild(insertBefore);\n\t\t\tpos = $.inArray(insertBefore, this.children);\n\t\t\t_assert(pos >= 0, \"insertBefore must be an existing child\");\n\t\t\t// insert nodeList after children[pos]\n\t\t\tthis.children.splice.apply(this.children, [pos, 0].concat(nodeList));\n\t\t}\n\t\tif(!this.parent || this.parent.ul || this.tr ){\n\t\t\t// Render children if the parent was rendered (or this is a root node)\n\t\t\t// Don't completely rerender every child, just the new ones!\n\t\t\tfor(i=0, l=nodeList.length; i<l; i++) {\n\t\t\t\tnodeList[i].render();   // New nodes were never rendered before\n\t\t\t}\n\t\t\t// Adjust classes where status may have changed\n\t\t\tif (!origFirstChild) {\n\t\t\t\tthis.renderStatus(); // Now expandable where it wasn't before\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Has a first child\n\t\t\t\tif (origFirstChild !== this.getFirstChild()) {\n\t\t\t\t\t// Different first child -- recompute classes\n\t\t\t\t\torigFirstChild.renderStatus();\n\t\t\t\t}\n\t\t\t\tif (origLastChild !== this.getLastChild()) {\n\t\t\t\t\t// Different last child -- recompute classes\n\t\t\t\t\torigLastChild.renderStatus();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif( this.tree.options.selectMode === 3 ){\n\t\t\tthis.fixSelection3FromEndNodes();\n\t\t}\n\t\tthis.triggerModifyChild(\"add\", nodeList.length === 1 ? nodeList[0] : null);\n\t\treturn firstNode;\n\t},\n\t/**\n\t * Add class to node's span tag and to .extraClasses.\n\t *\n\t * @param {string} className class name\n\t *\n\t * @since 2.17\n\t */\n\taddClass: function(className){\n\t\treturn this.toggleClass(className, true);\n\t},\n\t/**\n\t * Append or prepend a node, or append a child node.\n\t *\n\t * This a convenience function that calls addChildren()\n\t *\n\t * @param {NodeData} node node definition\n\t * @param {string} [mode=child] 'before', 'after', 'firstChild', or 'child' ('over' is a synonym for 'child')\n\t * @returns {FancytreeNode} new node\n\t */\n\taddNode: function(node, mode){\n\t\tif(mode === undefined || mode === \"over\"){\n\t\t\tmode = \"child\";\n\t\t}\n\t\tswitch(mode){\n\t\tcase \"after\":\n\t\t\treturn this.getParent().addChildren(node, this.getNextSibling());\n\t\tcase \"before\":\n\t\t\treturn this.getParent().addChildren(node, this);\n\t\tcase \"firstChild\":\n\t\t\t// Insert before the first child if any\n\t\t\tvar insertBefore = (this.children ? this.children[0] : null);\n\t\t\treturn this.addChildren(node, insertBefore);\n\t\tcase \"child\":\n\t\tcase \"over\":\n\t\t\treturn this.addChildren(node);\n\t\t}\n\t\t_assert(false, \"Invalid mode: \" + mode);\n\t},\n\t/**Add child status nodes that indicate 'More...', etc.\n\t *\n\t * This also maintains the node's `partload` property.\n\t * @param {boolean|object} node optional node definition. Pass `false` to remove all paging nodes.\n\t * @param {string} [mode='child'] 'child'|firstChild'\n\t * @since 2.15\n\t */\n\taddPagingNode: function(node, mode){\n\t\tvar i, n;\n\n\t\tmode = mode || \"child\";\n\t\tif( node === false ) {\n\t\t\tfor(i=this.children.length-1; i >= 0; i--) {\n\t\t\t\tn = this.children[i];\n\t\t\t\tif( n.statusNodeType === \"paging\" ) {\n\t\t\t\t\tthis.removeChild(n);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.partload = false;\n\t\t\treturn;\n\t\t}\n\t\tnode = $.extend({\n\t\t\ttitle: this.tree.options.strings.moreData,\n\t\t\tstatusNodeType: \"paging\",\n\t\t\ticon: false\n\t\t}, node);\n\t\tthis.partload = true;\n\t\treturn this.addNode(node, mode);\n\t},\n\t/**\n\t * Append new node after this.\n\t *\n\t * This a convenience function that calls addNode(node, 'after')\n\t *\n\t * @param {NodeData} node node definition\n\t * @returns {FancytreeNode} new node\n\t */\n\tappendSibling: function(node){\n\t\treturn this.addNode(node, \"after\");\n\t},\n\t/**\n\t * Modify existing child nodes.\n\t *\n\t * @param {NodePatch} patch\n\t * @returns {$.Promise}\n\t * @see FancytreeNode#addChildren\n\t */\n\tapplyPatch: function(patch) {\n\t\t// patch [key, null] means 'remove'\n\t\tif(patch === null){\n\t\t\tthis.remove();\n\t\t\treturn _getResolvedPromise(this);\n\t\t}\n\t\t// TODO: make sure that root node is not collapsed or modified\n\t\t// copy (most) attributes to node.ATTR or node.data.ATTR\n\t\tvar name, promise, v,\n\t\t\tIGNORE_MAP = { children: true, expanded: true, parent: true }; // TODO: should be global\n\n\t\tfor(name in patch){\n\t\t\tv = patch[name];\n\t\t\tif( !IGNORE_MAP[name] && !$.isFunction(v)){\n\t\t\t\tif(NODE_ATTR_MAP[name]){\n\t\t\t\t\tthis[name] = v;\n\t\t\t\t}else{\n\t\t\t\t\tthis.data[name] = v;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Remove and/or create children\n\t\tif(patch.hasOwnProperty(\"children\")){\n\t\t\tthis.removeChildren();\n\t\t\tif(patch.children){ // only if not null and not empty list\n\t\t\t\t// TODO: addChildren instead?\n\t\t\t\tthis._setChildren(patch.children);\n\t\t\t}\n\t\t\t// TODO: how can we APPEND or INSERT child nodes?\n\t\t}\n\t\tif(this.isVisible()){\n\t\t\tthis.renderTitle();\n\t\t\tthis.renderStatus();\n\t\t}\n\t\t// Expand collapse (final step, since this may be async)\n\t\tif(patch.hasOwnProperty(\"expanded\")){\n\t\t\tpromise = this.setExpanded(patch.expanded);\n\t\t}else{\n\t\t\tpromise = _getResolvedPromise(this);\n\t\t}\n\t\treturn promise;\n\t},\n\t/** Collapse all sibling nodes.\n\t * @returns {$.Promise}\n\t */\n\tcollapseSiblings: function() {\n\t\treturn this.tree._callHook(\"nodeCollapseSiblings\", this);\n\t},\n\t/** Copy this node as sibling or child of `node`.\n\t *\n\t * @param {FancytreeNode} node source node\n\t * @param {string} [mode=child] 'before' | 'after' | 'child'\n\t * @param {Function} [map] callback function(NodeData) that could modify the new node\n\t * @returns {FancytreeNode} new\n\t */\n\tcopyTo: function(node, mode, map) {\n\t\treturn node.addNode(this.toDict(true, map), mode);\n\t},\n\t/** Count direct and indirect children.\n\t *\n\t * @param {boolean} [deep=true] pass 'false' to only count direct children\n\t * @returns {int} number of child nodes\n\t */\n\tcountChildren: function(deep) {\n\t\tvar cl = this.children, i, l, n;\n\t\tif( !cl ){\n\t\t\treturn 0;\n\t\t}\n\t\tn = cl.length;\n\t\tif(deep !== false){\n\t\t\tfor(i=0, l=n; i<l; i++){\n\t\t\t\tn += cl[i].countChildren();\n\t\t\t}\n\t\t}\n\t\treturn n;\n\t},\n\t// TODO: deactivate()\n\t/** Write to browser console if debugLevel >= 2 (prepending node info)\n\t *\n\t * @param {*} msg string or object or array of such\n\t */\n\tdebug: function(msg){\n\t\tif( this.tree.options.debugLevel >= 2 ) {\n\t\t\tArray.prototype.unshift.call(arguments, this.toString());\n\t\t\tconsoleApply(\"log\", arguments);\n\t\t}\n\t},\n\t/** Deprecated.\n\t * @deprecated since 2014-02-16. Use resetLazy() instead.\n\t */\n\tdiscard: function(){\n\t\tthis.warn(\"FancytreeNode.discard() is deprecated since 2014-02-16. Use .resetLazy() instead.\");\n\t\treturn this.resetLazy();\n\t},\n\t/** Remove DOM elements for all descendents. May be called on .collapse event\n\t * to keep the DOM small.\n\t * @param {boolean} [includeSelf=false]\n\t */\n\tdiscardMarkup: function(includeSelf){\n\t\tvar fn = includeSelf ? \"nodeRemoveMarkup\" : \"nodeRemoveChildMarkup\";\n\t\tthis.tree._callHook(fn, this);\n\t},\n\t/**Find all nodes that match condition (excluding self).\n\t *\n\t * @param {string | function(node)} match title string to search for, or a\n\t *     callback function that returns `true` if a node is matched.\n\t * @returns {FancytreeNode[]} array of nodes (may be empty)\n\t */\n\tfindAll: function(match) {\n\t\tmatch = $.isFunction(match) ? match : _makeNodeTitleMatcher(match);\n\t\tvar res = [];\n\t\tthis.visit(function(n){\n\t\t\tif(match(n)){\n\t\t\t\tres.push(n);\n\t\t\t}\n\t\t});\n\t\treturn res;\n\t},\n\t/**Find first node that matches condition (excluding self).\n\t *\n\t * @param {string | function(node)} match title string to search for, or a\n\t *     callback function that returns `true` if a node is matched.\n\t * @returns {FancytreeNode} matching node or null\n\t * @see FancytreeNode#findAll\n\t */\n\tfindFirst: function(match) {\n\t\tmatch = $.isFunction(match) ? match : _makeNodeTitleMatcher(match);\n\t\tvar res = null;\n\t\tthis.visit(function(n){\n\t\t\tif(match(n)){\n\t\t\t\tres = n;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\treturn res;\n\t},\n\t/* Apply selection state (internal use only) */\n\t_changeSelectStatusAttrs: function (state) {\n\t\tvar changed = false;\n\n\t\tswitch(state){\n\t\tcase false:\n\t\t\tchanged = ( this.selected || this.partsel );\n\t\t\tthis.selected = false;\n\t\t\tthis.partsel = false;\n\t\t\tbreak;\n\t\tcase true:\n\t\t\tchanged = ( !this.selected || !this.partsel );\n\t\t\tthis.selected = true;\n\t\t\tthis.partsel = true;\n\t\t\tbreak;\n\t\tcase undefined:\n\t\t\tchanged = ( this.selected || !this.partsel );\n\t\t\tthis.selected = false;\n\t\t\tthis.partsel = true;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t_assert(false, \"invalid state: \" + state);\n\t\t}\n\t\t// this.debug(\"fixSelection3AfterLoad() _changeSelectStatusAttrs()\", state, changed);\n\t\tif( changed ){\n\t\t\tthis.renderStatus();\n\t\t}\n\t\treturn changed;\n\t},\n\t/**\n\t * Fix selection status, after this node was (de)selected in multi-hier mode.\n\t * This includes (de)selecting all children.\n\t */\n\tfixSelection3AfterClick: function() {\n\t\tvar flag = this.isSelected();\n\n//\t\tthis.debug(\"fixSelection3AfterClick()\");\n\n\t\tthis.visit(function(node){\n\t\t\tnode._changeSelectStatusAttrs(flag);\n\t\t});\n\t\tthis.fixSelection3FromEndNodes();\n\t},\n\t/**\n\t * Fix selection status for multi-hier mode.\n\t * Only end-nodes are considered to update the descendants branch and parents.\n\t * Should be called after this node has loaded new children or after\n\t * children have been modified using the API.\n\t */\n\tfixSelection3FromEndNodes: function() {\n//\t\tthis.debug(\"fixSelection3FromEndNodes()\");\n\t\t_assert(this.tree.options.selectMode === 3, \"expected selectMode 3\");\n\n\t\t// Visit all end nodes and adjust their parent's `selected` and `partsel`\n\t\t// attributes. Return selection state true, false, or undefined.\n\t\tfunction _walk(node){\n\t\t\tvar i, l, child, s, state, allSelected,someSelected,\n\t\t\t\tchildren = node.children;\n\n\t\t\tif( children && children.length ){\n\t\t\t\t// check all children recursively\n\t\t\t\tallSelected = true;\n\t\t\t\tsomeSelected = false;\n\n\t\t\t\tfor( i=0, l=children.length; i<l; i++ ){\n\t\t\t\t\tchild = children[i];\n\t\t\t\t\t// the selection state of a node is not relevant; we need the end-nodes\n\t\t\t\t\ts = _walk(child);\n\t\t\t\t\tif( s !== false ) {\n\t\t\t\t\t\tsomeSelected = true;\n\t\t\t\t\t}\n\t\t\t\t\tif( s !== true ) {\n\t\t\t\t\t\tallSelected = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tstate = allSelected ? true : (someSelected ? undefined : false);\n\t\t\t}else{\n\t\t\t\t// This is an end-node: simply report the status\n//\t\t\t\tstate = ( node.unselectable ) ? undefined : !!node.selected;\n\t\t\t\tstate = !!node.selected;\n\t\t\t}\n\t\t\tnode._changeSelectStatusAttrs(state);\n\t\t\treturn state;\n\t\t}\n\t\t_walk(this);\n\n\t\t// Update parent's state\n\t\tthis.visitParents(function(node){\n\t\t\tvar i, l, child, state,\n\t\t\t\tchildren = node.children,\n\t\t\t\tallSelected = true,\n\t\t\t\tsomeSelected = false;\n\n\t\t\tfor( i=0, l=children.length; i<l; i++ ){\n\t\t\t\tchild = children[i];\n\t\t\t\t// When fixing the parents, we trust the sibling status (i.e.\n\t\t\t\t// we don't recurse)\n\t\t\t\tif( child.selected || child.partsel ) {\n\t\t\t\t\tsomeSelected = true;\n\t\t\t\t}\n\t\t\t\tif( !child.unselectable && !child.selected ) {\n\t\t\t\t\tallSelected = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tstate = allSelected ? true : (someSelected ? undefined : false);\n\t\t\tnode._changeSelectStatusAttrs(state);\n\t\t});\n\t},\n\t// TODO: focus()\n\t/**\n\t * Update node data. If dict contains 'children', then also replace\n\t * the hole sub tree.\n\t * @param {NodeData} dict\n\t *\n\t * @see FancytreeNode#addChildren\n\t * @see FancytreeNode#applyPatch\n\t */\n\tfromDict: function(dict) {\n\t\t// copy all other attributes to this.data.xxx\n\t\tfor(var name in dict){\n\t\t\tif(NODE_ATTR_MAP[name]){\n\t\t\t\t// node.NAME = dict.NAME\n\t\t\t\tthis[name] = dict[name];\n\t\t\t}else if(name === \"data\"){\n\t\t\t\t// node.data += dict.data\n\t\t\t\t$.extend(this.data, dict.data);\n\t\t\t}else if(!$.isFunction(dict[name]) && !NONE_NODE_DATA_MAP[name]){\n\t\t\t\t// node.data.NAME = dict.NAME\n\t\t\t\tthis.data[name] = dict[name];\n\t\t\t}\n\t\t}\n\t\tif(dict.children){\n\t\t\t// recursively set children and render\n\t\t\tthis.removeChildren();\n\t\t\tthis.addChildren(dict.children);\n\t\t}\n\t\tthis.renderTitle();\n/*\n\t\tvar children = dict.children;\n\t\tif(children === undefined){\n\t\t\tthis.data = $.extend(this.data, dict);\n\t\t\tthis.render();\n\t\t\treturn;\n\t\t}\n\t\tdict = $.extend({}, dict);\n\t\tdict.children = undefined;\n\t\tthis.data = $.extend(this.data, dict);\n\t\tthis.removeChildren();\n\t\tthis.addChild(children);\n*/\n\t},\n\t/** Return the list of child nodes (undefined for unexpanded lazy nodes).\n\t * @returns {FancytreeNode[] | undefined}\n\t */\n\tgetChildren: function() {\n\t\tif(this.hasChildren() === undefined){ // TODO: only required for lazy nodes?\n\t\t\treturn undefined; // Lazy node: unloaded, currently loading, or load error\n\t\t}\n\t\treturn this.children;\n\t},\n\t/** Return the first child node or null.\n\t * @returns {FancytreeNode | null}\n\t */\n\tgetFirstChild: function() {\n\t\treturn this.children ? this.children[0] : null;\n\t},\n\t/** Return the 0-based child index.\n\t * @returns {int}\n\t */\n\tgetIndex: function() {\n//\t\treturn this.parent.children.indexOf(this);\n\t\treturn $.inArray(this, this.parent.children); // indexOf doesn't work in IE7\n\t},\n\t/** Return the hierarchical child index (1-based, e.g. '3.2.4').\n\t * @param {string} [separator=\".\"]\n\t * @param {int} [digits=1]\n\t * @returns {string}\n\t */\n\tgetIndexHier: function(separator, digits) {\n\t\tseparator = separator || \".\";\n\t\tvar s,\n\t\t\tres = [];\n\t\t$.each(this.getParentList(false, true), function(i, o){\n\t\t\ts = \"\" + (o.getIndex() + 1);\n\t\t\tif( digits ){\n\t\t\t\t// prepend leading zeroes\n\t\t\t\ts = (\"0000000\" + s).substr(-digits);\n\t\t\t}\n\t\t\tres.push(s);\n\t\t});\n\t\treturn res.join(separator);\n\t},\n\t/** Return the parent keys separated by options.keyPathSeparator, e.g. \"id_1/id_17/id_32\".\n\t * @param {boolean} [excludeSelf=false]\n\t * @returns {string}\n\t */\n\tgetKeyPath: function(excludeSelf) {\n\t\tvar path = [],\n\t\t\tsep = this.tree.options.keyPathSeparator;\n\t\tthis.visitParents(function(n){\n\t\t\tif(n.parent){\n\t\t\t\tpath.unshift(n.key);\n\t\t\t}\n\t\t}, !excludeSelf);\n\t\treturn sep + path.join(sep);\n\t},\n\t/** Return the last child of this node or null.\n\t * @returns {FancytreeNode | null}\n\t */\n\tgetLastChild: function() {\n\t\treturn this.children ? this.children[this.children.length - 1] : null;\n\t},\n\t/** Return node depth. 0: System root node, 1: visible top-level node, 2: first sub-level, ... .\n\t * @returns {int}\n\t */\n\tgetLevel: function() {\n\t\tvar level = 0,\n\t\t\tdtn = this.parent;\n\t\twhile( dtn ) {\n\t\t\tlevel++;\n\t\t\tdtn = dtn.parent;\n\t\t}\n\t\treturn level;\n\t},\n\t/** Return the successor node (under the same parent) or null.\n\t * @returns {FancytreeNode | null}\n\t */\n\tgetNextSibling: function() {\n\t\t// TODO: use indexOf, if available: (not in IE6)\n\t\tif( this.parent ){\n\t\t\tvar i, l,\n\t\t\t\tac = this.parent.children;\n\n\t\t\tfor(i=0, l=ac.length-1; i<l; i++){ // up to length-2, so next(last) = null\n\t\t\t\tif( ac[i] === this ){\n\t\t\t\t\treturn ac[i+1];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t},\n\t/** Return the parent node (null for the system root node).\n\t * @returns {FancytreeNode | null}\n\t */\n\tgetParent: function() {\n\t\t// TODO: return null for top-level nodes?\n\t\treturn this.parent;\n\t},\n\t/** Return an array of all parent nodes (top-down).\n\t * @param {boolean} [includeRoot=false] Include the invisible system root node.\n\t * @param {boolean} [includeSelf=false] Include the node itself.\n\t * @returns {FancytreeNode[]}\n\t */\n\tgetParentList: function(includeRoot, includeSelf) {\n\t\tvar l = [],\n\t\t\tdtn = includeSelf ? this : this.parent;\n\t\twhile( dtn ) {\n\t\t\tif( includeRoot || dtn.parent ){\n\t\t\t\tl.unshift(dtn);\n\t\t\t}\n\t\t\tdtn = dtn.parent;\n\t\t}\n\t\treturn l;\n\t},\n\t/** Return the predecessor node (under the same parent) or null.\n\t * @returns {FancytreeNode | null}\n\t */\n\tgetPrevSibling: function() {\n\t\tif( this.parent ){\n\t\t\tvar i, l,\n\t\t\t\tac = this.parent.children;\n\n\t\t\tfor(i=1, l=ac.length; i<l; i++){ // start with 1, so prev(first) = null\n\t\t\t\tif( ac[i] === this ){\n\t\t\t\t\treturn ac[i-1];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t},\n\t/**\n\t * Return an array of selected descendant nodes.\n\t * @param {boolean} [stopOnParents=false] only return the topmost selected\n\t *     node (useful with selectMode 3)\n\t * @returns {FancytreeNode[]}\n\t */\n\tgetSelectedNodes: function(stopOnParents) {\n\t\tvar nodeList = [];\n\t\tthis.visit(function(node){\n\t\t\tif( node.selected ) {\n\t\t\t\tnodeList.push(node);\n\t\t\t\tif( stopOnParents === true ){\n\t\t\t\t\treturn \"skip\"; // stop processing this branch\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn nodeList;\n\t},\n\t/** Return true if node has children. Return undefined if not sure, i.e. the node is lazy and not yet loaded).\n\t * @returns {boolean | undefined}\n\t */\n\thasChildren: function() {\n\t\tif(this.lazy){\n\t\t\tif(this.children == null ){\n\t\t\t\t// null or undefined: Not yet loaded\n\t\t\t\treturn undefined;\n\t\t\t}else if(this.children.length === 0){\n\t\t\t\t// Loaded, but response was empty\n\t\t\t\treturn false;\n\t\t\t}else if(this.children.length === 1 && this.children[0].isStatusNode() ){\n\t\t\t\t// Currently loading or load error\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\treturn !!( this.children && this.children.length );\n\t},\n\t/** Return true if node has keyboard focus.\n\t * @returns {boolean}\n\t */\n\thasFocus: function() {\n\t\treturn (this.tree.hasFocus() && this.tree.focusNode === this);\n\t},\n\t/** Write to browser console if debugLevel >= 1 (prepending node info)\n\t *\n\t * @param {*} msg string or object or array of such\n\t */\n\tinfo: function(msg){\n\t\tif( this.tree.options.debugLevel >= 1 ) {\n\t\t\tArray.prototype.unshift.call(arguments, this.toString());\n\t\t\tconsoleApply(\"info\", arguments);\n\t\t}\n\t},\n\t/** Return true if node is active (see also FancytreeNode#isSelected).\n\t * @returns {boolean}\n\t */\n\tisActive: function() {\n\t\treturn (this.tree.activeNode === this);\n\t},\n\t/** Return true if node is a direct child of otherNode.\n\t * @param {FancytreeNode} otherNode\n\t * @returns {boolean}\n\t */\n\tisChildOf: function(otherNode) {\n\t\treturn (this.parent && this.parent === otherNode);\n\t},\n\t/** Return true, if node is a direct or indirect sub node of otherNode.\n\t * @param {FancytreeNode} otherNode\n\t * @returns {boolean}\n\t */\n\tisDescendantOf: function(otherNode) {\n\t\tif(!otherNode || otherNode.tree !== this.tree){\n\t\t\treturn false;\n\t\t}\n\t\tvar p = this.parent;\n\t\twhile( p ) {\n\t\t\tif( p === otherNode ){\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tp = p.parent;\n\t\t}\n\t\treturn false;\n\t},\n\t/** Return true if node is expanded.\n\t * @returns {boolean}\n\t */\n\tisExpanded: function() {\n\t\treturn !!this.expanded;\n\t},\n\t/** Return true if node is the first node of its parent's children.\n\t * @returns {boolean}\n\t */\n\tisFirstSibling: function() {\n\t\tvar p = this.parent;\n\t\treturn !p || p.children[0] === this;\n\t},\n\t/** Return true if node is a folder, i.e. has the node.folder attribute set.\n\t * @returns {boolean}\n\t */\n\tisFolder: function() {\n\t\treturn !!this.folder;\n\t},\n\t/** Return true if node is the last node of its parent's children.\n\t * @returns {boolean}\n\t */\n\tisLastSibling: function() {\n\t\tvar p = this.parent;\n\t\treturn !p || p.children[p.children.length-1] === this;\n\t},\n\t/** Return true if node is lazy (even if data was already loaded)\n\t * @returns {boolean}\n\t */\n\tisLazy: function() {\n\t\treturn !!this.lazy;\n\t},\n\t/** Return true if node is lazy and loaded. For non-lazy nodes always return true.\n\t * @returns {boolean}\n\t */\n\tisLoaded: function() {\n\t\treturn !this.lazy || this.hasChildren() !== undefined; // Also checks if the only child is a status node\n\t},\n\t/** Return true if children are currently beeing loaded, i.e. a Ajax request is pending.\n\t * @returns {boolean}\n\t */\n\tisLoading: function() {\n\t\treturn !!this._isLoading;\n\t},\n\t/*\n\t * @deprecated since v2.4.0:  Use isRootNode() instead\n\t */\n\tisRoot: function() {\n\t\treturn this.isRootNode();\n\t},\n\t/** (experimental) Return true if this is partially loaded.\n\t * @returns {boolean}\n\t * @since 2.15\n\t */\n\tisPartload: function() {\n\t\treturn !!this.partload;\n\t},\n\t/** Return true if this is the (invisible) system root node.\n\t * @returns {boolean}\n\t * @since 2.4\n\t */\n\tisRootNode: function() {\n\t\treturn (this.tree.rootNode === this);\n\t},\n\t/** Return true if node is selected, i.e. has a checkmark set (see also FancytreeNode#isActive).\n\t * @returns {boolean}\n\t */\n\tisSelected: function() {\n\t\treturn !!this.selected;\n\t},\n\t/** Return true if this node is a temporarily generated system node like\n\t * 'loading', 'paging', or 'error' (node.statusNodeType contains the type).\n\t * @returns {boolean}\n\t */\n\tisStatusNode: function() {\n\t\treturn !!this.statusNodeType;\n\t},\n\t/** Return true if this node is a status node of type 'paging'.\n\t * @returns {boolean}\n\t * @since 2.15\n\t */\n\tisPagingNode: function() {\n\t\treturn this.statusNodeType === \"paging\";\n\t},\n\t/** Return true if this a top level node, i.e. a direct child of the (invisible) system root node.\n\t * @returns {boolean}\n\t * @since 2.4\n\t */\n\tisTopLevel: function() {\n\t\treturn (this.tree.rootNode === this.parent);\n\t},\n\t/** Return true if node is lazy and not yet loaded. For non-lazy nodes always return false.\n\t * @returns {boolean}\n\t */\n\tisUndefined: function() {\n\t\treturn this.hasChildren() === undefined; // also checks if the only child is a status node\n\t},\n\t/** Return true if all parent nodes are expanded. Note: this does not check\n\t * whether the node is scrolled into the visible part of the screen.\n\t * @returns {boolean}\n\t */\n\tisVisible: function() {\n\t\tvar i, l,\n\t\t\tparents = this.getParentList(false, false);\n\n\t\tfor(i=0, l=parents.length; i<l; i++){\n\t\t\tif( ! parents[i].expanded ){ return false; }\n\t\t}\n\t\treturn true;\n\t},\n\t/** Deprecated.\n\t * @deprecated since 2014-02-16: use load() instead.\n\t */\n\tlazyLoad: function(discard) {\n\t\tthis.warn(\"FancytreeNode.lazyLoad() is deprecated since 2014-02-16. Use .load() instead.\");\n\t\treturn this.load(discard);\n\t},\n\t/**\n\t * Load all children of a lazy node if neccessary. The <i>expanded</i> state is maintained.\n\t * @param {boolean} [forceReload=false] Pass true to discard any existing nodes before. Otherwise this method does nothing if the node was already loaded.\n\t * @returns {$.Promise}\n\t */\n\tload: function(forceReload) {\n\t\tvar res, source,\n\t\t\tthat = this,\n\t\t\twasExpanded = this.isExpanded();\n\n\t\t_assert( this.isLazy(), \"load() requires a lazy node\" );\n\t\t// _assert( forceReload || this.isUndefined(), \"Pass forceReload=true to re-load a lazy node\" );\n\t\tif( !forceReload && !this.isUndefined() ) {\n\t\t\treturn _getResolvedPromise(this);\n\t\t}\n\t\tif( this.isLoaded() ){\n\t\t\tthis.resetLazy(); // also collapses\n\t\t}\n\t\t// This method is also called by setExpanded() and loadKeyPath(), so we\n\t\t// have to avoid recursion.\n\t\tsource = this.tree._triggerNodeEvent(\"lazyLoad\", this);\n\t\tif( source === false ) { // #69\n\t\t\treturn _getResolvedPromise(this);\n\t\t}\n\t\t_assert(typeof source !== \"boolean\", \"lazyLoad event must return source in data.result\");\n\t\tres = this.tree._callHook(\"nodeLoadChildren\", this, source);\n\t\tif( wasExpanded ) {\n\t\t\tthis.expanded = true;\n\t\t\tres.always(function(){\n\t\t\t\tthat.render();\n\t\t\t});\n\t\t} else {\n\t\t\tres.always(function(){\n\t\t\t\tthat.renderStatus();  // fix expander icon to 'loaded'\n\t\t\t});\n\t\t}\n\t\treturn res;\n\t},\n\t/** Expand all parents and optionally scroll into visible area as neccessary.\n\t * Promise is resolved, when lazy loading and animations are done.\n\t * @param {object} [opts] passed to `setExpanded()`.\n\t *     Defaults to {noAnimation: false, noEvents: false, scrollIntoView: true}\n\t * @returns {$.Promise}\n\t */\n\tmakeVisible: function(opts) {\n\t\tvar i,\n\t\t\tthat = this,\n\t\t\tdeferreds = [],\n\t\t\tdfd = new $.Deferred(),\n\t\t\tparents = this.getParentList(false, false),\n\t\t\tlen = parents.length,\n\t\t\teffects = !(opts && opts.noAnimation === true),\n\t\t\tscroll = !(opts && opts.scrollIntoView === false);\n\n\t\t// Expand bottom-up, so only the top node is animated\n\t\tfor(i = len - 1; i >= 0; i--){\n\t\t\t// that.debug(\"pushexpand\" + parents[i]);\n\t\t\tdeferreds.push(parents[i].setExpanded(true, opts));\n\t\t}\n\t\t$.when.apply($, deferreds).done(function(){\n\t\t\t// All expands have finished\n\t\t\t// that.debug(\"expand DONE\", scroll);\n\t\t\tif( scroll ){\n\t\t\t\tthat.scrollIntoView(effects).done(function(){\n\t\t\t\t\t// that.debug(\"scroll DONE\");\n\t\t\t\t\tdfd.resolve();\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tdfd.resolve();\n\t\t\t}\n\t\t});\n\t\treturn dfd.promise();\n\t},\n\t/** Move this node to targetNode.\n\t *  @param {FancytreeNode} targetNode\n\t *  @param {string} mode <pre>\n\t *      'child': append this node as last child of targetNode.\n\t *               This is the default. To be compatble with the D'n'd\n\t *               hitMode, we also accept 'over'.\n\t *      'firstChild': add this node as first child of targetNode.\n\t *      'before': add this node as sibling before targetNode.\n\t *      'after': add this node as sibling after targetNode.</pre>\n\t *  @param {function} [map] optional callback(FancytreeNode) to allow modifcations\n\t */\n\tmoveTo: function(targetNode, mode, map) {\n\t\tif(mode === undefined || mode === \"over\"){\n\t\t\tmode = \"child\";\n\t\t} else if ( mode === \"firstChild\" ) {\n\t\t\tif( targetNode.children && targetNode.children.length ) {\n\t\t\t\tmode = \"before\";\n\t\t\t\ttargetNode = targetNode.children[0];\n\t\t\t} else {\n\t\t\t\tmode = \"child\";\n\t\t\t}\n\t\t}\n\t\tvar pos,\n\t\t\tprevParent = this.parent,\n\t\t\ttargetParent = (mode === \"child\") ? targetNode : targetNode.parent;\n\n\t\tif(this === targetNode){\n\t\t\treturn;\n\t\t}else if( !this.parent  ){\n\t\t\t$.error(\"Cannot move system root\");\n\t\t}else if( targetParent.isDescendantOf(this) ){\n\t\t\t$.error(\"Cannot move a node to its own descendant\");\n\t\t}\n\t\tif( targetParent !== prevParent ) {\n\t\t\tprevParent.triggerModifyChild(\"remove\", this);\n\t\t}\n\t\t// Unlink this node from current parent\n\t\tif( this.parent.children.length === 1 ) {\n\t\t\tif( this.parent === targetParent ){\n\t\t\t\treturn; // #258\n\t\t\t}\n\t\t\tthis.parent.children = this.parent.lazy ? [] : null;\n\t\t\tthis.parent.expanded = false;\n\t\t} else {\n\t\t\tpos = $.inArray(this, this.parent.children);\n\t\t\t_assert(pos >= 0, \"invalid source parent\");\n\t\t\tthis.parent.children.splice(pos, 1);\n\t\t}\n\t\t// Remove from source DOM parent\n//\t\tif(this.parent.ul){\n//\t\t\tthis.parent.ul.removeChild(this.li);\n//\t\t}\n\n\t\t// Insert this node to target parent's child list\n\t\tthis.parent = targetParent;\n\t\tif( targetParent.hasChildren() ) {\n\t\t\tswitch(mode) {\n\t\t\tcase \"child\":\n\t\t\t\t// Append to existing target children\n\t\t\t\ttargetParent.children.push(this);\n\t\t\t\tbreak;\n\t\t\tcase \"before\":\n\t\t\t\t// Insert this node before target node\n\t\t\t\tpos = $.inArray(targetNode, targetParent.children);\n\t\t\t\t_assert(pos >= 0, \"invalid target parent\");\n\t\t\t\ttargetParent.children.splice(pos, 0, this);\n\t\t\t\tbreak;\n\t\t\tcase \"after\":\n\t\t\t\t// Insert this node after target node\n\t\t\t\tpos = $.inArray(targetNode, targetParent.children);\n\t\t\t\t_assert(pos >= 0, \"invalid target parent\");\n\t\t\t\ttargetParent.children.splice(pos+1, 0, this);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t$.error(\"Invalid mode \" + mode);\n\t\t\t}\n\t\t} else {\n\t\t\ttargetParent.children = [ this ];\n\t\t}\n\t\t// Parent has no <ul> tag yet:\n//\t\tif( !targetParent.ul ) {\n//\t\t\t// This is the parent's first child: create UL tag\n//\t\t\t// (Hidden, because it will be\n//\t\t\ttargetParent.ul = document.createElement(\"ul\");\n//\t\t\ttargetParent.ul.style.display = \"none\";\n//\t\t\ttargetParent.li.appendChild(targetParent.ul);\n//\t\t}\n//\t\t// Issue 319: Add to target DOM parent (only if node was already rendered(expanded))\n//\t\tif(this.li){\n//\t\t\ttargetParent.ul.appendChild(this.li);\n//\t\t}^\n\n\t\t// Let caller modify the nodes\n\t\tif( map ){\n\t\t\ttargetNode.visit(map, true);\n\t\t}\n\t\tif( targetParent === prevParent ) {\n\t\t\ttargetParent.triggerModifyChild(\"move\", this);\n\t\t} else {\n\t\t\t// prevParent.triggerModifyChild(\"remove\", this);\n\t\t\ttargetParent.triggerModifyChild(\"add\", this);\n\t\t}\n\t\t// Handle cross-tree moves\n\t\tif( this.tree !== targetNode.tree ) {\n\t\t\t// Fix node.tree for all source nodes\n//\t\t\t_assert(false, \"Cross-tree move is not yet implemented.\");\n\t\t\tthis.warn(\"Cross-tree moveTo is experimantal!\");\n\t\t\tthis.visit(function(n){\n\t\t\t\t// TODO: fix selection state and activation, ...\n\t\t\t\tn.tree = targetNode.tree;\n\t\t\t}, true);\n\t\t}\n\n\t\t// A collaposed node won't re-render children, so we have to remove it manually\n\t\t// if( !targetParent.expanded ){\n\t\t//   prevParent.ul.removeChild(this.li);\n\t\t// }\n\n\t\t// Update HTML markup\n\t\tif( !prevParent.isDescendantOf(targetParent)) {\n\t\t\tprevParent.render();\n\t\t}\n\t\tif( !targetParent.isDescendantOf(prevParent) && targetParent !== prevParent) {\n\t\t\ttargetParent.render();\n\t\t}\n\t\t// TODO: fix selection state\n\t\t// TODO: fix active state\n\n/*\n\t\tvar tree = this.tree;\n\t\tvar opts = tree.options;\n\t\tvar pers = tree.persistence;\n\n\n\t\t// Always expand, if it's below minExpandLevel\n//\t\ttree.logDebug (\"%s._addChildNode(%o), l=%o\", this, ftnode, ftnode.getLevel());\n\t\tif ( opts.minExpandLevel >= ftnode.getLevel() ) {\n//\t\t\ttree.logDebug (\"Force expand for %o\", ftnode);\n\t\t\tthis.bExpanded = true;\n\t\t}\n\n\t\t// In multi-hier mode, update the parents selection state\n\t\t// DT issue #82: only if not initializing, because the children may not exist yet\n//\t\tif( !ftnode.data.isStatusNode() && opts.selectMode==3 && !isInitializing )\n//\t\t\tftnode._fixSelectionState();\n\n\t\t// In multi-hier mode, update the parents selection state\n\t\tif( ftnode.bSelected && opts.selectMode==3 ) {\n\t\t\tvar p = this;\n\t\t\twhile( p ) {\n\t\t\t\tif( !p.hasSubSel )\n\t\t\t\t\tp._setSubSel(true);\n\t\t\t\tp = p.parent;\n\t\t\t}\n\t\t}\n\t\t// render this node and the new child\n\t\tif ( tree.bEnableUpdate )\n\t\t\tthis.render();\n\n\t\treturn ftnode;\n\n*/\n\t},\n\t/** Set focus relative to this node and optionally activate.\n\t *\n\t * @param {number} where The keyCode that would normally trigger this move,\n\t *\t\te.g. `$.ui.keyCode.LEFT` would collapse the node if it\n\t *      is expanded or move to the parent oterwise.\n\t * @param {boolean} [activate=true]\n\t * @returns {$.Promise}\n\t */\n\tnavigate: function(where, activate) {\n\t\tvar i, parents, res,\n\t\t\thandled = true,\n\t\t\tKC = $.ui.keyCode,\n\t\t\tsib = null;\n\n\t\t// Navigate to node\n\t\tfunction _goto(n){\n\t\t\tif( n ){\n\t\t\t\t// setFocus/setActive will scroll later (if autoScroll is specified)\n\t\t\t\ttry { n.makeVisible({scrollIntoView: false}); } catch(e) {} // #272\n\t\t\t\t// Node may still be hidden by a filter\n\t\t\t\tif( ! $(n.span).is(\":visible\") ) {\n\t\t\t\t\tn.debug(\"Navigate: skipping hidden node\");\n\t\t\t\t\tn.navigate(where, activate);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\treturn activate === false ? n.setFocus() : n.setActive();\n\t\t\t}\n\t\t}\n\n\t\tswitch( where ) {\n\t\t\tcase KC.BACKSPACE:\n\t\t\t\tif( this.parent && this.parent.parent ) {\n\t\t\t\t\tres = _goto(this.parent);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase KC.HOME:\n\t\t\t\tthis.tree.visit(function(n){  // goto first visible node\n\t\t\t\t\tif( $(n.span).is(\":visible\") ) {\n\t\t\t\t\t\tres = _goto(n);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase KC.END:\n\t\t\t\tthis.tree.visit(function(n){  // goto last visible node\n\t\t\t\t\tif( $(n.span).is(\":visible\") ) {\n\t\t\t\t\t\tres = n;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tif( res ) {\n\t\t\t\t\tres = _goto(res);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase KC.LEFT:\n\t\t\t\tif( this.expanded ) {\n\t\t\t\t\tthis.setExpanded(false);\n\t\t\t\t\tres = _goto(this);\n\t\t\t\t} else if( this.parent && this.parent.parent ) {\n\t\t\t\t\tres = _goto(this.parent);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase KC.RIGHT:\n\t\t\t\tif( !this.expanded && (this.children || this.lazy) ) {\n\t\t\t\t\tthis.setExpanded();\n\t\t\t\t\tres = _goto(this);\n\t\t\t\t} else if( this.children && this.children.length ) {\n\t\t\t\t\tres = _goto(this.children[0]);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase KC.UP:\n\t\t\t\tsib = this.getPrevSibling();\n\t\t\t\t// #359: skip hidden sibling nodes, preventing a _goto() recursion\n\t\t\t\twhile( sib && !$(sib.span).is(\":visible\") ) {\n\t\t\t\t\tsib = sib.getPrevSibling();\n\t\t\t\t}\n\t\t\t\twhile( sib && sib.expanded && sib.children && sib.children.length ) {\n\t\t\t\t\tsib = sib.children[sib.children.length - 1];\n\t\t\t\t}\n\t\t\t\tif( !sib && this.parent && this.parent.parent ){\n\t\t\t\t\tsib = this.parent;\n\t\t\t\t}\n\t\t\t\tres = _goto(sib);\n\t\t\t\tbreak;\n\t\t\tcase KC.DOWN:\n\t\t\t\tif( this.expanded && this.children && this.children.length ) {\n\t\t\t\t\tsib = this.children[0];\n\t\t\t\t} else {\n\t\t\t\t\tparents = this.getParentList(false, true);\n\t\t\t\t\tfor(i=parents.length-1; i>=0; i--) {\n\t\t\t\t\t\tsib = parents[i].getNextSibling();\n\t\t\t\t\t\t// #359: skip hidden sibling nodes, preventing a _goto() recursion\n\t\t\t\t\t\twhile( sib && !$(sib.span).is(\":visible\") ) {\n\t\t\t\t\t\t\tsib = sib.getNextSibling();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif( sib ){ break; }\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tres = _goto(sib);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\thandled = false;\n\t\t}\n\t\treturn res || _getResolvedPromise();\n\t},\n\t/**\n\t * Remove this node (not allowed for system root).\n\t */\n\tremove: function() {\n\t\treturn this.parent.removeChild(this);\n\t},\n\t/**\n\t * Remove childNode from list of direct children.\n\t * @param {FancytreeNode} childNode\n\t */\n\tremoveChild: function(childNode) {\n\t\treturn this.tree._callHook(\"nodeRemoveChild\", this, childNode);\n\t},\n\t/**\n\t * Remove all child nodes and descendents. This converts the node into a leaf.<br>\n\t * If this was a lazy node, it is still considered 'loaded'; call node.resetLazy()\n\t * in order to trigger lazyLoad on next expand.\n\t */\n\tremoveChildren: function() {\n\t\treturn this.tree._callHook(\"nodeRemoveChildren\", this);\n\t},\n\t/**\n\t * Remove class from node's span tag and .extraClasses.\n\t *\n\t * @param {string} className class name\n\t *\n\t * @since 2.17\n\t */\n\tremoveClass: function(className){\n\t\treturn this.toggleClass(className, false);\n\t},\n\t/**\n\t * This method renders and updates all HTML markup that is required\n\t * to display this node in its current state.<br>\n\t * Note:\n\t * <ul>\n\t * <li>It should only be neccessary to call this method after the node object\n\t *     was modified by direct access to its properties, because the common\n\t *     API methods (node.setTitle(), moveTo(), addChildren(), remove(), ...)\n\t *     already handle this.\n\t * <li> {@link FancytreeNode#renderTitle} and {@link FancytreeNode#renderStatus}\n\t *     are implied. If changes are more local, calling only renderTitle() or\n\t *     renderStatus() may be sufficient and faster.\n\t * </ul>\n\t *\n\t * @param {boolean} [force=false] re-render, even if html markup was already created\n\t * @param {boolean} [deep=false] also render all descendants, even if parent is collapsed\n\t */\n\trender: function(force, deep) {\n\t\treturn this.tree._callHook(\"nodeRender\", this, force, deep);\n\t},\n\t/** Create HTML markup for the node's outer &lt;span> (expander, checkbox, icon, and title).\n\t * Implies {@link FancytreeNode#renderStatus}.\n\t * @see Fancytree_Hooks#nodeRenderTitle\n\t */\n\trenderTitle: function() {\n\t\treturn this.tree._callHook(\"nodeRenderTitle\", this);\n\t},\n\t/** Update element's CSS classes according to node state.\n\t * @see Fancytree_Hooks#nodeRenderStatus\n\t */\n\trenderStatus: function() {\n\t\treturn this.tree._callHook(\"nodeRenderStatus\", this);\n\t},\n\t/**\n\t * (experimental) Replace this node with `source`.\n\t * (Currently only available for paging nodes.)\n\t * @param {NodeData[]} source List of child node definitions\n\t * @since 2.15\n\t */\n\treplaceWith: function(source) {\n\t\tvar res,\n\t\t\tparent = this.parent,\n\t\t\tpos = $.inArray(this, parent.children),\n\t\t\tthat = this;\n\n\t\t_assert( this.isPagingNode(), \"replaceWith() currently requires a paging status node\" );\n\n\t\tres = this.tree._callHook(\"nodeLoadChildren\", this, source);\n\t\tres.done(function(data){\n\t\t\t// New nodes are currently children of `this`.\n\t\t\tvar children = that.children;\n\t\t\t// Prepend newly loaded child nodes to `this`\n\t\t\t// Move new children after self\n\t\t\tfor( i=0; i<children.length; i++ ) {\n\t\t\t\tchildren[i].parent = parent;\n\t\t\t}\n\t\t\tparent.children.splice.apply(parent.children, [pos + 1, 0].concat(children));\n\n\t\t\t// Remove self\n\t\t\tthat.children = null;\n\t\t\tthat.remove();\n\t\t\t// Redraw new nodes\n\t\t\tparent.render();\n\t\t\t// TODO: set node.partload = false if this was tha last paging node?\n\t\t\t// parent.addPagingNode(false);\n\t\t}).fail(function(){\n\t\t\tthat.setExpanded();\n\t\t});\n\t\treturn res;\n\t\t// $.error(\"Not implemented: replaceWith()\");\n\t},\n\t/**\n\t * Remove all children, collapse, and set the lazy-flag, so that the lazyLoad\n\t * event is triggered on next expand.\n\t */\n\tresetLazy: function() {\n\t\tthis.removeChildren();\n\t\tthis.expanded = false;\n\t\tthis.lazy = true;\n\t\tthis.children = undefined;\n\t\tthis.renderStatus();\n\t},\n\t/** Schedule activity for delayed execution (cancel any pending request).\n\t *  scheduleAction('cancel') will only cancel a pending request (if any).\n\t * @param {string} mode\n\t * @param {number} ms\n\t */\n\tscheduleAction: function(mode, ms) {\n\t\tif( this.tree.timer ) {\n\t\t\tclearTimeout(this.tree.timer);\n//            this.tree.debug(\"clearTimeout(%o)\", this.tree.timer);\n\t\t}\n\t\tthis.tree.timer = null;\n\t\tvar self = this; // required for closures\n\t\tswitch (mode) {\n\t\tcase \"cancel\":\n\t\t\t// Simply made sure that timer was cleared\n\t\t\tbreak;\n\t\tcase \"expand\":\n\t\t\tthis.tree.timer = setTimeout(function(){\n\t\t\t\tself.tree.debug(\"setTimeout: trigger expand\");\n\t\t\t\tself.setExpanded(true);\n\t\t\t}, ms);\n\t\t\tbreak;\n\t\tcase \"activate\":\n\t\t\tthis.tree.timer = setTimeout(function(){\n\t\t\t\tself.tree.debug(\"setTimeout: trigger activate\");\n\t\t\t\tself.setActive(true);\n\t\t\t}, ms);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t$.error(\"Invalid mode \" + mode);\n\t\t}\n//        this.tree.debug(\"setTimeout(%s, %s): %s\", mode, ms, this.tree.timer);\n\t},\n\t/**\n\t *\n\t * @param {boolean | PlainObject} [effects=false] animation options.\n\t * @param {object} [options=null] {topNode: null, effects: ..., parent: ...} this node will remain visible in\n\t *     any case, even if `this` is outside the scroll pane.\n\t * @returns {$.Promise}\n\t */\n\tscrollIntoView: function(effects, options) {\n\t\tif( options !== undefined && _isNode(options) ) {\n\t\t\tthis.warn(\"scrollIntoView() with 'topNode' option is deprecated since 2014-05-08. Use 'options.topNode' instead.\");\n\t\t\toptions = {topNode: options};\n\t\t}\n\t\t// this.$scrollParent = (this.options.scrollParent === \"auto\") ? $ul.scrollParent() : $(this.options.scrollParent);\n\t\t// this.$scrollParent = this.$scrollParent.length ? this.$scrollParent || this.$container;\n\n\t\tvar topNodeY, nodeY, horzScrollbarHeight, containerOffsetTop,\n\t\t\topts = $.extend({\n\t\t\t\teffects: (effects === true) ? {duration: 200, queue: false} : effects,\n\t\t\t\tscrollOfs: this.tree.options.scrollOfs,\n\t\t\t\tscrollParent: this.tree.options.scrollParent || this.tree.$container,\n\t\t\t\ttopNode: null\n\t\t\t}, options),\n\t\t\tdfd = new $.Deferred(),\n\t\t\tthat = this,\n\t\t\tnodeHeight = $(this.span).height(),\n\t\t\t$container = $(opts.scrollParent),\n\t\t\ttopOfs = opts.scrollOfs.top || 0,\n\t\t\tbottomOfs = opts.scrollOfs.bottom || 0,\n\t\t\tcontainerHeight = $container.height(),// - topOfs - bottomOfs,\n\t\t\tscrollTop = $container.scrollTop(),\n\t\t\t$animateTarget = $container,\n\t\t\tisParentWindow = $container[0] === window,\n\t\t\ttopNode = opts.topNode || null,\n\t\t\tnewScrollTop = null;\n\n\t\t// this.debug(\"scrollIntoView(), scrollTop=\" + scrollTop, opts.scrollOfs);\n//\t\t_assert($(this.span).is(\":visible\"), \"scrollIntoView node is invisible\"); // otherwise we cannot calc offsets\n\t\tif( !$(this.span).is(\":visible\") ) {\n\t\t\t// We cannot calc offsets for hidden elements\n\t\t\tthis.warn(\"scrollIntoView(): node is invisible.\");\n\t\t\treturn _getResolvedPromise();\n\t\t}\n\t\tif( isParentWindow ) {\n\t\t\tnodeY = $(this.span).offset().top;\n\t\t\ttopNodeY = (topNode && topNode.span) ? $(topNode.span).offset().top : 0;\n\t\t\t$animateTarget = $(\"html,body\");\n\n\t\t} else {\n\t\t\t_assert($container[0] !== document && $container[0] !== document.body,\n\t\t\t\t\"scrollParent should be a simple element or `window`, not document or body.\");\n\n\t\t\tcontainerOffsetTop = $container.offset().top,\n\t\t\tnodeY = $(this.span).offset().top - containerOffsetTop + scrollTop; // relative to scroll parent\n\t\t\ttopNodeY = topNode ? $(topNode.span).offset().top - containerOffsetTop + scrollTop : 0;\n\t\t\thorzScrollbarHeight = Math.max(0, ($container.innerHeight() - $container[0].clientHeight));\n\t\t\tcontainerHeight -= horzScrollbarHeight;\n\t\t}\n\n\t\t// this.debug(\"    scrollIntoView(), nodeY=\" + nodeY + \", containerHeight=\" + containerHeight);\n\t\tif( nodeY < (scrollTop + topOfs) ){\n\t\t\t// Node is above visible container area\n\t\t\tnewScrollTop = nodeY - topOfs;\n\t\t\t// this.debug(\"    scrollIntoView(), UPPER newScrollTop=\" + newScrollTop);\n\n\t\t}else if((nodeY + nodeHeight) > (scrollTop + containerHeight - bottomOfs)){\n\t\t\tnewScrollTop = nodeY + nodeHeight - containerHeight + bottomOfs;\n\t\t\t// this.debug(\"    scrollIntoView(), LOWER newScrollTop=\" + newScrollTop);\n\t\t\t// If a topNode was passed, make sure that it is never scrolled\n\t\t\t// outside the upper border\n\t\t\tif(topNode){\n\t\t\t\t_assert(topNode.isRootNode() || $(topNode.span).is(\":visible\"), \"topNode must be visible\");\n\t\t\t\tif( topNodeY < newScrollTop ){\n\t\t\t\t\tnewScrollTop = topNodeY - topOfs;\n\t\t\t\t\t// this.debug(\"    scrollIntoView(), TOP newScrollTop=\" + newScrollTop);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif(newScrollTop !== null){\n\t\t\t// this.debug(\"    scrollIntoView(), SET newScrollTop=\" + newScrollTop);\n\t\t\tif(opts.effects){\n\t\t\t\topts.effects.complete = function(){\n\t\t\t\t\tdfd.resolveWith(that);\n\t\t\t\t};\n\t\t\t\t$animateTarget.stop(true).animate({\n\t\t\t\t\tscrollTop: newScrollTop\n\t\t\t\t}, opts.effects);\n\t\t\t}else{\n\t\t\t\t$animateTarget[0].scrollTop = newScrollTop;\n\t\t\t\tdfd.resolveWith(this);\n\t\t\t}\n\t\t}else{\n\t\t\tdfd.resolveWith(this);\n\t\t}\n\t\treturn dfd.promise();\n\t},\n\n\t/**Activate this node.\n\t * @param {boolean} [flag=true] pass false to deactivate\n\t * @param {object} [opts] additional options. Defaults to {noEvents: false, noFocus: false}\n\t * @returns {$.Promise}\n\t */\n\tsetActive: function(flag, opts){\n\t\treturn this.tree._callHook(\"nodeSetActive\", this, flag, opts);\n\t},\n\t/**Expand or collapse this node. Promise is resolved, when lazy loading and animations are done.\n\t * @param {boolean} [flag=true] pass false to collapse\n\t * @param {object} [opts] additional options. Defaults to {noAnimation: false, noEvents: false}\n\t * @returns {$.Promise}\n\t */\n\tsetExpanded: function(flag, opts){\n\t\treturn this.tree._callHook(\"nodeSetExpanded\", this, flag, opts);\n\t},\n\t/**Set keyboard focus to this node.\n\t * @param {boolean} [flag=true] pass false to blur\n\t * @see Fancytree#setFocus\n\t */\n\tsetFocus: function(flag){\n\t\treturn this.tree._callHook(\"nodeSetFocus\", this, flag);\n\t},\n\t/**Select this node, i.e. check the checkbox.\n\t * @param {boolean} [flag=true] pass false to deselect\n\t */\n\tsetSelected: function(flag){\n\t\treturn this.tree._callHook(\"nodeSetSelected\", this, flag);\n\t},\n\t/**Mark a lazy node as 'error', 'loading', 'nodata', or 'ok'.\n\t * @param {string} status 'error'|'empty'|'ok'\n\t * @param {string} [message]\n\t * @param {string} [details]\n\t */\n\tsetStatus: function(status, message, details){\n\t\treturn this.tree._callHook(\"nodeSetStatus\", this, status, message, details);\n\t},\n\t/**Rename this node.\n\t * @param {string} title\n\t */\n\tsetTitle: function(title){\n\t\tthis.title = title;\n\t\tthis.renderTitle();\n\t\tthis.triggerModify(\"rename\");\n\t},\n\t/**Sort child list by title.\n\t * @param {function} [cmp] custom compare function(a, b) that returns -1, 0, or 1 (defaults to sort by title).\n\t * @param {boolean} [deep=false] pass true to sort all descendant nodes\n\t */\n\tsortChildren: function(cmp, deep) {\n\t\tvar i,l,\n\t\t\tcl = this.children;\n\n\t\tif( !cl ){\n\t\t\treturn;\n\t\t}\n\t\tcmp = cmp || function(a, b) {\n\t\t\tvar x = a.title.toLowerCase(),\n\t\t\t\ty = b.title.toLowerCase();\n\t\t\treturn x === y ? 0 : x > y ? 1 : -1;\n\t\t\t};\n\t\tcl.sort(cmp);\n\t\tif( deep ){\n\t\t\tfor(i=0, l=cl.length; i<l; i++){\n\t\t\t\tif( cl[i].children ){\n\t\t\t\t\tcl[i].sortChildren(cmp, \"$norender$\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif( deep !== \"$norender$\" ){\n\t\t\tthis.render();\n\t\t}\n\t\tthis.triggerModifyChild(\"sort\");\n\t},\n\t/** Convert node (or whole branch) into a plain object.\n\t *\n\t * The result is compatible with node.addChildren().\n\t *\n\t * @param {boolean} [recursive=false] include child nodes\n\t * @param {function} [callback] callback(dict, node) is called for every node, in order to allow modifications\n\t * @returns {NodeData}\n\t */\n\ttoDict: function(recursive, callback) {\n\t\tvar i, l, node,\n\t\t\tdict = {},\n\t\t\tself = this;\n\n\t\t$.each(NODE_ATTRS, function(i, a){\n\t\t\tif(self[a] || self[a] === false){\n\t\t\t\tdict[a] = self[a];\n\t\t\t}\n\t\t});\n\t\tif(!$.isEmptyObject(this.data)){\n\t\t\tdict.data = $.extend({}, this.data);\n\t\t\tif($.isEmptyObject(dict.data)){\n\t\t\t\tdelete dict.data;\n\t\t\t}\n\t\t}\n\t\tif( callback ){\n\t\t\tcallback(dict, self);\n\t\t}\n\t\tif( recursive ) {\n\t\t\tif(this.hasChildren()){\n\t\t\t\tdict.children = [];\n\t\t\t\tfor(i=0, l=this.children.length; i<l; i++ ){\n\t\t\t\t\tnode = this.children[i];\n\t\t\t\t\tif( !node.isStatusNode() ){\n\t\t\t\t\t\tdict.children.push(node.toDict(true, callback));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}else{\n//                dict.children = null;\n\t\t\t}\n\t\t}\n\t\treturn dict;\n\t},\n\t/**\n\t * Set, clear, or toggle class of node's span tag and .extraClasses.\n\t *\n\t * @param {string} className class name (separate multiple classes by space)\n\t * @param {boolean} [flag] true/false to add/remove class. If omitted, class is toggled.\n\t * @returns {boolean} true if a class was added\n\t *\n\t * @since 2.17\n\t */\n\ttoggleClass: function(value, flag){\n\t\tvar className, hasClass,\n\t\t\trnotwhite = ( /\\S+/g ),\n\t\t\tclassNames = value.match( rnotwhite ) || [],\n\t\t\ti = 0,\n\t\t\twasAdded = false,\n\t\t\tstatusElem = this[this.tree.statusClassPropName],\n\t\t\tcurClasses = (\" \" + (this.extraClasses || \"\") + \" \");\n\n\t\t// this.info(\"toggleClass('\" + value + \"', \" + flag + \")\", curClasses);\n\t\t// Modify DOM element directly if it already exists\n\t\tif( statusElem ) {\n\t\t\t$(statusElem).toggleClass(value, flag);\n\t\t}\n\t\t// Modify node.extraClasses to make this change persistent\n\t\t// Toggle if flag was not passed\n\t\twhile ( className = classNames[ i++ ] ) {\n\t\t\thasClass = curClasses.indexOf(\" \" + className + \" \") >= 0;\n\t\t\tflag = (flag === undefined) ? (!hasClass) : !!flag;\n\t\t\tif ( flag ) {\n\t\t\t\tif( !hasClass ) {\n\t\t\t\t\tcurClasses += className + \" \";\n\t\t\t\t\twasAdded = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\twhile ( curClasses.indexOf( \" \" + className + \" \" ) > -1 ) {\n\t\t\t\t\tcurClasses = curClasses.replace( \" \" + className + \" \", \" \" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis.extraClasses = $.trim(curClasses);\n\t\t// this.info(\"-> toggleClass('\" + value + \"', \" + flag + \"): '\" + this.extraClasses + \"'\");\n\t\treturn wasAdded;\n\t},\n\t/** Flip expanded status.  */\n\ttoggleExpanded: function(){\n\t\treturn this.tree._callHook(\"nodeToggleExpanded\", this);\n\t},\n\t/** Flip selection status.  */\n\ttoggleSelected: function(){\n\t\treturn this.tree._callHook(\"nodeToggleSelected\", this);\n\t},\n\ttoString: function() {\n\t\treturn \"<FancytreeNode(#\" + this.key + \", '\" + this.title + \"')>\";\n\t},\n\t/**\n\t * Trigger `modifyChild` event on a parent to signal that a child was modified.\n\t * @param {string} operation Type of change: 'add', 'remove', 'rename', 'move', 'data', ...\n\t * @param {FancytreeNode} [childNode]\n\t * @param {object} [extra]\n\t */\n\ttriggerModifyChild: function(operation, childNode, extra){\n\t\tvar data,\n\t\t\tmodifyChild = this.tree.options.modifyChild;\n\n\t\tif ( modifyChild ){\n\t\t\tif( childNode && childNode.parent !== this ) {\n\t\t\t\t$.error(\"childNode \" + childNode + \" is not a child of \" + this);\n\t\t\t}\n\t\t\tdata = {\n\t\t\t\tnode: this,\n\t\t\t\ttree: this.tree,\n\t\t\t\toperation: operation,\n\t\t\t\tchildNode: childNode || null\n\t\t\t};\n\t\t\tif( extra ) {\n\t\t\t\t$.extend(data, extra);\n\t\t\t}\n\t\t\tmodifyChild({type: \"modifyChild\"}, data);\n\t\t}\n\t},\n\t/**\n\t * Trigger `modifyChild` event on node.parent(!).\n\t * @param {string} operation Type of change: 'add', 'remove', 'rename', 'move', 'data', ...\n\t * @param {object} [extra]\n\t */\n\ttriggerModify: function(operation, extra){\n\t\tthis.parent.triggerModifyChild(operation, this, extra);\n\t},\n\t/** Call fn(node) for all child nodes.<br>\n\t * Stop iteration, if fn() returns false. Skip current branch, if fn() returns \"skip\".<br>\n\t * Return false if iteration was stopped.\n\t *\n\t * @param {function} fn the callback function.\n\t *     Return false to stop iteration, return \"skip\" to skip this node and\n\t *     its children only.\n\t * @param {boolean} [includeSelf=false]\n\t * @returns {boolean}\n\t */\n\tvisit: function(fn, includeSelf) {\n\t\tvar i, l,\n\t\t\tres = true,\n\t\t\tchildren = this.children;\n\n\t\tif( includeSelf === true ) {\n\t\t\tres = fn(this);\n\t\t\tif( res === false || res === \"skip\" ){\n\t\t\t\treturn res;\n\t\t\t}\n\t\t}\n\t\tif(children){\n\t\t\tfor(i=0, l=children.length; i<l; i++){\n\t\t\t\tres = children[i].visit(fn, true);\n\t\t\t\tif( res === false ){\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn res;\n\t},\n\t/** Call fn(node) for all child nodes and recursively load lazy children.<br>\n\t * <b>Note:</b> If you need this method, you probably should consider to review\n\t * your architecture! Recursivley loading nodes is a perfect way for lazy\n\t * programmers to flood the server with requests ;-)\n\t *\n\t * @param {function} [fn] optional callback function.\n\t *     Return false to stop iteration, return \"skip\" to skip this node and\n\t *     its children only.\n\t * @param {boolean} [includeSelf=false]\n\t * @returns {$.Promise}\n\t * @since 2.4\n\t */\n\tvisitAndLoad: function(fn, includeSelf, _recursion) {\n\t\tvar dfd, res, loaders,\n\t\t\tnode = this;\n\n\t\t// node.debug(\"visitAndLoad\");\n\t\tif( fn && includeSelf === true ) {\n\t\t\tres = fn(node);\n\t\t\tif( res === false || res === \"skip\" ) {\n\t\t\t\treturn _recursion ? res : _getResolvedPromise();\n\t\t\t}\n\t\t}\n\t\tif( !node.children && !node.lazy ) {\n\t\t\treturn _getResolvedPromise();\n\t\t}\n\t\tdfd = new $.Deferred();\n\t\tloaders = [];\n\t\t// node.debug(\"load()...\");\n\t\tnode.load().done(function(){\n\t\t\t// node.debug(\"load()... done.\");\n\t\t\tfor(var i=0, l=node.children.length; i<l; i++){\n\t\t\t\tres = node.children[i].visitAndLoad(fn, true, true);\n\t\t\t\tif( res === false ) {\n\t\t\t\t\tdfd.reject();\n\t\t\t\t\tbreak;\n\t\t\t\t} else if ( res !== \"skip\" ) {\n\t\t\t\t\tloaders.push(res); // Add promise to the list\n\t\t\t\t}\n\t\t\t}\n\t\t\t$.when.apply(this, loaders).then(function(){\n\t\t\t\tdfd.resolve();\n\t\t\t});\n\t\t});\n\t\treturn dfd.promise();\n\t},\n\t/** Call fn(node) for all parent nodes, bottom-up, including invisible system root.<br>\n\t * Stop iteration, if fn() returns false.<br>\n\t * Return false if iteration was stopped.\n\t *\n\t * @param {function} fn the callback function.\n\t *     Return false to stop iteration, return \"skip\" to skip this node and children only.\n\t * @param {boolean} [includeSelf=false]\n\t * @returns {boolean}\n\t */\n\tvisitParents: function(fn, includeSelf) {\n\t\t// Visit parent nodes (bottom up)\n\t\tif(includeSelf && fn(this) === false){\n\t\t\treturn false;\n\t\t}\n\t\tvar p = this.parent;\n\t\twhile( p ) {\n\t\t\tif(fn(p) === false){\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tp = p.parent;\n\t\t}\n\t\treturn true;\n\t},\n\t/** Write warning to browser console (prepending node info)\n\t *\n\t * @param {*} msg string or object or array of such\n\t */\n\twarn: function(msg){\n\t\tArray.prototype.unshift.call(arguments, this.toString());\n\t\tconsoleApply(\"warn\", arguments);\n\t}\n};\n\n\n/* *****************************************************************************\n * Fancytree\n */\n/**\n * Construct a new tree object.\n *\n * @class Fancytree\n * @classdesc The controller behind a fancytree.\n * This class also contains 'hook methods': see {@link Fancytree_Hooks}.\n *\n * @param {Widget} widget\n *\n * @property {string} _id Automatically generated unique tree instance ID, e.g. \"1\".\n * @property {string} _ns Automatically generated unique tree namespace, e.g. \".fancytree-1\".\n * @property {FancytreeNode} activeNode Currently active node or null.\n * @property {string} ariaPropName Property name of FancytreeNode that contains the element which will receive the aria attributes.\n *     Typically \"li\", but \"tr\" for table extension.\n * @property {jQueryObject} $container Outer &lt;ul> element (or &lt;table> element for ext-table).\n * @property {jQueryObject} $div A jQuery object containing the element used to instantiate the tree widget (`widget.element`)\n * @property {object} data Metadata, i.e. properties that may be passed to `source` in addition to a children array.\n * @property {object} ext Hash of all active plugin instances.\n * @property {FancytreeNode} focusNode Currently focused node or null.\n * @property {FancytreeNode} lastSelectedNode Used to implement selectMode 1 (single select)\n * @property {string} nodeContainerAttrName Property name of FancytreeNode that contains the outer element of single nodes.\n *     Typically \"li\", but \"tr\" for table extension.\n * @property {FancytreeOptions} options Current options, i.e. default options + options passed to constructor.\n * @property {FancytreeNode} rootNode Invisible system root node.\n * @property {string} statusClassPropName Property name of FancytreeNode that contains the element which will receive the status classes.\n *     Typically \"span\", but \"tr\" for table extension.\n * @property {object} widget Base widget instance.\n */\nfunction Fancytree(widget) {\n\tthis.widget = widget;\n\tthis.$div = widget.element;\n\tthis.options = widget.options;\n\tif( this.options ) {\n\t\tif(  $.isFunction(this.options.lazyload ) && !$.isFunction(this.options.lazyLoad) ) {\n\t\t\tthis.options.lazyLoad = function() {\n\t\t\t\tFT.warn(\"The 'lazyload' event is deprecated since 2014-02-25. Use 'lazyLoad' (with uppercase L) instead.\");\n\t\t\t\treturn widget.options.lazyload.apply(this, arguments);\n\t\t\t};\n\t\t}\n\t\tif( $.isFunction(this.options.loaderror) ) {\n\t\t\t$.error(\"The 'loaderror' event was renamed since 2014-07-03. Use 'loadError' (with uppercase E) instead.\");\n\t\t}\n\t\tif( this.options.fx !== undefined ) {\n\t\t\tFT.warn(\"The 'fx' option was replaced by 'toggleEffect' since 2014-11-30.\");\n\t\t}\n\t\tif( this.options.removeNode !== undefined ) {\n\t\t\t$.error(\"The 'removeNode' event was replaced by 'modifyChild' since 2.20 (2016-09-10).\");\n\t\t}\n\t}\n\tthis.ext = {}; // Active extension instances\n\t// allow to init tree.data.foo from <div data-foo=''>\n\tthis.data = _getElementDataAsDict(this.$div);\n\t// TODO: use widget.uuid instead?\n\tthis._id = $.ui.fancytree._nextId++;\n\t// TODO: use widget.eventNamespace instead?\n\tthis._ns = \".fancytree-\" + this._id; // append for namespaced events\n\tthis.activeNode = null;\n\tthis.focusNode = null;\n\tthis._hasFocus = null;\n\tthis._enableUpdate = true;\n\t// this._dirtyRoots = null;\n\tthis.lastSelectedNode = null;\n\tthis.systemFocusElement = null;\n\tthis.lastQuicksearchTerm = \"\";\n\tthis.lastQuicksearchTime = 0;\n\n\tthis.statusClassPropName = \"span\";\n\tthis.ariaPropName = \"li\";\n\tthis.nodeContainerAttrName = \"li\";\n\n\t// Remove previous markup if any\n\tthis.$div.find(\">ul.fancytree-container\").remove();\n\n\t// Create a node without parent.\n\tvar fakeParent = { tree: this },\n\t\t$ul;\n\tthis.rootNode = new FancytreeNode(fakeParent, {\n\t\ttitle: \"root\",\n\t\tkey: \"root_\" + this._id,\n\t\tchildren: null,\n\t\texpanded: true\n\t});\n\tthis.rootNode.parent = null;\n\n\t// Create root markup\n\t$ul = $(\"<ul>\", {\n\t\t\"class\": \"ui-fancytree fancytree-container fancytree-plain\"\n\t}).appendTo(this.$div);\n\tthis.$container = $ul;\n\tthis.rootNode.ul = $ul[0];\n\n\tif(this.options.debugLevel == null){\n\t\tthis.options.debugLevel = FT.debugLevel;\n\t}\n\t// Add container to the TAB chain\n\t// See http://www.w3.org/TR/wai-aria-practices/#focus_activedescendant\n\t// #577: Allow to set tabindex to \"0\", \"-1\" and \"\"\n\tthis.$container.attr(\"tabindex\", this.options.tabindex);\n\n\tif( this.options.rtl ) {\n\t\tthis.$container.attr(\"DIR\", \"RTL\").addClass(\"fancytree-rtl\");\n\t// }else{\n\t//\tthis.$container.attr(\"DIR\", null).removeClass(\"fancytree-rtl\");\n\t}\n\tif(this.options.aria){\n\t\tthis.$container.attr(\"role\", \"tree\");\n\t\tif( this.options.selectMode !== 1 ) {\n\t\t\tthis.$container.attr(\"aria-multiselectable\", true);\n\t\t}\n\t}\n}\n\n\nFancytree.prototype = /** @lends Fancytree# */{\n\t/* Return a context object that can be re-used for _callHook().\n\t * @param {Fancytree | FancytreeNode | EventData} obj\n\t * @param {Event} originalEvent\n\t * @param {Object} extra\n\t * @returns {EventData}\n\t */\n\t_makeHookContext: function(obj, originalEvent, extra) {\n\t\tvar ctx, tree;\n\t\tif(obj.node !== undefined){\n\t\t\t// obj is already a context object\n\t\t\tif(originalEvent && obj.originalEvent !== originalEvent){\n\t\t\t\t$.error(\"invalid args\");\n\t\t\t}\n\t\t\tctx = obj;\n\t\t}else if(obj.tree){\n\t\t\t// obj is a FancytreeNode\n\t\t\ttree = obj.tree;\n\t\t\tctx = { node: obj, tree: tree, widget: tree.widget, options: tree.widget.options, originalEvent: originalEvent };\n\t\t}else if(obj.widget){\n\t\t\t// obj is a Fancytree\n\t\t\tctx = { node: null, tree: obj, widget: obj.widget, options: obj.widget.options, originalEvent: originalEvent };\n\t\t}else{\n\t\t\t$.error(\"invalid args\");\n\t\t}\n\t\tif(extra){\n\t\t\t$.extend(ctx, extra);\n\t\t}\n\t\treturn ctx;\n\t},\n\t/* Trigger a hook function: funcName(ctx, [...]).\n\t *\n\t * @param {string} funcName\n\t * @param {Fancytree|FancytreeNode|EventData} contextObject\n\t * @param {any}  [_extraArgs] optional additional arguments\n\t * @returns {any}\n\t */\n\t_callHook: function(funcName, contextObject, _extraArgs) {\n\t\tvar ctx = this._makeHookContext(contextObject),\n\t\t\tfn = this[funcName],\n\t\t\targs = Array.prototype.slice.call(arguments, 2);\n\t\tif(!$.isFunction(fn)){\n\t\t\t$.error(\"_callHook('\" + funcName + \"') is not a function\");\n\t\t}\n\t\targs.unshift(ctx);\n//\t\tthis.debug(\"_hook\", funcName, ctx.node && ctx.node.toString() || ctx.tree.toString(), args);\n\t\treturn fn.apply(this, args);\n\t},\n\t/* Check if current extensions dependencies are met and throw an error if not.\n\t *\n\t * This method may be called inside the `treeInit` hook for custom extensions.\n\t *\n\t * @param {string} extension name of the required extension\n\t * @param {boolean} [required=true] pass `false` if the extension is optional, but we want to check for order if it is present\n\t * @param {boolean} [before] `true` if `name` must be included before this, `false` otherwise (use `null` if order doesn't matter)\n\t * @param {string} [message] optional error message (defaults to a descriptve error message)\n\t */\n\t_requireExtension: function(name, required, before, message) {\n\t\tbefore = !!before;\n\t\tvar thisName = this._local.name,\n\t\t\textList = this.options.extensions,\n\t\t\tisBefore = $.inArray(name, extList) < $.inArray(thisName, extList),\n\t\t\tisMissing = required && this.ext[name] == null,\n\t\t\tbadOrder = !isMissing && before != null && (before !== isBefore);\n\n\t\t_assert(thisName && thisName !== name, \"invalid or same name\");\n\n\t\tif( isMissing || badOrder ){\n\t\t\tif( !message ){\n\t\t\t\tif( isMissing || required ){\n\t\t\t\t\tmessage = \"'\" + thisName + \"' extension requires '\" + name + \"'\";\n\t\t\t\t\tif( badOrder ){\n\t\t\t\t\t\tmessage += \" to be registered \" + (before ? \"before\" : \"after\") + \" itself\";\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\tmessage = \"If used together, `\" + name + \"` must be registered \" + (before ? \"before\" : \"after\") + \" `\" + thisName + \"`\";\n\t\t\t\t}\n\t\t\t}\n\t\t\t$.error(message);\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\t/** Activate node with a given key and fire focus and activate events.\n\t *\n\t * A prevously activated node will be deactivated.\n\t * If activeVisible option is set, all parents will be expanded as necessary.\n\t * Pass key = false, to deactivate the current node only.\n\t * @param {string} key\n\t * @returns {FancytreeNode} activated node (null, if not found)\n\t */\n\tactivateKey: function(key) {\n\t\tvar node = this.getNodeByKey(key);\n\t\tif(node){\n\t\t\tnode.setActive();\n\t\t}else if(this.activeNode){\n\t\t\tthis.activeNode.setActive(false);\n\t\t}\n\t\treturn node;\n\t},\n\t/** (experimental) Add child status nodes that indicate 'More...', ....\n\t * @param {boolean|object} node optional node definition. Pass `false` to remove all paging nodes.\n\t * @param {string} [mode='append'] 'child'|firstChild'\n\t * @since 2.15\n\t */\n\taddPagingNode: function(node, mode){\n\t\treturn this.rootNode.addPagingNode(node, mode);\n\t},\n\t/** (experimental) Modify existing data model.\n\t *\n\t * @param {Array} patchList array of [key, NodePatch] arrays\n\t * @returns {$.Promise} resolved, when all patches have been applied\n\t * @see TreePatch\n\t */\n\tapplyPatch: function(patchList) {\n\t\tvar dfd, i, p2, key, patch, node,\n\t\t\tpatchCount = patchList.length,\n\t\t\tdeferredList = [];\n\n\t\tfor(i=0; i<patchCount; i++){\n\t\t\tp2 = patchList[i];\n\t\t\t_assert(p2.length === 2, \"patchList must be an array of length-2-arrays\");\n\t\t\tkey = p2[0];\n\t\t\tpatch = p2[1];\n\t\t\tnode = (key === null) ? this.rootNode : this.getNodeByKey(key);\n\t\t\tif(node){\n\t\t\t\tdfd = new $.Deferred();\n\t\t\t\tdeferredList.push(dfd);\n\t\t\t\tnode.applyPatch(patch).always(_makeResolveFunc(dfd, node));\n\t\t\t}else{\n\t\t\t\tthis.warn(\"could not find node with key '\" + key + \"'\");\n\t\t\t}\n\t\t}\n\t\t// Return a promise that is resolved, when ALL patches were applied\n\t\treturn $.when.apply($, deferredList).promise();\n\t},\n\t/* TODO: implement in dnd extension\n\tcancelDrag: function() {\n\t\tvar dd = $.ui.ddmanager.current;\n\t\tif(dd){\n\t\t\tdd.cancel();\n\t\t}\n\t},\n   */\n\t/** Remove all nodes.\n\t * @since 2.14\n\t */\n\tclear: function(source) {\n\t\tthis._callHook(\"treeClear\", this);\n\t},\n   /** Return the number of nodes.\n\t* @returns {integer}\n\t*/\n\tcount: function() {\n\t\treturn this.rootNode.countChildren();\n\t},\n\t/** Write to browser console if debugLevel >= 2 (prepending tree name)\n\t *\n\t * @param {*} msg string or object or array of such\n\t */\n\tdebug: function(msg){\n\t\tif( this.options.debugLevel >= 2 ) {\n\t\t\tArray.prototype.unshift.call(arguments, this.toString());\n\t\t\tconsoleApply(\"log\", arguments);\n\t\t}\n\t},\n\t// TODO: disable()\n\t// TODO: enable()\n\t/** Temporarily suppress rendering to improve performance on bulk-updates.\n\t *\n\t * @param {boolean} flag\n\t * @returns {boolean} previous status\n\t * @since 2.19\n\t */\n\tenableUpdate: function(flag) {\n\t\tflag = ( flag !== false );\n\t\t/*jshint -W018 */  // Confusing use of '!'\n\t\tif ( !!this._enableUpdate === !!flag ) {\n\t\t\treturn flag;\n\t\t}\n\t\t/*jshint +W018 */\n\t\tthis._enableUpdate = flag;\n\t\tif ( flag ) {\n\t\t\tthis.debug(\"enableUpdate(true): redraw \", this._dirtyRoots);\n\t\t\tthis.render();\n\t\t} else {\n\t\t// \tthis._dirtyRoots = null;\n\t\t\tthis.debug(\"enableUpdate(false)...\");\n\t\t}\n\t\treturn !flag; // return previous value\n\t},\n\t/**Find all nodes that matches condition.\n\t *\n\t * @param {string | function(node)} match title string to search for, or a\n\t *     callback function that returns `true` if a node is matched.\n\t * @returns {FancytreeNode[]} array of nodes (may be empty)\n\t * @see FancytreeNode#findAll\n\t * @since 2.12\n\t */\n\tfindAll: function(match) {\n\t\treturn this.rootNode.findAll(match);\n\t},\n\t/**Find first node that matches condition.\n\t *\n\t * @param {string | function(node)} match title string to search for, or a\n\t *     callback function that returns `true` if a node is matched.\n\t * @returns {FancytreeNode} matching node or null\n\t * @see FancytreeNode#findFirst\n\t * @since 2.12\n\t */\n\tfindFirst: function(match) {\n\t\treturn this.rootNode.findFirst(match);\n\t},\n\t/** Find the next visible node that starts with `match`, starting at `startNode`\n\t * and wrap-around at the end.\n\t *\n\t * @param {string|function} match\n\t * @param {FancytreeNode} [startNode] defaults to first node\n\t * @returns {FancytreeNode} matching node or null\n\t */\n\tfindNextNode: function(match, startNode, visibleOnly) {\n\t\tvar stopNode = null,\n\t\t\tparentChildren = startNode.parent.children,\n\t\t\tmatchingNode = null,\n\t\t\twalkVisible = function(parent, idx, fn) {\n\t\t\t\tvar i, grandParent,\n\t\t\t\t\tparentChildren = parent.children,\n\t\t\t\t\tsiblingCount = parentChildren.length,\n\t\t\t\t\tnode = parentChildren[idx];\n\t\t\t\t// visit node itself\n\t\t\t\tif( node && fn(node) === false ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t// visit descendants\n\t\t\t\tif( node && node.children && node.expanded ) {\n\t\t\t\t\tif( walkVisible(node, 0, fn) === false ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// visit subsequent siblings\n\t\t\t\tfor( i = idx + 1; i < siblingCount; i++ ) {\n\t\t\t\t\tif( walkVisible(parent, i, fn) === false ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// visit parent's subsequent siblings\n\t\t\t\tgrandParent = parent.parent;\n\t\t\t\tif( grandParent ) {\n\t\t\t\t\treturn walkVisible(grandParent, grandParent.children.indexOf(parent) + 1, fn);\n\t\t\t\t} else {\n\t\t\t\t\t// wrap-around: restart with first node\n\t\t\t\t\treturn walkVisible(parent, 0, fn);\n\t\t\t\t}\n\t\t\t};\n\n\t\tmatch = (typeof match === \"string\") ? _makeNodeTitleStartMatcher(match) : match;\n\t\tstartNode = startNode || this.getFirstChild();\n\n\t\twalkVisible(startNode.parent, parentChildren.indexOf(startNode), function(node){\n\t\t\t// Stop iteration if we see the start node a second time\n\t\t\tif( node === stopNode ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tstopNode = stopNode || node;\n\t\t\t// Ignore nodes hidden by a filter\n\t\t\tif( ! $(node.span).is(\":visible\") ) {\n\t\t\t\tnode.debug(\"quicksearch: skipping hidden node\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Test if we found a match, but search for a second match if this\n\t\t\t// was the currently active node\n\t\t\tif( match(node) ) {\n\t\t\t\t// node.debug(\"quicksearch match \" + node.title, startNode);\n\t\t\t\tmatchingNode = node;\n\t\t\t\tif( matchingNode !== startNode ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn matchingNode;\n\t},\n\t// TODO: fromDict\n\t/**\n\t * Generate INPUT elements that can be submitted with html forms.\n\t *\n\t * In selectMode 3 only the topmost selected nodes are considered, unless\n\t * `opts.stopOnParents: false` is passed.\n\t *\n\t * @example\n\t * // Generate input elements for active and selected nodes\n\t * tree.generateFormElements();\n\t * // Generate input elements selected nodes, using a custom `name` attribute\n\t * tree.generateFormElements(\"cust_sel\", false);\n\t * // Generate input elements using a custom filter\n\t * tree.generateFormElements(true, true, { filter: function(node) {\n\t *     return node.isSelected() && node.data.yes;\n\t * }});\n\t *\n\t * @param {boolean | string} [selected=true] Pass false to disable, pass a string to override the field name (default: 'ft_ID[]')\n\t * @param {boolean | string} [active=true] Pass false to disable, pass a string to override the field name (default: 'ft_ID_active')\n\t * @param {object} [opts] default { filter: null, stopOnParents: true }\n\t */\n\tgenerateFormElements: function(selected, active, opts) {\n\t\topts = opts || {};\n\n\t\tvar nodeList,\n\t\t\tselectedName = (typeof selected === \"string\") ? selected : \"ft_\" + this._id + \"[]\",\n\t\t\tactiveName = (typeof active === \"string\") ? active : \"ft_\" + this._id + \"_active\",\n\t\t\tid = \"fancytree_result_\" + this._id,\n\t\t\t$result = $(\"#\" + id),\n\t\t\tstopOnParents = this.options.selectMode === 3 && opts.stopOnParents !== false;\n\n\t\tif($result.length){\n\t\t\t$result.empty();\n\t\t}else{\n\t\t\t$result = $(\"<div>\", {\n\t\t\t\tid: id\n\t\t\t}).hide().insertAfter(this.$container);\n\t\t}\n\t\tif(active !== false && this.activeNode){\n\t\t\t$result.append($(\"<input>\", {\n\t\t\t\ttype: \"radio\",\n\t\t\t\tname: activeName,\n\t\t\t\tvalue: this.activeNode.key,\n\t\t\t\tchecked: true\n\t\t\t}));\n\t\t}\n\t\tfunction _appender( node ) {\n\t\t\t$result.append($(\"<input>\", {\n\t\t\t\ttype: \"checkbox\",\n\t\t\t\tname: selectedName,\n\t\t\t\tvalue: node.key,\n\t\t\t\tchecked: true\n\t\t\t}));\n\t\t}\n\t\tif ( opts.filter ) {\n\t\t\tthis.visit(function(node) {\n\t\t\t\tvar res = opts.filter(node);\n\t\t\t\tif( res === \"skip\" ) { return res; }\n\t\t\t\tif ( res !== false ) {\n\t\t\t\t\t_appender(node);\n\t\t\t\t}\n\t\t\t});\n\t\t} else if ( selected !== false ) {\n\t\t\tnodeList = this.getSelectedNodes(stopOnParents);\n\t\t\t$.each(nodeList, function(idx, node) {\n\t\t\t\t_appender(node);\n\t\t\t});\n\t\t}\n\t},\n\t/**\n\t * Return the currently active node or null.\n\t * @returns {FancytreeNode}\n\t */\n\tgetActiveNode: function() {\n\t\treturn this.activeNode;\n\t},\n\t/** Return the first top level node if any (not the invisible root node).\n\t * @returns {FancytreeNode | null}\n\t */\n\tgetFirstChild: function() {\n\t\treturn this.rootNode.getFirstChild();\n\t},\n\t/**\n\t * Return node that has keyboard focus or null.\n\t * @returns {FancytreeNode}\n\t */\n\tgetFocusNode: function() {\n\t\treturn this.focusNode;\n\t},\n\t/**\n\t * Return node with a given key or null if not found.\n\t * @param {string} key\n\t * @param {FancytreeNode} [searchRoot] only search below this node\n\t * @returns {FancytreeNode | null}\n\t */\n\tgetNodeByKey: function(key, searchRoot) {\n\t\t// Search the DOM by element ID (assuming this is faster than traversing all nodes).\n\t\t// $(\"#...\") has problems, if the key contains '.', so we use getElementById()\n\t\tvar el, match;\n\t\tif(!searchRoot){\n\t\t\tel = document.getElementById(this.options.idPrefix + key);\n\t\t\tif( el ){\n\t\t\t\treturn el.ftnode ? el.ftnode : null;\n\t\t\t}\n\t\t}\n\t\t// Not found in the DOM, but still may be in an unrendered part of tree\n\t\t// TODO: optimize with specialized loop\n\t\t// TODO: consider keyMap?\n\t\tsearchRoot = searchRoot || this.rootNode;\n\t\tmatch = null;\n\t\tsearchRoot.visit(function(node){\n//            window.console.log(\"getNodeByKey(\" + key + \"): \", node.key);\n\t\t\tif(node.key === key) {\n\t\t\t\tmatch = node;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}, true);\n\t\treturn match;\n\t},\n\t/** Return the invisible system root node.\n\t * @returns {FancytreeNode}\n\t */\n\tgetRootNode: function() {\n\t\treturn this.rootNode;\n\t},\n\t/**\n\t * Return an array of selected nodes.\n\t * @param {boolean} [stopOnParents=false] only return the topmost selected\n\t *     node (useful with selectMode 3)\n\t * @returns {FancytreeNode[]}\n\t */\n\tgetSelectedNodes: function(stopOnParents) {\n\t\treturn this.rootNode.getSelectedNodes(stopOnParents);\n\t},\n\t/** Return true if the tree control has keyboard focus\n\t * @returns {boolean}\n\t */\n\thasFocus: function(){\n\t\treturn !!this._hasFocus;\n\t},\n\t/** Write to browser console if debugLevel >= 1 (prepending tree name)\n\t * @param {*} msg string or object or array of such\n\t */\n\tinfo: function(msg){\n\t\tif( this.options.debugLevel >= 1 ) {\n\t\t\tArray.prototype.unshift.call(arguments, this.toString());\n\t\t\tconsoleApply(\"info\", arguments);\n\t\t}\n\t},\n/*\n\tTODO: isInitializing: function() {\n\t\treturn ( this.phase==\"init\" || this.phase==\"postInit\" );\n\t},\n\tTODO: isReloading: function() {\n\t\treturn ( this.phase==\"init\" || this.phase==\"postInit\" ) && this.options.persist && this.persistence.cookiesFound;\n\t},\n\tTODO: isUserEvent: function() {\n\t\treturn ( this.phase==\"userEvent\" );\n\t},\n*/\n\n\t/**\n\t * Make sure that a node with a given ID is loaded, by traversing - and\n\t * loading - its parents. This method is ment for lazy hierarchies.\n\t * A callback is executed for every node as we go.\n\t * @example\n\t * tree.loadKeyPath(\"/_3/_23/_26/_27\", function(node, status){\n\t *   if(status === \"loaded\") {\n\t *     console.log(\"loaded intermiediate node \" + node);\n\t *   }else if(status === \"ok\") {\n\t *     node.activate();\n\t *   }\n\t * });\n\t *\n\t * @param {string | string[]} keyPathList one or more key paths (e.g. '/3/2_1/7')\n\t * @param {function} callback callback(node, status) is called for every visited node ('loading', 'loaded', 'ok', 'error')\n\t * @returns {$.Promise}\n\t */\n\tloadKeyPath: function(keyPathList, callback, _rootNode) {\n\t\tvar deferredList, dfd, i, path, key, loadMap, node, root, segList,\n\t\t\tsep = this.options.keyPathSeparator,\n\t\t\tself = this;\n\n\t\tcallback = callback || $.noop;\n\t\tif(!$.isArray(keyPathList)){\n\t\t\tkeyPathList = [keyPathList];\n\t\t}\n\t\t// Pass 1: handle all path segments for nodes that are already loaded\n\t\t// Collect distinct top-most lazy nodes in a map\n\t\tloadMap = {};\n\n\t\tfor(i=0; i<keyPathList.length; i++){\n\t\t\troot = _rootNode || this.rootNode;\n\t\t\tpath = keyPathList[i];\n\t\t\t// strip leading slash\n\t\t\tif(path.charAt(0) === sep){\n\t\t\t\tpath = path.substr(1);\n\t\t\t}\n\t\t\t// traverse and strip keys, until we hit a lazy, unloaded node\n\t\t\tsegList = path.split(sep);\n\t\t\twhile(segList.length){\n\t\t\t\tkey = segList.shift();\n//                node = _findDirectChild(root, key);\n\t\t\t\tnode = root._findDirectChild(key);\n\t\t\t\tif(!node){\n\t\t\t\t\tthis.warn(\"loadKeyPath: key not found: \" + key + \" (parent: \" + root + \")\");\n\t\t\t\t\tcallback.call(this, key, \"error\");\n\t\t\t\t\tbreak;\n\t\t\t\t}else if(segList.length === 0){\n\t\t\t\t\tcallback.call(this, node, \"ok\");\n\t\t\t\t\tbreak;\n\t\t\t\t}else if(!node.lazy || (node.hasChildren() !== undefined )){\n\t\t\t\t\tcallback.call(this, node, \"loaded\");\n\t\t\t\t\troot = node;\n\t\t\t\t}else{\n\t\t\t\t\tcallback.call(this, node, \"loaded\");\n//                    segList.unshift(key);\n\t\t\t\t\tif(loadMap[key]){\n\t\t\t\t\t\tloadMap[key].push(segList.join(sep));\n\t\t\t\t\t}else{\n\t\t\t\t\t\tloadMap[key] = [segList.join(sep)];\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n//        alert(\"loadKeyPath: loadMap=\" + JSON.stringify(loadMap));\n\t\t// Now load all lazy nodes and continue itearation for remaining paths\n\t\tdeferredList = [];\n\t\t// Avoid jshint warning 'Don't make functions within a loop.':\n\t\tfunction __lazyload(key, node, dfd){\n\t\t\tcallback.call(self, node, \"loading\");\n\t\t\tnode.load().done(function(){\n\t\t\t\tself.loadKeyPath.call(self, loadMap[key], callback, node).always(_makeResolveFunc(dfd, self));\n\t\t\t}).fail(function(errMsg){\n\t\t\t\tself.warn(\"loadKeyPath: error loading: \" + key + \" (parent: \" + root + \")\");\n\t\t\t\tcallback.call(self, node, \"error\");\n\t\t\t\tdfd.reject();\n\t\t\t});\n\t\t}\n\t\tfor(key in loadMap){\n\t\t\tnode = root._findDirectChild(key);\n\t\t\tif (node == null) {  // #576\n\t\t\t\tnode = self.getNodeByKey(key);\n\t\t\t}\n\t\t\tdfd = new $.Deferred();\n\t\t\tdeferredList.push(dfd);\n\t\t\t__lazyload(key, node, dfd);\n\t\t}\n\t\t// Return a promise that is resolved, when ALL paths were loaded\n\t\treturn $.when.apply($, deferredList).promise();\n\t},\n\t/** Re-fire beforeActivate, activate, and (optional) focus events.\n\t * Calling this method in the `init` event, will activate the node that\n\t * was marked 'active' in the source data, and optionally set the keyboard\n\t * focus.\n\t * @param [setFocus=false]\n\t */\n\treactivate: function(setFocus) {\n\t\tvar res,\n\t\t\tnode = this.activeNode;\n\n\t\tif( !node ) {\n\t\t\treturn _getResolvedPromise();\n\t\t}\n\t\tthis.activeNode = null; // Force re-activating\n\t\tres = node.setActive(true, {noFocus: true});\n\t\tif( setFocus ){\n\t\t\tnode.setFocus();\n\t\t}\n\t\treturn res;\n\t},\n\t/** Reload tree from source and return a promise.\n\t * @param [source] optional new source (defaults to initial source data)\n\t * @returns {$.Promise}\n\t */\n\treload: function(source) {\n\t\tthis._callHook(\"treeClear\", this);\n\t\treturn this._callHook(\"treeLoad\", this, source);\n\t},\n\t/**Render tree (i.e. create DOM elements for all top-level nodes).\n\t * @param {boolean} [force=false] create DOM elemnts, even if parent is collapsed\n\t * @param {boolean} [deep=false]\n\t */\n\trender: function(force, deep) {\n\t\treturn this.rootNode.render(force, deep);\n\t},\n\t// TODO: selectKey: function(key, select)\n\t// TODO: serializeArray: function(stopOnParents)\n\t/**\n\t * @param {boolean} [flag=true]\n\t */\n\tsetFocus: function(flag) {\n\t\treturn this._callHook(\"treeSetFocus\", this, flag);\n\t},\n\t/**\n\t * Return all nodes as nested list of {@link NodeData}.\n\t *\n\t * @param {boolean} [includeRoot=false] Returns the hidden system root node (and its children)\n\t * @param {function} [callback] callback(dict, node) is called for every node, in order to allow modifications\n\t * @returns {Array | object}\n\t * @see FancytreeNode#toDict\n\t */\n\ttoDict: function(includeRoot, callback){\n\t\tvar res = this.rootNode.toDict(true, callback);\n\t\treturn includeRoot ? res : res.children;\n\t},\n\t/* Implicitly called for string conversions.\n\t * @returns {string}\n\t */\n\ttoString: function(){\n\t\treturn \"<Fancytree(#\" + this._id + \")>\";\n\t},\n\t/* _trigger a widget event with additional node ctx.\n\t * @see EventData\n\t */\n\t_triggerNodeEvent: function(type, node, originalEvent, extra) {\n//\t\tthis.debug(\"_trigger(\" + type + \"): '\" + ctx.node.title + \"'\", ctx);\n\t\tvar ctx = this._makeHookContext(node, originalEvent, extra),\n\t\t\tres = this.widget._trigger(type, originalEvent, ctx);\n\t\tif(res !== false && ctx.result !== undefined){\n\t\t\treturn ctx.result;\n\t\t}\n\t\treturn res;\n\t},\n\t/* _trigger a widget event with additional tree data. */\n\t_triggerTreeEvent: function(type, originalEvent, extra) {\n//\t\tthis.debug(\"_trigger(\" + type + \")\", ctx);\n\t\tvar ctx = this._makeHookContext(this, originalEvent, extra),\n\t\t\tres = this.widget._trigger(type, originalEvent, ctx);\n\n\t\tif(res !== false && ctx.result !== undefined){\n\t\t\treturn ctx.result;\n\t\t}\n\t\treturn res;\n\t},\n\t/** Call fn(node) for all nodes.\n\t *\n\t * @param {function} fn the callback function.\n\t *     Return false to stop iteration, return \"skip\" to skip this node and children only.\n\t * @returns {boolean} false, if the iterator was stopped.\n\t */\n\tvisit: function(fn) {\n\t\treturn this.rootNode.visit(fn, false);\n\t},\n\t/** Write warning to browser console (prepending tree info)\n\t *\n\t * @param {*} msg string or object or array of such\n\t */\n\twarn: function(msg){\n\t\tArray.prototype.unshift.call(arguments, this.toString());\n\t\tconsoleApply(\"warn\", arguments);\n\t}\n};\n\n/**\n * These additional methods of the {@link Fancytree} class are 'hook functions'\n * that can be used and overloaded by extensions.\n * (See <a href=\"https://github.com/mar10/fancytree/wiki/TutorialExtensions\">writing extensions</a>.)\n * @mixin Fancytree_Hooks\n */\n$.extend(Fancytree.prototype,\n\t/** @lends Fancytree_Hooks# */\n\t{\n\t/** Default handling for mouse click events.\n\t *\n\t * @param {EventData} ctx\n\t */\n\tnodeClick: function(ctx) {\n\t\tvar activate, expand,\n\t\t\t// event = ctx.originalEvent,\n\t\t\ttargetType = ctx.targetType,\n\t\t\tnode = ctx.node;\n\n//\t    this.debug(\"ftnode.onClick(\" + event.type + \"): ftnode:\" + this + \", button:\" + event.button + \", which: \" + event.which, ctx);\n\t\t// TODO: use switch\n\t\t// TODO: make sure clicks on embedded <input> doesn't steal focus (see table sample)\n\t\tif( targetType === \"expander\" ) {\n\t\t\tif( node.isLoading() ) {\n\t\t\t\t// #495: we probably got a click event while a lazy load is pending.\n\t\t\t\t// The 'expanded' state is not yet set, so 'toggle' would expand\n\t\t\t\t// and trigger lazyLoad again.\n\t\t\t\t// It would be better to allow to collapse/expand the status node\n\t\t\t\t// while loading (instead of ignoring), but that would require some\n\t\t\t\t// more work.\n\t\t\t\tnode.debug(\"Got 2nd click while loading: ignored\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Clicking the expander icon always expands/collapses\n\t\t\tthis._callHook(\"nodeToggleExpanded\", ctx);\n\n\t\t} else if( targetType === \"checkbox\" ) {\n\t\t\t// Clicking the checkbox always (de)selects\n\t\t\tthis._callHook(\"nodeToggleSelected\", ctx);\n\t\t\tif( ctx.options.focusOnSelect ) { // #358\n\t\t\t\tthis._callHook(\"nodeSetFocus\", ctx, true);\n\t\t\t}\n\n\t\t} else {\n\t\t\t// Honor `clickFolderMode` for\n\t\t\texpand = false;\n\t\t\tactivate = true;\n\t\t\tif( node.folder ) {\n\t\t\t\tswitch( ctx.options.clickFolderMode ) {\n\t\t\t\tcase 2: // expand only\n\t\t\t\t\texpand = true;\n\t\t\t\t\tactivate = false;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3: // expand and activate\n\t\t\t\t\tactivate = true;\n\t\t\t\t\texpand = true; //!node.isExpanded();\n\t\t\t\t\tbreak;\n\t\t\t\t// else 1 or 4: just activate\n\t\t\t\t}\n\t\t\t}\n\t\t\tif( activate ) {\n\t\t\t\tthis.nodeSetFocus(ctx);\n\t\t\t\tthis._callHook(\"nodeSetActive\", ctx, true);\n\t\t\t}\n\t\t\tif( expand ) {\n\t\t\t\tif(!activate){\n//                    this._callHook(\"nodeSetFocus\", ctx);\n\t\t\t\t}\n//\t\t\t\tthis._callHook(\"nodeSetExpanded\", ctx, true);\n\t\t\t\tthis._callHook(\"nodeToggleExpanded\", ctx);\n\t\t\t}\n\t\t}\n\t\t// Make sure that clicks stop, otherwise <a href='#'> jumps to the top\n\t\t// if(event.target.localName === \"a\" && event.target.className === \"fancytree-title\"){\n\t\t// \tevent.preventDefault();\n\t\t// }\n\t\t// TODO: return promise?\n\t},\n\t/** Collapse all other  children of same parent.\n\t *\n\t * @param {EventData} ctx\n\t * @param {object} callOpts\n\t */\n\tnodeCollapseSiblings: function(ctx, callOpts) {\n\t\t// TODO: return promise?\n\t\tvar ac, i, l,\n\t\t\tnode = ctx.node;\n\n\t\tif( node.parent ){\n\t\t\tac = node.parent.children;\n\t\t\tfor (i=0, l=ac.length; i<l; i++) {\n\t\t\t\tif ( ac[i] !== node && ac[i].expanded ){\n\t\t\t\t\tthis._callHook(\"nodeSetExpanded\", ac[i], false, callOpts);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\t/** Default handling for mouse douleclick events.\n\t * @param {EventData} ctx\n\t */\n\tnodeDblclick: function(ctx) {\n\t\t// TODO: return promise?\n\t\tif( ctx.targetType === \"title\" && ctx.options.clickFolderMode === 4) {\n//\t\t\tthis.nodeSetFocus(ctx);\n//\t\t\tthis._callHook(\"nodeSetActive\", ctx, true);\n\t\t\tthis._callHook(\"nodeToggleExpanded\", ctx);\n\t\t}\n\t\t// TODO: prevent text selection on dblclicks\n\t\tif( ctx.targetType === \"title\" ) {\n\t\t\tctx.originalEvent.preventDefault();\n\t\t}\n\t},\n\t/** Default handling for mouse keydown events.\n\t *\n\t * NOTE: this may be called with node == null if tree (but no node) has focus.\n\t * @param {EventData} ctx\n\t */\n\tnodeKeydown: function(ctx) {\n\t\t// TODO: return promise?\n\t\tvar matchNode, stamp, res, focusNode,\n\t\t\tevent = ctx.originalEvent,\n\t\t\tnode = ctx.node,\n\t\t\ttree = ctx.tree,\n\t\t\topts = ctx.options,\n\t\t\twhich = event.which,\n\t\t\twhichChar = String.fromCharCode(which),\n\t\t\tclean = !(event.altKey || event.ctrlKey || event.metaKey || event.shiftKey),\n\t\t\t$target = $(event.target),\n\t\t\thandled = true,\n\t\t\tactivate = !(event.ctrlKey || !opts.autoActivate );\n\n\t\t// (node || FT).debug(\"ftnode.nodeKeydown(\" + event.type + \"): ftnode:\" + this + \", charCode:\" + event.charCode + \", keyCode: \" + event.keyCode + \", which: \" + event.which);\n\t\t// FT.debug(\"eventToString\", which, '\"' + String.fromCharCode(which) + '\"', '\"' + FT.eventToString(event) + '\"');\n\n\t\t// Set focus to active (or first node) if no other node has the focus yet\n\t\tif( !node ){\n\t\t\tfocusNode = (this.getActiveNode() || this.getFirstChild());\n\t\t\tif (focusNode){\n\t\t\t\tfocusNode.setFocus();\n\t\t\t\tnode = ctx.node = this.focusNode;\n\t\t\t\tnode.debug(\"Keydown force focus on active node\");\n\t\t\t}\n\t\t}\n\n\t\tif( opts.quicksearch && clean && /\\w/.test(whichChar) &&\n\t\t\t\t!SPECIAL_KEYCODES[which] &&  // #659\n\t\t\t\t!$target.is(\":input:enabled\") ) {\n\t\t\t// Allow to search for longer streaks if typed in quickly\n\t\t\tstamp = new Date().getTime();\n\t\t\tif( stamp - tree.lastQuicksearchTime > 500 ) {\n\t\t\t\ttree.lastQuicksearchTerm = \"\";\n\t\t\t}\n\t\t\ttree.lastQuicksearchTime = stamp;\n\t\t\ttree.lastQuicksearchTerm += whichChar;\n\t\t\t// tree.debug(\"quicksearch find\", tree.lastQuicksearchTerm);\n\t\t\tmatchNode = tree.findNextNode(tree.lastQuicksearchTerm, tree.getActiveNode());\n\t\t\tif( matchNode ) {\n\t\t\t\tmatchNode.setActive();\n\t\t\t}\n\t\t\tevent.preventDefault();\n\t\t\treturn;\n\t\t}\n\t\tswitch( FT.eventToString(event) ) {\n\t\t\tcase \"+\":\n\t\t\tcase \"=\": // 187: '+' @ Chrome, Safari\n\t\t\t\ttree.nodeSetExpanded(ctx, true);\n\t\t\t\tbreak;\n\t\t\tcase \"-\":\n\t\t\t\ttree.nodeSetExpanded(ctx, false);\n\t\t\t\tbreak;\n\t\t\tcase \"space\":\n\t\t\t\tif( node.isPagingNode() ) {\n\t\t\t\t\ttree._triggerNodeEvent(\"clickPaging\", ctx, event);\n\t\t\t\t} else if(opts.checkbox){\n\t\t\t\t\ttree.nodeToggleSelected(ctx);\n\t\t\t\t}else{\n\t\t\t\t\ttree.nodeSetActive(ctx, true);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"return\":\n\t\t\t\ttree.nodeSetActive(ctx, true);\n\t\t\t\tbreak;\n\t\t\tcase \"home\":\n\t\t\tcase \"end\":\n\t\t\tcase \"backspace\":\n\t\t\tcase \"left\":\n\t\t\tcase \"right\":\n\t\t\tcase \"up\":\n\t\t\tcase \"down\":\n\t\t\t\tres = node.navigate(event.which, activate, true);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\thandled = false;\n\t\t}\n\t\tif(handled){\n\t\t\tevent.preventDefault();\n\t\t}\n\t},\n\n\n\t// /** Default handling for mouse keypress events. */\n\t// nodeKeypress: function(ctx) {\n\t//     var event = ctx.originalEvent;\n\t// },\n\n\t// /** Trigger lazyLoad event (async). */\n\t// nodeLazyLoad: function(ctx) {\n\t//     var node = ctx.node;\n\t//     if(this._triggerNodeEvent())\n\t// },\n\t/** Load child nodes (async).\n\t *\n\t * @param {EventData} ctx\n\t * @param {object[]|object|string|$.Promise|function} source\n\t * @returns {$.Promise} The deferred will be resolved as soon as the (ajax)\n\t *     data was rendered.\n\t */\n\tnodeLoadChildren: function(ctx, source) {\n\t\tvar ajax, delay, dfd,\n\t\t\ttree = ctx.tree,\n\t\t\tnode = ctx.node,\n\t\t\trequestId = new Date().getTime();\n\n\t\tif($.isFunction(source)){\n\t\t\tsource = source.call(tree, {type: \"source\"}, ctx);\n\t\t\t_assert(!$.isFunction(source), \"source callback must not return another function\");\n\t\t}\n\t\tif(source.url){\n\t\t\tif( node._requestId ) {\n\t\t\t\tnode.warn(\"Recursive load request #\" + requestId + \" while #\" + node._requestId + \" is pending.\");\n\t\t\t// } else {\n\t\t\t// \tnode.debug(\"Send load request #\" + requestId);\n\t\t\t}\n\t\t\t// `source` is an Ajax options object\n\t\t\tajax = $.extend({}, ctx.options.ajax, source);\n\t\t\tnode._requestId = requestId;\n\t\t\tif(ajax.debugDelay){\n\t\t\t\t// simulate a slow server\n\t\t\t\tdelay = ajax.debugDelay;\n\t\t\t\tif($.isArray(delay)){ // random delay range [min..max]\n\t\t\t\t\tdelay = delay[0] + Math.random() * (delay[1] - delay[0]);\n\t\t\t\t}\n\t\t\t\tnode.warn(\"nodeLoadChildren waiting debugDelay \" + Math.round(delay) + \" ms ...\");\n\t\t\t\tajax.debugDelay = false;\n\t\t\t\tdfd = $.Deferred(function (dfd) {\n\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t$.ajax(ajax)\n\t\t\t\t\t\t\t.done(function () {\tdfd.resolveWith(this, arguments); })\n\t\t\t\t\t\t\t.fail(function () {\tdfd.rejectWith(this, arguments); });\n\t\t\t\t\t}, delay);\n\t\t\t\t});\n\t\t\t}else{\n\t\t\t\tdfd = $.ajax(ajax);\n\t\t\t}\n\n\t\t\t// Defer the deferred: we want to be able to reject, even if ajax\n\t\t\t// resolved ok.\n\t\t\tsource = new $.Deferred();\n\t\t\tdfd.done(function (data, textStatus, jqXHR) {\n\t\t\t\tvar errorObj, res;\n\n\t\t\t\tif((this.dataType === \"json\" || this.dataType === \"jsonp\") && typeof data === \"string\"){\n\t\t\t\t\t$.error(\"Ajax request returned a string (did you get the JSON dataType wrong?).\");\n\t\t\t\t}\n\t\t\t\tif( node._requestId && node._requestId > requestId ) {\n\t\t\t\t\t// The expected request time stamp is later than `requestId`\n\t\t\t\t\t// (which was kept as as closure variable to this handler function)\n\t\t\t\t\t// node.warn(\"Ignored load response for obsolete request #\" + requestId + \" (expected #\" + node._requestId + \")\");\n\t\t\t\t\tsource.rejectWith(this, [RECURSIVE_REQUEST_ERROR]);\n\t\t\t\t\treturn;\n\t\t\t\t// } else {\n\t\t\t\t// \tnode.debug(\"Response returned for load request #\" + requestId);\n\t\t\t\t}\n\t\t\t\t// postProcess is similar to the standard ajax dataFilter hook,\n\t\t\t\t// but it is also called for JSONP\n\t\t\t\tif( ctx.options.postProcess ){\n\t\t\t\t\ttry {\n\t\t\t\t\t\tres = tree._triggerNodeEvent(\"postProcess\", ctx, ctx.originalEvent, {\n\t\t\t\t\t\t\tresponse: data, error: null, dataType: this.dataType\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\tres = { error: e, message: \"\" + e, details: \"postProcess failed\"};\n\t\t\t\t\t}\n\t\t\t\t\tif( res.error ) {\n\t\t\t\t\t\terrorObj = $.isPlainObject(res.error) ? res.error : {message: res.error};\n\t\t\t\t\t\terrorObj = tree._makeHookContext(node, null, errorObj);\n\t\t\t\t\t\tsource.rejectWith(this, [errorObj]);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tdata = $.isArray(res) ? res : data;\n\n\t\t\t\t} else if (data && data.hasOwnProperty(\"d\") && ctx.options.enableAspx ) {\n\t\t\t\t\t// Process ASPX WebMethod JSON object inside \"d\" property\n\t\t\t\t\tdata = (typeof data.d === \"string\") ? $.parseJSON(data.d) : data.d;\n\t\t\t\t}\n\t\t\t\tsource.resolveWith(this, [data]);\n\t\t\t}).fail(function (jqXHR, textStatus, errorThrown) {\n\t\t\t\tvar errorObj = tree._makeHookContext(node, null, {\n\t\t\t\t\terror: jqXHR,\n\t\t\t\t\targs: Array.prototype.slice.call(arguments),\n\t\t\t\t\tmessage: errorThrown,\n\t\t\t\t\tdetails: jqXHR.status + \": \" + errorThrown\n\t\t\t\t});\n\t\t\t\tsource.rejectWith(this, [errorObj]);\n\t\t\t});\n\t\t}\n\t\t// #383: accept and convert ECMAScript 6 Promise\n\t\tif( $.isFunction(source.then) && $.isFunction(source[\"catch\"]) ) {\n\t\t\tdfd = source;\n\t\t\tsource = new $.Deferred();\n\t\t\tdfd.then(function(value){\n\t\t\t\tsource.resolve(value);\n\t\t\t}, function(reason){\n\t\t\t\tsource.reject(reason);\n\t\t\t});\n\t\t}\n\t\tif($.isFunction(source.promise)){\n\t\t\t// `source` is a deferred, i.e. ajax request\n\t\t\t// _assert(!node.isLoading(), \"recursive load\");\n\t\t\ttree.nodeSetStatus(ctx, \"loading\");\n\n\t\t\tsource.done(function (children) {\n\t\t\t\ttree.nodeSetStatus(ctx, \"ok\");\n\t\t\t\tnode._requestId = null;\n\t\t\t}).fail(function(error){\n\t\t\t\tvar ctxErr;\n\n\t\t\t\tif ( error === RECURSIVE_REQUEST_ERROR ) {\n\t\t\t\t\tnode.warn(\"Ignored response for obsolete load request #\" + requestId + \" (expected #\" + node._requestId + \")\");\n\t\t\t\t\treturn;\n\t\t\t\t} else if (error.node && error.error && error.message) {\n\t\t\t\t\t// error is already a context object\n\t\t\t\t\tctxErr = error;\n\t\t\t\t} else {\n\t\t\t\t\tctxErr = tree._makeHookContext(node, null, {\n\t\t\t\t\t\terror: error, // it can be jqXHR or any custom error\n\t\t\t\t\t\targs: Array.prototype.slice.call(arguments),\n\t\t\t\t\t\tmessage: error ? (error.message || error.toString()) : \"\"\n\t\t\t\t\t});\n\t\t\t\t\tif( ctxErr.message === \"[object Object]\" ) {\n\t\t\t\t\t\tctxErr.message = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tnode.warn(\"Load children failed (\" + ctxErr.message + \")\", ctxErr);\n\t\t\t\tif( tree._triggerNodeEvent(\"loadError\", ctxErr, null) !== false ) {\n\t\t\t\t\ttree.nodeSetStatus(ctx, \"error\", ctxErr.message, ctxErr.details);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t// $.when(source) resolves also for non-deferreds\n\t\treturn $.when(source).done(function(children){\n\t\t\tvar metaData;\n\n\t\t\tif( $.isPlainObject(children) ){\n\t\t\t\t// We got {foo: 'abc', children: [...]}\n\t\t\t\t// Copy extra properties to tree.data.foo\n\t\t\t\t_assert(node.isRootNode(), \"source may only be an object for root nodes (expecting an array of child objects otherwise)\");\n\t\t\t\t_assert($.isArray(children.children), \"if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')\");\n\t\t\t\tmetaData = children;\n\t\t\t\tchildren = children.children;\n\t\t\t\tdelete metaData.children;\n\t\t\t\t$.extend(tree.data, metaData);\n\t\t\t}\n\t\t\t_assert($.isArray(children), \"expected array of children\");\n\t\t\tnode._setChildren(children);\n\t\t\t// trigger fancytreeloadchildren\n\t\t\ttree._triggerNodeEvent(\"loadChildren\", node);\n\t\t});\n\t},\n\t/** [Not Implemented]  */\n\tnodeLoadKeyPath: function(ctx, keyPathList) {\n\t\t// TODO: implement and improve\n\t\t// http://code.google.com/p/dynatree/issues/detail?id=222\n\t},\n\t/**\n\t * Remove a single direct child of ctx.node.\n\t * @param {EventData} ctx\n\t * @param {FancytreeNode} childNode dircect child of ctx.node\n\t */\n\tnodeRemoveChild: function(ctx, childNode) {\n\t\tvar idx,\n\t\t\tnode = ctx.node,\n\t\t\t// opts = ctx.options,\n\t\t\tsubCtx = $.extend({}, ctx, {node: childNode}),\n\t\t\tchildren = node.children;\n\n\t\t// FT.debug(\"nodeRemoveChild()\", node.toString(), childNode.toString());\n\n\t\tif( children.length === 1 ) {\n\t\t\t_assert(childNode === children[0], \"invalid single child\");\n\t\t\treturn this.nodeRemoveChildren(ctx);\n\t\t}\n\t\tif( this.activeNode && (childNode === this.activeNode || this.activeNode.isDescendantOf(childNode))){\n\t\t\tthis.activeNode.setActive(false); // TODO: don't fire events\n\t\t}\n\t\tif( this.focusNode && (childNode === this.focusNode || this.focusNode.isDescendantOf(childNode))){\n\t\t\tthis.focusNode = null;\n\t\t}\n\t\t// TODO: persist must take care to clear select and expand cookies\n\t\tthis.nodeRemoveMarkup(subCtx);\n\t\tthis.nodeRemoveChildren(subCtx);\n\t\tidx = $.inArray(childNode, children);\n\t\t_assert(idx >= 0, \"invalid child\");\n\t\t// Notify listeners\n\t\tnode.triggerModifyChild(\"remove\", childNode);\n\t\t// Unlink to support GC\n\t\tchildNode.visit(function(n){\n\t\t\tn.parent = null;\n\t\t}, true);\n\t\tthis._callHook(\"treeRegisterNode\", this, false, childNode);\n\t\t// remove from child list\n\t\tchildren.splice(idx, 1);\n\t},\n\t/**Remove HTML markup for all descendents of ctx.node.\n\t * @param {EventData} ctx\n\t */\n\tnodeRemoveChildMarkup: function(ctx) {\n\t\tvar node = ctx.node;\n\n\t\t// FT.debug(\"nodeRemoveChildMarkup()\", node.toString());\n\t\t// TODO: Unlink attr.ftnode to support GC\n\t\tif(node.ul){\n\t\t\tif( node.isRootNode() ) {\n\t\t\t\t$(node.ul).empty();\n\t\t\t} else {\n\t\t\t\t$(node.ul).remove();\n\t\t\t\tnode.ul = null;\n\t\t\t}\n\t\t\tnode.visit(function(n){\n\t\t\t\tn.li = n.ul = null;\n\t\t\t});\n\t\t}\n\t},\n\t/**Remove all descendants of ctx.node.\n\t* @param {EventData} ctx\n\t*/\n\tnodeRemoveChildren: function(ctx) {\n\t\tvar subCtx,\n\t\t\ttree = ctx.tree,\n\t\t\tnode = ctx.node,\n\t\t\tchildren = node.children;\n\t\t\t// opts = ctx.options;\n\n\t\t// FT.debug(\"nodeRemoveChildren()\", node.toString());\n\t\tif(!children){\n\t\t\treturn;\n\t\t}\n\t\tif( this.activeNode && this.activeNode.isDescendantOf(node)){\n\t\t\tthis.activeNode.setActive(false); // TODO: don't fire events\n\t\t}\n\t\tif( this.focusNode && this.focusNode.isDescendantOf(node)){\n\t\t\tthis.focusNode = null;\n\t\t}\n\t\t// TODO: persist must take care to clear select and expand cookies\n\t\tthis.nodeRemoveChildMarkup(ctx);\n\t\t// Unlink children to support GC\n\t\t// TODO: also delete this.children (not possible using visit())\n\t\tsubCtx = $.extend({}, ctx);\n\t\tnode.triggerModifyChild(\"remove\", null);\n\t\tnode.visit(function(n){\n\t\t\tn.parent = null;\n\t\t\ttree._callHook(\"treeRegisterNode\", tree, false, n);\n\t\t});\n\t\tif( node.lazy ){\n\t\t\t// 'undefined' would be interpreted as 'not yet loaded' for lazy nodes\n\t\t\tnode.children = [];\n\t\t} else{\n\t\t\tnode.children = null;\n\t\t}\n\t\tif( !node.isRootNode() ) {\n\t\t\tnode.expanded = false;  // #449, #459\n\t\t}\n\t\tthis.nodeRenderStatus(ctx);\n\t},\n\t/**Remove HTML markup for ctx.node and all its descendents.\n\t * @param {EventData} ctx\n\t */\n\tnodeRemoveMarkup: function(ctx) {\n\t\tvar node = ctx.node;\n\t\t// FT.debug(\"nodeRemoveMarkup()\", node.toString());\n\t\t// TODO: Unlink attr.ftnode to support GC\n\t\tif(node.li){\n\t\t\t$(node.li).remove();\n\t\t\tnode.li = null;\n\t\t}\n\t\tthis.nodeRemoveChildMarkup(ctx);\n\t},\n\t/**\n\t * Create `&lt;li>&lt;span>..&lt;/span> .. &lt;/li>` tags for this node.\n\t *\n\t * This method takes care that all HTML markup is created that is required\n\t * to display this node in its current state.\n\t *\n\t * Call this method to create new nodes, or after the strucuture\n\t * was changed (e.g. after moving this node or adding/removing children)\n\t * nodeRenderTitle() and nodeRenderStatus() are implied.\n\t *\n\t * &lt;code>\n\t * &lt;li id='KEY' ftnode=NODE>\n\t *     &lt;span class='fancytree-node fancytree-expanded fancytree-has-children fancytree-lastsib fancytree-exp-el fancytree-ico-e'>\n\t *         &lt;span class=\"fancytree-expander\">&lt;/span>\n\t *         &lt;span class=\"fancytree-checkbox\">&lt;/span> // only present in checkbox mode\n\t *         &lt;span class=\"fancytree-icon\">&lt;/span>\n\t *         &lt;a href=\"#\" class=\"fancytree-title\"> Node 1 &lt;/a>\n\t *     &lt;/span>\n\t *     &lt;ul> // only present if node has children\n\t *         &lt;li id='KEY' ftnode=NODE> child1 ... &lt;/li>\n\t *         &lt;li id='KEY' ftnode=NODE> child2 ... &lt;/li>\n\t *     &lt;/ul>\n\t * &lt;/li>\n\t * &lt;/code>\n\t *\n\t * @param {EventData} ctx\n\t * @param {boolean} [force=false] re-render, even if html markup was already created\n\t * @param {boolean} [deep=false] also render all descendants, even if parent is collapsed\n\t * @param {boolean} [collapsed=false] force root node to be collapsed, so we can apply animated expand later\n\t */\n\tnodeRender: function(ctx, force, deep, collapsed, _recursive) {\n\t\t/* This method must take care of all cases where the current data mode\n\t\t * (i.e. node hierarchy) does not match the current markup.\n\t\t *\n\t\t * - node was not yet rendered:\n\t\t *   create markup\n\t\t * - node was rendered: exit fast\n\t\t * - children have been added\n\t\t * - children have been removed\n\t\t */\n\t\tvar childLI, childNode1, childNode2, i, l, next, subCtx,\n\t\t\tnode = ctx.node,\n\t\t\ttree = ctx.tree,\n\t\t\topts = ctx.options,\n\t\t\taria = opts.aria,\n\t\t\tfirstTime = false,\n\t\t\tparent = node.parent,\n\t\t\tisRootNode = !parent,\n\t\t\tchildren = node.children,\n\t\t\tsuccessorLi = null;\n\t\t// FT.debug(\"nodeRender(\" + !!force + \", \" + !!deep + \")\", node.toString());\n\n\t\tif( tree._enableUpdate === false ) {\n\t\t\t// tree.debug(\"no render\", tree._enableUpdate);\n\t\t\treturn;\n\t\t}\n\t\tif( ! isRootNode && ! parent.ul ) {\n\t\t\t// Calling node.collapse on a deep, unrendered node\n\t\t\treturn;\n\t\t}\n\t\t_assert(isRootNode || parent.ul, \"parent UL must exist\");\n\n\t\t// Render the node\n\t\tif( !isRootNode ){\n\t\t\t// Discard markup on force-mode, or if it is not linked to parent <ul>\n\t\t\tif(node.li && (force || (node.li.parentNode !== node.parent.ul) ) ){\n\t\t\t\tif( node.li.parentNode === node.parent.ul ){\n\t\t\t\t\t// #486: store following node, so we can insert the new markup there later\n\t\t\t\t\tsuccessorLi = node.li.nextSibling;\n\t\t\t\t}else{\n\t\t\t\t\t// May happen, when a top-level node was dropped over another\n\t\t\t\t\tthis.debug(\"Unlinking \" + node + \" (must be child of \" + node.parent + \")\");\n\t\t\t\t}\n//\t            this.debug(\"nodeRemoveMarkup...\");\n\t\t\t\tthis.nodeRemoveMarkup(ctx);\n\t\t\t}\n\t\t\t// Create <li><span /> </li>\n//\t\t\tnode.debug(\"render...\");\n\t\t\tif( !node.li ) {\n//\t            node.debug(\"render... really\");\n\t\t\t\tfirstTime = true;\n\t\t\t\tnode.li = document.createElement(\"li\");\n\t\t\t\tnode.li.ftnode = node;\n\n\t\t\t\t// We set role 'treeitem' to the title span instead\n\t\t\t\tif(aria){\n\t\t\t\t\t// TODO: why does the next line don't work:\n\t\t\t\t\t// node.li.role = \"treeitem\";\n\t\t\t\t\t// $(node.li).attr(\"role\", \"treeitem\");\n\t\t\t\t\t// .attr(\"aria-labelledby\", \"ftal_\" + opts.idPrefix + node.key);\n\t\t\t\t}\n\t\t\t\tif( node.key && opts.generateIds ){\n\t\t\t\t\tnode.li.id = opts.idPrefix + node.key;\n\t\t\t\t}\n\t\t\t\tnode.span = document.createElement(\"span\");\n\t\t\t\tnode.span.className = \"fancytree-node\";\n\t\t\t\tif(aria){\n\t\t\t\t\t$(node.li).attr(\"aria-labelledby\", \"ftal_\" + opts.idPrefix + node.key);\n\t\t\t\t\t// $(node.span).attr(\"aria-labelledby\", \"ftal_\" + opts.idPrefix + node.key);\n\t\t\t\t}\n\t\t\t\tnode.li.appendChild(node.span);\n\n\t\t\t\t// Create inner HTML for the <span> (expander, checkbox, icon, and title)\n\t\t\t\tthis.nodeRenderTitle(ctx);\n\n\t\t\t\t// Allow tweaking and binding, after node was created for the first time\n\t\t\t\tif ( opts.createNode ){\n\t\t\t\t\topts.createNode.call(tree, {type: \"createNode\"}, ctx);\n\t\t\t\t}\n\t\t\t}else{\n//\t\t\t\tthis.nodeRenderTitle(ctx);\n\t\t\t\tthis.nodeRenderStatus(ctx);\n\t\t\t}\n\t\t\t// Allow tweaking after node state was rendered\n\t\t\tif ( opts.renderNode ){\n\t\t\t\topts.renderNode.call(tree, {type: \"renderNode\"}, ctx);\n\t\t\t}\n\t\t}\n\n\t\t// Visit child nodes\n\t\tif( children ){\n\t\t\tif( isRootNode || node.expanded || deep === true ) {\n\t\t\t\t// Create a UL to hold the children\n\t\t\t\tif( !node.ul ){\n\t\t\t\t\tnode.ul = document.createElement(\"ul\");\n\t\t\t\t\tif((collapsed === true && !_recursive) || !node.expanded){\n\t\t\t\t\t\t// hide top UL, so we can use an animation to show it later\n\t\t\t\t\t\tnode.ul.style.display = \"none\";\n\t\t\t\t\t}\n\t\t\t\t\tif(aria){\n\t\t\t\t\t\t$(node.ul).attr(\"role\", \"group\");\n\t\t\t\t\t}\n\t\t\t\t\tif ( node.li ) { // issue #67\n\t\t\t\t\t\tnode.li.appendChild(node.ul);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnode.tree.$div.append(node.ul);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Add child markup\n\t\t\t\tfor(i=0, l=children.length; i<l; i++) {\n\t\t\t\t\tsubCtx = $.extend({}, ctx, {node: children[i]});\n\t\t\t\t\tthis.nodeRender(subCtx, force, deep, false, true);\n\t\t\t\t}\n\t\t\t\t// Remove <li> if nodes have moved to another parent\n\t\t\t\tchildLI = node.ul.firstChild;\n\t\t\t\twhile( childLI ){\n\t\t\t\t\tchildNode2 = childLI.ftnode;\n\t\t\t\t\tif( childNode2 && childNode2.parent !== node ) {\n\t\t\t\t\t\tnode.debug(\"_fixParent: remove missing \" + childNode2, childLI);\n\t\t\t\t\t\tnext = childLI.nextSibling;\n\t\t\t\t\t\tchildLI.parentNode.removeChild(childLI);\n\t\t\t\t\t\tchildLI = next;\n\t\t\t\t\t}else{\n\t\t\t\t\t\tchildLI = childLI.nextSibling;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Make sure, that <li> order matches node.children order.\n\t\t\t\tchildLI = node.ul.firstChild;\n\t\t\t\tfor(i=0, l=children.length-1; i<l; i++) {\n\t\t\t\t\tchildNode1 = children[i];\n\t\t\t\t\tchildNode2 = childLI.ftnode;\n\t\t\t\t\tif( childNode1 !== childNode2 ) {\n\t\t\t\t\t\t// node.debug(\"_fixOrder: mismatch at index \" + i + \": \" + childNode1 + \" != \" + childNode2);\n\t\t\t\t\t\tnode.ul.insertBefore(childNode1.li, childNode2.li);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tchildLI = childLI.nextSibling;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\t// No children: remove markup if any\n\t\t\tif( node.ul ){\n//\t\t\t\talert(\"remove child markup for \" + node);\n\t\t\t\tthis.warn(\"remove child markup for \" + node);\n\t\t\t\tthis.nodeRemoveChildMarkup(ctx);\n\t\t\t}\n\t\t}\n\t\tif( !isRootNode ){\n\t\t\t// Update element classes according to node state\n\t\t\t// this.nodeRenderStatus(ctx);\n\t\t\t// Finally add the whole structure to the DOM, so the browser can render\n\t\t\tif( firstTime ){\n\t\t\t\t// #486: successorLi is set, if we re-rendered (i.e. discarded)\n\t\t\t\t// existing markup, which  we want to insert at the same position.\n\t\t\t\t// (null is equivalent to append)\n//\t\t\t\tparent.ul.appendChild(node.li);\n\t\t\t\tparent.ul.insertBefore(node.li, successorLi);\n\t\t\t}\n\t\t}\n\t},\n\t/** Create HTML inside the node's outer &lt;span> (i.e. expander, checkbox,\n\t * icon, and title).\n\t *\n\t * nodeRenderStatus() is implied.\n\t * @param {EventData} ctx\n\t * @param {string} [title] optinal new title\n\t */\n\tnodeRenderTitle: function(ctx, title) {\n\t\t// set node connector images, links and text\n\t\tvar id, icon, nodeTitle, role, tabindex, tooltip,\n\t\t\tnode = ctx.node,\n\t\t\ttree = ctx.tree,\n\t\t\topts = ctx.options,\n\t\t\taria = opts.aria,\n\t\t\tlevel = node.getLevel(),\n\t\t\tares = [];\n\n\t\tif(title !== undefined){\n\t\t\tnode.title = title;\n\t\t}\n\t\tif ( !node.span || tree._enableUpdate === false ) {\n\t\t\t// Silently bail out if node was not rendered yet, assuming\n\t\t\t// node.render() will be called as the node becomes visible\n\t\t\treturn;\n\t\t}\n\t\t// Connector (expanded, expandable or simple)\n\t\tif( level < opts.minExpandLevel ) {\n\t\t\tif( !node.lazy ) {\n\t\t\t\tnode.expanded = true;\n\t\t\t}\n\t\t\tif(level > 1){\n\t\t\t\tif(aria){\n\t\t\t\t\tares.push(\"<span role='button' class='fancytree-expander fancytree-expander-fixed'></span>\");\n\t\t\t\t}else{\n\t\t\t\t\tares.push(\"<span class='fancytree-expander fancytree-expander-fixed''></span>\");\n\t\t\t\t}\n\t\t\t}\n\t\t\t// .. else (i.e. for root level) skip expander/connector alltogether\n\t\t} else {\n\t\t\tif(aria){\n\t\t\t\tares.push(\"<span role='button' class='fancytree-expander'></span>\");\n\t\t\t}else{\n\t\t\t\tares.push(\"<span class='fancytree-expander'></span>\");\n\t\t\t}\n\t\t}\n\t\t// Checkbox mode\n\t\tif( opts.checkbox && node.hideCheckbox !== true && !node.isStatusNode() ) {\n\t\t\tif(aria){\n\t\t\t\tares.push(\"<span role='checkbox' class='fancytree-checkbox'></span>\");\n\t\t\t}else{\n\t\t\t\tares.push(\"<span class='fancytree-checkbox'></span>\");\n\t\t\t}\n\t\t}\n\t\t// Folder or doctype icon\n\t\tif( node.data.iconClass !== undefined ) {  // 2015-11-16\n\t\t\t// Handle / warn about backward compatibility\n\t\t\tif( node.icon ) {\n\t\t\t\t$.error(\"'iconClass' node option is deprecated since v2.14.0: use 'icon' only instead\");\n\t\t\t} else {\n\t\t\t\tnode.warn(\"'iconClass' node option is deprecated since v2.14.0: use 'icon' instead\");\n\t\t\t\tnode.icon = node.data.iconClass;\n\t\t\t}\n\t\t}\n\t\t// If opts.icon is a callback and returns something other than undefined, use that\n\t\t// else if node.icon is a boolean or string, use that\n\t\t// else if opts.icon is a boolean or string, use that\n\t\t// else show standard icon (which may be different for folders or documents)\n\t\ticon = FT.evalOption(\"icon\", node, node, opts, true);\n\t\tif( typeof icon !== \"boolean\" ) {\n\t\t\t// icon is defined, but not true/false: must be a string\n\t\t\ticon = \"\" + icon;\n\t\t}\n\t\t// if( $.isFunction(opts.icon) ) {\n\t\t// \ticon = opts.icon.call(tree, {type: \"icon\"}, ctx);\n\t\t// \tif( icon == null ) {\n\t\t// \t\ticon = node.icon;\n\t\t// \t}\n\t\t// } else {\n\t\t// \ticon = (node.icon != null) ? node.icon : opts.icon;\n\t\t// }\n\t\t// if( icon == null ) {\n\t\t// \ticon = true;  // no icon option at all: show default icon\n\t\t// } else {\n\t\t// \tif( typeof icon !== \"boolean\" ) {\n\t\t// \t\t// icon is defined, but not true/false: must be a string\n\t\t// \t\ticon = \"\" + icon;\n\t\t// \t}\n\t\t// }\n\t\tif( icon !== false ) {\n\t\t\trole = aria ? \" role='img'\" : \"\";\n\t\t\tif ( typeof icon === \"string\" ) {\n\t\t\t\tif( TEST_IMG.test(icon) ) {\n\t\t\t\t\t// node.icon is an image url. Prepend imagePath\n\t\t\t\t\ticon = (icon.charAt(0) === \"/\") ? icon : ((opts.imagePath || \"\") + icon);\n\t\t\t\t\tares.push(\"<img src='\" + icon + \"' class='fancytree-icon' alt='' />\");\n\t\t\t\t} else {\n\t\t\t\t\tares.push(\"<span \" + role + \" class='fancytree-custom-icon \" + icon +  \"'></span>\");\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// standard icon: theme css will take care of this\n\t\t\t\tares.push(\"<span \" + role + \" class='fancytree-icon'></span>\");\n\t\t\t}\n\t\t}\n\t\t// Node title\n\t\tnodeTitle = \"\";\n\t\tif ( opts.renderTitle ){\n\t\t\tnodeTitle = opts.renderTitle.call(tree, {type: \"renderTitle\"}, ctx) || \"\";\n\t\t}\n\t\tif ( !nodeTitle ) {\n\t\t\tif( node.tooltip ) {\n\t\t\t\ttooltip = node.tooltip;\n\t\t\t} else if ( opts.tooltip ) {\n\t\t\t\ttooltip = opts.tooltip === true ? node.title : opts.tooltip.call(tree, node);\n\t\t\t}\n\t\t\ttooltip = tooltip ? \" title='\" + _escapeTooltip(tooltip) + \"'\" : \"\";\n\t\t\tid = aria ? \" id='ftal_\" + opts.idPrefix + node.key + \"'\" : \"\";\n\t\t\t// role = \"\";\n\t\t\trole = aria ? \" role='treeitem'\" : \"\";\n\t\t\ttabindex = opts.titlesTabbable ? \" tabindex='0'\" : \"\";\n\n\t\t\tnodeTitle = \"<span \" + role + \" class='fancytree-title'\" +\n\t\t\t\tid + tooltip + tabindex + \">\" +\n\t\t\t\t(opts.escapeTitles ? _escapeHtml(node.title) : node.title) +\n\t\t\t\t\"</span>\";\n\t\t}\n\t\tares.push(nodeTitle);\n\t\t// Note: this will trigger focusout, if node had the focus\n\t\t//$(node.span).html(ares.join(\"\")); // it will cleanup the jQuery data currently associated with SPAN (if any), but it executes more slowly\n\t\tnode.span.innerHTML = ares.join(\"\");\n\t\t// Update CSS classes\n\t\tthis.nodeRenderStatus(ctx);\n\t\tif ( opts.enhanceTitle ){\n\t\t\tctx.$title = $(\">span.fancytree-title\", node.span);\n\t\t\tnodeTitle = opts.enhanceTitle.call(tree, {type: \"enhanceTitle\"}, ctx) || \"\";\n\t\t}\n\t},\n\t/** Update element classes according to node state.\n\t * @param {EventData} ctx\n\t */\n\tnodeRenderStatus: function(ctx) {\n\t\t// Set classes for current status\n\t\tvar node = ctx.node,\n\t\t\ttree = ctx.tree,\n\t\t\topts = ctx.options,\n//\t\t\tnodeContainer = node[tree.nodeContainerAttrName],\n\t\t\thasChildren = node.hasChildren(),\n\t\t\tisLastSib = node.isLastSibling(),\n\t\t\taria = opts.aria,\n\t\t\t// $ariaElem = aria ? $(node[tree.ariaPropName]) : null,\n\t\t\t$ariaElem = $(node.span).find(\".fancytree-title\"),\n\t\t\tcn = opts._classNames,\n\t\t\tcnList = [],\n\t\t\tstatusElem = node[tree.statusClassPropName];\n\n\t\tif( !statusElem || tree._enableUpdate === false ){\n\t\t\t// if this function is called for an unrendered node, ignore it (will be updated on nect render anyway)\n\t\t\treturn;\n\t\t}\n\t\t// Build a list of class names that we will add to the node <span>\n\t\tcnList.push(cn.node);\n\t\tif( tree.activeNode === node ){\n\t\t\tcnList.push(cn.active);\n//\t\t\t$(\">span.fancytree-title\", statusElem).attr(\"tabindex\", \"0\");\n//\t\t\ttree.$container.removeAttr(\"tabindex\");\n\t\t// }else{\n//\t\t\t$(\">span.fancytree-title\", statusElem).removeAttr(\"tabindex\");\n//\t\t\ttree.$container.attr(\"tabindex\", \"0\");\n\t\t}\n\t\tif( tree.focusNode === node ){\n\t\t\tcnList.push(cn.focused);\n\t\t\t// if(aria){\n\t\t\t// \t$ariaElem.attr(\"aria-activedescendant\", true);\n\t\t\t// }\n\t\t}else if(aria){\n\t\t\t// $ariaElem.removeAttr(\"aria-activedescendant\");\n\t\t}\n\t\tif( node.expanded ){\n\t\t\tcnList.push(cn.expanded);\n\t\t\tif(aria){\n\t\t\t\t$ariaElem.attr(\"aria-expanded\", true);\n\t\t\t}\n\t\t}else if( aria ){\n\t\t\tif( hasChildren ) {\n\t\t\t\t$ariaElem.attr(\"aria-expanded\", false);\n\t\t\t} else {\n\t\t\t\t$ariaElem.removeAttr(\"aria-expanded\");\n\t\t\t}\n\t\t}\n\t\tif( node.folder ){\n\t\t\tcnList.push(cn.folder);\n\t\t}\n\t\tif( hasChildren !== false ){\n\t\t\tcnList.push(cn.hasChildren);\n\t\t}\n\t\t// TODO: required?\n\t\tif( isLastSib ){\n\t\t\tcnList.push(cn.lastsib);\n\t\t}\n\t\tif( node.lazy && node.children == null ){\n\t\t\tcnList.push(cn.lazy);\n\t\t}\n\t\tif( node.partload ){\n\t\t\tcnList.push(cn.partload);\n\t\t}\n\t\tif( node.partsel ){\n\t\t\tcnList.push(cn.partsel);\n\t\t}\n\t\tif( node.unselectable ){\n\t\t\tcnList.push(cn.unselectable);\n\t\t}\n\t\tif( node._isLoading ){\n\t\t\tcnList.push(cn.loading);\n\t\t}\n\t\tif( node._error ){\n\t\t\tcnList.push(cn.error);\n\t\t}\n\t\tif( node.statusNodeType ) {\n\t\t\tcnList.push(cn.statusNodePrefix + node.statusNodeType);\n\t\t}\n\t\tif( node.selected ){\n\t\t\tcnList.push(cn.selected);\n\t\t\tif(aria){\n\t\t\t\t$ariaElem.attr(\"aria-selected\", true);\n\t\t\t}\n\t\t}else if(aria){\n\t\t\t$ariaElem.attr(\"aria-selected\", false);\n\t\t}\n\t\tif( node.extraClasses ){\n\t\t\tcnList.push(node.extraClasses);\n\t\t}\n\t\t// IE6 doesn't correctly evaluate multiple class names,\n\t\t// so we create combined class names that can be used in the CSS\n\t\tif( hasChildren === false ){\n\t\t\tcnList.push(cn.combinedExpanderPrefix + \"n\" +\n\t\t\t\t\t(isLastSib ? \"l\" : \"\")\n\t\t\t\t\t);\n\t\t}else{\n\t\t\tcnList.push(cn.combinedExpanderPrefix +\n\t\t\t\t\t(node.expanded ? \"e\" : \"c\") +\n\t\t\t\t\t(node.lazy && node.children == null ? \"d\" : \"\") +\n\t\t\t\t\t(isLastSib ? \"l\" : \"\")\n\t\t\t\t\t);\n\t\t}\n\t\tcnList.push(cn.combinedIconPrefix +\n\t\t\t\t(node.expanded ? \"e\" : \"c\") +\n\t\t\t\t(node.folder ? \"f\" : \"\")\n\t\t\t\t);\n//        node.span.className = cnList.join(\" \");\n\t\tstatusElem.className = cnList.join(\" \");\n\n\t\t// TODO: we should not set this in the <span> tag also, if we set it here:\n\t\t// Maybe most (all) of the classes should be set in LI instead of SPAN?\n\t\tif(node.li){\n\t\t\tnode.li.className = isLastSib ? cn.lastsib : \"\";\n\t\t}\n\t},\n\t/** Activate node.\n\t * flag defaults to true.\n\t * If flag is true, the node is activated (must be a synchronous operation)\n\t * If flag is false, the node is deactivated (must be a synchronous operation)\n\t * @param {EventData} ctx\n\t * @param {boolean} [flag=true]\n\t * @param {object} [opts] additional options. Defaults to {noEvents: false, noFocus: false}\n\t * @returns {$.Promise}\n\t */\n\tnodeSetActive: function(ctx, flag, callOpts) {\n\t\t// Handle user click / [space] / [enter], according to clickFolderMode.\n\t\tcallOpts = callOpts || {};\n\t\tvar subCtx,\n\t\t\tnode = ctx.node,\n\t\t\ttree = ctx.tree,\n\t\t\topts = ctx.options,\n\t\t\tnoEvents = (callOpts.noEvents === true),\n\t\t\tnoFocus = (callOpts.noFocus === true),\n\t\t\tisActive = (node === tree.activeNode);\n\n\t\t// flag defaults to true\n\t\tflag = (flag !== false);\n\t\t// node.debug(\"nodeSetActive\", flag);\n\n\t\tif(isActive === flag){\n\t\t\t// Nothing to do\n\t\t\treturn _getResolvedPromise(node);\n\t\t}else if(flag && !noEvents && this._triggerNodeEvent(\"beforeActivate\", node, ctx.originalEvent) === false ){\n\t\t\t// Callback returned false\n\t\t\treturn _getRejectedPromise(node, [\"rejected\"]);\n\t\t}\n\t\tif(flag){\n\t\t\tif(tree.activeNode){\n\t\t\t\t_assert(tree.activeNode !== node, \"node was active (inconsistency)\");\n\t\t\t\tsubCtx = $.extend({}, ctx, {node: tree.activeNode});\n\t\t\t\ttree.nodeSetActive(subCtx, false);\n\t\t\t\t_assert(tree.activeNode === null, \"deactivate was out of sync?\");\n\t\t\t}\n\t\t\tif(opts.activeVisible){\n\t\t\t\t// If no focus is set (noFocus: true) and there is no focused node, this node is made visible.\n\t\t\t\tnode.makeVisible({scrollIntoView: noFocus && tree.focusNode == null});\n\t\t\t}\n\t\t\ttree.activeNode = node;\n\t\t\ttree.nodeRenderStatus(ctx);\n\t\t\tif( !noFocus ) {\n\t\t\t\ttree.nodeSetFocus(ctx);\n\t\t\t}\n\t\t\tif( !noEvents ) {\n\t\t\t\ttree._triggerNodeEvent(\"activate\", node, ctx.originalEvent);\n\t\t\t}\n\t\t}else{\n\t\t\t_assert(tree.activeNode === node, \"node was not active (inconsistency)\");\n\t\t\ttree.activeNode = null;\n\t\t\tthis.nodeRenderStatus(ctx);\n\t\t\tif( !noEvents ) {\n\t\t\t\tctx.tree._triggerNodeEvent(\"deactivate\", node, ctx.originalEvent);\n\t\t\t}\n\t\t}\n\t\treturn _getResolvedPromise(node);\n\t},\n\t/** Expand or collapse node, return Deferred.promise.\n\t *\n\t * @param {EventData} ctx\n\t * @param {boolean} [flag=true]\n\t * @param {object} [opts] additional options. Defaults to {noAnimation: false, noEvents: false}\n\t * @returns {$.Promise} The deferred will be resolved as soon as the (lazy)\n\t *     data was retrieved, rendered, and the expand animation finshed.\n\t */\n\tnodeSetExpanded: function(ctx, flag, callOpts) {\n\t\tcallOpts = callOpts || {};\n\t\tvar _afterLoad, dfd, i, l, parents, prevAC,\n\t\t\tnode = ctx.node,\n\t\t\ttree = ctx.tree,\n\t\t\topts = ctx.options,\n\t\t\tnoAnimation = (callOpts.noAnimation === true),\n\t\t\tnoEvents = (callOpts.noEvents === true);\n\n\t\t// flag defaults to true\n\t\tflag = (flag !== false);\n\n\t\t// node.debug(\"nodeSetExpanded(\" + flag + \")\");\n\n\t\tif((node.expanded && flag) || (!node.expanded && !flag)){\n\t\t\t// Nothing to do\n\t\t\t// node.debug(\"nodeSetExpanded(\" + flag + \"): nothing to do\");\n\t\t\treturn _getResolvedPromise(node);\n\t\t}else if(flag && !node.lazy && !node.hasChildren() ){\n\t\t\t// Prevent expanding of empty nodes\n\t\t\t// return _getRejectedPromise(node, [\"empty\"]);\n\t\t\treturn _getResolvedPromise(node);\n\t\t}else if( !flag && node.getLevel() < opts.minExpandLevel ) {\n\t\t\t// Prevent collapsing locked levels\n\t\t\treturn _getRejectedPromise(node, [\"locked\"]);\n\t\t}else if ( !noEvents && this._triggerNodeEvent(\"beforeExpand\", node, ctx.originalEvent) === false ){\n\t\t\t// Callback returned false\n\t\t\treturn _getRejectedPromise(node, [\"rejected\"]);\n\t\t}\n\t\t// If this node inside a collpased node, no animation and scrolling is needed\n\t\tif( !noAnimation && !node.isVisible() ) {\n\t\t\tnoAnimation = callOpts.noAnimation = true;\n\t\t}\n\n\t\tdfd = new $.Deferred();\n\n\t\t// Auto-collapse mode: collapse all siblings\n\t\tif( flag && !node.expanded && opts.autoCollapse ) {\n\t\t\tparents = node.getParentList(false, true);\n\t\t\tprevAC = opts.autoCollapse;\n\t\t\ttry{\n\t\t\t\topts.autoCollapse = false;\n\t\t\t\tfor(i=0, l=parents.length; i<l; i++){\n\t\t\t\t\t// TODO: should return promise?\n\t\t\t\t\tthis._callHook(\"nodeCollapseSiblings\", parents[i], callOpts);\n\t\t\t\t}\n\t\t\t}finally{\n\t\t\t\topts.autoCollapse = prevAC;\n\t\t\t}\n\t\t}\n\t\t// Trigger expand/collapse after expanding\n\t\tdfd.done(function(){\n\t\t\tvar\tlastChild = node.getLastChild();\n\n\t\t\tif( flag && opts.autoScroll && !noAnimation && lastChild ) {\n\t\t\t\t// Scroll down to last child, but keep current node visible\n\t\t\t\tlastChild.scrollIntoView(true, {topNode: node}).always(function(){\n\t\t\t\t\tif( !noEvents ) {\n\t\t\t\t\t\tctx.tree._triggerNodeEvent(flag ? \"expand\" : \"collapse\", ctx);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tif( !noEvents ) {\n\t\t\t\t\tctx.tree._triggerNodeEvent(flag ? \"expand\" : \"collapse\", ctx);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\t// vvv Code below is executed after loading finished:\n\t\t_afterLoad = function(callback){\n\t\t\tvar isVisible, isExpanded,\n\t\t\t\teffect = opts.toggleEffect;\n\n\t\t\tnode.expanded = flag;\n\t\t\t// Create required markup, but make sure the top UL is hidden, so we\n\t\t\t// can animate later\n\t\t\ttree._callHook(\"nodeRender\", ctx, false, false, true);\n\n\t\t\t// Hide children, if node is collapsed\n\t\t\tif( node.ul ) {\n\t\t\t\tisVisible = (node.ul.style.display !== \"none\");\n\t\t\t\tisExpanded = !!node.expanded;\n\t\t\t\tif ( isVisible === isExpanded ) {\n\t\t\t\t\tnode.warn(\"nodeSetExpanded: UL.style.display already set\");\n\n\t\t\t\t} else if ( !effect || noAnimation ) {\n\t\t\t\t\tnode.ul.style.display = ( node.expanded || !parent ) ? \"\" : \"none\";\n\n\t\t\t\t} else {\n\t\t\t\t\t// The UI toggle() effect works with the ext-wide extension,\n\t\t\t\t\t// while jQuery.animate() has problems when the title span\n\t\t\t\t\t// has positon: absolute\n\t\t\t\t\t// See #716, #717\n\t\t\t\t\t$(node.ul).parent().addClass(\"fancytree-animating\");\n\t\t\t\t\t$(node.ul)\n\t\t\t\t\t\t.addClass(\"fancytree-animating\")\n\t\t\t\t\t\t.toggle(effect.effect, effect.options, effect.duration, function(){\n\t\t\t\t\t\t\t$(this).removeClass(\"fancytree-animating\");\n\t\t\t\t\t\t\t$(this).parent().removeClass(\"fancytree-animating\");\n\t\t\t\t\t\t\tcallback();\n\t\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tcallback();\n\t\t};\n\t\t// ^^^ Code above is executed after loading finshed.\n\n\t\t// Load lazy nodes, if any. Then continue with _afterLoad()\n\t\tif(flag && node.lazy && node.hasChildren() === undefined){\n\t\t\t// node.debug(\"nodeSetExpanded: load start...\");\n\t\t\tnode.load().done(function(){\n\t\t\t\t// node.debug(\"nodeSetExpanded: load done\");\n\t\t\t\tif(dfd.notifyWith){ // requires jQuery 1.6+\n\t\t\t\t\tdfd.notifyWith(node, [\"loaded\"]);\n\t\t\t\t}\n\t\t\t\t_afterLoad(function () { dfd.resolveWith(node); });\n\t\t\t}).fail(function(errMsg){\n\t\t\t\t_afterLoad(function () { dfd.rejectWith(node, [\"load failed (\" + errMsg + \")\"]); });\n\t\t\t});\n/*\n\t\t\tvar source = tree._triggerNodeEvent(\"lazyLoad\", node, ctx.originalEvent);\n\t\t\t_assert(typeof source !== \"boolean\", \"lazyLoad event must return source in data.result\");\n\t\t\tnode.debug(\"nodeSetExpanded: load start...\");\n\t\t\tthis._callHook(\"nodeLoadChildren\", ctx, source).done(function(){\n\t\t\t\tnode.debug(\"nodeSetExpanded: load done\");\n\t\t\t\tif(dfd.notifyWith){ // requires jQuery 1.6+\n\t\t\t\t\tdfd.notifyWith(node, [\"loaded\"]);\n\t\t\t\t}\n\t\t\t\t_afterLoad.call(tree);\n\t\t\t}).fail(function(errMsg){\n\t\t\t\tdfd.rejectWith(node, [\"load failed (\" + errMsg + \")\"]);\n\t\t\t});\n*/\n\t\t}else{\n\t\t\t_afterLoad(function () { dfd.resolveWith(node); });\n\t\t}\n\t\t// node.debug(\"nodeSetExpanded: returns\");\n\t\treturn dfd.promise();\n\t},\n\t/** Focus or blur this node.\n\t * @param {EventData} ctx\n\t * @param {boolean} [flag=true]\n\t */\n\tnodeSetFocus: function(ctx, flag) {\n\t\t// ctx.node.debug(\"nodeSetFocus(\" + flag + \")\");\n\t\tvar ctx2,\n\t\t\ttree = ctx.tree,\n\t\t\tnode = ctx.node,\n\t\t\topts = tree.options,\n\t\t\t// et = ctx.originalEvent && ctx.originalEvent.type,\n\t\t\tisInput = ctx.originalEvent ? $(ctx.originalEvent.target).is(\":input\") : false;\n\n\t\tflag = (flag !== false);\n\n\t\t// (node || tree).debug(\"nodeSetFocus(\" + flag + \"), event: \" + et + \", isInput: \"+ isInput);\n\t\t// Blur previous node if any\n\t\tif(tree.focusNode){\n\t\t\tif(tree.focusNode === node && flag){\n\t\t\t\t// node.debug(\"nodeSetFocus(\" + flag + \"): nothing to do\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tctx2 = $.extend({}, ctx, {node: tree.focusNode});\n\t\t\ttree.focusNode = null;\n\t\t\tthis._triggerNodeEvent(\"blur\", ctx2);\n\t\t\tthis._callHook(\"nodeRenderStatus\", ctx2);\n\t\t}\n\t\t// Set focus to container and node\n\t\tif(flag){\n\t\t\tif( !this.hasFocus() ){\n\t\t\t\tnode.debug(\"nodeSetFocus: forcing container focus\");\n\t\t\t\tthis._callHook(\"treeSetFocus\", ctx, true, {calledByNode: true});\n\t\t\t}\n\t\t\tnode.makeVisible({scrollIntoView: false});\n\t\t\ttree.focusNode = node;\n\t\t\tif( opts.titlesTabbable ) {\n\t\t\t\tif( !isInput ) { // #621\n\t\t\t\t\t$(node.span).find(\".fancytree-title\").focus();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We cannot set KB focus to a node, so use the tree container\n\t\t\t\t// #563, #570: IE scrolls on every call to .focus(), if the container\n\t\t\t\t// is partially outside the viewport. So do it only, when absolutely\n\t\t\t\t// neccessary:\n\t\t\t\tif( $(document.activeElement).closest(\".fancytree-container\").length === 0 ) {\n\t\t\t\t\t$(tree.$container).focus();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif( opts.aria ){\n\t\t\t\t$(tree.$container).attr(\"aria-activedescendant\",\n\t\t\t\t\t\"ftal_\" + opts.idPrefix + node.key);\n\t\t\t}\n//\t\t\t$(node.span).find(\".fancytree-title\").focus();\n\t\t\tthis._triggerNodeEvent(\"focus\", ctx);\n//          if( opts.autoActivate ){\n//              tree.nodeSetActive(ctx, true);\n//          }\n\t\t\tif( opts.autoScroll ){\n\t\t\t\tnode.scrollIntoView();\n\t\t\t}\n\t\t\tthis._callHook(\"nodeRenderStatus\", ctx);\n\t\t}\n\t},\n\t/** (De)Select node, return new status (sync).\n\t *\n\t * @param {EventData} ctx\n\t * @param {boolean} [flag=true]\n\t */\n\tnodeSetSelected: function(ctx, flag) {\n\t\tvar node = ctx.node,\n\t\t\ttree = ctx.tree,\n\t\t\topts = ctx.options;\n\t\t// flag defaults to true\n\t\tflag = (flag !== false);\n\n\t\t// node.debug(\"nodeSetSelected(\" + flag + \")\", ctx);\n\t\tif( node.unselectable){\n\t\t\treturn;\n\t\t}\n\t\t// TODO: !!node.expanded is nicer, but doesn't pass jshint\n\t\t// https://github.com/jshint/jshint/issues/455\n//        if( !!node.expanded === !!flag){\n\t\tif((node.selected && flag) || (!node.selected && !flag)){\n\t\t\treturn !!node.selected;\n\t\t}else if ( this._triggerNodeEvent(\"beforeSelect\", node, ctx.originalEvent) === false ){\n\t\t\treturn !!node.selected;\n\t\t}\n\t\tif(flag && opts.selectMode === 1){\n\t\t\t// single selection mode\n\t\t\tif(tree.lastSelectedNode){\n\t\t\t\ttree.lastSelectedNode.setSelected(false);\n\t\t\t}\n\t\t}else if(opts.selectMode === 3){\n\t\t\t// multi.hier selection mode\n\t\t\tnode.selected = flag;\n//\t\t\tthis._fixSelectionState(node);\n\t\t\tnode.fixSelection3AfterClick();\n\t\t}\n\t\tnode.selected = flag;\n\t\tthis.nodeRenderStatus(ctx);\n\t\ttree.lastSelectedNode = flag ? node : null;\n\t\ttree._triggerNodeEvent(\"select\", ctx);\n\t},\n\t/** Show node status (ok, loading, error, nodata) using styles and a dummy child node.\n\t *\n\t * @param {EventData} ctx\n\t * @param status\n\t * @param message\n\t * @param details\n\t * @since 2.3\n\t */\n\tnodeSetStatus: function(ctx, status, message, details) {\n\t\tvar node = ctx.node,\n\t\t\ttree = ctx.tree;\n\n\t\tfunction _clearStatusNode() {\n\t\t\t// Remove dedicated dummy node, if any\n\t\t\tvar firstChild = ( node.children ? node.children[0] : null );\n\t\t\tif ( firstChild && firstChild.isStatusNode() ) {\n\t\t\t\ttry{\n\t\t\t\t\t// I've seen exceptions here with loadKeyPath...\n\t\t\t\t\tif(node.ul){\n\t\t\t\t\t\tnode.ul.removeChild(firstChild.li);\n\t\t\t\t\t\tfirstChild.li = null; // avoid leaks (DT issue 215)\n\t\t\t\t\t}\n\t\t\t\t}catch(e){}\n\t\t\t\tif( node.children.length === 1 ){\n\t\t\t\t\tnode.children = [];\n\t\t\t\t}else{\n\t\t\t\t\tnode.children.shift();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfunction _setStatusNode(data, type) {\n\t\t\t// Create/modify the dedicated dummy node for 'loading...' or\n\t\t\t// 'error!' status. (only called for direct child of the invisible\n\t\t\t// system root)\n\t\t\tvar firstChild = ( node.children ? node.children[0] : null );\n\t\t\tif ( firstChild && firstChild.isStatusNode() ) {\n\t\t\t\t$.extend(firstChild, data);\n\t\t\t\tfirstChild.statusNodeType = type;\n\t\t\t\ttree._callHook(\"nodeRenderTitle\", firstChild);\n\t\t\t} else {\n\t\t\t\tnode._setChildren([data]);\n\t\t\t\tnode.children[0].statusNodeType = type;\n\t\t\t\ttree.render();\n\t\t\t}\n\t\t\treturn node.children[0];\n\t\t}\n\n\t\tswitch( status ){\n\t\tcase \"ok\":\n\t\t\t_clearStatusNode();\n\t\t\tnode._isLoading = false;\n\t\t\tnode._error = null;\n\t\t\tnode.renderStatus();\n\t\t\tbreak;\n\t\tcase \"loading\":\n\t\t\tif( !node.parent ) {\n\t\t\t\t_setStatusNode({\n\t\t\t\t\ttitle: tree.options.strings.loading + (message ? \" (\" + message + \")\" : \"\"),\n\t\t\t\t\t// icon: true,  // needed for 'loding' icon\n\t\t\t\t\tcheckbox: false,\n\t\t\t\t\ttooltip: details\n\t\t\t\t}, status);\n\t\t\t}\n\t\t\tnode._isLoading = true;\n\t\t\tnode._error = null;\n\t\t\tnode.renderStatus();\n\t\t\tbreak;\n\t\tcase \"error\":\n\t\t\t_setStatusNode({\n\t\t\t\ttitle: tree.options.strings.loadError + (message ? \" (\" + message + \")\" : \"\"),\n\t\t\t\t// icon: false,\n\t\t\t\tcheckbox: false,\n\t\t\t\ttooltip: details\n\t\t\t}, status);\n\t\t\tnode._isLoading = false;\n\t\t\tnode._error = { message: message, details: details };\n\t\t\tnode.renderStatus();\n\t\t\tbreak;\n\t\tcase \"nodata\":\n\t\t\t_setStatusNode({\n\t\t\t\ttitle: tree.options.strings.noData,\n\t\t\t\t// icon: false,\n\t\t\t\tcheckbox: false,\n\t\t\t\ttooltip: details\n\t\t\t}, status);\n\t\t\tnode._isLoading = false;\n\t\t\tnode._error = null;\n\t\t\tnode.renderStatus();\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t$.error(\"invalid node status \" + status);\n\t\t}\n\t},\n\t/**\n\t *\n\t * @param {EventData} ctx\n\t */\n\tnodeToggleExpanded: function(ctx) {\n\t\treturn this.nodeSetExpanded(ctx, !ctx.node.expanded);\n\t},\n\t/**\n\t * @param {EventData} ctx\n\t */\n\tnodeToggleSelected: function(ctx) {\n\t\treturn this.nodeSetSelected(ctx, !ctx.node.selected);\n\t},\n\t/** Remove all nodes.\n\t * @param {EventData} ctx\n\t */\n\ttreeClear: function(ctx) {\n\t\tvar tree = ctx.tree;\n\t\ttree.activeNode = null;\n\t\ttree.focusNode = null;\n\t\ttree.$div.find(\">ul.fancytree-container\").empty();\n\t\t// TODO: call destructors and remove reference loops\n\t\ttree.rootNode.children = null;\n\t},\n\t/** Widget was created (called only once, even it re-initialized).\n\t * @param {EventData} ctx\n\t */\n\ttreeCreate: function(ctx) {\n\t},\n\t/** Widget was destroyed.\n\t * @param {EventData} ctx\n\t */\n\ttreeDestroy: function(ctx) {\n\t\tthis.$div.find(\">ul.fancytree-container\").remove();\n\t\tthis.$source && this.$source.removeClass(\"ui-helper-hidden\");\n\t},\n\t/** Widget was (re-)initialized.\n\t * @param {EventData} ctx\n\t */\n\ttreeInit: function(ctx) {\n\t\t//this.debug(\"Fancytree.treeInit()\");\n\t\tthis.treeLoad(ctx);\n\t},\n\t/** Parse Fancytree from source, as configured in the options.\n\t * @param {EventData} ctx\n\t * @param {object} [source] optional new source (use last data otherwise)\n\t */\n\ttreeLoad: function(ctx, source) {\n\t\tvar metaData, type, $ul,\n\t\t\ttree = ctx.tree,\n\t\t\t$container = ctx.widget.element,\n\t\t\tdfd,\n\t\t\t// calling context for root node\n\t\t\trootCtx = $.extend({}, ctx, {node: this.rootNode});\n\n\t\tif(tree.rootNode.children){\n\t\t\tthis.treeClear(ctx);\n\t\t}\n\t\tsource = source || this.options.source;\n\n\t\tif(!source){\n\t\t\ttype = $container.data(\"type\") || \"html\";\n\t\t\tswitch(type){\n\t\t\tcase \"html\":\n\t\t\t\t$ul = $container.find(\">ul:first\");\n\t\t\t\t$ul.addClass(\"ui-fancytree-source ui-helper-hidden\");\n\t\t\t\tsource = $.ui.fancytree.parseHtml($ul);\n\t\t\t\t// allow to init tree.data.foo from <ul data-foo=''>\n\t\t\t\tthis.data = $.extend(this.data, _getElementDataAsDict($ul));\n\t\t\t\tbreak;\n\t\t\tcase \"json\":\n\t\t\t\tsource = $.parseJSON($container.text());\n\t\t\t\t// $container already contains the <ul>, but we remove the plain (json) text\n\t\t\t\t// $container.empty();\n\t\t\t\t$container.contents().filter(function(){\n\t\t\t\t\treturn (this.nodeType === 3);\n\t\t\t\t}).remove();\n\t\t\t\tif( $.isPlainObject(source) ){\n\t\t\t\t\t// We got {foo: 'abc', children: [...]}\n\t\t\t\t\t// Copy extra properties to tree.data.foo\n\t\t\t\t\t_assert($.isArray(source.children), \"if an object is passed as source, it must contain a 'children' array (all other properties are added to 'tree.data')\");\n\t\t\t\t\tmetaData = source;\n\t\t\t\t\tsource = source.children;\n\t\t\t\t\tdelete metaData.children;\n\t\t\t\t\t$.extend(tree.data, metaData);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t$.error(\"Invalid data-type: \" + type);\n\t\t\t}\n\t\t}else if(typeof source === \"string\"){\n\t\t\t// TODO: source is an element ID\n\t\t\t$.error(\"Not implemented\");\n\t\t}\n\n\t\t// Trigger fancytreeinit after nodes have been loaded\n\t\tdfd = this.nodeLoadChildren(rootCtx, source).done(function(){\n\t\t\ttree.render();\n\t\t\tif( ctx.options.selectMode === 3 ){\n\t\t\t\ttree.rootNode.fixSelection3FromEndNodes();\n\t\t\t}\n\t\t\tif( tree.activeNode && tree.options.activeVisible ) {\n\t\t\t\ttree.activeNode.makeVisible();\n\t\t\t}\n\t\t\ttree._triggerTreeEvent(\"init\", null, { status: true });\n\t\t}).fail(function(){\n\t\t\ttree.render();\n\t\t\ttree._triggerTreeEvent(\"init\", null, { status: false });\n\t\t});\n\t\treturn dfd;\n\t},\n\t/** Node was inserted into or removed from the tree.\n\t * @param {EventData} ctx\n\t * @param {boolean} add\n\t * @param {FancytreeNode} node\n\t */\n\ttreeRegisterNode: function(ctx, add, node) {\n\t},\n\t/** Widget got focus.\n\t * @param {EventData} ctx\n\t * @param {boolean} [flag=true]\n\t */\n\ttreeSetFocus: function(ctx, flag, callOpts) {\n\t\tfunction ensureTreeFocus(thisTree) {\n\t\t\tif (!thisTree.activeNode && thisTree.getFirstChild()) {\n\t\t\t\tthisTree.getFirstChild().setFocus();\n\t\t\t}\n\t\t}\n\n\t\tflag = (flag !== false);\n\n\t\t// this.debug(\"treeSetFocus(\" + flag + \"), callOpts: \", callOpts, this.hasFocus());\n\t\t// this.debug(\"    focusNode: \" + this.focusNode);\n\t\t// this.debug(\"    activeNode: \" + this.activeNode);\n\t\tif( flag !== this.hasFocus() ){\n\t\t\tthis._hasFocus = flag;\n\t\t\tif( !flag && this.focusNode ) {\n\t\t\t\t// Node also looses focus if widget blurs\n\t\t\t\tthis.focusNode.setFocus(false);\n\t\t\t} else if ( flag && (!callOpts || !callOpts.calledByNode) ) {\n\t\t\t\t$(this.$container).focus();\n\t\t\t}\n\t\t\tthis.$container.toggleClass(\"fancytree-treefocus\", flag);\n\t\t\tthis._triggerTreeEvent(flag ? \"focusTree\" : \"blurTree\");\n\t\t\tif( flag ) {\n\t\t\t\t// Check after timeout to ensure mousedown processing is complete\n\t\t\t\t// and the clicked node is already activated\n\t\t\t\tvar thisTree = this;\n\t\t\t\tsetTimeout(function() { ensureTreeFocus(thisTree); }, 0);\n\t\t\t}\n\t\t}\n\t},\n\t/** Widget option was set using `$().fancytree(\"option\", \"foo\", \"bar\")`.\n\t * @param {EventData} ctx\n\t * @param {string} key option name\n\t * @param {any} value option value\n\t */\n\ttreeSetOption: function(ctx, key, value) {\n\t\tvar tree = ctx.tree,\n\t\t\tcallDefault = true,\n\t\t\trerender = false;\n\n\t\tswitch( key ) {\n\t\tcase \"aria\":\n\t\tcase \"checkbox\":\n\t\tcase \"icon\":\n\t\tcase \"minExpandLevel\":\n\t\tcase \"tabindex\":\n\t\t\ttree._callHook(\"treeCreate\", tree);\n\t\t\trerender = true;\n\t\t\tbreak;\n\t\tcase \"escapeTitles\":\n\t\tcase \"tooltip\":\n\t\t\trerender = true;\n\t\t\tbreak;\n\t\tcase \"rtl\":\n\t\t\tif( value === false ) {\n\t\t\t\ttree.$container.attr(\"DIR\", null).removeClass(\"fancytree-rtl\");\n\t\t\t}else{\n\t\t\t\ttree.$container.attr(\"DIR\", \"RTL\").addClass(\"fancytree-rtl\");\n\t\t\t}\n\t\t\trerender = true;\n\t\t\tbreak;\n\t\tcase \"source\":\n\t\t\tcallDefault = false;\n\t\t\ttree._callHook(\"treeLoad\", tree, value);\n\t\t\trerender = true;\n\t\t\tbreak;\n\t\t}\n\t\ttree.debug(\"set option \" + key + \"=\" + value + \" <\" + typeof(value) + \">\");\n\t\tif(callDefault){\n\t\t\tif( this.widget._super ) {\n\t\t\t\t// jQuery UI 1.9+\n\t\t\t\tthis.widget._super.call( this.widget, key, value );\n\t\t\t} else {\n\t\t\t\t// jQuery UI <= 1.8, we have to manually invoke the _setOption method from the base widget\n\t\t\t\t$.Widget.prototype._setOption.call(this.widget, key, value);\n\t\t\t}\n\t\t}\n\t\tif(rerender){\n\t\t\ttree.render(true, false);  // force, not-deep\n\t\t}\n\t}\n});\n\n\n/* ******************************************************************************\n * jQuery UI widget boilerplate\n */\n\n/**\n * The plugin (derrived from <a href=\" http://api.jqueryui.com/jQuery.widget/\">jQuery.Widget</a>).<br>\n * This constructor is not called directly. Use `$(selector).fancytree({})`\n * to initialize the plugin instead.<br>\n * <pre class=\"sh_javascript sunlight-highlight-javascript\">// Access widget methods and members:\n * var tree = $(\"#tree\").fancytree(\"getTree\");\n * var node = $(\"#tree\").fancytree(\"getActiveNode\", \"1234\");\n * </pre>\n *\n * @mixin Fancytree_Widget\n */\n\n$.widget(\"ui.fancytree\",\n\t/** @lends Fancytree_Widget# */\n\t{\n\t/**These options will be used as defaults\n\t * @type {FancytreeOptions}\n\t */\n\toptions:\n\t{\n\t\tactiveVisible: true,\n\t\tajax: {\n\t\t\ttype: \"GET\",\n\t\t\tcache: false, // false: Append random '_' argument to the request url to prevent caching.\n//          timeout: 0, // >0: Make sure we get an ajax error if server is unreachable\n\t\t\tdataType: \"json\" // Expect json format and pass json object to callbacks.\n\t\t},  //\n\t\taria: false,\n\t\tautoActivate: true,\n\t\tautoCollapse: false,\n\t\tautoScroll: false,\n\t\tcheckbox: false,\n\t\tclickFolderMode: 4,\n\t\tdebugLevel: null, // 0..2 (null: use global setting $.ui.fancytree.debugInfo)\n\t\tdisabled: false, // TODO: required anymore?\n\t\tenableAspx: true, // TODO: document\n\t\tescapeTitles: false,\n\t\textensions: [],\n\t\t// fx: { height: \"toggle\", duration: 200 },\n\t\t// toggleEffect: { effect: \"drop\", options: {direction: \"left\"}, duration: 200 },\n\t\t// toggleEffect: { effect: \"slide\", options: {direction: \"up\"}, duration: 200 },\n\t\ttoggleEffect: { effect: \"blind\", options: {direction: \"vertical\", scale: \"box\"}, duration: 200 },\n\t\tgenerateIds: false,\n\t\ticon: true,\n\t\tidPrefix: \"ft_\",\n\t\tfocusOnSelect: false,\n\t\tkeyboard: true,\n\t\tkeyPathSeparator: \"/\",\n\t\tminExpandLevel: 1,\n\t\tquicksearch: false,\n\t\trtl: false,\n\t\tscrollOfs: {top: 0, bottom: 0},\n\t\tscrollParent: null,\n\t\tselectMode: 2,\n\t\tstrings: {\n\t\t\tloading: \"Loading&#8230;\",\n\t\t\tloadError: \"Load error!\",\n\t\t\tmoreData: \"More&#8230;\",\n\t\t\tnoData: \"No data.\"\n\t\t},\n\t\ttabindex: \"0\",\n\t\ttitlesTabbable: false,\n\t\ttooltip: false,\n\t\t_classNames: {\n\t\t\tnode: \"fancytree-node\",\n\t\t\tfolder: \"fancytree-folder\",\n\t\t\tcombinedExpanderPrefix: \"fancytree-exp-\",\n\t\t\tcombinedIconPrefix: \"fancytree-ico-\",\n\t\t\thasChildren: \"fancytree-has-children\",\n\t\t\tactive: \"fancytree-active\",\n\t\t\tselected: \"fancytree-selected\",\n\t\t\texpanded: \"fancytree-expanded\",\n\t\t\tlazy: \"fancytree-lazy\",\n\t\t\tfocused: \"fancytree-focused\",\n\t\t\tpartload: \"fancytree-partload\",\n\t\t\tpartsel: \"fancytree-partsel\",\n\t\t\tunselectable: \"fancytree-unselectable\",\n\t\t\tlastsib: \"fancytree-lastsib\",\n\t\t\tloading: \"fancytree-loading\",\n\t\t\terror: \"fancytree-error\",\n\t\t\tstatusNodePrefix: \"fancytree-statusnode-\"\n\t\t},\n\t\t// events\n\t\tlazyLoad: null,\n\t\tpostProcess: null\n\t},\n\t/* Set up the widget, Called on first $().fancytree() */\n\t_create: function() {\n\t\tthis.tree = new Fancytree(this);\n\n\t\tthis.$source = this.source || this.element.data(\"type\") === \"json\" ? this.element\n\t\t\t: this.element.find(\">ul:first\");\n\t\t// Subclass Fancytree instance with all enabled extensions\n\t\tvar extension, extName, i,\n\t\t\topts = this.options,\n\t\t\textensions = opts.extensions,\n\t\t\tbase = this.tree;\n\n\t\tfor(i=0; i<extensions.length; i++){\n\t\t\textName = extensions[i];\n\t\t\textension = $.ui.fancytree._extensions[extName];\n\t\t\tif(!extension){\n\t\t\t\t$.error(\"Could not apply extension '\" + extName + \"' (it is not registered, did you forget to include it?)\");\n\t\t\t}\n\t\t\t// Add extension options as tree.options.EXTENSION\n//\t\t\t_assert(!this.tree.options[extName], \"Extension name must not exist as option name: \" + extName);\n\t\t\tthis.tree.options[extName] = $.extend(true, {}, extension.options, this.tree.options[extName]);\n\t\t\t// Add a namespace tree.ext.EXTENSION, to hold instance data\n\t\t\t_assert(this.tree.ext[extName] === undefined, \"Extension name must not exist as Fancytree.ext attribute: '\" + extName + \"'\");\n//\t\t\tthis.tree[extName] = extension;\n\t\t\tthis.tree.ext[extName] = {};\n\t\t\t// Subclass Fancytree methods using proxies.\n\t\t\t_subclassObject(this.tree, base, extension, extName);\n\t\t\t// current extension becomes base for the next extension\n\t\t\tbase = extension;\n\t\t}\n\t\t//\n\t\tif( opts.icons !== undefined ) {  // 2015-11-16\n\t\t\tif( opts.icon !== true ) {\n\t\t\t\t$.error(\"'icons' tree option is deprecated since v2.14.0: use 'icon' only instead\");\n\t\t\t} else {\n\t\t\t\tthis.tree.warn(\"'icons' tree option is deprecated since v2.14.0: use 'icon' instead\");\n\t\t\t\topts.icon = opts.icons;\n\t\t\t}\n\t\t}\n\t\tif( opts.iconClass !== undefined ) {  // 2015-11-16\n\t\t\tif( opts.icon ) {\n\t\t\t\t$.error(\"'iconClass' tree option is deprecated since v2.14.0: use 'icon' only instead\");\n\t\t\t} else {\n\t\t\t\tthis.tree.warn(\"'iconClass' tree option is deprecated since v2.14.0: use 'icon' instead\");\n\t\t\t\topts.icon = opts.iconClass;\n\t\t\t}\n\t\t}\n\t\tif( opts.tabbable !== undefined ) {  // 2016-04-04\n\t\t\topts.tabindex = opts.tabbable ? \"0\" : \"-1\";\n\t\t\tthis.tree.warn(\"'tabbable' tree option is deprecated since v2.17.0: use 'tabindex='\" + opts.tabindex + \"' instead\");\n\t\t}\n\t\t//\n\t\tthis.tree._callHook(\"treeCreate\", this.tree);\n\t\t// Note: 'fancytreecreate' event is fired by widget base class\n//        this.tree._triggerTreeEvent(\"create\");\n\t},\n\n\t/* Called on every $().fancytree() */\n\t_init: function() {\n\t\tthis.tree._callHook(\"treeInit\", this.tree);\n\t\t// TODO: currently we call bind after treeInit, because treeInit\n\t\t// might change tree.$container.\n\t\t// It would be better, to move ebent binding into hooks altogether\n\t\tthis._bind();\n\t},\n\n\t/* Use the _setOption method to respond to changes to options */\n\t_setOption: function(key, value) {\n\t\treturn this.tree._callHook(\"treeSetOption\", this.tree, key, value);\n\t},\n\n\t/** Use the destroy method to clean up any modifications your widget has made to the DOM */\n\tdestroy: function() {\n\t\tthis._unbind();\n\t\tthis.tree._callHook(\"treeDestroy\", this.tree);\n\t\t// In jQuery UI 1.8, you must invoke the destroy method from the base widget\n\t\t$.Widget.prototype.destroy.call(this);\n\t\t// TODO: delete tree and nodes to make garbage collect easier?\n\t\t// TODO: In jQuery UI 1.9 and above, you would define _destroy instead of destroy and not call the base method\n\t},\n\n\t// -------------------------------------------------------------------------\n\n\t/* Remove all event handlers for our namespace */\n\t_unbind: function() {\n\t\tvar ns = this.tree._ns;\n\t\tthis.element.off(ns);\n\t\tthis.tree.$container.off(ns);\n\t\t$(document).off(ns);\n\t},\n\t/* Add mouse and kyboard handlers to the container */\n\t_bind: function() {\n\t\tvar that = this,\n\t\t\topts = this.options,\n\t\t\ttree = this.tree,\n\t\t\tns = tree._ns\n\t\t\t// selstartEvent = ( $.support.selectstart ? \"selectstart\" : \"mousedown\" )\n\t\t\t;\n\n\t\t// Remove all previuous handlers for this tree\n\t\tthis._unbind();\n\n\t\t//alert(\"keydown\" + ns + \"foc=\" + tree.hasFocus() + tree.$container);\n\t\t// tree.debug(\"bind events; container: \", tree.$container);\n\t\ttree.$container.on(\"focusin\" + ns + \" focusout\" + ns, function(event){\n\t\t\tvar node = FT.getNode(event),\n\t\t\t\tflag = (event.type === \"focusin\");\n\t\t\t// tree.debug(\"Tree container got event \" + event.type, node, event);\n\t\t\t// tree.treeOnFocusInOut.call(tree, event);\n\t\t\tif(node){\n\t\t\t\t// For example clicking into an <input> that is part of a node\n\t\t\t\ttree._callHook(\"nodeSetFocus\", tree._makeHookContext(node, event), flag);\n\t\t\t\t// tree._callHook(\"nodeSetFocus\", node, flag);\n\t\t\t}else{\n\t\t\t\ttree._callHook(\"treeSetFocus\", tree, flag);\n\t\t\t}\n\t\t}).on(\"selectstart\" + ns, \"span.fancytree-title\", function(event){\n\t\t\t// prevent mouse-drags to select text ranges\n\t\t\t// tree.debug(\"<span title> got event \" + event.type);\n\t\t\tevent.preventDefault();\n\t\t}).on(\"keydown\" + ns, function(event){\n\t\t\t// TODO: also bind keyup and keypress\n\t\t\t// tree.debug(\"got event \" + event.type + \", hasFocus:\" + tree.hasFocus());\n\t\t\t// if(opts.disabled || opts.keyboard === false || !tree.hasFocus() ){\n\t\t\tif(opts.disabled || opts.keyboard === false ){\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tvar res,\n\t\t\t\tnode = tree.focusNode, // node may be null\n\t\t\t\tctx = tree._makeHookContext(node || tree, event),\n\t\t\t\tprevPhase = tree.phase;\n\n\t\t\ttry {\n\t\t\t\ttree.phase = \"userEvent\";\n\t\t\t\t// If a 'fancytreekeydown' handler returns false, skip the default\n\t\t\t\t// handling (implemented by tree.nodeKeydown()).\n\t\t\t\tif(node){\n\t\t\t\t\tres = tree._triggerNodeEvent(\"keydown\", node, event);\n\t\t\t\t}else{\n\t\t\t\t\tres = tree._triggerTreeEvent(\"keydown\", event);\n\t\t\t\t}\n\t\t\t\tif ( res === \"preventNav\" ){\n\t\t\t\t\tres = true; // prevent keyboard navigation, but don't prevent default handling of embedded input controls\n\t\t\t\t} else if ( res !== false ){\n\t\t\t\t\tres = tree._callHook(\"nodeKeydown\", ctx);\n\t\t\t\t}\n\t\t\t\treturn res;\n\t\t\t} finally {\n\t\t\t\ttree.phase = prevPhase;\n\t\t\t}\n\t\t}).on(\"mousedown\" + ns + \" dblclick\" + ns, function(event){\n\t\t\t// that.tree.debug(\"event(\" + event + \"): !\");\n\t\t\tif(opts.disabled){\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tvar ctx,\n\t\t\t\tet = FT.getEventTarget(event),\n\t\t\t\tnode = et.node,\n\t\t\t\ttree = that.tree,\n\t\t\t\tprevPhase = tree.phase;\n\n\t\t\t// that.tree.debug(\"event(\" + event.type + \"): node: \", node);\n\t\t\tif( !node ){\n\t\t\t\treturn true;  // Allow bubbling of other events\n\t\t\t}\n\t\t\tctx = tree._makeHookContext(node, event);\n\t\t\t// that.tree.debug(\"event(\" + event.type + \"): node: \", node);\n\t\t\ttry {\n\t\t\t\ttree.phase = \"userEvent\";\n\t\t\t\tswitch(event.type) {\n\t\t\t\tcase \"mousedown\":\n\t\t\t\t\tctx.targetType = et.type;\n\t\t\t\t\tif( node.isPagingNode() ) {\n\t\t\t\t\t\treturn tree._triggerNodeEvent(\"clickPaging\", ctx, event) === true;\n\t\t\t\t\t}\n\t\t\t\t\treturn ( tree._triggerNodeEvent(\"click\", ctx, event) === false ) ? false : tree._callHook(\"nodeClick\", ctx);\n\t\t\t\tcase \"dblclick\":\n\t\t\t\t\tctx.targetType = et.type;\n\t\t\t\t\treturn ( tree._triggerNodeEvent(\"dblclick\", ctx, event) === false ) ? false : tree._callHook(\"nodeDblclick\", ctx);\n\t\t\t\t}\n//             } catch(e) {\n// //                var _ = null; // DT issue 117 // TODO\n//                 $.error(e);\n\t\t\t} finally {\n\t\t\t\ttree.phase = prevPhase;\n\t\t\t}\n\t\t});\n\t},\n\t/** Return the active node or null.\n\t * @returns {FancytreeNode}\n\t */\n\tgetActiveNode: function() {\n\t\treturn this.tree.activeNode;\n\t},\n\t/** Return the matching node or null.\n\t * @param {string} key\n\t * @returns {FancytreeNode}\n\t */\n\tgetNodeByKey: function(key) {\n\t\treturn this.tree.getNodeByKey(key);\n\t},\n\t/** Return the invisible system root node.\n\t * @returns {FancytreeNode}\n\t */\n\tgetRootNode: function() {\n\t\treturn this.tree.rootNode;\n\t},\n\t/** Return the current tree instance.\n\t * @returns {Fancytree}\n\t */\n\tgetTree: function() {\n\t\treturn this.tree;\n\t}\n});\n\n// $.ui.fancytree was created by the widget factory. Create a local shortcut:\nFT = $.ui.fancytree;\n\n/**\n * Static members in the `$.ui.fancytree` namespace.<br>\n * <br>\n * <pre class=\"sh_javascript sunlight-highlight-javascript\">// Access static members:\n * var node = $.ui.fancytree.getNode(element);\n * alert($.ui.fancytree.version);\n * </pre>\n *\n * @mixin Fancytree_Static\n */\n$.extend($.ui.fancytree,\n\t/** @lends Fancytree_Static# */\n\t{\n\t/** @type {string} */\n\tversion: \"@VERSION\",      // Set to semver by 'grunt release'\n\t/** @type {string} */\n\tbuildType: \"development\", // Set to 'production' by 'grunt build'\n\t/** @type {int} */\n\tdebugLevel: 2,            // Set to 1 by 'grunt build'\n\t\t\t\t\t\t\t  // Used by $.ui.fancytree.debug() and as default for tree.options.debugLevel\n\n\t_nextId: 1,\n\t_nextNodeKey: 1,\n\t_extensions: {},\n\t// focusTree: null,\n\n\t/** Expose class object as $.ui.fancytree._FancytreeClass */\n\t_FancytreeClass: Fancytree,\n\t/** Expose class object as $.ui.fancytree._FancytreeNodeClass */\n\t_FancytreeNodeClass: FancytreeNode,\n\t/* Feature checks to provide backwards compatibility */\n\tjquerySupports: {\n\t\t// http://jqueryui.com/upgrade-guide/1.9/#deprecated-offset-option-merged-into-my-and-at\n\t\tpositionMyOfs: isVersionAtLeast($.ui.version, 1, 9)\n\t\t},\n\t/** Throw an error if condition fails (debug method).\n\t * @param {boolean} cond\n\t * @param {string} msg\n\t */\n\tassert: function(cond, msg){\n\t\treturn _assert(cond, msg);\n\t},\n\t/** Return a function that executes *fn* at most every *timeout* ms.\n\t * @param {integer} timeout\n\t * @param {function} fn\n\t * @param {boolean} [invokeAsap=false]\n\t * @param {any} [ctx]\n\t */\n\tdebounce: function(timeout, fn, invokeAsap, ctx) {\n\t\tvar timer;\n\t\tif(arguments.length === 3 && typeof invokeAsap !== \"boolean\") {\n\t\t\tctx = invokeAsap;\n\t\t\tinvokeAsap = false;\n\t\t}\n\t\treturn function() {\n\t\t\tvar args = arguments;\n\t\t\tctx = ctx || this;\n\t\t\tinvokeAsap && !timer && fn.apply(ctx, args);\n\t\t\tclearTimeout(timer);\n\t\t\ttimer = setTimeout(function() {\n\t\t\t\tinvokeAsap || fn.apply(ctx, args);\n\t\t\t\ttimer = null;\n\t\t\t}, timeout);\n\t\t};\n\t},\n\t/** Write message to console if debugLevel >= 2\n\t * @param {string} msg\n\t */\n\tdebug: function(msg){\n\t\t/*jshint expr:true */\n\t\t($.ui.fancytree.debugLevel >= 2) && consoleApply(\"log\", arguments);\n\t},\n\t/** Write error message to console.\n\t * @param {string} msg\n\t */\n\terror: function(msg){\n\t\tconsoleApply(\"error\", arguments);\n\t},\n\t/** Convert &lt;, &gt;, &amp;, &quot;, &#39;, &#x2F; to the equivalent entities.\n\t *\n\t * @param {string} s\n\t * @returns {string}\n\t */\n\tescapeHtml: _escapeHtml,\n\t/** Make jQuery.position() arguments backwards compatible, i.e. if\n\t * jQuery UI version <= 1.8, convert\n\t *   { my: \"left+3 center\", at: \"left bottom\", of: $target }\n\t * to\n\t *   { my: \"left center\", at: \"left bottom\", of: $target, offset: \"3  0\" }\n\t *\n\t * See http://jqueryui.com/upgrade-guide/1.9/#deprecated-offset-option-merged-into-my-and-at\n\t * and http://jsfiddle.net/mar10/6xtu9a4e/\n\t */\n\tfixPositionOptions: function(opts) {\n\t\tif( opts.offset || (\"\" + opts.my + opts.at ).indexOf(\"%\") >= 0 ) {\n\t\t   $.error(\"expected new position syntax (but '%' is not supported)\");\n\t\t}\n\t\tif( ! $.ui.fancytree.jquerySupports.positionMyOfs ) {\n\t\t\tvar // parse 'left+3 center' into ['left+3 center', 'left', '+3', 'center', undefined]\n\t\t\t\tmyParts = /(\\w+)([+-]?\\d+)?\\s+(\\w+)([+-]?\\d+)?/.exec(opts.my),\n\t\t\t\tatParts = /(\\w+)([+-]?\\d+)?\\s+(\\w+)([+-]?\\d+)?/.exec(opts.at),\n\t\t\t\t// convert to numbers\n\t\t\t\tdx = (myParts[2] ? (+myParts[2]) : 0) + (atParts[2] ? (+atParts[2]) : 0),\n\t\t\t\tdy = (myParts[4] ? (+myParts[4]) : 0) + (atParts[4] ? (+atParts[4]) : 0);\n\n\t\t\topts = $.extend({}, opts, { // make a copy and overwrite\n\t\t\t\tmy: myParts[1] + \" \" + myParts[3],\n\t\t\t\tat: atParts[1] + \" \" + atParts[3]\n\t\t\t});\n\t\t\tif( dx || dy ) {\n\t\t\t\topts.offset = \"\" + dx + \" \" + dy;\n\t\t\t}\n\t\t}\n\t\treturn opts;\n\t},\n\t/** Return a {node: FancytreeNode, type: TYPE} object for a mouse event.\n\t *\n\t * @param {Event} event Mouse event, e.g. click, ...\n\t * @returns {string} 'title' | 'prefix' | 'expander' | 'checkbox' | 'icon' | undefined\n\t */\n\tgetEventTargetType: function(event){\n\t\treturn this.getEventTarget(event).type;\n\t},\n\t/** Return a {node: FancytreeNode, type: TYPE} object for a mouse event.\n\t *\n\t * @param {Event} event Mouse event, e.g. click, ...\n\t * @returns {object} Return a {node: FancytreeNode, type: TYPE} object\n\t *     TYPE: 'title' | 'prefix' | 'expander' | 'checkbox' | 'icon' | undefined\n\t */\n\tgetEventTarget: function(event){\n\t\tvar tcn = event && event.target ? event.target.className : \"\",\n\t\t\tres = {node: this.getNode(event.target), type: undefined};\n\t\t// We use a fast version of $(res.node).hasClass()\n\t\t// See http://jsperf.com/test-for-classname/2\n\t\tif( /\\bfancytree-title\\b/.test(tcn) ){\n\t\t\tres.type = \"title\";\n\t\t}else if( /\\bfancytree-expander\\b/.test(tcn) ){\n\t\t\tres.type = (res.node.hasChildren() === false ? \"prefix\" : \"expander\");\n\t\t}else if( /\\bfancytree-checkbox\\b/.test(tcn) || /\\bfancytree-radio\\b/.test(tcn) ){\n\t\t\tres.type = \"checkbox\";\n\t\t}else if( /\\bfancytree-icon\\b/.test(tcn) ){\n\t\t\tres.type = \"icon\";\n\t\t}else if( /\\bfancytree-node\\b/.test(tcn) ){\n\t\t\t// Somewhere near the title\n\t\t\tres.type = \"title\";\n\t\t}else if( event && event.target && $(event.target).closest(\".fancytree-title\").length ) {\n\t\t\t// #228: clicking an embedded element inside a title\n\t\t\tres.type = \"title\";\n\t\t}\n\t\treturn res;\n\t},\n\t/** Return a FancytreeNode instance from element, event, or jQuery object.\n\t *\n\t * @param {Element | jQueryObject | Event} el\n\t * @returns {FancytreeNode} matching node or null\n\t */\n\tgetNode: function(el){\n\t\tif(el instanceof FancytreeNode){\n\t\t\treturn el; // el already was a FancytreeNode\n\t\t}else if( el instanceof jQuery ){\n\t\t\tel = el[0]; // el was a jQuery object: use the DOM element\n\t\t}else if(el.originalEvent !== undefined){\n\t\t\tel = el.target; // el was an Event\n\t\t}\n\t\twhile( el ) {\n\t\t\tif(el.ftnode) {\n\t\t\t\treturn el.ftnode;\n\t\t\t}\n\t\t\tel = el.parentNode;\n\t\t}\n\t\treturn null;\n\t},\n\t/** Return a Fancytree instance, from element, index, event, or jQueryObject.\n\t *\n\t * @param {Element | jQueryObject | Event | integer | string} [el]\n\t * @returns {Fancytree} matching tree or null\n\t * @example\n\t * $.ui.fancytree.getTree();   // Get first Fancytree instance on page\n\t * $.ui.fancytree.getTree(1);  // Get second Fancytree instance on page\n\t * $.ui.fancytree.getTree(\"#tree\"); // Get tree for this matching element\n\t *\n\t * @since 2.13\n\t */\n\tgetTree: function(el){\n\t\tvar widget;\n\n\t\tif( el instanceof Fancytree ) {\n\t\t\treturn el; // el already was a Fancytree\n\t\t}\n\t\tif( el === undefined ) {\n\t\t\tel = 0;  // get first tree\n\t\t}\n\t\tif( typeof el === \"number\" ) {\n\t\t\tel = $(\".fancytree-container\").eq(el); // el was an integer: return nth instance\n\t\t} else if( typeof el === \"string\" ) {\n\t\t\tel = $(el).eq(0); // el was a selector: use first match\n\t\t} else if( el.selector !== undefined ) {\n\t\t\tel = el.eq(0); // el was a jQuery object: use the first DOM element\n\t\t} else if( el.originalEvent !== undefined ) {\n\t\t\tel = $(el.target); // el was an Event\n\t\t}\n\t\tel = el.closest(\":ui-fancytree\");\n\t\twidget = el.data(\"ui-fancytree\") || el.data(\"fancytree\"); // the latter is required by jQuery <= 1.8\n\t\treturn widget ? widget.tree : null;\n\t},\n\t/** Return an option value that has a default, but may be overridden by a \n\t * callback or a node instance attribute.\n\t *\n\t * Evaluation sequence:<br>\n\t *\n\t * If tree.options.<optionName> is a callback that returns something, use that.<br>\n\t * Else if node.<optionName> is defined, use that.<br>\n\t * Else if tree.options.<optionName> is a value, use that.<br>\n\t * Else use `defaultValue`.\n\t *\n\t * @param {string} optionName name of the option property (on node and tree)\n\t * @param {FancytreeNode} node passed to the callback\n\t * @param {object} nodeObject where to look for the local option property, e.g. `node` or `node.data`\n\t * @param {object} treeOption where to look for the tree option, e.g. `tree.options` or `tree.options.dnd5`\n\t * @param {any} [defaultValue]\n\t * @returns {any}\n\t *\n\t * @example\n\t * // Check for node.foo, tree,options.foo(), and tree.options.foo:\n\t * $.ui.fancytree.evalOption(\"foo\", node, node, tree.options);\n\t * // Check for node.data.bar, tree,options.qux.bar(), and tree.options.qux.bar:\n\t * $.ui.fancytree.evalOption(\"bar\", node, node.data, tree.options.qux);\n\t *\n\t * @since 2.22\n\t */\n\tevalOption: function(optionName, node, nodeObject, treeOptions, defaultValue) {\n\t\tvar ctx, res,\n\t\t\ttree = node.tree,\n\t\t\ttreeOpt = treeOptions[optionName],\n\t\t\tnodeOpt = nodeObject[optionName];\n\n\t\tif( $.isFunction(treeOpt) ) {\n\t\t\tctx = { node: node, tree: tree, widget: tree.widget, options: tree.widget.options };\n\t\t\tres = treeOpt.call(tree, {type: optionName}, ctx);\n\t\t\tif( res == null ) {\n\t\t\t\tres = nodeOpt;\n\t\t\t}\n\t\t} else {\n\t\t\tres = (nodeOpt != null) ? nodeOpt : treeOpt;\n\t\t}\n\t\tif( res == null ) {\n\t\t\tres = defaultValue;  // no option set at all: return default\n\t\t}\n\t\treturn res;\n\t},\n\t/** Convert a keydown or mouse event to a canonical string like 'ctrl+a',\n\t * 'ctrl+shift+f2', 'shift+leftdblclick'.\n\t *\n\t * This is especially handy for switch-statements in event handlers.\n\t *\n\t * @param {event}\n\t * @returns {string}\n\t *\n\t * @example\n\t \n\tswitch( $.ui.fancytree.eventToString(event) ) {\n\t\tcase \"-\":\n\t\t\ttree.nodeSetExpanded(ctx, false);\n\t\t\tbreak;\n\t\tcase \"shift+return\":\n\t\t\ttree.nodeSetActive(ctx, true);\n\t\t\tbreak;\n\t\tcase \"down\":\n\t\t\tres = node.navigate(event.which, activate, true);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\thandled = false;\n\t}\n\tif( handled ){\n\t\tevent.preventDefault();\n\t}\n\t */\n\teventToString: function(event) {\n\t\t// Poor-man's hotkeys. See here for a complete implementation:\n\t\t//   https://github.com/jeresig/jquery.hotkeys\n\t\tvar which = event.which,\n\t\t\tet = event.type,\n\t\t\ts = [];\n\n\t\tif( event.altKey ) { s.push(\"alt\"); }\n\t\tif( event.ctrlKey ) { s.push(\"ctrl\"); }\n\t\tif( event.metaKey ) { s.push(\"meta\"); }\n\t\tif( event.shiftKey ) { s.push(\"shift\"); }\n\n\t\tif( et === \"click\" || et === \"dblclick\" ) {\n\t\t\ts.push(MOUSE_BUTTONS[event.button] + et);\n\t\t} else {\n\t\t\tif( !IGNORE_KEYCODES[which] ) {\n\t\t\t\ts.push( SPECIAL_KEYCODES[which] || String.fromCharCode(which).toLowerCase() );\n\t\t\t}\n\t\t}\n\t\treturn s.join(\"+\");\n\t},\n\t/** Write message to console if debugLevel >= 1\n\t * @param {string} msg\n\t */\n\tinfo: function(msg){\n\t\t/*jshint expr:true */\n\t\t($.ui.fancytree.debugLevel >= 1) && consoleApply(\"info\", arguments);\n\t},\n\t/* @deprecated: use eventToString(event) instead.\n\t */\n\tkeyEventToString: function(event) {\n\t\tthis.warn(\"keyEventToString() is deprecated: use eventToString()\");\n\t\treturn this.eventToString(event);\n\t},\n\t/** Return a wrapped handler method, that provides `this.super`.\n\t *\n\t * @example\n\t\t// Implement `opts.createNode` event to add the 'draggable' attribute\n\t\t$.ui.fancytree.overrideMethod(ctx.options, \"createNode\", function(event, data) {\n\t\t\t// Default processing if any\n\t\t\tthis._super.apply(this, arguments);\n\t\t\t// Add 'draggable' attribute\n\t\t\tdata.node.span.draggable = true;\n\t\t});\n\t *\n\t * @param {object} instance\n\t * @param {string} methodName\n\t * @param {function} handler\n\t */\n\toverrideMethod: function(instance, methodName, handler){\n\t\tvar prevSuper,\n\t\t\t_super = instance[methodName] || $.noop;\n\n\t\t// context = context || this;\n\n\t\tinstance[methodName] = function() {\n\t\t\ttry {\n\t\t\t\tprevSuper = this._super;\n\t\t\t\tthis._super = _super;\n\t\t\t\treturn handler.apply(this, arguments);\n\t\t\t} finally {\n\t\t\t\tthis._super = prevSuper;\n\t\t\t}\n\t\t};\n\t},\n\t/**\n\t * Parse tree data from HTML <ul> markup\n\t *\n\t * @param {jQueryObject} $ul\n\t * @returns {NodeData[]}\n\t */\n\tparseHtml: function($ul) {\n\t\t// TODO: understand this:\n\t\t/*jshint validthis:true */\n\t\tvar classes, className, extraClasses, i, iPos, l, tmp, tmp2,\n\t\t\t$children = $ul.find(\">li\"),\n\t\t\tchildren = [];\n\n\t\t$children.each(function() {\n\t\t\tvar allData, lowerCaseAttr,\n\t\t\t\t$li = $(this),\n\t\t\t\t$liSpan = $li.find(\">span:first\", this),\n\t\t\t\t$liA = $liSpan.length ? null : $li.find(\">a:first\"),\n\t\t\t\td = { tooltip: null, data: {} };\n\n\t\t\tif( $liSpan.length ) {\n\t\t\t\td.title = $liSpan.html();\n\n\t\t\t} else if( $liA && $liA.length ) {\n\t\t\t\t// If a <li><a> tag is specified, use it literally and extract href/target.\n\t\t\t\td.title = $liA.html();\n\t\t\t\td.data.href = $liA.attr(\"href\");\n\t\t\t\td.data.target = $liA.attr(\"target\");\n\t\t\t\td.tooltip = $liA.attr(\"title\");\n\n\t\t\t} else {\n\t\t\t\t// If only a <li> tag is specified, use the trimmed string up to\n\t\t\t\t// the next child <ul> tag.\n\t\t\t\td.title = $li.html();\n\t\t\t\tiPos = d.title.search(/<ul/i);\n\t\t\t\tif( iPos >= 0 ){\n\t\t\t\t\td.title = d.title.substring(0, iPos);\n\t\t\t\t}\n\t\t\t}\n\t\t\td.title = $.trim(d.title);\n\n\t\t\t// Make sure all fields exist\n\t\t\tfor(i=0, l=CLASS_ATTRS.length; i<l; i++){\n\t\t\t\td[CLASS_ATTRS[i]] = undefined;\n\t\t\t}\n\t\t\t// Initialize to `true`, if class is set and collect extraClasses\n\t\t\tclasses = this.className.split(\" \");\n\t\t\textraClasses = [];\n\t\t\tfor(i=0, l=classes.length; i<l; i++){\n\t\t\t\tclassName = classes[i];\n\t\t\t\tif(CLASS_ATTR_MAP[className]){\n\t\t\t\t\td[className] = true;\n\t\t\t\t}else{\n\t\t\t\t\textraClasses.push(className);\n\t\t\t\t}\n\t\t\t}\n\t\t\td.extraClasses = extraClasses.join(\" \");\n\n\t\t\t// Parse node options from ID, title and class attributes\n\t\t\ttmp = $li.attr(\"title\");\n\t\t\tif( tmp ){\n\t\t\t\td.tooltip = tmp; // overrides <a title='...'>\n\t\t\t}\n\t\t\ttmp = $li.attr(\"id\");\n\t\t\tif( tmp ){\n\t\t\t\td.key = tmp;\n\t\t\t}\n\t\t\t// Add <li data-NAME='...'> as node.data.NAME\n\t\t\tallData = _getElementDataAsDict($li);\n\t\t\tif( allData && !$.isEmptyObject(allData) ) {\n\t\t\t\t// #507: convert data-hidecheckbox (lower case) to hideCheckbox\n\t\t\t\tfor( lowerCaseAttr in NODE_ATTR_LOWERCASE_MAP ) {\n\t\t\t\t\tif( allData.hasOwnProperty(lowerCaseAttr) ) {\n\t\t\t\t\t\tallData[NODE_ATTR_LOWERCASE_MAP[lowerCaseAttr]] = allData[lowerCaseAttr];\n\t\t\t\t\t\tdelete allData[lowerCaseAttr];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// #56: Allow to set special node.attributes from data-...\n\t\t\t\tfor(i=0, l=NODE_ATTRS.length; i<l; i++){\n\t\t\t\t\ttmp = NODE_ATTRS[i];\n\t\t\t\t\ttmp2 = allData[tmp];\n\t\t\t\t\tif( tmp2 != null ) {\n\t\t\t\t\t\tdelete allData[tmp];\n\t\t\t\t\t\td[tmp] = tmp2;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// All other data-... goes to node.data...\n\t\t\t\t$.extend(d.data, allData);\n\t\t\t}\n\t\t\t// Recursive reading of child nodes, if LI tag contains an UL tag\n\t\t\t$ul = $li.find(\">ul:first\");\n\t\t\tif( $ul.length ) {\n\t\t\t\td.children = $.ui.fancytree.parseHtml($ul);\n\t\t\t}else{\n\t\t\t\td.children = d.lazy ? undefined : null;\n\t\t\t}\n\t\t\tchildren.push(d);\n//            FT.debug(\"parse \", d, children);\n\t\t});\n\t\treturn children;\n\t},\n\t/** Add Fancytree extension definition to the list of globally available extensions.\n\t *\n\t * @param {object} definition\n\t */\n\tregisterExtension: function(definition){\n\t\t_assert(definition.name != null, \"extensions must have a `name` property.\");\n\t\t_assert(definition.version != null, \"extensions must have a `version` property.\");\n\t\t$.ui.fancytree._extensions[definition.name] = definition;\n\t},\n\t/** Inverse of escapeHtml().\n\t *\n\t * @param {string} s\n\t * @returns {string}\n\t */\n\tunescapeHtml: function(s){\n\t\tvar e = document.createElement(\"div\");\n\t\te.innerHTML = s;\n\t\treturn e.childNodes.length === 0 ? \"\" : e.childNodes[0].nodeValue;\n\t},\n\t/** Write warning message to console.\n\t * @param {string} msg\n\t */\n\twarn: function(msg){\n\t\tconsoleApply(\"warn\", arguments);\n\t}\n});\n\n}(jQuery, window, document));\n"
  },
  {
    "path": "lib/jscolor.js",
    "content": "/**\r\n * jscolor - JavaScript Color Picker\r\n *\r\n * @link    http://jscolor.com\r\n * @license For open source use: GPLv3\r\n *          For commercial use: JSColor Commercial License\r\n * @author  Jan Odvarko\r\n * @version 2.0.4\r\n *\r\n * See usage examples at http://jscolor.com/examples/\r\n */\r\n\r\n\r\n\"use strict\";\r\n\r\n\r\nif (!window.jscolor) { window.jscolor = (function () {\r\n\r\n\r\nvar jsc = {\r\n\r\n\r\n\tregister : function () {\r\n\t\tjsc.attachDOMReadyEvent(jsc.init);\r\n\t\tjsc.attachEvent(document, 'mousedown', jsc.onDocumentMouseDown);\r\n\t\tjsc.attachEvent(document, 'touchstart', jsc.onDocumentTouchStart);\r\n\t\tjsc.attachEvent(window, 'resize', jsc.onWindowResize);\r\n\t},\r\n\r\n\r\n\tinit : function () {\r\n\t\tif (jsc.jscolor.lookupClass) {\r\n\t\t\tjsc.jscolor.installByClassName(jsc.jscolor.lookupClass);\r\n\t\t}\r\n\t},\r\n\r\n\r\n\ttryInstallOnElements : function (elms, className) {\r\n\t\tvar matchClass = new RegExp('(^|\\\\s)(' + className + ')(\\\\s*(\\\\{[^}]*\\\\})|\\\\s|$)', 'i');\r\n\r\n\t\tfor (var i = 0; i < elms.length; i += 1) {\r\n\t\t\tif (elms[i].type !== undefined && elms[i].type.toLowerCase() == 'color') {\r\n\t\t\t\tif (jsc.isColorAttrSupported) {\r\n\t\t\t\t\t// skip inputs of type 'color' if supported by the browser\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tvar m;\r\n\t\t\tif (!elms[i].jscolor && elms[i].className && (m = elms[i].className.match(matchClass))) {\r\n\t\t\t\tvar targetElm = elms[i];\r\n\t\t\t\tvar optsStr = null;\r\n\r\n\t\t\t\tvar dataOptions = jsc.getDataAttr(targetElm, 'jscolor');\r\n\t\t\t\tif (dataOptions !== null) {\r\n\t\t\t\t\toptsStr = dataOptions;\r\n\t\t\t\t} else if (m[4]) {\r\n\t\t\t\t\toptsStr = m[4];\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar opts = {};\r\n\t\t\t\tif (optsStr) {\r\n\t\t\t\t\ttry {\r\n\t\t\t\t\t\topts = (new Function ('return (' + optsStr + ')'))();\r\n\t\t\t\t\t} catch(eParseError) {\r\n\t\t\t\t\t\tjsc.warn('Error parsing jscolor options: ' + eParseError + ':\\n' + optsStr);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\ttargetElm.jscolor = new jsc.jscolor(targetElm, opts);\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\r\n\tisColorAttrSupported : (function () {\r\n\t\tvar elm = document.createElement('input');\r\n\t\tif (elm.setAttribute) {\r\n\t\t\telm.setAttribute('type', 'color');\r\n\t\t\tif (elm.type.toLowerCase() == 'color') {\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn false;\r\n\t})(),\r\n\r\n\r\n\tisCanvasSupported : (function () {\r\n\t\tvar elm = document.createElement('canvas');\r\n\t\treturn !!(elm.getContext && elm.getContext('2d'));\r\n\t})(),\r\n\r\n\r\n\tfetchElement : function (mixed) {\r\n\t\treturn typeof mixed === 'string' ? document.getElementById(mixed) : mixed;\r\n\t},\r\n\r\n\r\n\tisElementType : function (elm, type) {\r\n\t\treturn elm.nodeName.toLowerCase() === type.toLowerCase();\r\n\t},\r\n\r\n\r\n\tgetDataAttr : function (el, name) {\r\n\t\tvar attrName = 'data-' + name;\r\n\t\tvar attrValue = el.getAttribute(attrName);\r\n\t\tif (attrValue !== null) {\r\n\t\t\treturn attrValue;\r\n\t\t}\r\n\t\treturn null;\r\n\t},\r\n\r\n\r\n\tattachEvent : function (el, evnt, func) {\r\n\t\tif (el.addEventListener) {\r\n\t\t\tel.addEventListener(evnt, func, false);\r\n\t\t} else if (el.attachEvent) {\r\n\t\t\tel.attachEvent('on' + evnt, func);\r\n\t\t}\r\n\t},\r\n\r\n\r\n\tdetachEvent : function (el, evnt, func) {\r\n\t\tif (el.removeEventListener) {\r\n\t\t\tel.removeEventListener(evnt, func, false);\r\n\t\t} else if (el.detachEvent) {\r\n\t\t\tel.detachEvent('on' + evnt, func);\r\n\t\t}\r\n\t},\r\n\r\n\r\n\t_attachedGroupEvents : {},\r\n\r\n\r\n\tattachGroupEvent : function (groupName, el, evnt, func) {\r\n\t\tif (!jsc._attachedGroupEvents.hasOwnProperty(groupName)) {\r\n\t\t\tjsc._attachedGroupEvents[groupName] = [];\r\n\t\t}\r\n\t\tjsc._attachedGroupEvents[groupName].push([el, evnt, func]);\r\n\t\tjsc.attachEvent(el, evnt, func);\r\n\t},\r\n\r\n\r\n\tdetachGroupEvents : function (groupName) {\r\n\t\tif (jsc._attachedGroupEvents.hasOwnProperty(groupName)) {\r\n\t\t\tfor (var i = 0; i < jsc._attachedGroupEvents[groupName].length; i += 1) {\r\n\t\t\t\tvar evt = jsc._attachedGroupEvents[groupName][i];\r\n\t\t\t\tjsc.detachEvent(evt[0], evt[1], evt[2]);\r\n\t\t\t}\r\n\t\t\tdelete jsc._attachedGroupEvents[groupName];\r\n\t\t}\r\n\t},\r\n\r\n\r\n\tattachDOMReadyEvent : function (func) {\r\n\t\tvar fired = false;\r\n\t\tvar fireOnce = function () {\r\n\t\t\tif (!fired) {\r\n\t\t\t\tfired = true;\r\n\t\t\t\tfunc();\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tif (document.readyState === 'complete') {\r\n\t\t\tsetTimeout(fireOnce, 1); // async\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (document.addEventListener) {\r\n\t\t\tdocument.addEventListener('DOMContentLoaded', fireOnce, false);\r\n\r\n\t\t\t// Fallback\r\n\t\t\twindow.addEventListener('load', fireOnce, false);\r\n\r\n\t\t} else if (document.attachEvent) {\r\n\t\t\t// IE\r\n\t\t\tdocument.attachEvent('onreadystatechange', function () {\r\n\t\t\t\tif (document.readyState === 'complete') {\r\n\t\t\t\t\tdocument.detachEvent('onreadystatechange', arguments.callee);\r\n\t\t\t\t\tfireOnce();\r\n\t\t\t\t}\r\n\t\t\t})\r\n\r\n\t\t\t// Fallback\r\n\t\t\twindow.attachEvent('onload', fireOnce);\r\n\r\n\t\t\t// IE7/8\r\n\t\t\tif (document.documentElement.doScroll && window == window.top) {\r\n\t\t\t\tvar tryScroll = function () {\r\n\t\t\t\t\tif (!document.body) { return; }\r\n\t\t\t\t\ttry {\r\n\t\t\t\t\t\tdocument.documentElement.doScroll('left');\r\n\t\t\t\t\t\tfireOnce();\r\n\t\t\t\t\t} catch (e) {\r\n\t\t\t\t\t\tsetTimeout(tryScroll, 1);\r\n\t\t\t\t\t}\r\n\t\t\t\t};\r\n\t\t\t\ttryScroll();\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\r\n\twarn : function (msg) {\r\n\t\tif (window.console && window.console.warn) {\r\n\t\t\twindow.console.warn(msg);\r\n\t\t}\r\n\t},\r\n\r\n\r\n\tpreventDefault : function (e) {\r\n\t\tif (e.preventDefault) { e.preventDefault(); }\r\n\t\te.returnValue = false;\r\n\t},\r\n\r\n\r\n\tcaptureTarget : function (target) {\r\n\t\t// IE\r\n\t\tif (target.setCapture) {\r\n\t\t\tjsc._capturedTarget = target;\r\n\t\t\tjsc._capturedTarget.setCapture();\r\n\t\t}\r\n\t},\r\n\r\n\r\n\treleaseTarget : function () {\r\n\t\t// IE\r\n\t\tif (jsc._capturedTarget) {\r\n\t\t\tjsc._capturedTarget.releaseCapture();\r\n\t\t\tjsc._capturedTarget = null;\r\n\t\t}\r\n\t},\r\n\r\n\r\n\tfireEvent : function (el, evnt) {\r\n\t\tif (!el) {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (document.createEvent) {\r\n\t\t\tvar ev = document.createEvent('HTMLEvents');\r\n\t\t\tev.initEvent(evnt, true, true);\r\n\t\t\tel.dispatchEvent(ev);\r\n\t\t} else if (document.createEventObject) {\r\n\t\t\tvar ev = document.createEventObject();\r\n\t\t\tel.fireEvent('on' + evnt, ev);\r\n\t\t} else if (el['on' + evnt]) { // alternatively use the traditional event model\r\n\t\t\tel['on' + evnt]();\r\n\t\t}\r\n\t},\r\n\r\n\r\n\tclassNameToList : function (className) {\r\n\t\treturn className.replace(/^\\s+|\\s+$/g, '').split(/\\s+/);\r\n\t},\r\n\r\n\r\n\t// The className parameter (str) can only contain a single class name\r\n\thasClass : function (elm, className) {\r\n\t\tif (!className) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\treturn -1 != (' ' + elm.className.replace(/\\s+/g, ' ') + ' ').indexOf(' ' + className + ' ');\r\n\t},\r\n\r\n\r\n\t// The className parameter (str) can contain multiple class names separated by whitespace\r\n\tsetClass : function (elm, className) {\r\n\t\tvar classList = jsc.classNameToList(className);\r\n\t\tfor (var i = 0; i < classList.length; i += 1) {\r\n\t\t\tif (!jsc.hasClass(elm, classList[i])) {\r\n\t\t\t\telm.className += (elm.className ? ' ' : '') + classList[i];\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\r\n\t// The className parameter (str) can contain multiple class names separated by whitespace\r\n\tunsetClass : function (elm, className) {\r\n\t\tvar classList = jsc.classNameToList(className);\r\n\t\tfor (var i = 0; i < classList.length; i += 1) {\r\n\t\t\tvar repl = new RegExp(\r\n\t\t\t\t'^\\\\s*' + classList[i] + '\\\\s*|' +\r\n\t\t\t\t'\\\\s*' + classList[i] + '\\\\s*$|' +\r\n\t\t\t\t'\\\\s+' + classList[i] + '(\\\\s+)',\r\n\t\t\t\t'g'\r\n\t\t\t);\r\n\t\t\telm.className = elm.className.replace(repl, '$1');\r\n\t\t}\r\n\t},\r\n\r\n\r\n\tgetStyle : function (elm) {\r\n\t\treturn window.getComputedStyle ? window.getComputedStyle(elm) : elm.currentStyle;\r\n\t},\r\n\r\n\r\n\tsetStyle : (function () {\r\n\t\tvar helper = document.createElement('div');\r\n\t\tvar getSupportedProp = function (names) {\r\n\t\t\tfor (var i = 0; i < names.length; i += 1) {\r\n\t\t\t\tif (names[i] in helper.style) {\r\n\t\t\t\t\treturn names[i];\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t};\r\n\t\tvar props = {\r\n\t\t\tborderRadius: getSupportedProp(['borderRadius', 'MozBorderRadius', 'webkitBorderRadius']),\r\n\t\t\tboxShadow: getSupportedProp(['boxShadow', 'MozBoxShadow', 'webkitBoxShadow'])\r\n\t\t};\r\n\t\treturn function (elm, prop, value) {\r\n\t\t\tswitch (prop.toLowerCase()) {\r\n\t\t\tcase 'opacity':\r\n\t\t\t\tvar alphaOpacity = Math.round(parseFloat(value) * 100);\r\n\t\t\t\telm.style.opacity = value;\r\n\t\t\t\telm.style.filter = 'alpha(opacity=' + alphaOpacity + ')';\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\telm.style[props[prop]] = value;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t};\r\n\t})(),\r\n\r\n\r\n\tsetBorderRadius : function (elm, value) {\r\n\t\tjsc.setStyle(elm, 'borderRadius', value || '0');\r\n\t},\r\n\r\n\r\n\tsetBoxShadow : function (elm, value) {\r\n\t\tjsc.setStyle(elm, 'boxShadow', value || 'none');\r\n\t},\r\n\r\n\r\n\tgetElementPos : function (e, relativeToViewport) {\r\n\t\tvar x=0, y=0;\r\n\t\tvar rect = e.getBoundingClientRect();\r\n\t\tx = rect.left;\r\n\t\ty = rect.top;\r\n\t\tif (!relativeToViewport) {\r\n\t\t\tvar viewPos = jsc.getViewPos();\r\n\t\t\tx += viewPos[0];\r\n\t\t\ty += viewPos[1];\r\n\t\t}\r\n\t\treturn [x, y];\r\n\t},\r\n\r\n\r\n\tgetElementSize : function (e) {\r\n\t\treturn [e.offsetWidth, e.offsetHeight];\r\n\t},\r\n\r\n\r\n\t// get pointer's X/Y coordinates relative to viewport\r\n\tgetAbsPointerPos : function (e) {\r\n\t\tif (!e) { e = window.event; }\r\n\t\tvar x = 0, y = 0;\r\n\t\tif (typeof e.changedTouches !== 'undefined' && e.changedTouches.length) {\r\n\t\t\t// touch devices\r\n\t\t\tx = e.changedTouches[0].clientX;\r\n\t\t\ty = e.changedTouches[0].clientY;\r\n\t\t} else if (typeof e.clientX === 'number') {\r\n\t\t\tx = e.clientX;\r\n\t\t\ty = e.clientY;\r\n\t\t}\r\n\t\treturn { x: x, y: y };\r\n\t},\r\n\r\n\r\n\t// get pointer's X/Y coordinates relative to target element\r\n\tgetRelPointerPos : function (e) {\r\n\t\tif (!e) { e = window.event; }\r\n\t\tvar target = e.target || e.srcElement;\r\n\t\tvar targetRect = target.getBoundingClientRect();\r\n\r\n\t\tvar x = 0, y = 0;\r\n\r\n\t\tvar clientX = 0, clientY = 0;\r\n\t\tif (typeof e.changedTouches !== 'undefined' && e.changedTouches.length) {\r\n\t\t\t// touch devices\r\n\t\t\tclientX = e.changedTouches[0].clientX;\r\n\t\t\tclientY = e.changedTouches[0].clientY;\r\n\t\t} else if (typeof e.clientX === 'number') {\r\n\t\t\tclientX = e.clientX;\r\n\t\t\tclientY = e.clientY;\r\n\t\t}\r\n\r\n\t\tx = clientX - targetRect.left;\r\n\t\ty = clientY - targetRect.top;\r\n\t\treturn { x: x, y: y };\r\n\t},\r\n\r\n\r\n\tgetViewPos : function () {\r\n\t\tvar doc = document.documentElement;\r\n\t\treturn [\r\n\t\t\t(window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0),\r\n\t\t\t(window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0)\r\n\t\t];\r\n\t},\r\n\r\n\r\n\tgetViewSize : function () {\r\n\t\tvar doc = document.documentElement;\r\n\t\treturn [\r\n\t\t\t(window.innerWidth || doc.clientWidth),\r\n\t\t\t(window.innerHeight || doc.clientHeight),\r\n\t\t];\r\n\t},\r\n\r\n\r\n\tredrawPosition : function () {\r\n\r\n\t\tif (jsc.picker && jsc.picker.owner) {\r\n\t\t\tvar thisObj = jsc.picker.owner;\r\n\r\n\t\t\tvar tp, vp;\r\n\r\n\t\t\tif (thisObj.fixed) {\r\n\t\t\t\t// Fixed elements are positioned relative to viewport,\r\n\t\t\t\t// therefore we can ignore the scroll offset\r\n\t\t\t\ttp = jsc.getElementPos(thisObj.targetElement, true); // target pos\r\n\t\t\t\tvp = [0, 0]; // view pos\r\n\t\t\t} else {\r\n\t\t\t\ttp = jsc.getElementPos(thisObj.targetElement); // target pos\r\n\t\t\t\tvp = jsc.getViewPos(); // view pos\r\n\t\t\t}\r\n\r\n\t\t\tvar ts = jsc.getElementSize(thisObj.targetElement); // target size\r\n\t\t\tvar vs = jsc.getViewSize(); // view size\r\n\t\t\tvar ps = jsc.getPickerOuterDims(thisObj); // picker size\r\n\t\t\tvar a, b, c;\r\n\t\t\tswitch (thisObj.position.toLowerCase()) {\r\n\t\t\t\tcase 'left': a=1; b=0; c=-1; break;\r\n\t\t\t\tcase 'right':a=1; b=0; c=1; break;\r\n\t\t\t\tcase 'top':  a=0; b=1; c=-1; break;\r\n\t\t\t\tdefault:     a=0; b=1; c=1; break;\r\n\t\t\t}\r\n\t\t\tvar l = (ts[b]+ps[b])/2;\r\n\r\n\t\t\t// compute picker position\r\n\t\t\tif (!thisObj.smartPosition) {\r\n\t\t\t\tvar pp = [\r\n\t\t\t\t\ttp[a],\r\n\t\t\t\t\ttp[b]+ts[b]-l+l*c\r\n\t\t\t\t];\r\n\t\t\t} else {\r\n\t\t\t\tvar pp = [\r\n\t\t\t\t\t-vp[a]+tp[a]+ps[a] > vs[a] ?\r\n\t\t\t\t\t\t(-vp[a]+tp[a]+ts[a]/2 > vs[a]/2 && tp[a]+ts[a]-ps[a] >= 0 ? tp[a]+ts[a]-ps[a] : tp[a]) :\r\n\t\t\t\t\t\ttp[a],\r\n\t\t\t\t\t-vp[b]+tp[b]+ts[b]+ps[b]-l+l*c > vs[b] ?\r\n\t\t\t\t\t\t(-vp[b]+tp[b]+ts[b]/2 > vs[b]/2 && tp[b]+ts[b]-l-l*c >= 0 ? tp[b]+ts[b]-l-l*c : tp[b]+ts[b]-l+l*c) :\r\n\t\t\t\t\t\t(tp[b]+ts[b]-l+l*c >= 0 ? tp[b]+ts[b]-l+l*c : tp[b]+ts[b]-l-l*c)\r\n\t\t\t\t];\r\n\t\t\t}\r\n\r\n\t\t\tvar x = pp[a];\r\n\t\t\tvar y = pp[b];\r\n\t\t\tvar positionValue = thisObj.fixed ? 'fixed' : 'absolute';\r\n\t\t\tvar contractShadow =\r\n\t\t\t\t(pp[0] + ps[0] > tp[0] || pp[0] < tp[0] + ts[0]) &&\r\n\t\t\t\t(pp[1] + ps[1] < tp[1] + ts[1]);\r\n\r\n\t\t\tjsc._drawPosition(thisObj, x, y, positionValue, contractShadow);\r\n\t\t}\r\n\t},\r\n\r\n\r\n\t_drawPosition : function (thisObj, x, y, positionValue, contractShadow) {\r\n\t\tvar vShadow = contractShadow ? 0 : thisObj.shadowBlur; // px\r\n\r\n\t\tjsc.picker.wrap.style.position = positionValue;\r\n\t\tjsc.picker.wrap.style.left = x + 'px';\r\n\t\tjsc.picker.wrap.style.top = y + 'px';\r\n\r\n\t\tjsc.setBoxShadow(\r\n\t\t\tjsc.picker.boxS,\r\n\t\t\tthisObj.shadow ?\r\n\t\t\t\tnew jsc.BoxShadow(0, vShadow, thisObj.shadowBlur, 0, thisObj.shadowColor) :\r\n\t\t\t\tnull);\r\n\t},\r\n\r\n\r\n\tgetPickerDims : function (thisObj) {\r\n\t\tvar displaySlider = !!jsc.getSliderComponent(thisObj);\r\n\t\tvar dims = [\r\n\t\t\t2 * thisObj.insetWidth + 2 * thisObj.padding + thisObj.width +\r\n\t\t\t\t(displaySlider ? 2 * thisObj.insetWidth + jsc.getPadToSliderPadding(thisObj) + thisObj.sliderSize : 0),\r\n\t\t\t2 * thisObj.insetWidth + 2 * thisObj.padding + thisObj.height +\r\n\t\t\t\t(thisObj.closable ? 2 * thisObj.insetWidth + thisObj.padding + thisObj.buttonHeight : 0)\r\n\t\t];\r\n\t\treturn dims;\r\n\t},\r\n\r\n\r\n\tgetPickerOuterDims : function (thisObj) {\r\n\t\tvar dims = jsc.getPickerDims(thisObj);\r\n\t\treturn [\r\n\t\t\tdims[0] + 2 * thisObj.borderWidth,\r\n\t\t\tdims[1] + 2 * thisObj.borderWidth\r\n\t\t];\r\n\t},\r\n\r\n\r\n\tgetPadToSliderPadding : function (thisObj) {\r\n\t\treturn Math.max(thisObj.padding, 1.5 * (2 * thisObj.pointerBorderWidth + thisObj.pointerThickness));\r\n\t},\r\n\r\n\r\n\tgetPadYComponent : function (thisObj) {\r\n\t\tswitch (thisObj.mode.charAt(1).toLowerCase()) {\r\n\t\t\tcase 'v': return 'v'; break;\r\n\t\t}\r\n\t\treturn 's';\r\n\t},\r\n\r\n\r\n\tgetSliderComponent : function (thisObj) {\r\n\t\tif (thisObj.mode.length > 2) {\r\n\t\t\tswitch (thisObj.mode.charAt(2).toLowerCase()) {\r\n\t\t\t\tcase 's': return 's'; break;\r\n\t\t\t\tcase 'v': return 'v'; break;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn null;\r\n\t},\r\n\r\n\r\n\tonDocumentMouseDown : function (e) {\r\n\t\tif (!e) { e = window.event; }\r\n\t\tvar target = e.target || e.srcElement;\r\n\r\n\t\tif (target._jscLinkedInstance) {\r\n\t\t\tif (target._jscLinkedInstance.showOnClick) {\r\n\t\t\t\ttarget._jscLinkedInstance.show();\r\n\t\t\t}\r\n\t\t} else if (target._jscControlName) {\r\n\t\t\tjsc.onControlPointerStart(e, target, target._jscControlName, 'mouse');\r\n\t\t} else {\r\n\t\t\t// Mouse is outside the picker controls -> hide the color picker!\r\n\t\t\tif (jsc.picker && jsc.picker.owner) {\r\n\t\t\t\tjsc.picker.owner.hide();\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\r\n\tonDocumentTouchStart : function (e) {\r\n\t\tif (!e) { e = window.event; }\r\n\t\tvar target = e.target || e.srcElement;\r\n\r\n\t\tif (target._jscLinkedInstance) {\r\n\t\t\tif (target._jscLinkedInstance.showOnClick) {\r\n\t\t\t\ttarget._jscLinkedInstance.show();\r\n\t\t\t}\r\n\t\t} else if (target._jscControlName) {\r\n\t\t\tjsc.onControlPointerStart(e, target, target._jscControlName, 'touch');\r\n\t\t} else {\r\n\t\t\tif (jsc.picker && jsc.picker.owner) {\r\n\t\t\t\tjsc.picker.owner.hide();\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\r\n\tonWindowResize : function (e) {\r\n\t\tjsc.redrawPosition();\r\n\t},\r\n\r\n\r\n\tonParentScroll : function (e) {\r\n\t\t// hide the picker when one of the parent elements is scrolled\r\n\t\tif (jsc.picker && jsc.picker.owner) {\r\n\t\t\tjsc.picker.owner.hide();\r\n\t\t}\r\n\t},\r\n\r\n\r\n\t_pointerMoveEvent : {\r\n\t\tmouse: 'mousemove',\r\n\t\ttouch: 'touchmove'\r\n\t},\r\n\t_pointerEndEvent : {\r\n\t\tmouse: 'mouseup',\r\n\t\ttouch: 'touchend'\r\n\t},\r\n\r\n\r\n\t_pointerOrigin : null,\r\n\t_capturedTarget : null,\r\n\r\n\r\n\tonControlPointerStart : function (e, target, controlName, pointerType) {\r\n\t\tvar thisObj = target._jscInstance;\r\n\r\n\t\tjsc.preventDefault(e);\r\n\t\tjsc.captureTarget(target);\r\n\r\n\t\tvar registerDragEvents = function (doc, offset) {\r\n\t\t\tjsc.attachGroupEvent('drag', doc, jsc._pointerMoveEvent[pointerType],\r\n\t\t\t\tjsc.onDocumentPointerMove(e, target, controlName, pointerType, offset));\r\n\t\t\tjsc.attachGroupEvent('drag', doc, jsc._pointerEndEvent[pointerType],\r\n\t\t\t\tjsc.onDocumentPointerEnd(e, target, controlName, pointerType));\r\n\t\t};\r\n\r\n\t\tregisterDragEvents(document, [0, 0]);\r\n\r\n\t\tif (window.parent && window.frameElement) {\r\n\t\t\tvar rect = window.frameElement.getBoundingClientRect();\r\n\t\t\tvar ofs = [-rect.left, -rect.top];\r\n\t\t\tregisterDragEvents(window.parent.window.document, ofs);\r\n\t\t}\r\n\r\n\t\tvar abs = jsc.getAbsPointerPos(e);\r\n\t\tvar rel = jsc.getRelPointerPos(e);\r\n\t\tjsc._pointerOrigin = {\r\n\t\t\tx: abs.x - rel.x,\r\n\t\t\ty: abs.y - rel.y\r\n\t\t};\r\n\r\n\t\tswitch (controlName) {\r\n\t\tcase 'pad':\r\n\t\t\t// if the slider is at the bottom, move it up\r\n\t\t\tswitch (jsc.getSliderComponent(thisObj)) {\r\n\t\t\tcase 's': if (thisObj.hsv[1] === 0) { thisObj.fromHSV(null, 100, null); }; break;\r\n\t\t\tcase 'v': if (thisObj.hsv[2] === 0) { thisObj.fromHSV(null, null, 100); }; break;\r\n\t\t\t}\r\n\t\t\tjsc.setPad(thisObj, e, 0, 0);\r\n\t\t\tbreak;\r\n\r\n\t\tcase 'sld':\r\n\t\t\tjsc.setSld(thisObj, e, 0);\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tjsc.dispatchFineChange(thisObj);\r\n\t},\r\n\r\n\r\n\tonDocumentPointerMove : function (e, target, controlName, pointerType, offset) {\r\n\t\treturn function (e) {\r\n\t\t\tvar thisObj = target._jscInstance;\r\n\t\t\tswitch (controlName) {\r\n\t\t\tcase 'pad':\r\n\t\t\t\tif (!e) { e = window.event; }\r\n\t\t\t\tjsc.setPad(thisObj, e, offset[0], offset[1]);\r\n\t\t\t\tjsc.dispatchFineChange(thisObj);\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase 'sld':\r\n\t\t\t\tif (!e) { e = window.event; }\r\n\t\t\t\tjsc.setSld(thisObj, e, offset[1]);\r\n\t\t\t\tjsc.dispatchFineChange(thisObj);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\r\n\tonDocumentPointerEnd : function (e, target, controlName, pointerType) {\r\n\t\treturn function (e) {\r\n\t\t\tvar thisObj = target._jscInstance;\r\n\t\t\tjsc.detachGroupEvents('drag');\r\n\t\t\tjsc.releaseTarget();\r\n\t\t\t// Always dispatch changes after detaching outstanding mouse handlers,\r\n\t\t\t// in case some user interaction will occur in user's onchange callback\r\n\t\t\t// that would intrude with current mouse events\r\n\t\t\tjsc.dispatchChange(thisObj);\r\n\t\t};\r\n\t},\r\n\r\n\r\n\tdispatchChange : function (thisObj) {\r\n\t\tif (thisObj.valueElement) {\r\n\t\t\tif (jsc.isElementType(thisObj.valueElement, 'input')) {\r\n\t\t\t\tjsc.fireEvent(thisObj.valueElement, 'change');\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\r\n\tdispatchFineChange : function (thisObj) {\r\n\t\tif (thisObj.onFineChange) {\r\n\t\t\tvar callback;\r\n\t\t\tif (typeof thisObj.onFineChange === 'string') {\r\n\t\t\t\tcallback = new Function (thisObj.onFineChange);\r\n\t\t\t} else {\r\n\t\t\t\tcallback = thisObj.onFineChange;\r\n\t\t\t}\r\n\t\t\tcallback.call(thisObj);\r\n\t\t}\r\n\t},\r\n\r\n\r\n\tsetPad : function (thisObj, e, ofsX, ofsY) {\r\n\t\tvar pointerAbs = jsc.getAbsPointerPos(e);\r\n\t\tvar x = ofsX + pointerAbs.x - jsc._pointerOrigin.x - thisObj.padding - thisObj.insetWidth;\r\n\t\tvar y = ofsY + pointerAbs.y - jsc._pointerOrigin.y - thisObj.padding - thisObj.insetWidth;\r\n\r\n\t\tvar xVal = x * (360 / (thisObj.width - 1));\r\n\t\tvar yVal = 100 - (y * (100 / (thisObj.height - 1)));\r\n\r\n\t\tswitch (jsc.getPadYComponent(thisObj)) {\r\n\t\tcase 's': thisObj.fromHSV(xVal, yVal, null, jsc.leaveSld); break;\r\n\t\tcase 'v': thisObj.fromHSV(xVal, null, yVal, jsc.leaveSld); break;\r\n\t\t}\r\n\t},\r\n\r\n\r\n\tsetSld : function (thisObj, e, ofsY) {\r\n\t\tvar pointerAbs = jsc.getAbsPointerPos(e);\r\n\t\tvar y = ofsY + pointerAbs.y - jsc._pointerOrigin.y - thisObj.padding - thisObj.insetWidth;\r\n\r\n\t\tvar yVal = 100 - (y * (100 / (thisObj.height - 1)));\r\n\r\n\t\tswitch (jsc.getSliderComponent(thisObj)) {\r\n\t\tcase 's': thisObj.fromHSV(null, yVal, null, jsc.leavePad); break;\r\n\t\tcase 'v': thisObj.fromHSV(null, null, yVal, jsc.leavePad); break;\r\n\t\t}\r\n\t},\r\n\r\n\r\n\t_vmlNS : 'jsc_vml_',\r\n\t_vmlCSS : 'jsc_vml_css_',\r\n\t_vmlReady : false,\r\n\r\n\r\n\tinitVML : function () {\r\n\t\tif (!jsc._vmlReady) {\r\n\t\t\t// init VML namespace\r\n\t\t\tvar doc = document;\r\n\t\t\tif (!doc.namespaces[jsc._vmlNS]) {\r\n\t\t\t\tdoc.namespaces.add(jsc._vmlNS, 'urn:schemas-microsoft-com:vml');\r\n\t\t\t}\r\n\t\t\tif (!doc.styleSheets[jsc._vmlCSS]) {\r\n\t\t\t\tvar tags = ['shape', 'shapetype', 'group', 'background', 'path', 'formulas', 'handles', 'fill', 'stroke', 'shadow', 'textbox', 'textpath', 'imagedata', 'line', 'polyline', 'curve', 'rect', 'roundrect', 'oval', 'arc', 'image'];\r\n\t\t\t\tvar ss = doc.createStyleSheet();\r\n\t\t\t\tss.owningElement.id = jsc._vmlCSS;\r\n\t\t\t\tfor (var i = 0; i < tags.length; i += 1) {\r\n\t\t\t\t\tss.addRule(jsc._vmlNS + '\\\\:' + tags[i], 'behavior:url(#default#VML);');\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tjsc._vmlReady = true;\r\n\t\t}\r\n\t},\r\n\r\n\r\n\tcreatePalette : function () {\r\n\r\n\t\tvar paletteObj = {\r\n\t\t\telm: null,\r\n\t\t\tdraw: null\r\n\t\t};\r\n\r\n\t\tif (jsc.isCanvasSupported) {\r\n\t\t\t// Canvas implementation for modern browsers\r\n\r\n\t\t\tvar canvas = document.createElement('canvas');\r\n\t\t\tvar ctx = canvas.getContext('2d');\r\n\r\n\t\t\tvar drawFunc = function (width, height, type) {\r\n\t\t\t\tcanvas.width = width;\r\n\t\t\t\tcanvas.height = height;\r\n\r\n\t\t\t\tctx.clearRect(0, 0, canvas.width, canvas.height);\r\n\r\n\t\t\t\tvar hGrad = ctx.createLinearGradient(0, 0, canvas.width, 0);\r\n\t\t\t\thGrad.addColorStop(0 / 6, '#F00');\r\n\t\t\t\thGrad.addColorStop(1 / 6, '#FF0');\r\n\t\t\t\thGrad.addColorStop(2 / 6, '#0F0');\r\n\t\t\t\thGrad.addColorStop(3 / 6, '#0FF');\r\n\t\t\t\thGrad.addColorStop(4 / 6, '#00F');\r\n\t\t\t\thGrad.addColorStop(5 / 6, '#F0F');\r\n\t\t\t\thGrad.addColorStop(6 / 6, '#F00');\r\n\r\n\t\t\t\tctx.fillStyle = hGrad;\r\n\t\t\t\tctx.fillRect(0, 0, canvas.width, canvas.height);\r\n\r\n\t\t\t\tvar vGrad = ctx.createLinearGradient(0, 0, 0, canvas.height);\r\n\t\t\t\tswitch (type.toLowerCase()) {\r\n\t\t\t\tcase 's':\r\n\t\t\t\t\tvGrad.addColorStop(0, 'rgba(255,255,255,0)');\r\n\t\t\t\t\tvGrad.addColorStop(1, 'rgba(255,255,255,1)');\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 'v':\r\n\t\t\t\t\tvGrad.addColorStop(0, 'rgba(0,0,0,0)');\r\n\t\t\t\t\tvGrad.addColorStop(1, 'rgba(0,0,0,1)');\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tctx.fillStyle = vGrad;\r\n\t\t\t\tctx.fillRect(0, 0, canvas.width, canvas.height);\r\n\t\t\t};\r\n\r\n\t\t\tpaletteObj.elm = canvas;\r\n\t\t\tpaletteObj.draw = drawFunc;\r\n\r\n\t\t} else {\r\n\t\t\t// VML fallback for IE 7 and 8\r\n\r\n\t\t\tjsc.initVML();\r\n\r\n\t\t\tvar vmlContainer = document.createElement('div');\r\n\t\t\tvmlContainer.style.position = 'relative';\r\n\t\t\tvmlContainer.style.overflow = 'hidden';\r\n\r\n\t\t\tvar hGrad = document.createElement(jsc._vmlNS + ':fill');\r\n\t\t\thGrad.type = 'gradient';\r\n\t\t\thGrad.method = 'linear';\r\n\t\t\thGrad.angle = '90';\r\n\t\t\thGrad.colors = '16.67% #F0F, 33.33% #00F, 50% #0FF, 66.67% #0F0, 83.33% #FF0'\r\n\r\n\t\t\tvar hRect = document.createElement(jsc._vmlNS + ':rect');\r\n\t\t\thRect.style.position = 'absolute';\r\n\t\t\thRect.style.left = -1 + 'px';\r\n\t\t\thRect.style.top = -1 + 'px';\r\n\t\t\thRect.stroked = false;\r\n\t\t\thRect.appendChild(hGrad);\r\n\t\t\tvmlContainer.appendChild(hRect);\r\n\r\n\t\t\tvar vGrad = document.createElement(jsc._vmlNS + ':fill');\r\n\t\t\tvGrad.type = 'gradient';\r\n\t\t\tvGrad.method = 'linear';\r\n\t\t\tvGrad.angle = '180';\r\n\t\t\tvGrad.opacity = '0';\r\n\r\n\t\t\tvar vRect = document.createElement(jsc._vmlNS + ':rect');\r\n\t\t\tvRect.style.position = 'absolute';\r\n\t\t\tvRect.style.left = -1 + 'px';\r\n\t\t\tvRect.style.top = -1 + 'px';\r\n\t\t\tvRect.stroked = false;\r\n\t\t\tvRect.appendChild(vGrad);\r\n\t\t\tvmlContainer.appendChild(vRect);\r\n\r\n\t\t\tvar drawFunc = function (width, height, type) {\r\n\t\t\t\tvmlContainer.style.width = width + 'px';\r\n\t\t\t\tvmlContainer.style.height = height + 'px';\r\n\r\n\t\t\t\thRect.style.width =\r\n\t\t\t\tvRect.style.width =\r\n\t\t\t\t\t(width + 1) + 'px';\r\n\t\t\t\thRect.style.height =\r\n\t\t\t\tvRect.style.height =\r\n\t\t\t\t\t(height + 1) + 'px';\r\n\r\n\t\t\t\t// Colors must be specified during every redraw, otherwise IE won't display\r\n\t\t\t\t// a full gradient during a subsequential redraw\r\n\t\t\t\thGrad.color = '#F00';\r\n\t\t\t\thGrad.color2 = '#F00';\r\n\r\n\t\t\t\tswitch (type.toLowerCase()) {\r\n\t\t\t\tcase 's':\r\n\t\t\t\t\tvGrad.color = vGrad.color2 = '#FFF';\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 'v':\r\n\t\t\t\t\tvGrad.color = vGrad.color2 = '#000';\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t};\r\n\t\t\t\r\n\t\t\tpaletteObj.elm = vmlContainer;\r\n\t\t\tpaletteObj.draw = drawFunc;\r\n\t\t}\r\n\r\n\t\treturn paletteObj;\r\n\t},\r\n\r\n\r\n\tcreateSliderGradient : function () {\r\n\r\n\t\tvar sliderObj = {\r\n\t\t\telm: null,\r\n\t\t\tdraw: null\r\n\t\t};\r\n\r\n\t\tif (jsc.isCanvasSupported) {\r\n\t\t\t// Canvas implementation for modern browsers\r\n\r\n\t\t\tvar canvas = document.createElement('canvas');\r\n\t\t\tvar ctx = canvas.getContext('2d');\r\n\r\n\t\t\tvar drawFunc = function (width, height, color1, color2) {\r\n\t\t\t\tcanvas.width = width;\r\n\t\t\t\tcanvas.height = height;\r\n\r\n\t\t\t\tctx.clearRect(0, 0, canvas.width, canvas.height);\r\n\r\n\t\t\t\tvar grad = ctx.createLinearGradient(0, 0, 0, canvas.height);\r\n\t\t\t\tgrad.addColorStop(0, color1);\r\n\t\t\t\tgrad.addColorStop(1, color2);\r\n\r\n\t\t\t\tctx.fillStyle = grad;\r\n\t\t\t\tctx.fillRect(0, 0, canvas.width, canvas.height);\r\n\t\t\t};\r\n\r\n\t\t\tsliderObj.elm = canvas;\r\n\t\t\tsliderObj.draw = drawFunc;\r\n\r\n\t\t} else {\r\n\t\t\t// VML fallback for IE 7 and 8\r\n\r\n\t\t\tjsc.initVML();\r\n\r\n\t\t\tvar vmlContainer = document.createElement('div');\r\n\t\t\tvmlContainer.style.position = 'relative';\r\n\t\t\tvmlContainer.style.overflow = 'hidden';\r\n\r\n\t\t\tvar grad = document.createElement(jsc._vmlNS + ':fill');\r\n\t\t\tgrad.type = 'gradient';\r\n\t\t\tgrad.method = 'linear';\r\n\t\t\tgrad.angle = '180';\r\n\r\n\t\t\tvar rect = document.createElement(jsc._vmlNS + ':rect');\r\n\t\t\trect.style.position = 'absolute';\r\n\t\t\trect.style.left = -1 + 'px';\r\n\t\t\trect.style.top = -1 + 'px';\r\n\t\t\trect.stroked = false;\r\n\t\t\trect.appendChild(grad);\r\n\t\t\tvmlContainer.appendChild(rect);\r\n\r\n\t\t\tvar drawFunc = function (width, height, color1, color2) {\r\n\t\t\t\tvmlContainer.style.width = width + 'px';\r\n\t\t\t\tvmlContainer.style.height = height + 'px';\r\n\r\n\t\t\t\trect.style.width = (width + 1) + 'px';\r\n\t\t\t\trect.style.height = (height + 1) + 'px';\r\n\r\n\t\t\t\tgrad.color = color1;\r\n\t\t\t\tgrad.color2 = color2;\r\n\t\t\t};\r\n\t\t\t\r\n\t\t\tsliderObj.elm = vmlContainer;\r\n\t\t\tsliderObj.draw = drawFunc;\r\n\t\t}\r\n\r\n\t\treturn sliderObj;\r\n\t},\r\n\r\n\r\n\tleaveValue : 1<<0,\r\n\tleaveStyle : 1<<1,\r\n\tleavePad : 1<<2,\r\n\tleaveSld : 1<<3,\r\n\r\n\r\n\tBoxShadow : (function () {\r\n\t\tvar BoxShadow = function (hShadow, vShadow, blur, spread, color, inset) {\r\n\t\t\tthis.hShadow = hShadow;\r\n\t\t\tthis.vShadow = vShadow;\r\n\t\t\tthis.blur = blur;\r\n\t\t\tthis.spread = spread;\r\n\t\t\tthis.color = color;\r\n\t\t\tthis.inset = !!inset;\r\n\t\t};\r\n\r\n\t\tBoxShadow.prototype.toString = function () {\r\n\t\t\tvar vals = [\r\n\t\t\t\tMath.round(this.hShadow) + 'px',\r\n\t\t\t\tMath.round(this.vShadow) + 'px',\r\n\t\t\t\tMath.round(this.blur) + 'px',\r\n\t\t\t\tMath.round(this.spread) + 'px',\r\n\t\t\t\tthis.color\r\n\t\t\t];\r\n\t\t\tif (this.inset) {\r\n\t\t\t\tvals.push('inset');\r\n\t\t\t}\r\n\t\t\treturn vals.join(' ');\r\n\t\t};\r\n\r\n\t\treturn BoxShadow;\r\n\t})(),\r\n\r\n\r\n\t//\r\n\t// Usage:\r\n\t// var myColor = new jscolor(<targetElement> [, <options>])\r\n\t//\r\n\r\n\tjscolor : function (targetElement, options) {\r\n\r\n\t\t// General options\r\n\t\t//\r\n\t\tthis.value = null; // initial HEX color. To change it later, use methods fromString(), fromHSV() and fromRGB()\r\n\t\tthis.valueElement = targetElement; // element that will be used to display and input the color code\r\n\t\tthis.styleElement = targetElement; // element that will preview the picked color using CSS backgroundColor\r\n\t\tthis.required = true; // whether the associated text <input> can be left empty\r\n\t\tthis.refine = true; // whether to refine the entered color code (e.g. uppercase it and remove whitespace)\r\n\t\tthis.hash = false; // whether to prefix the HEX color code with # symbol\r\n\t\tthis.uppercase = true; // whether to uppercase the color code\r\n\t\tthis.onFineChange = null; // called instantly every time the color changes (value can be either a function or a string with javascript code)\r\n\t\tthis.activeClass = 'jscolor-active'; // class to be set to the target element when a picker window is open on it\r\n\t\tthis.minS = 0; // min allowed saturation (0 - 100)\r\n\t\tthis.maxS = 100; // max allowed saturation (0 - 100)\r\n\t\tthis.minV = 0; // min allowed value (brightness) (0 - 100)\r\n\t\tthis.maxV = 100; // max allowed value (brightness) (0 - 100)\r\n\r\n\t\t// Accessing the picked color\r\n\t\t//\r\n\t\tthis.hsv = [0, 0, 100]; // read-only  [0-360, 0-100, 0-100]\r\n\t\tthis.rgb = [255, 255, 255]; // read-only  [0-255, 0-255, 0-255]\r\n\r\n\t\t// Color Picker options\r\n\t\t//\r\n\t\tthis.width = 181; // width of color palette (in px)\r\n\t\tthis.height = 101; // height of color palette (in px)\r\n\t\tthis.showOnClick = true; // whether to display the color picker when user clicks on its target element\r\n\t\tthis.mode = 'HSV'; // HSV | HVS | HS | HV - layout of the color picker controls\r\n\t\tthis.position = 'bottom'; // left | right | top | bottom - position relative to the target element\r\n\t\tthis.smartPosition = true; // automatically change picker position when there is not enough space for it\r\n\t\tthis.sliderSize = 16; // px\r\n\t\tthis.crossSize = 8; // px\r\n\t\tthis.closable = false; // whether to display the Close button\r\n\t\tthis.closeText = 'Close';\r\n\t\tthis.buttonColor = '#000000'; // CSS color\r\n\t\tthis.buttonHeight = 18; // px\r\n\t\tthis.padding = 12; // px\r\n\t\tthis.backgroundColor = '#FFFFFF'; // CSS color\r\n\t\tthis.borderWidth = 1; // px\r\n\t\tthis.borderColor = '#BBBBBB'; // CSS color\r\n\t\tthis.borderRadius = 8; // px\r\n\t\tthis.insetWidth = 1; // px\r\n\t\tthis.insetColor = '#BBBBBB'; // CSS color\r\n\t\tthis.shadow = true; // whether to display shadow\r\n\t\tthis.shadowBlur = 15; // px\r\n\t\tthis.shadowColor = 'rgba(0,0,0,0.2)'; // CSS color\r\n\t\tthis.pointerColor = '#4C4C4C'; // px\r\n\t\tthis.pointerBorderColor = '#FFFFFF'; // px\r\n        this.pointerBorderWidth = 1; // px\r\n        this.pointerThickness = 2; // px\r\n\t\tthis.zIndex = 1000;\r\n\t\tthis.container = null; // where to append the color picker (BODY element by default)\r\n\r\n\r\n\t\tfor (var opt in options) {\r\n\t\t\tif (options.hasOwnProperty(opt)) {\r\n\t\t\t\tthis[opt] = options[opt];\r\n\t\t\t}\r\n\t\t}\r\n\r\n\r\n\t\tthis.hide = function () {\r\n\t\t\tif (isPickerOwner()) {\r\n\t\t\t\tdetachPicker();\r\n\t\t\t}\r\n\t\t};\r\n\r\n\r\n\t\tthis.show = function () {\r\n\t\t\tdrawPicker();\r\n\t\t};\r\n\r\n\r\n\t\tthis.redraw = function () {\r\n\t\t\tif (isPickerOwner()) {\r\n\t\t\t\tdrawPicker();\r\n\t\t\t}\r\n\t\t};\r\n\r\n\r\n\t\tthis.importColor = function () {\r\n\t\t\tif (!this.valueElement) {\r\n\t\t\t\tthis.exportColor();\r\n\t\t\t} else {\r\n\t\t\t\tif (jsc.isElementType(this.valueElement, 'input')) {\r\n\t\t\t\t\tif (!this.refine) {\r\n\t\t\t\t\t\tif (!this.fromString(this.valueElement.value, jsc.leaveValue)) {\r\n\t\t\t\t\t\t\tif (this.styleElement) {\r\n\t\t\t\t\t\t\t\tthis.styleElement.style.backgroundImage = this.styleElement._jscOrigStyle.backgroundImage;\r\n\t\t\t\t\t\t\t\tthis.styleElement.style.backgroundColor = this.styleElement._jscOrigStyle.backgroundColor;\r\n\t\t\t\t\t\t\t\tthis.styleElement.style.color = this.styleElement._jscOrigStyle.color;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tthis.exportColor(jsc.leaveValue | jsc.leaveStyle);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t} else if (!this.required && /^\\s*$/.test(this.valueElement.value)) {\r\n\t\t\t\t\t\tthis.valueElement.value = '';\r\n\t\t\t\t\t\tif (this.styleElement) {\r\n\t\t\t\t\t\t\tthis.styleElement.style.backgroundImage = this.styleElement._jscOrigStyle.backgroundImage;\r\n\t\t\t\t\t\t\tthis.styleElement.style.backgroundColor = this.styleElement._jscOrigStyle.backgroundColor;\r\n\t\t\t\t\t\t\tthis.styleElement.style.color = this.styleElement._jscOrigStyle.color;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tthis.exportColor(jsc.leaveValue | jsc.leaveStyle);\r\n\r\n\t\t\t\t\t} else if (this.fromString(this.valueElement.value)) {\r\n\t\t\t\t\t\t// managed to import color successfully from the value -> OK, don't do anything\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tthis.exportColor();\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// not an input element -> doesn't have any value\r\n\t\t\t\t\tthis.exportColor();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t};\r\n\r\n\r\n\t\tthis.exportColor = function (flags) {\r\n\t\t\tif (!(flags & jsc.leaveValue) && this.valueElement) {\r\n\t\t\t\tvar value = this.toString();\r\n\t\t\t\tif (this.uppercase) { value = value.toUpperCase(); }\r\n\t\t\t\tif (this.hash) { value = '#' + value; }\r\n\r\n\t\t\t\tif (jsc.isElementType(this.valueElement, 'input')) {\r\n\t\t\t\t\tthis.valueElement.value = value;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tthis.valueElement.innerHTML = value;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (!(flags & jsc.leaveStyle)) {\r\n\t\t\t\tif (this.styleElement) {\r\n\t\t\t\t\tthis.styleElement.style.backgroundImage = 'none';\r\n\t\t\t\t\tthis.styleElement.style.backgroundColor = '#' + this.toString();\r\n\t\t\t\t\tthis.styleElement.style.color = this.isLight() ? '#000' : '#FFF';\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (!(flags & jsc.leavePad) && isPickerOwner()) {\r\n\t\t\t\tredrawPad();\r\n\t\t\t}\r\n\t\t\tif (!(flags & jsc.leaveSld) && isPickerOwner()) {\r\n\t\t\t\tredrawSld();\r\n\t\t\t}\r\n\t\t};\r\n\r\n\r\n\t\t// h: 0-360\r\n\t\t// s: 0-100\r\n\t\t// v: 0-100\r\n\t\t//\r\n\t\tthis.fromHSV = function (h, s, v, flags) { // null = don't change\r\n\t\t\tif (h !== null) {\r\n\t\t\t\tif (isNaN(h)) { return false; }\r\n\t\t\t\th = Math.max(0, Math.min(360, h));\r\n\t\t\t}\r\n\t\t\tif (s !== null) {\r\n\t\t\t\tif (isNaN(s)) { return false; }\r\n\t\t\t\ts = Math.max(0, Math.min(100, this.maxS, s), this.minS);\r\n\t\t\t}\r\n\t\t\tif (v !== null) {\r\n\t\t\t\tif (isNaN(v)) { return false; }\r\n\t\t\t\tv = Math.max(0, Math.min(100, this.maxV, v), this.minV);\r\n\t\t\t}\r\n\r\n\t\t\tthis.rgb = HSV_RGB(\r\n\t\t\t\th===null ? this.hsv[0] : (this.hsv[0]=h),\r\n\t\t\t\ts===null ? this.hsv[1] : (this.hsv[1]=s),\r\n\t\t\t\tv===null ? this.hsv[2] : (this.hsv[2]=v)\r\n\t\t\t);\r\n\r\n\t\t\tthis.exportColor(flags);\r\n\t\t};\r\n\r\n\r\n\t\t// r: 0-255\r\n\t\t// g: 0-255\r\n\t\t// b: 0-255\r\n\t\t//\r\n\t\tthis.fromRGB = function (r, g, b, flags) { // null = don't change\r\n\t\t\tif (r !== null) {\r\n\t\t\t\tif (isNaN(r)) { return false; }\r\n\t\t\t\tr = Math.max(0, Math.min(255, r));\r\n\t\t\t}\r\n\t\t\tif (g !== null) {\r\n\t\t\t\tif (isNaN(g)) { return false; }\r\n\t\t\t\tg = Math.max(0, Math.min(255, g));\r\n\t\t\t}\r\n\t\t\tif (b !== null) {\r\n\t\t\t\tif (isNaN(b)) { return false; }\r\n\t\t\t\tb = Math.max(0, Math.min(255, b));\r\n\t\t\t}\r\n\r\n\t\t\tvar hsv = RGB_HSV(\r\n\t\t\t\tr===null ? this.rgb[0] : r,\r\n\t\t\t\tg===null ? this.rgb[1] : g,\r\n\t\t\t\tb===null ? this.rgb[2] : b\r\n\t\t\t);\r\n\t\t\tif (hsv[0] !== null) {\r\n\t\t\t\tthis.hsv[0] = Math.max(0, Math.min(360, hsv[0]));\r\n\t\t\t}\r\n\t\t\tif (hsv[2] !== 0) {\r\n\t\t\t\tthis.hsv[1] = hsv[1]===null ? null : Math.max(0, this.minS, Math.min(100, this.maxS, hsv[1]));\r\n\t\t\t}\r\n\t\t\tthis.hsv[2] = hsv[2]===null ? null : Math.max(0, this.minV, Math.min(100, this.maxV, hsv[2]));\r\n\r\n\t\t\t// update RGB according to final HSV, as some values might be trimmed\r\n\t\t\tvar rgb = HSV_RGB(this.hsv[0], this.hsv[1], this.hsv[2]);\r\n\t\t\tthis.rgb[0] = rgb[0];\r\n\t\t\tthis.rgb[1] = rgb[1];\r\n\t\t\tthis.rgb[2] = rgb[2];\r\n\r\n\t\t\tthis.exportColor(flags);\r\n\t\t};\r\n\r\n\r\n\t\tthis.fromString = function (str, flags) {\r\n\t\t\tvar m;\r\n\t\t\tif (m = str.match(/^\\W*([0-9A-F]{3}([0-9A-F]{3})?)\\W*$/i)) {\r\n\t\t\t\t// HEX notation\r\n\t\t\t\t//\r\n\r\n\t\t\t\tif (m[1].length === 6) {\r\n\t\t\t\t\t// 6-char notation\r\n\t\t\t\t\tthis.fromRGB(\r\n\t\t\t\t\t\tparseInt(m[1].substr(0,2),16),\r\n\t\t\t\t\t\tparseInt(m[1].substr(2,2),16),\r\n\t\t\t\t\t\tparseInt(m[1].substr(4,2),16),\r\n\t\t\t\t\t\tflags\r\n\t\t\t\t\t);\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// 3-char notation\r\n\t\t\t\t\tthis.fromRGB(\r\n\t\t\t\t\t\tparseInt(m[1].charAt(0) + m[1].charAt(0),16),\r\n\t\t\t\t\t\tparseInt(m[1].charAt(1) + m[1].charAt(1),16),\r\n\t\t\t\t\t\tparseInt(m[1].charAt(2) + m[1].charAt(2),16),\r\n\t\t\t\t\t\tflags\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\t\t\t\treturn true;\r\n\r\n\t\t\t} else if (m = str.match(/^\\W*rgba?\\(([^)]*)\\)\\W*$/i)) {\r\n\t\t\t\tvar params = m[1].split(',');\r\n\t\t\t\tvar re = /^\\s*(\\d*)(\\.\\d+)?\\s*$/;\r\n\t\t\t\tvar mR, mG, mB;\r\n\t\t\t\tif (\r\n\t\t\t\t\tparams.length >= 3 &&\r\n\t\t\t\t\t(mR = params[0].match(re)) &&\r\n\t\t\t\t\t(mG = params[1].match(re)) &&\r\n\t\t\t\t\t(mB = params[2].match(re))\r\n\t\t\t\t) {\r\n\t\t\t\t\tvar r = parseFloat((mR[1] || '0') + (mR[2] || ''));\r\n\t\t\t\t\tvar g = parseFloat((mG[1] || '0') + (mG[2] || ''));\r\n\t\t\t\t\tvar b = parseFloat((mB[1] || '0') + (mB[2] || ''));\r\n\t\t\t\t\tthis.fromRGB(r, g, b, flags);\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn false;\r\n\t\t};\r\n\r\n\r\n\t\tthis.toString = function () {\r\n\t\t\treturn (\r\n\t\t\t\t(0x100 | Math.round(this.rgb[0])).toString(16).substr(1) +\r\n\t\t\t\t(0x100 | Math.round(this.rgb[1])).toString(16).substr(1) +\r\n\t\t\t\t(0x100 | Math.round(this.rgb[2])).toString(16).substr(1)\r\n\t\t\t);\r\n\t\t};\r\n\r\n\r\n\t\tthis.toHEXString = function () {\r\n\t\t\treturn '#' + this.toString().toUpperCase();\r\n\t\t};\r\n\r\n\r\n\t\tthis.toRGBString = function () {\r\n\t\t\treturn ('rgb(' +\r\n\t\t\t\tMath.round(this.rgb[0]) + ',' +\r\n\t\t\t\tMath.round(this.rgb[1]) + ',' +\r\n\t\t\t\tMath.round(this.rgb[2]) + ')'\r\n\t\t\t);\r\n\t\t};\r\n\r\n\r\n\t\tthis.isLight = function () {\r\n\t\t\treturn (\r\n\t\t\t\t0.213 * this.rgb[0] +\r\n\t\t\t\t0.715 * this.rgb[1] +\r\n\t\t\t\t0.072 * this.rgb[2] >\r\n\t\t\t\t255 / 2\r\n\t\t\t);\r\n\t\t};\r\n\r\n\r\n\t\tthis._processParentElementsInDOM = function () {\r\n\t\t\tif (this._linkedElementsProcessed) { return; }\r\n\t\t\tthis._linkedElementsProcessed = true;\r\n\r\n\t\t\tvar elm = this.targetElement;\r\n\t\t\tdo {\r\n\t\t\t\t// If the target element or one of its parent nodes has fixed position,\r\n\t\t\t\t// then use fixed positioning instead\r\n\t\t\t\t//\r\n\t\t\t\t// Note: In Firefox, getComputedStyle returns null in a hidden iframe,\r\n\t\t\t\t// that's why we need to check if the returned style object is non-empty\r\n\t\t\t\tvar currStyle = jsc.getStyle(elm);\r\n\t\t\t\tif (currStyle && currStyle.position.toLowerCase() === 'fixed') {\r\n\t\t\t\t\tthis.fixed = true;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (elm !== this.targetElement) {\r\n\t\t\t\t\t// Ensure to attach onParentScroll only once to each parent element\r\n\t\t\t\t\t// (multiple targetElements can share the same parent nodes)\r\n\t\t\t\t\t//\r\n\t\t\t\t\t// Note: It's not just offsetParents that can be scrollable,\r\n\t\t\t\t\t// that's why we loop through all parent nodes\r\n\t\t\t\t\tif (!elm._jscEventsAttached) {\r\n\t\t\t\t\t\tjsc.attachEvent(elm, 'scroll', jsc.onParentScroll);\r\n\t\t\t\t\t\telm._jscEventsAttached = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t} while ((elm = elm.parentNode) && !jsc.isElementType(elm, 'body'));\r\n\t\t};\r\n\r\n\r\n\t\t// r: 0-255\r\n\t\t// g: 0-255\r\n\t\t// b: 0-255\r\n\t\t//\r\n\t\t// returns: [ 0-360, 0-100, 0-100 ]\r\n\t\t//\r\n\t\tfunction RGB_HSV (r, g, b) {\r\n\t\t\tr /= 255;\r\n\t\t\tg /= 255;\r\n\t\t\tb /= 255;\r\n\t\t\tvar n = Math.min(Math.min(r,g),b);\r\n\t\t\tvar v = Math.max(Math.max(r,g),b);\r\n\t\t\tvar m = v - n;\r\n\t\t\tif (m === 0) { return [ null, 0, 100 * v ]; }\r\n\t\t\tvar h = r===n ? 3+(b-g)/m : (g===n ? 5+(r-b)/m : 1+(g-r)/m);\r\n\t\t\treturn [\r\n\t\t\t\t60 * (h===6?0:h),\r\n\t\t\t\t100 * (m/v),\r\n\t\t\t\t100 * v\r\n\t\t\t];\r\n\t\t}\r\n\r\n\r\n\t\t// h: 0-360\r\n\t\t// s: 0-100\r\n\t\t// v: 0-100\r\n\t\t//\r\n\t\t// returns: [ 0-255, 0-255, 0-255 ]\r\n\t\t//\r\n\t\tfunction HSV_RGB (h, s, v) {\r\n\t\t\tvar u = 255 * (v / 100);\r\n\r\n\t\t\tif (h === null) {\r\n\t\t\t\treturn [ u, u, u ];\r\n\t\t\t}\r\n\r\n\t\t\th /= 60;\r\n\t\t\ts /= 100;\r\n\r\n\t\t\tvar i = Math.floor(h);\r\n\t\t\tvar f = i%2 ? h-i : 1-(h-i);\r\n\t\t\tvar m = u * (1 - s);\r\n\t\t\tvar n = u * (1 - s * f);\r\n\t\t\tswitch (i) {\r\n\t\t\t\tcase 6:\r\n\t\t\t\tcase 0: return [u,n,m];\r\n\t\t\t\tcase 1: return [n,u,m];\r\n\t\t\t\tcase 2: return [m,u,n];\r\n\t\t\t\tcase 3: return [m,n,u];\r\n\t\t\t\tcase 4: return [n,m,u];\r\n\t\t\t\tcase 5: return [u,m,n];\r\n\t\t\t}\r\n\t\t}\r\n\r\n\r\n\t\tfunction detachPicker () {\r\n\t\t\tjsc.unsetClass(THIS.targetElement, THIS.activeClass);\r\n\t\t\tjsc.picker.wrap.parentNode.removeChild(jsc.picker.wrap);\r\n\t\t\tdelete jsc.picker.owner;\r\n\t\t}\r\n\r\n\r\n\t\tfunction drawPicker () {\r\n\r\n\t\t\t// At this point, when drawing the picker, we know what the parent elements are\r\n\t\t\t// and we can do all related DOM operations, such as registering events on them\r\n\t\t\t// or checking their positioning\r\n\t\t\tTHIS._processParentElementsInDOM();\r\n\r\n\t\t\tif (!jsc.picker) {\r\n\t\t\t\tjsc.picker = {\r\n\t\t\t\t\towner: null,\r\n\t\t\t\t\twrap : document.createElement('div'),\r\n\t\t\t\t\tbox : document.createElement('div'),\r\n\t\t\t\t\tboxS : document.createElement('div'), // shadow area\r\n\t\t\t\t\tboxB : document.createElement('div'), // border\r\n\t\t\t\t\tpad : document.createElement('div'),\r\n\t\t\t\t\tpadB : document.createElement('div'), // border\r\n\t\t\t\t\tpadM : document.createElement('div'), // mouse/touch area\r\n\t\t\t\t\tpadPal : jsc.createPalette(),\r\n\t\t\t\t\tcross : document.createElement('div'),\r\n\t\t\t\t\tcrossBY : document.createElement('div'), // border Y\r\n\t\t\t\t\tcrossBX : document.createElement('div'), // border X\r\n\t\t\t\t\tcrossLY : document.createElement('div'), // line Y\r\n\t\t\t\t\tcrossLX : document.createElement('div'), // line X\r\n\t\t\t\t\tsld : document.createElement('div'),\r\n\t\t\t\t\tsldB : document.createElement('div'), // border\r\n\t\t\t\t\tsldM : document.createElement('div'), // mouse/touch area\r\n\t\t\t\t\tsldGrad : jsc.createSliderGradient(),\r\n\t\t\t\t\tsldPtrS : document.createElement('div'), // slider pointer spacer\r\n\t\t\t\t\tsldPtrIB : document.createElement('div'), // slider pointer inner border\r\n\t\t\t\t\tsldPtrMB : document.createElement('div'), // slider pointer middle border\r\n\t\t\t\t\tsldPtrOB : document.createElement('div'), // slider pointer outer border\r\n\t\t\t\t\tbtn : document.createElement('div'),\r\n\t\t\t\t\tbtnT : document.createElement('span') // text\r\n\t\t\t\t};\r\n\r\n\t\t\t\tjsc.picker.pad.appendChild(jsc.picker.padPal.elm);\r\n\t\t\t\tjsc.picker.padB.appendChild(jsc.picker.pad);\r\n\t\t\t\tjsc.picker.cross.appendChild(jsc.picker.crossBY);\r\n\t\t\t\tjsc.picker.cross.appendChild(jsc.picker.crossBX);\r\n\t\t\t\tjsc.picker.cross.appendChild(jsc.picker.crossLY);\r\n\t\t\t\tjsc.picker.cross.appendChild(jsc.picker.crossLX);\r\n\t\t\t\tjsc.picker.padB.appendChild(jsc.picker.cross);\r\n\t\t\t\tjsc.picker.box.appendChild(jsc.picker.padB);\r\n\t\t\t\tjsc.picker.box.appendChild(jsc.picker.padM);\r\n\r\n\t\t\t\tjsc.picker.sld.appendChild(jsc.picker.sldGrad.elm);\r\n\t\t\t\tjsc.picker.sldB.appendChild(jsc.picker.sld);\r\n\t\t\t\tjsc.picker.sldB.appendChild(jsc.picker.sldPtrOB);\r\n\t\t\t\tjsc.picker.sldPtrOB.appendChild(jsc.picker.sldPtrMB);\r\n\t\t\t\tjsc.picker.sldPtrMB.appendChild(jsc.picker.sldPtrIB);\r\n\t\t\t\tjsc.picker.sldPtrIB.appendChild(jsc.picker.sldPtrS);\r\n\t\t\t\tjsc.picker.box.appendChild(jsc.picker.sldB);\r\n\t\t\t\tjsc.picker.box.appendChild(jsc.picker.sldM);\r\n\r\n\t\t\t\tjsc.picker.btn.appendChild(jsc.picker.btnT);\r\n\t\t\t\tjsc.picker.box.appendChild(jsc.picker.btn);\r\n\r\n\t\t\t\tjsc.picker.boxB.appendChild(jsc.picker.box);\r\n\t\t\t\tjsc.picker.wrap.appendChild(jsc.picker.boxS);\r\n\t\t\t\tjsc.picker.wrap.appendChild(jsc.picker.boxB);\r\n\t\t\t}\r\n\r\n\t\t\tvar p = jsc.picker;\r\n\r\n\t\t\tvar displaySlider = !!jsc.getSliderComponent(THIS);\r\n\t\t\tvar dims = jsc.getPickerDims(THIS);\r\n\t\t\tvar crossOuterSize = (2 * THIS.pointerBorderWidth + THIS.pointerThickness + 2 * THIS.crossSize);\r\n\t\t\tvar padToSliderPadding = jsc.getPadToSliderPadding(THIS);\r\n\t\t\tvar borderRadius = Math.min(\r\n\t\t\t\tTHIS.borderRadius,\r\n\t\t\t\tMath.round(THIS.padding * Math.PI)); // px\r\n\t\t\tvar padCursor = 'crosshair';\r\n\r\n\t\t\t// wrap\r\n\t\t\tp.wrap.style.clear = 'both';\r\n\t\t\tp.wrap.style.width = (dims[0] + 2 * THIS.borderWidth) + 'px';\r\n\t\t\tp.wrap.style.height = (dims[1] + 2 * THIS.borderWidth) + 'px';\r\n\t\t\tp.wrap.style.zIndex = THIS.zIndex;\r\n\r\n\t\t\t// picker\r\n\t\t\tp.box.style.width = dims[0] + 'px';\r\n\t\t\tp.box.style.height = dims[1] + 'px';\r\n\r\n\t\t\tp.boxS.style.position = 'absolute';\r\n\t\t\tp.boxS.style.left = '0';\r\n\t\t\tp.boxS.style.top = '0';\r\n\t\t\tp.boxS.style.width = '100%';\r\n\t\t\tp.boxS.style.height = '100%';\r\n\t\t\tjsc.setBorderRadius(p.boxS, borderRadius + 'px');\r\n\r\n\t\t\t// picker border\r\n\t\t\tp.boxB.style.position = 'relative';\r\n\t\t\tp.boxB.style.border = THIS.borderWidth + 'px solid';\r\n\t\t\tp.boxB.style.borderColor = THIS.borderColor;\r\n\t\t\tp.boxB.style.background = THIS.backgroundColor;\r\n\t\t\tjsc.setBorderRadius(p.boxB, borderRadius + 'px');\r\n\r\n\t\t\t// IE hack:\r\n\t\t\t// If the element is transparent, IE will trigger the event on the elements under it,\r\n\t\t\t// e.g. on Canvas or on elements with border\r\n\t\t\tp.padM.style.background =\r\n\t\t\tp.sldM.style.background =\r\n\t\t\t\t'#FFF';\r\n\t\t\tjsc.setStyle(p.padM, 'opacity', '0');\r\n\t\t\tjsc.setStyle(p.sldM, 'opacity', '0');\r\n\r\n\t\t\t// pad\r\n\t\t\tp.pad.style.position = 'relative';\r\n\t\t\tp.pad.style.width = THIS.width + 'px';\r\n\t\t\tp.pad.style.height = THIS.height + 'px';\r\n\r\n\t\t\t// pad palettes (HSV and HVS)\r\n\t\t\tp.padPal.draw(THIS.width, THIS.height, jsc.getPadYComponent(THIS));\r\n\r\n\t\t\t// pad border\r\n\t\t\tp.padB.style.position = 'absolute';\r\n\t\t\tp.padB.style.left = THIS.padding + 'px';\r\n\t\t\tp.padB.style.top = THIS.padding + 'px';\r\n\t\t\tp.padB.style.border = THIS.insetWidth + 'px solid';\r\n\t\t\tp.padB.style.borderColor = THIS.insetColor;\r\n\r\n\t\t\t// pad mouse area\r\n\t\t\tp.padM._jscInstance = THIS;\r\n\t\t\tp.padM._jscControlName = 'pad';\r\n\t\t\tp.padM.style.position = 'absolute';\r\n\t\t\tp.padM.style.left = '0';\r\n\t\t\tp.padM.style.top = '0';\r\n\t\t\tp.padM.style.width = (THIS.padding + 2 * THIS.insetWidth + THIS.width + padToSliderPadding / 2) + 'px';\r\n\t\t\tp.padM.style.height = dims[1] + 'px';\r\n\t\t\tp.padM.style.cursor = padCursor;\r\n\r\n\t\t\t// pad cross\r\n\t\t\tp.cross.style.position = 'absolute';\r\n\t\t\tp.cross.style.left =\r\n\t\t\tp.cross.style.top =\r\n\t\t\t\t'0';\r\n\t\t\tp.cross.style.width =\r\n\t\t\tp.cross.style.height =\r\n\t\t\t\tcrossOuterSize + 'px';\r\n\r\n\t\t\t// pad cross border Y and X\r\n\t\t\tp.crossBY.style.position =\r\n\t\t\tp.crossBX.style.position =\r\n\t\t\t\t'absolute';\r\n\t\t\tp.crossBY.style.background =\r\n\t\t\tp.crossBX.style.background =\r\n\t\t\t\tTHIS.pointerBorderColor;\r\n\t\t\tp.crossBY.style.width =\r\n\t\t\tp.crossBX.style.height =\r\n\t\t\t\t(2 * THIS.pointerBorderWidth + THIS.pointerThickness) + 'px';\r\n\t\t\tp.crossBY.style.height =\r\n\t\t\tp.crossBX.style.width =\r\n\t\t\t\tcrossOuterSize + 'px';\r\n\t\t\tp.crossBY.style.left =\r\n\t\t\tp.crossBX.style.top =\r\n\t\t\t\t(Math.floor(crossOuterSize / 2) - Math.floor(THIS.pointerThickness / 2) - THIS.pointerBorderWidth) + 'px';\r\n\t\t\tp.crossBY.style.top =\r\n\t\t\tp.crossBX.style.left =\r\n\t\t\t\t'0';\r\n\r\n\t\t\t// pad cross line Y and X\r\n\t\t\tp.crossLY.style.position =\r\n\t\t\tp.crossLX.style.position =\r\n\t\t\t\t'absolute';\r\n\t\t\tp.crossLY.style.background =\r\n\t\t\tp.crossLX.style.background =\r\n\t\t\t\tTHIS.pointerColor;\r\n\t\t\tp.crossLY.style.height =\r\n\t\t\tp.crossLX.style.width =\r\n\t\t\t\t(crossOuterSize - 2 * THIS.pointerBorderWidth) + 'px';\r\n\t\t\tp.crossLY.style.width =\r\n\t\t\tp.crossLX.style.height =\r\n\t\t\t\tTHIS.pointerThickness + 'px';\r\n\t\t\tp.crossLY.style.left =\r\n\t\t\tp.crossLX.style.top =\r\n\t\t\t\t(Math.floor(crossOuterSize / 2) - Math.floor(THIS.pointerThickness / 2)) + 'px';\r\n\t\t\tp.crossLY.style.top =\r\n\t\t\tp.crossLX.style.left =\r\n\t\t\t\tTHIS.pointerBorderWidth + 'px';\r\n\r\n\t\t\t// slider\r\n\t\t\tp.sld.style.overflow = 'hidden';\r\n\t\t\tp.sld.style.width = THIS.sliderSize + 'px';\r\n\t\t\tp.sld.style.height = THIS.height + 'px';\r\n\r\n\t\t\t// slider gradient\r\n\t\t\tp.sldGrad.draw(THIS.sliderSize, THIS.height, '#000', '#000');\r\n\r\n\t\t\t// slider border\r\n\t\t\tp.sldB.style.display = displaySlider ? 'block' : 'none';\r\n\t\t\tp.sldB.style.position = 'absolute';\r\n\t\t\tp.sldB.style.right = THIS.padding + 'px';\r\n\t\t\tp.sldB.style.top = THIS.padding + 'px';\r\n\t\t\tp.sldB.style.border = THIS.insetWidth + 'px solid';\r\n\t\t\tp.sldB.style.borderColor = THIS.insetColor;\r\n\r\n\t\t\t// slider mouse area\r\n\t\t\tp.sldM._jscInstance = THIS;\r\n\t\t\tp.sldM._jscControlName = 'sld';\r\n\t\t\tp.sldM.style.display = displaySlider ? 'block' : 'none';\r\n\t\t\tp.sldM.style.position = 'absolute';\r\n\t\t\tp.sldM.style.right = '0';\r\n\t\t\tp.sldM.style.top = '0';\r\n\t\t\tp.sldM.style.width = (THIS.sliderSize + padToSliderPadding / 2 + THIS.padding + 2 * THIS.insetWidth) + 'px';\r\n\t\t\tp.sldM.style.height = dims[1] + 'px';\r\n\t\t\tp.sldM.style.cursor = 'default';\r\n\r\n\t\t\t// slider pointer inner and outer border\r\n\t\t\tp.sldPtrIB.style.border =\r\n\t\t\tp.sldPtrOB.style.border =\r\n\t\t\t\tTHIS.pointerBorderWidth + 'px solid ' + THIS.pointerBorderColor;\r\n\r\n\t\t\t// slider pointer outer border\r\n\t\t\tp.sldPtrOB.style.position = 'absolute';\r\n\t\t\tp.sldPtrOB.style.left = -(2 * THIS.pointerBorderWidth + THIS.pointerThickness) + 'px';\r\n\t\t\tp.sldPtrOB.style.top = '0';\r\n\r\n\t\t\t// slider pointer middle border\r\n\t\t\tp.sldPtrMB.style.border = THIS.pointerThickness + 'px solid ' + THIS.pointerColor;\r\n\r\n\t\t\t// slider pointer spacer\r\n\t\t\tp.sldPtrS.style.width = THIS.sliderSize + 'px';\r\n\t\t\tp.sldPtrS.style.height = sliderPtrSpace + 'px';\r\n\r\n\t\t\t// the Close button\r\n\t\t\tfunction setBtnBorder () {\r\n\t\t\t\tvar insetColors = THIS.insetColor.split(/\\s+/);\r\n\t\t\t\tvar outsetColor = insetColors.length < 2 ? insetColors[0] : insetColors[1] + ' ' + insetColors[0] + ' ' + insetColors[0] + ' ' + insetColors[1];\r\n\t\t\t\tp.btn.style.borderColor = outsetColor;\r\n\t\t\t}\r\n\t\t\tp.btn.style.display = THIS.closable ? 'block' : 'none';\r\n\t\t\tp.btn.style.position = 'absolute';\r\n\t\t\tp.btn.style.left = THIS.padding + 'px';\r\n\t\t\tp.btn.style.bottom = THIS.padding + 'px';\r\n\t\t\tp.btn.style.padding = '0 15px';\r\n\t\t\tp.btn.style.height = THIS.buttonHeight + 'px';\r\n\t\t\tp.btn.style.border = THIS.insetWidth + 'px solid';\r\n\t\t\tsetBtnBorder();\r\n\t\t\tp.btn.style.color = THIS.buttonColor;\r\n\t\t\tp.btn.style.font = '12px sans-serif';\r\n\t\t\tp.btn.style.textAlign = 'center';\r\n\t\t\ttry {\r\n\t\t\t\tp.btn.style.cursor = 'pointer';\r\n\t\t\t} catch(eOldIE) {\r\n\t\t\t\tp.btn.style.cursor = 'hand';\r\n\t\t\t}\r\n\t\t\tp.btn.onmousedown = function () {\r\n\t\t\t\tTHIS.hide();\r\n\t\t\t};\r\n\t\t\tp.btnT.style.lineHeight = THIS.buttonHeight + 'px';\r\n\t\t\tp.btnT.innerHTML = '';\r\n\t\t\tp.btnT.appendChild(document.createTextNode(THIS.closeText));\r\n\r\n\t\t\t// place pointers\r\n\t\t\tredrawPad();\r\n\t\t\tredrawSld();\r\n\r\n\t\t\t// If we are changing the owner without first closing the picker,\r\n\t\t\t// make sure to first deal with the old owner\r\n\t\t\tif (jsc.picker.owner && jsc.picker.owner !== THIS) {\r\n\t\t\t\tjsc.unsetClass(jsc.picker.owner.targetElement, THIS.activeClass);\r\n\t\t\t}\r\n\r\n\t\t\t// Set the new picker owner\r\n\t\t\tjsc.picker.owner = THIS;\r\n\r\n\t\t\t// The redrawPosition() method needs picker.owner to be set, that's why we call it here,\r\n\t\t\t// after setting the owner\r\n\t\t\tif (jsc.isElementType(container, 'body')) {\r\n\t\t\t\tjsc.redrawPosition();\r\n\t\t\t} else {\r\n\t\t\t\tjsc._drawPosition(THIS, 0, 0, 'relative', false);\r\n\t\t\t}\r\n\r\n\t\t\tif (p.wrap.parentNode != container) {\r\n\t\t\t\tcontainer.appendChild(p.wrap);\r\n\t\t\t}\r\n\r\n\t\t\tjsc.setClass(THIS.targetElement, THIS.activeClass);\r\n\t\t}\r\n\r\n\r\n\t\tfunction redrawPad () {\r\n\t\t\t// redraw the pad pointer\r\n\t\t\tswitch (jsc.getPadYComponent(THIS)) {\r\n\t\t\tcase 's': var yComponent = 1; break;\r\n\t\t\tcase 'v': var yComponent = 2; break;\r\n\t\t\t}\r\n\t\t\tvar x = Math.round((THIS.hsv[0] / 360) * (THIS.width - 1));\r\n\t\t\tvar y = Math.round((1 - THIS.hsv[yComponent] / 100) * (THIS.height - 1));\r\n\t\t\tvar crossOuterSize = (2 * THIS.pointerBorderWidth + THIS.pointerThickness + 2 * THIS.crossSize);\r\n\t\t\tvar ofs = -Math.floor(crossOuterSize / 2);\r\n\t\t\tjsc.picker.cross.style.left = (x + ofs) + 'px';\r\n\t\t\tjsc.picker.cross.style.top = (y + ofs) + 'px';\r\n\r\n\t\t\t// redraw the slider\r\n\t\t\tswitch (jsc.getSliderComponent(THIS)) {\r\n\t\t\tcase 's':\r\n\t\t\t\tvar rgb1 = HSV_RGB(THIS.hsv[0], 100, THIS.hsv[2]);\r\n\t\t\t\tvar rgb2 = HSV_RGB(THIS.hsv[0], 0, THIS.hsv[2]);\r\n\t\t\t\tvar color1 = 'rgb(' +\r\n\t\t\t\t\tMath.round(rgb1[0]) + ',' +\r\n\t\t\t\t\tMath.round(rgb1[1]) + ',' +\r\n\t\t\t\t\tMath.round(rgb1[2]) + ')';\r\n\t\t\t\tvar color2 = 'rgb(' +\r\n\t\t\t\t\tMath.round(rgb2[0]) + ',' +\r\n\t\t\t\t\tMath.round(rgb2[1]) + ',' +\r\n\t\t\t\t\tMath.round(rgb2[2]) + ')';\r\n\t\t\t\tjsc.picker.sldGrad.draw(THIS.sliderSize, THIS.height, color1, color2);\r\n\t\t\t\tbreak;\r\n\t\t\tcase 'v':\r\n\t\t\t\tvar rgb = HSV_RGB(THIS.hsv[0], THIS.hsv[1], 100);\r\n\t\t\t\tvar color1 = 'rgb(' +\r\n\t\t\t\t\tMath.round(rgb[0]) + ',' +\r\n\t\t\t\t\tMath.round(rgb[1]) + ',' +\r\n\t\t\t\t\tMath.round(rgb[2]) + ')';\r\n\t\t\t\tvar color2 = '#000';\r\n\t\t\t\tjsc.picker.sldGrad.draw(THIS.sliderSize, THIS.height, color1, color2);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\r\n\t\tfunction redrawSld () {\r\n\t\t\tvar sldComponent = jsc.getSliderComponent(THIS);\r\n\t\t\tif (sldComponent) {\r\n\t\t\t\t// redraw the slider pointer\r\n\t\t\t\tswitch (sldComponent) {\r\n\t\t\t\tcase 's': var yComponent = 1; break;\r\n\t\t\t\tcase 'v': var yComponent = 2; break;\r\n\t\t\t\t}\r\n\t\t\t\tvar y = Math.round((1 - THIS.hsv[yComponent] / 100) * (THIS.height - 1));\r\n\t\t\t\tjsc.picker.sldPtrOB.style.top = (y - (2 * THIS.pointerBorderWidth + THIS.pointerThickness) - Math.floor(sliderPtrSpace / 2)) + 'px';\r\n\t\t\t}\r\n\t\t}\r\n\r\n\r\n\t\tfunction isPickerOwner () {\r\n\t\t\treturn jsc.picker && jsc.picker.owner === THIS;\r\n\t\t}\r\n\r\n\r\n\t\tfunction blurValue () {\r\n\t\t\tTHIS.importColor();\r\n\t\t}\r\n\r\n\r\n\t\t// Find the target element\r\n\t\tif (typeof targetElement === 'string') {\r\n\t\t\tvar id = targetElement;\r\n\t\t\tvar elm = document.getElementById(id);\r\n\t\t\tif (elm) {\r\n\t\t\t\tthis.targetElement = elm;\r\n\t\t\t} else {\r\n\t\t\t\tjsc.warn('Could not find target element with ID \\'' + id + '\\'');\r\n\t\t\t}\r\n\t\t} else if (targetElement) {\r\n\t\t\tthis.targetElement = targetElement;\r\n\t\t} else {\r\n\t\t\tjsc.warn('Invalid target element: \\'' + targetElement + '\\'');\r\n\t\t}\r\n\r\n\t\tif (this.targetElement._jscLinkedInstance) {\r\n\t\t\tjsc.warn('Cannot link jscolor twice to the same element. Skipping.');\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthis.targetElement._jscLinkedInstance = this;\r\n\r\n\t\t// Find the value element\r\n\t\tthis.valueElement = jsc.fetchElement(this.valueElement);\r\n\t\t// Find the style element\r\n\t\tthis.styleElement = jsc.fetchElement(this.styleElement);\r\n\r\n\t\tvar THIS = this;\r\n\t\tvar container =\r\n\t\t\tthis.container ?\r\n\t\t\tjsc.fetchElement(this.container) :\r\n\t\t\tdocument.getElementsByTagName('body')[0];\r\n\t\tvar sliderPtrSpace = 3; // px\r\n\r\n\t\t// For BUTTON elements it's important to stop them from sending the form when clicked\r\n\t\t// (e.g. in Safari)\r\n\t\tif (jsc.isElementType(this.targetElement, 'button')) {\r\n\t\t\tif (this.targetElement.onclick) {\r\n\t\t\t\tvar origCallback = this.targetElement.onclick;\r\n\t\t\t\tthis.targetElement.onclick = function (evt) {\r\n\t\t\t\t\torigCallback.call(this, evt);\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t};\r\n\t\t\t} else {\r\n\t\t\t\tthis.targetElement.onclick = function () { return false; };\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t/*\r\n\t\tvar elm = this.targetElement;\r\n\t\tdo {\r\n\t\t\t// If the target element or one of its offsetParents has fixed position,\r\n\t\t\t// then use fixed positioning instead\r\n\t\t\t//\r\n\t\t\t// Note: In Firefox, getComputedStyle returns null in a hidden iframe,\r\n\t\t\t// that's why we need to check if the returned style object is non-empty\r\n\t\t\tvar currStyle = jsc.getStyle(elm);\r\n\t\t\tif (currStyle && currStyle.position.toLowerCase() === 'fixed') {\r\n\t\t\t\tthis.fixed = true;\r\n\t\t\t}\r\n\r\n\t\t\tif (elm !== this.targetElement) {\r\n\t\t\t\t// attach onParentScroll so that we can recompute the picker position\r\n\t\t\t\t// when one of the offsetParents is scrolled\r\n\t\t\t\tif (!elm._jscEventsAttached) {\r\n\t\t\t\t\tjsc.attachEvent(elm, 'scroll', jsc.onParentScroll);\r\n\t\t\t\t\telm._jscEventsAttached = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} while ((elm = elm.offsetParent) && !jsc.isElementType(elm, 'body'));\r\n\t\t*/\r\n\r\n\t\t// valueElement\r\n\t\tif (this.valueElement) {\r\n\t\t\tif (jsc.isElementType(this.valueElement, 'input')) {\r\n\t\t\t\tvar updateField = function () {\r\n\t\t\t\t\tTHIS.fromString(THIS.valueElement.value, jsc.leaveValue);\r\n\t\t\t\t\tjsc.dispatchFineChange(THIS);\r\n\t\t\t\t};\r\n\t\t\t\tjsc.attachEvent(this.valueElement, 'keyup', updateField);\r\n\t\t\t\tjsc.attachEvent(this.valueElement, 'input', updateField);\r\n\t\t\t\tjsc.attachEvent(this.valueElement, 'blur', blurValue);\r\n\t\t\t\tthis.valueElement.setAttribute('autocomplete', 'off');\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// styleElement\r\n\t\tif (this.styleElement) {\r\n\t\t\tthis.styleElement._jscOrigStyle = {\r\n\t\t\t\tbackgroundImage : this.styleElement.style.backgroundImage,\r\n\t\t\t\tbackgroundColor : this.styleElement.style.backgroundColor,\r\n\t\t\t\tcolor : this.styleElement.style.color\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\tif (this.value) {\r\n\t\t\t// Try to set the color from the .value option and if unsuccessful,\r\n\t\t\t// export the current color\r\n\t\t\tthis.fromString(this.value) || this.exportColor();\r\n\t\t} else {\r\n\t\t\tthis.importColor();\r\n\t\t}\r\n\t}\r\n\r\n};\r\n\r\n\r\n//================================\r\n// Public properties and methods\r\n//================================\r\n\r\n\r\n// By default, search for all elements with class=\"jscolor\" and install a color picker on them.\r\n//\r\n// You can change what class name will be looked for by setting the property jscolor.lookupClass\r\n// anywhere in your HTML document. To completely disable the automatic lookup, set it to null.\r\n//\r\njsc.jscolor.lookupClass = 'jscolor';\r\n\r\n\r\njsc.jscolor.installByClassName = function (className) {\r\n\tvar inputElms = document.getElementsByTagName('input');\r\n\tvar buttonElms = document.getElementsByTagName('button');\r\n\r\n\tjsc.tryInstallOnElements(inputElms, className);\r\n\tjsc.tryInstallOnElements(buttonElms, className);\r\n};\r\n\r\n\r\njsc.register();\r\n\r\n\r\nreturn jsc.jscolor;\r\n\r\n\r\n})(); }\r\n"
  },
  {
    "path": "lib/keyCharToCode.js",
    "content": "// https://www.npmjs.com/package/keycode\n// Original key mappings lifted from http://jsfiddle.net/vWx8V/ via http://stackoverflow.com/questions/5603195/full-list-of-javascript-keycodes\n\nvar keyCharToCode = {\n    \"BACKSPACE\": 8,\n    \"TAB\": 9,\n    \"ENTER\": 13,\n    \"CTRL\": 17,\n    \"ALT\": 18,\n    \"PAUSE/BREAK\": 19,\n    \"CAPS LOCK\": 20,\n    \"ESC\": 27,\n    \"SPACE\": 32,\n    \"PAGE UP\": 33,\n    \"PAGE DOWN\": 34,\n    \"END\": 35,\n    \"HOME\": 36,\n    \"LEFT\": 37,\n    \"UP\": 38,\n    \"RIGHT\": 39,\n    \"DOWN\": 40,\n    \"INSERT\": 45,\n    \"DELETE\": 46,\n    \"0\": 48,\n    \"1\": 49,\n    \"2\": 50,\n    \"3\": 51,\n    \"4\": 52,\n    \"5\": 53,\n    \"6\": 54,\n    \"7\": 55,\n    \"8\": 56,\n    \"9\": 57,\n    \"A\": 65,\n    \"B\": 66,\n    \"C\": 67,\n    \"D\": 68,\n    \"E\": 69,\n    \"F\": 70,\n    \"G\": 71,\n    \"H\": 72,\n    \"I\": 73,\n    \"J\": 74,\n    \"K\": 75,\n    \"L\": 76,\n    \"M\": 77,\n    \"N\": 78,\n    \"O\": 79,\n    \"P\": 80,\n    \"Q\": 81,\n    \"R\": 82,\n    \"S\": 83,\n    \"T\": 84,\n    \"U\": 85,\n    \"V\": 86,\n    \"W\": 87,\n    \"X\": 88,\n    \"Y\": 89,\n    \"Z\": 90,\n    \"NUM 0\": 96,\n    \"NUM 1\": 97,\n    \"NUM 2\": 98,\n    \"NUM 3\": 99,\n    \"NUM 4\": 100,\n    \"NUM 5\": 101,\n    \"NUM 6\": 102,\n    \"NUM 7\": 103,\n    \"NUM 8\": 104,\n    \"NUM 9\": 105,\n    \"NUM *\": 106,\n    \"NUM +\": 107,\n    \"NUM -\": 109,\n    \"NUM .\": 110,\n    \"NUM /\": 111,\n    \"F1\": 112,\n    \"F2\": 113,\n    \"F3\": 114,\n    \"F4\": 115,\n    \"F5\": 116,\n    \"F6\": 117,\n    \"F7\": 118,\n    \"F8\": 119,\n    \"F9\": 120,\n    \"F10\": 121,\n    \"F11\": 122,\n    \"F12\": 123,\n    \"NUM LOCK\": 144,\n    \"SCROLL LOCK\": 145,\n    \"MY COMPUTER\": 182,\n    \"MY CALCULATOR\": 183,\n    \";\": 186,\n    \"=\": 187,\n    \",\": 188,\n    \"-\": 189,\n    \".\": 190,\n    \"/\": 191,\n    \"`\": 192,\n    \"[\": 219,\n    \"\\\\\": 220,\n    \"]\": 221,\n    \"'\": 222\n};\n\nvar codeToKeyChar = {};\nfor (var key in keyCharToCode) {\n    codeToKeyChar[keyCharToCode[key]] = key;\n}"
  },
  {
    "path": "lib/lerp.js",
    "content": "//https://github.com/mattdesl/lerp/blob/master/index.js\nvar lerp = function (v0, v1, t) { return v0*(1-t)+v1*t; };"
  },
  {
    "path": "lib/libgif.js",
    "content": "// Modified by zrispo, control-f zrispo to see da things\n\n/*\n\tSuperGif\n\n\tExample usage:\n\n\t\t<img src=\"./example1_preview.gif\" rel:animated_src=\"./example1.gif\" width=\"360\" height=\"360\" rel:auto_play=\"1\" />\n\n\t\t<script type=\"text/javascript\">\n\t\t\t$$('img').each(function (img_tag) {\n\t\t\t\tif (/.*\\.gif/.test(img_tag.src)) {\n\t\t\t\t\tvar rub = new SuperGif({ gif: img_tag } );\n\t\t\t\t\trub.load();\n\t\t\t\t}\n\t\t\t});\n\t\t</script>\n\n\tImage tag attributes:\n\n\t\trel:animated_src -\tIf this url is specified, it's loaded into the player instead of src.\n\t\t\t\t\t\t\tThis allows a preview frame to be shown until animated gif data is streamed into the canvas\n\n\t\trel:auto_play -\t\tDefaults to 1 if not specified. If set to zero, a call to the play() method is needed\n\n\tConstructor options args\n\n\t\tgif \t\t\t\tRequired. The DOM element of an img tag.\n\t\tloop_mode\t\t\tOptional. Setting this to false will force disable looping of the gif.\n\t\tauto_play \t\t\tOptional. Same as the rel:auto_play attribute above, this arg overrides the img tag info.\n\t\tmax_width\t\t\tOptional. Scale images over max_width down to max_width. Helpful with mobile.\n \t\ton_end\t\t\t\tOptional. Add a callback for when the gif reaches the end of a single loop (one iteration). The first argument passed will be the gif HTMLElement.\n\t\tloop_delay\t\t\tOptional. The amount of time to pause (in ms) after each single loop (iteration).\n\t\tdraw_while_loading\tOptional. Determines whether the gif will be drawn to the canvas whilst it is loaded.\n\t\tshow_progress_bar\tOptional. Only applies when draw_while_loading is set to true.\n\n\tInstance methods\n\n\t\t// loading\n\t\tload( callback )\t\tLoads the gif specified by the src or rel:animated_src sttributie of the img tag into a canvas element and then calls callback if one is passed\n\t\tload_url( src, callback )\tLoads the gif file specified in the src argument into a canvas element and then calls callback if one is passed\n\n\t\t// play controls\n\t\tplay -\t\t\t\tStart playing the gif\n\t\tpause -\t\t\t\tStop playing the gif\n\t\tmove_to(i) -\t\tMove to frame i of the gif\n\t\tmove_relative(i) -\tMove i frames ahead (or behind if i < 0)\n\n\t\t// getters\n\t\tget_canvas\t\t\tThe canvas element that the gif is playing in. Handy for assigning event handlers to.\n\t\tget_playing\t\t\tWhether or not the gif is currently playing\n\t\tget_loading\t\t\tWhether or not the gif has finished loading/parsing\n\t\tget_auto_play\t\tWhether or not the gif is set to play automatically\n\t\tget_length\t\t\tThe number of frames in the gif\n\t\tget_current_frame\tThe index of the currently displayed frame of the gif\n\n\t\tFor additional customization (viewport inside iframe) these params may be passed:\n\t\tc_w, c_h - width and height of canvas\n\t\tvp_t, vp_l, vp_ w, vp_h - top, left, width and height of the viewport\n\n\t\tA bonus: few articles to understand what is going on\n\t\t\thttp://enthusiasms.org/post/16976438906\n\t\t\thttp://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp\n\t\t\thttp://humpy77.deviantart.com/journal/Frame-Delay-Times-for-Animated-GIFs-214150546\n\n*/\n(function (root, factory) {\n    if (typeof define === 'function' && define.amd) {\n        define([], factory);\n    } else if (typeof exports === 'object') {\n        module.exports = factory();\n    } else {\n        root.SuperGif = factory();\n    }\n}(this, function () {\n    // Generic functions\n    var bitsToNum = function (ba) {\n        return ba.reduce(function (s, n) {\n            return s * 2 + n;\n        }, 0);\n    };\n\n    var byteToBitArr = function (bite) {\n        var a = [];\n        for (var i = 7; i >= 0; i--) {\n            a.push( !! (bite & (1 << i)));\n        }\n        return a;\n    };\n\n    // Stream\n    /**\n     * @constructor\n     */\n    // Make compiler happy.\n    var Stream = function (data) {\n        this.data = data;\n        this.len = this.data.length;\n        this.pos = 0;\n\n        this.readByte = function () {\n            if (this.pos >= this.data.length) {\n                throw new Error('Attempted to read past end of stream.');\n            }\n            if (data instanceof Uint8Array)\n                return data[this.pos++];\n            else\n                return data.charCodeAt(this.pos++) & 0xFF;\n        };\n\n        this.readBytes = function (n) {\n            var bytes = [];\n            for (var i = 0; i < n; i++) {\n                bytes.push(this.readByte());\n            }\n            return bytes;\n        };\n\n        this.read = function (n) {\n            var s = '';\n            for (var i = 0; i < n; i++) {\n                s += String.fromCharCode(this.readByte());\n            }\n            return s;\n        };\n\n        this.readUnsigned = function () { // Little-endian.\n            var a = this.readBytes(2);\n            return (a[1] << 8) + a[0];\n        };\n    };\n\n    var lzwDecode = function (minCodeSize, data) {\n        // TODO: Now that the GIF parser is a bit different, maybe this should get an array of bytes instead of a String?\n        var pos = 0; // Maybe this streaming thing should be merged with the Stream?\n        var readCode = function (size) {\n            var code = 0;\n            for (var i = 0; i < size; i++) {\n                if (data.charCodeAt(pos >> 3) & (1 << (pos & 7))) {\n                    code |= 1 << i;\n                }\n                pos++;\n            }\n            return code;\n        };\n\n        var output = [];\n\n        var clearCode = 1 << minCodeSize;\n        var eoiCode = clearCode + 1;\n\n        var codeSize = minCodeSize + 1;\n\n        var dict = [];\n\n        var clear = function () {\n            dict = [];\n            codeSize = minCodeSize + 1;\n            for (var i = 0; i < clearCode; i++) {\n                dict[i] = [i];\n            }\n            dict[clearCode] = [];\n            dict[eoiCode] = null;\n\n        };\n\n        var code;\n        var last;\n\n        var counter = 0;\n\n        while (true) {\n            //console.log(counter)\n            if(counter > 100000) break;\n            counter++;\n\n            last = code;\n            code = readCode(codeSize);\n\n            if (code === clearCode) {\n                clear();\n                continue;\n            }\n            if (code === eoiCode) break;\n\n            if (code < dict.length) {\n                if (last !== clearCode) {\n                    dict.push(dict[last].concat(dict[code][0]));\n                }\n            }\n            else {\n                if (code !== dict.length) throw new Error('Invalid LZW code.');\n                dict.push(dict[last].concat(dict[last][0]));\n            }\n            output.push.apply(output, dict[code]);\n\n            if (dict.length === (1 << codeSize) && codeSize < 12) {\n                // If we're at the last code and codeSize is 12, the next code will be a clearCode, and it'll be 12 bits long.\n                codeSize++;\n            }\n        }\n\n        // I don't know if this is technically an error, but some GIFs do it.\n        //if (Math.ceil(pos / 8) !== data.length) throw new Error('Extraneous LZW bytes.');\n        return output;\n    };\n\n\n    // The actual parsing; returns an object with properties.\n    var parseGIF = function (st, handler) {\n        handler || (handler = {});\n\n        // LZW (GIF-specific)\n        var parseCT = function (entries) { // Each entry is 3 bytes, for RGB.\n            var ct = [];\n            for (var i = 0; i < entries; i++) {\n                ct.push(st.readBytes(3));\n            }\n            return ct;\n        };\n\n        var readSubBlocks = function () {\n            var size, data;\n            data = '';\n            do {\n                size = st.readByte();\n                data += st.read(size);\n            } while (size !== 0);\n            return data;\n        };\n\n        var parseHeader = function () {\n            var hdr = {};\n            hdr.sig = st.read(3);\n            hdr.ver = st.read(3);\n            if (hdr.sig !== 'GIF') throw new Error('Not a GIF file.'); // XXX: This should probably be handled more nicely.\n            hdr.width = st.readUnsigned();\n            hdr.height = st.readUnsigned();\n\n            var bits = byteToBitArr(st.readByte());\n            hdr.gctFlag = bits.shift();\n            hdr.colorRes = bitsToNum(bits.splice(0, 3));\n            hdr.sorted = bits.shift();\n            hdr.gctSize = bitsToNum(bits.splice(0, 3));\n\n            hdr.bgColor = st.readByte();\n            hdr.pixelAspectRatio = st.readByte(); // if not 0, aspectRatio = (pixelAspectRatio + 15) / 64\n            if (hdr.gctFlag) {\n                hdr.gct = parseCT(1 << (hdr.gctSize + 1));\n            }\n            handler.hdr && handler.hdr(hdr);\n        };\n\n        var parseExt = function (block) {\n            var parseGCExt = function (block) {\n                var blockSize = st.readByte(); // Always 4\n                var bits = byteToBitArr(st.readByte());\n                block.reserved = bits.splice(0, 3); // Reserved; should be 000.\n                block.disposalMethod = bitsToNum(bits.splice(0, 3));\n                block.userInput = bits.shift();\n                block.transparencyGiven = bits.shift();\n\n                block.delayTime = st.readUnsigned();\n\n                block.transparencyIndex = st.readByte();\n\n                block.terminator = st.readByte();\n\n                handler.gce && handler.gce(block);\n            };\n\n            var parseComExt = function (block) {\n                block.comment = readSubBlocks();\n                handler.com && handler.com(block);\n            };\n\n            var parsePTExt = function (block) {\n                // No one *ever* uses this. If you use it, deal with parsing it yourself.\n                var blockSize = st.readByte(); // Always 12\n                block.ptHeader = st.readBytes(12);\n                block.ptData = readSubBlocks();\n                handler.pte && handler.pte(block);\n            };\n\n            var parseAppExt = function (block) {\n                var parseNetscapeExt = function (block) {\n                    var blockSize = st.readByte(); // Always 3\n                    block.unknown = st.readByte(); // ??? Always 1? What is this?\n                    block.iterations = st.readUnsigned();\n                    block.terminator = st.readByte();\n                    handler.app && handler.app.NETSCAPE && handler.app.NETSCAPE(block);\n                };\n\n                var parseUnknownAppExt = function (block) {\n                    block.appData = readSubBlocks();\n                    // FIXME: This won't work if a handler wants to match on any identifier.\n                    handler.app && handler.app[block.identifier] && handler.app[block.identifier](block);\n                };\n\n                var blockSize = st.readByte(); // Always 11\n                block.identifier = st.read(8);\n                block.authCode = st.read(3);\n                switch (block.identifier) {\n                    case 'NETSCAPE':\n                        parseNetscapeExt(block);\n                        break;\n                    default:\n                        parseUnknownAppExt(block);\n                        break;\n                }\n            };\n\n            var parseUnknownExt = function (block) {\n                block.data = readSubBlocks();\n                handler.unknown && handler.unknown(block);\n            };\n\n            block.label = st.readByte();\n            switch (block.label) {\n                case 0xF9:\n                    block.extType = 'gce';\n                    parseGCExt(block);\n                    break;\n                case 0xFE:\n                    block.extType = 'com';\n                    parseComExt(block);\n                    break;\n                case 0x01:\n                    block.extType = 'pte';\n                    parsePTExt(block);\n                    break;\n                case 0xFF:\n                    block.extType = 'app';\n                    parseAppExt(block);\n                    break;\n                default:\n                    block.extType = 'unknown';\n                    parseUnknownExt(block);\n                    break;\n            }\n        };\n\n        var parseImg = function (img) {\n            var deinterlace = function (pixels, width) {\n                // Of course this defeats the purpose of interlacing. And it's *probably*\n                // the least efficient way it's ever been implemented. But nevertheless...\n                var newPixels = new Array(pixels.length);\n                var rows = pixels.length / width;\n                var cpRow = function (toRow, fromRow) {\n                    var fromPixels = pixels.slice(fromRow * width, (fromRow + 1) * width);\n                    newPixels.splice.apply(newPixels, [toRow * width, width].concat(fromPixels));\n                };\n\n                // See appendix E.\n                var offsets = [0, 4, 2, 1];\n                var steps = [8, 8, 4, 2];\n\n                var fromRow = 0;\n                for (var pass = 0; pass < 4; pass++) {\n                    for (var toRow = offsets[pass]; toRow < rows; toRow += steps[pass]) {\n                        cpRow(toRow, fromRow)\n                        fromRow++;\n                    }\n                }\n\n                return newPixels;\n            };\n\n            img.leftPos = st.readUnsigned();\n            img.topPos = st.readUnsigned();\n            img.width = st.readUnsigned();\n            img.height = st.readUnsigned();\n\n            var bits = byteToBitArr(st.readByte());\n            img.lctFlag = bits.shift();\n            img.interlaced = bits.shift();\n            img.sorted = bits.shift();\n            img.reserved = bits.splice(0, 2);\n            img.lctSize = bitsToNum(bits.splice(0, 3));\n\n            if (img.lctFlag) {\n                img.lct = parseCT(1 << (img.lctSize + 1));\n            }\n\n            img.lzwMinCodeSize = st.readByte();\n\n            var lzwData = readSubBlocks();\n\n            img.pixels = lzwDecode(img.lzwMinCodeSize, lzwData);\n\n            if (img.interlaced) { // Move\n                img.pixels = deinterlace(img.pixels, img.width);\n            }\n\n            handler.img && handler.img(img);\n        };\n\n        var parseBlock = function () {\n            var block = {};\n            block.sentinel = st.readByte();\n\n            switch (String.fromCharCode(block.sentinel)) { // For ease of matching\n                case '!':\n                    block.type = 'ext';\n                    parseExt(block);\n                    break;\n                case ',':\n                    block.type = 'img';\n                    parseImg(block);\n                    break;\n                case ';':\n                    block.type = 'eof';\n                    handler.eof && handler.eof(block);\n                    break;\n                default:\n                    throw new Error('Unknown block: 0x' + block.sentinel.toString(16)); // TODO: Pad this with a 0.\n            }\n\n            if (block.type !== 'eof') setTimeout(parseBlock, 0);\n        };\n\n        var parse = function () {\n            parseHeader();\n            setTimeout(parseBlock, 0);\n        };\n\n        parse();\n    };\n\n    var SuperGif = function ( opts ) {\n        var options = {\n            //viewport position\n            vp_l: 0,\n            vp_t: 0,\n            vp_w: null,\n            vp_h: null,\n            //canvas sizes\n            c_w: null,\n            c_h: null\n        };\n        for (var i in opts ) { options[i] = opts[i] }\n        if (options.vp_w && options.vp_h) options.is_vp = true;\n\n        var stream;\n        var hdr;\n\n        var loadError = null;\n        var loading = false;\n\n        var transparency = null;\n        var delay = null;\n        var disposalMethod = null;\n        var disposalRestoreFromIdx = null;\n        var lastDisposalMethod = null;\n        var frame = null;\n        var lastImg = null;\n\n        var playing = true;\n        var forward = true;\n\n        var ctx_scaled = false;\n\n        var frames = [];\n        var frameOffsets = []; // elements have .x and .y properties\n\n        var gif = options.gif;\n        if (typeof options.auto_play == 'undefined')\n            options.auto_play = (!gif.getAttribute('rel:auto_play') || gif.getAttribute('rel:auto_play') == '1');\n\n        var onEndListener = (options.hasOwnProperty('on_end') ? options.on_end : null);\n        var loopDelay = (options.hasOwnProperty('loop_delay') ? options.loop_delay : 0);\n        var overrideLoopMode = (options.hasOwnProperty('loop_mode') ? options.loop_mode : 'auto');\n        var drawWhileLoading = (options.hasOwnProperty('draw_while_loading') ? options.draw_while_loading : true);\n        var showProgressBar = drawWhileLoading ? (options.hasOwnProperty('show_progress_bar') ? options.show_progress_bar : true) : false;\n        var progressBarHeight = (options.hasOwnProperty('progressbar_height') ? options.progressbar_height : 25);\n        var progressBarBackgroundColor = (options.hasOwnProperty('progressbar_background_color') ? options.progressbar_background_color : 'rgba(255,255,255,0.4)');\n        var progressBarForegroundColor = (options.hasOwnProperty('progressbar_foreground_color') ? options.progressbar_foreground_color : 'rgba(255,0,22,.8)');\n\n        var clear = function () {\n            transparency = null;\n            delay = null;\n            lastDisposalMethod = disposalMethod;\n            disposalMethod = null;\n            frame = null;\n        };\n\n        // XXX: There's probably a better way to handle catching exceptions when\n        // callbacks are involved.\n        var doParse = function () {\n            try {\n                parseGIF(stream, handler);\n            }\n            catch (err) {\n                doLoadError('parse');\n            }\n        };\n\n        var doText = function (text) {\n            toolbar.innerHTML = text; // innerText? Escaping? Whatever.\n            toolbar.style.visibility = 'visible';\n        };\n\n        var setSizes = function(w, h) {\n            canvas.width = w * get_canvas_scale();\n            canvas.height = h * get_canvas_scale();\n            toolbar.style.minWidth = ( w * get_canvas_scale() ) + 'px';\n\n            tmpCanvas.width = w;\n            tmpCanvas.height = h;\n            tmpCanvas.style.width = w + 'px';\n            tmpCanvas.style.height = h + 'px';\n            tmpCanvas.getContext('2d').setTransform(1, 0, 0, 1, 0, 0);\n        };\n\n        var setFrameOffset = function(frame, offset) {\n            if (!frameOffsets[frame]) {\n                frameOffsets[frame] = offset;\n                return;\n            }\n            if (typeof offset.x !== 'undefined') {\n                frameOffsets[frame].x = offset.x;\n            }\n            if (typeof offset.y !== 'undefined') {\n                frameOffsets[frame].y = offset.y;\n            }\n        };\n\n        var doShowProgress = function (pos, length, draw) {\n            if (draw && showProgressBar) {\n                var height = progressBarHeight;\n                var left, mid, top, width;\n                if (options.is_vp) {\n                    if (!ctx_scaled) {\n                        top = (options.vp_t + options.vp_h - height);\n                        height = height;\n                        left = options.vp_l;\n                        mid = left + (pos / length) * options.vp_w;\n                        width = canvas.width;\n                    } else {\n                        top = (options.vp_t + options.vp_h - height) / get_canvas_scale();\n                        height = height / get_canvas_scale();\n                        left = (options.vp_l / get_canvas_scale() );\n                        mid = left + (pos / length) * (options.vp_w / get_canvas_scale());\n                        width = canvas.width / get_canvas_scale();\n                    }\n                    //some debugging, draw rect around viewport\n                    if (false) {\n                        if (!ctx_scaled) {\n                            var l = options.vp_l, t = options.vp_t;\n                            var w = options.vp_w, h = options.vp_h;\n                        } else {\n                            var l = options.vp_l/get_canvas_scale(), t = options.vp_t/get_canvas_scale();\n                            var w = options.vp_w/get_canvas_scale(), h = options.vp_h/get_canvas_scale();\n                        }\n                        ctx.rect(l,t,w,h);\n                        ctx.stroke();\n                    }\n                }\n                else {\n                    top = (canvas.height - height) / (ctx_scaled ? get_canvas_scale() : 1);\n                    mid = ((pos / length) * canvas.width) / (ctx_scaled ? get_canvas_scale() : 1);\n                    width = canvas.width / (ctx_scaled ? get_canvas_scale() : 1 );\n                    height /= ctx_scaled ? get_canvas_scale() : 1;\n                }\n\n                ctx.fillStyle = progressBarBackgroundColor;\n                ctx.fillRect(mid, top, width - mid, height);\n\n                ctx.fillStyle = progressBarForegroundColor;\n                ctx.fillRect(0, top, mid, height);\n            }\n        };\n\n        var doLoadError = function (originOfError) {\n            var drawError = function () {\n                ctx.fillStyle = 'black';\n                ctx.fillRect(0, 0, options.c_w ? options.c_w : hdr.width, options.c_h ? options.c_h : hdr.height);\n                ctx.strokeStyle = 'red';\n                ctx.lineWidth = 3;\n                ctx.moveTo(0, 0);\n                ctx.lineTo(options.c_w ? options.c_w : hdr.width, options.c_h ? options.c_h : hdr.height);\n                ctx.moveTo(0, options.c_h ? options.c_h : hdr.height);\n                ctx.lineTo(options.c_w ? options.c_w : hdr.width, 0);\n                ctx.stroke();\n            };\n\n            loadError = originOfError;\n            hdr = {\n                width: gif.width,\n                height: gif.height\n            }; // Fake header.\n            frames = [];\n            drawError();\n        };\n\n        var doHdr = function (_hdr) {\n            hdr = _hdr;\n            setSizes(hdr.width, hdr.height)\n        };\n\n        var doGCE = function (gce) {\n            pushFrame();\n            clear();\n            transparency = gce.transparencyGiven ? gce.transparencyIndex : null;\n            delay = gce.delayTime;\n            disposalMethod = gce.disposalMethod;\n            // We don't have much to do with the rest of GCE.\n        };\n\n        var pushFrame = function () {\n            if (!frame) return;\n            frames.push({\n                            data: frame.getImageData(0, 0, hdr.width, hdr.height),\n                            delay: delay\n                        });\n            frameOffsets.push({ x: 0, y: 0 });\n        };\n\n        var doImg = function (img) {\n            if (!frame) frame = tmpCanvas.getContext('2d');\n\n            var currIdx = frames.length;\n\n            //ct = color table, gct = global color table\n            var ct = img.lctFlag ? img.lct : hdr.gct; // TODO: What if neither exists?\n\n            /*\n            Disposal method indicates the way in which the graphic is to\n            be treated after being displayed.\n\n            Values :    0 - No disposal specified. The decoder is\n                            not required to take any action.\n                        1 - Do not dispose. The graphic is to be left\n                            in place.\n                        2 - Restore to background color. The area used by the\n                            graphic must be restored to the background color.\n                        3 - Restore to previous. The decoder is required to\n                            restore the area overwritten by the graphic with\n                            what was there prior to rendering the graphic.\n\n                            Importantly, \"previous\" means the frame state\n                            after the last disposal of method 0, 1, or 2.\n            */\n            if (currIdx > 0) {\n                if (lastDisposalMethod === 3) {\n                    // Restore to previous\n                    // If we disposed every frame including first frame up to this point, then we have\n                    // no composited frame to restore to. In this case, restore to background instead.\n                    if (disposalRestoreFromIdx !== null) {\n                    \tframe.putImageData(frames[disposalRestoreFromIdx].data, 0, 0);\n                    } else {\n                    \tframe.clearRect(lastImg.leftPos, lastImg.topPos, lastImg.width, lastImg.height);\n                    }\n                } else {\n                    disposalRestoreFromIdx = currIdx - 1;\n                }\n\n                if (lastDisposalMethod === 2) {\n                    // Restore to background color\n                    // Browser implementations historically restore to transparent; we do the same.\n                    // http://www.wizards-toolkit.org/discourse-server/viewtopic.php?f=1&t=21172#p86079\n                    frame.clearRect(lastImg.leftPos, lastImg.topPos, lastImg.width, lastImg.height);\n                }\n            }\n            // else, Undefined/Do not dispose.\n            // frame contains final pixel data from the last frame; do nothing\n\n            //Get existing pixels for img region after applying disposal method\n            var imgData = frame.getImageData(img.leftPos, img.topPos, img.width, img.height);\n\n            //apply color table colors\n            img.pixels.forEach(function (pixel, i) {\n                // imgData.data === [R,G,B,A,R,G,B,A,...]\n                if (pixel !== transparency) {\n                    imgData.data[i * 4 + 0] = ct[pixel][0];\n                    imgData.data[i * 4 + 1] = ct[pixel][1];\n                    imgData.data[i * 4 + 2] = ct[pixel][2];\n                    imgData.data[i * 4 + 3] = 255; // Opaque.\n                }\n            });\n\n            frame.putImageData(imgData, img.leftPos, img.topPos);\n\n            if (!ctx_scaled) {\n                ctx.scale(get_canvas_scale(),get_canvas_scale());\n                ctx_scaled = true;\n            }\n\n            // We could use the on-page canvas directly, except that we draw a progress\n            // bar for each image chunk (not just the final image).\n            if (drawWhileLoading) {\n                ctx.drawImage(tmpCanvas, 0, 0);\n                drawWhileLoading = options.auto_play;\n            }\n\n            lastImg = img;\n        };\n\n        var player = (function () {\n            var i = -1;\n            var iterationCount = 0;\n\n            var showingInfo = false;\n            var pinned = false;\n\n            /**\n             * Gets the index of the frame \"up next\".\n             * @returns {number}\n             */\n            var getNextFrameNo = function () {\n                var delta = (forward ? 1 : -1);\n                return (i + delta + frames.length) % frames.length;\n            };\n\n            var stepFrame = function (amount) { // XXX: Name is confusing.\n                i = i + amount;\n\n                putFrame();\n            };\n\n            var step = (function () {\n                var stepping = false;\n\n                var completeLoop = function () {\n                    if (onEndListener !== null)\n                        onEndListener(gif);\n                    iterationCount++;\n\n                    if (overrideLoopMode !== false || iterationCount < 0) {\n                        doStep();\n                    } else {\n                        stepping = false;\n                        playing = false;\n                    }\n                };\n\n                var doStep = function () {\n                    stepping = playing;\n                    if (!stepping) return;\n\n                    stepFrame(1);\n                    var delay = frames[i].delay * 10;\n                    if (!delay) delay = 100; // FIXME: Should this even default at all? What should it be?\n\n                    var nextFrameNo = getNextFrameNo();\n                    if (nextFrameNo === 0) {\n                        delay += loopDelay;\n                        setTimeout(completeLoop, delay);\n                    } else {\n                        setTimeout(doStep, delay);\n                    }\n                };\n\n                return function () {\n                    if (!stepping) setTimeout(doStep, 0);\n                };\n            }());\n\n            var putFrame = function () {\n                var offset;\n                i = parseInt(i, 10);\n\n                if (i > frames.length - 1){\n                    i = 0;\n                }\n\n                if (i < 0){\n                    i = 0;\n                }\n\n                offset = frameOffsets[i];\n\n                tmpCanvas.getContext(\"2d\").putImageData(frames[i].data, offset.x, offset.y);\n                ctx.globalCompositeOperation = \"copy\";\n                ctx.drawImage(tmpCanvas, 0, 0);\n            };\n\n            var play = function () {\n                playing = true;\n                step();\n            };\n\n            var pause = function () {\n                playing = false;\n            };\n\n\n            return {\n                init: function () {\n                    if (loadError) return;\n\n                    if ( ! (options.c_w && options.c_h) ) {\n                        ctx.scale(get_canvas_scale(),get_canvas_scale());\n                    }\n\n                    if (options.auto_play) {\n                        step();\n                    }\n                    else {\n                        i = 0;\n                        putFrame();\n                    }\n                },\n                step: step,\n                play: play,\n                pause: pause,\n                playing: playing,\n                move_relative: stepFrame,\n                current_frame: function() { return i; },\n                length: function() { return frames.length },\n                move_to: function ( frame_idx ) {\n                    i = frame_idx;\n                    putFrame();\n                }\n            }\n        }());\n\n        var doDecodeProgress = function (draw) {\n            doShowProgress(stream.pos, stream.data.length, draw);\n        };\n\n        var doNothing = function () {};\n        /**\n         * @param{boolean=} draw Whether to draw progress bar or not; this is not idempotent because of translucency.\n         *                       Note that this means that the text will be unsynchronized with the progress bar on non-frames;\n         *                       but those are typically so small (GCE etc.) that it doesn't really matter. TODO: Do this properly.\n         */\n        var withProgress = function (fn, draw) {\n            return function (block) {\n                fn(block);\n                doDecodeProgress(draw);\n            };\n        };\n\n\n        var handler = {\n            hdr: withProgress(doHdr),\n            gce: withProgress(doGCE),\n            com: withProgress(doNothing),\n            // I guess that's all for now.\n            app: {\n                // TODO: Is there much point in actually supporting iterations?\n                NETSCAPE: withProgress(doNothing)\n            },\n            img: withProgress(doImg, true),\n            eof: function (block) {\n                //toolbar.style.display = '';\n                pushFrame();\n                doDecodeProgress(false);\n                if ( ! (options.c_w && options.c_h) ) {\n                    canvas.width = hdr.width * get_canvas_scale();\n                    canvas.height = hdr.height * get_canvas_scale();\n                }\n                player.init();\n                loading = false;\n                if (load_callback) {\n                    load_callback(gif);\n                }\n\n            }\n        };\n\n        var init = function () {\n            var parent = gif.parentNode;\n\n            var div = document.createElement('div');\n            canvas = document.createElement('canvas');\n            ctx = canvas.getContext('2d');\n            toolbar = document.createElement('div');\n\n            tmpCanvas = document.createElement('canvas');\n\n            div.width = canvas.width = gif.width;\n            div.height = canvas.height = gif.height;\n            toolbar.style.minWidth = gif.width + 'px';\n\n            div.className = 'jsgif';\n            toolbar.className = 'jsgif_toolbar';\n            //div.appendChild(canvas);  //zrispo - dont need this\n            //div.appendChild(toolbar); //zrispo - dont need this\n\n            parent.insertBefore(div, gif);\n            parent.removeChild(gif);\n\n            if (options.c_w && options.c_h) setSizes(options.c_w, options.c_h);\n            initialized=true;\n        };\n\n        var get_canvas_scale = function() {\n            var scale;\n            if (options.max_width && hdr && hdr.width > options.max_width) {\n                scale = options.max_width / hdr.width;\n            }\n            else {\n                scale = 1;\n            }\n            return scale;\n        }\n\n        var canvas, ctx, toolbar, tmpCanvas;\n        var initialized = false;\n        var load_callback = false;\n\n        var load_setup = function(callback) {\n            if (loading) return false;\n            if (callback) load_callback = callback;\n            else load_callback = false;\n\n            loading = true;\n            frames = [];\n            clear();\n            disposalRestoreFromIdx = null;\n            lastDisposalMethod = null;\n            frame = null;\n            lastImg = null;\n\n            return true;\n        }\n\n        return {\n            // play controls\n            play: player.play,\n            pause: player.pause,\n            move_relative: player.move_relative,\n            move_to: player.move_to,\n\n            // getters for instance vars\n            get_playing      : function() { return playing },\n            get_canvas       : function() { return canvas },\n            get_canvas_scale : function() { return get_canvas_scale() },\n            get_loading      : function() { return loading },\n            get_auto_play    : function() { return options.auto_play },\n            get_length       : function() { return player.length() },\n            get_current_frame: function() { return player.current_frame() },\n            load_url: function(src,callback){\n                if (!load_setup(callback)) return;\n\n                var h = new XMLHttpRequest();\n                // new browsers (XMLHttpRequest2-compliant)\n                h.open('GET', src, true);\n\n                if ('overrideMimeType' in h) {\n                    h.overrideMimeType('text/plain; charset=x-user-defined');\n                }\n\n                // old browsers (XMLHttpRequest-compliant)\n                else if ('responseType' in h) {\n                    h.responseType = 'arraybuffer';\n                }\n\n                // IE9 (Microsoft.XMLHTTP-compliant)\n                else {\n                    h.setRequestHeader('Accept-Charset', 'x-user-defined');\n                }\n\n                h.onloadstart = function() {\n                    // Wait until connection is opened to replace the gif element with a canvas to avoid a blank img\n                    if (!initialized) init();\n                };\n                h.onload = function(e) {\n                    if (this.status != 200) {\n                        doLoadError('xhr - response');\n                    }\n                    // emulating response field for IE9\n                    if (!('response' in this)) {\n                        this.response = new VBArray(this.responseText).toArray().map(String.fromCharCode).join('');\n                    }\n                    var data = this.response;\n                    if (data.toString().indexOf(\"ArrayBuffer\") > 0) {\n                        data = new Uint8Array(data);\n                    }\n\n                    stream = new Stream(data);\n                    setTimeout(doParse, 0);\n                };\n                h.onprogress = function (e) {\n                    if (e.lengthComputable) doShowProgress(e.loaded, e.total, true);\n                };\n                h.onerror = function() { doLoadError('xhr'); };\n                h.send();\n            },\n            load: function (callback) {\n                this.load_url(gif.getAttribute('rel:animated_src') || gif.src,callback);\n            },\n            load_raw: function(arr, callback) {\n                if (!load_setup(callback)) return;\n                if (!initialized) init();\n                stream = new Stream(arr);\n                setTimeout(doParse, 0);\n            },\n\n            // Added by zrispo to get frames outta the gif\n            getFrameDataURLs: function () {\n                var frameDataURLs = [];\n                for(var i = 0; i < frames.length; i++) {\n                    var offset = frameOffsets[i];\n                    tmpCanvas.getContext(\"2d\").putImageData(frames[i].data, offset.x, offset.y);\n                    frameDataURLs.push(tmpCanvas.toDataURL())\n                }\n                return frameDataURLs;\n            },\n            set_frame_offset: setFrameOffset\n        };\n    };\n\n    return SuperGif;\n}));\n\n\n"
  },
  {
    "path": "lib/localstoragewrapper.js",
    "content": "window.saveData = function (key, data) {\n\tif(!localStorage.savedData) \n\t\tlocalStorage.savedData = JSON.stringify({});\n\n\tvar savedData = JSON.parse(localStorage.savedData)\n\tvar type = typeof data;\n\tsavedData[key] = {\n\t\ttype: type,\n\t\tdata: (type === 'object') ? JSON.stringify(data) : data\n\t};\n\tlocalStorage.savedData = JSON.stringify(savedData);\n}\n\nwindow.getData = function (key) {\n\tvar savedData = JSON.parse(localStorage.savedData)\n\tif(savedData[key] !== undefined) {\n\t\tvar value = savedData[key];\n\t\tif(value.type === 'number') {\n\t\t\treturn parseFloat(value.data)\n\t\t} else if (value.type === 'string') {\n\t\t\treturn value.data;\n\t\t} else if (value.type === 'object') {\n\t\t\treturn JSON.parse(value.data);\n\t\t}\n\t} else {\n\t\tthrow (new Error(key + \" does not exist in saved data.\"))\n\t}\n}\n"
  },
  {
    "path": "lib/nouislider.css",
    "content": "/*! nouislider - 9.2.0 - 2017-01-11 10:35:35 */\n/* Functional styling;\n * These styles are required for noUiSlider to function.\n * You don't need to change these rules to apply your design.\n */\n.noUi-target,\n.noUi-target * {\n  -webkit-touch-callout: none;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n  -webkit-user-select: none;\n  -ms-touch-action: none;\n  touch-action: none;\n  -ms-user-select: none;\n  -moz-user-select: none;\n  user-select: none;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\n.noUi-target {\n  position: relative;\n  direction: ltr;\n}\n.noUi-base {\n  width: 100%;\n  height: 100%;\n  position: relative;\n  z-index: 1;\n  /* Fix 401 */\n}\n.noUi-connect {\n  position: absolute;\n  right: 0;\n  top: 0;\n  left: 0;\n  bottom: 0;\n}\n.noUi-origin {\n  position: absolute;\n  height: 0;\n  width: 0;\n}\n.noUi-handle {\n  position: relative;\n  z-index: 1;\n}\n.noUi-state-tap .noUi-connect,\n.noUi-state-tap .noUi-origin {\n  -webkit-transition: top 0.3s, right 0.3s, bottom 0.3s, left 0.3s;\n  transition: top 0.3s, right 0.3s, bottom 0.3s, left 0.3s;\n}\n.noUi-state-drag * {\n  cursor: inherit !important;\n}\n/* Painting and performance;\n * Browsers can paint handles in their own layer.\n */\n.noUi-base,\n.noUi-handle {\n  -webkit-transform: translate3d(0, 0, 0);\n  transform: translate3d(0, 0, 0);\n}\n/* Slider size and handle placement;\n */\n.noUi-horizontal {\n  height: 18px;\n}\n.noUi-horizontal .noUi-handle {\n  width: 34px;\n  height: 28px;\n  left: -17px;\n  top: -6px;\n}\n.noUi-vertical {\n  width: 18px;\n}\n.noUi-vertical .noUi-handle {\n  width: 28px;\n  height: 34px;\n  left: -6px;\n  top: -17px;\n}\n/* Styling;\n */\n.noUi-target {\n  background: #FAFAFA;\n  border-radius: 4px;\n  border: 1px solid #D3D3D3;\n  box-shadow: inset 0 1px 1px #F0F0F0, 0 3px 6px -5px #BBB;\n}\n.noUi-connect {\n  background: #3FB8AF;\n  box-shadow: inset 0 0 3px rgba(51, 51, 51, 0.45);\n  -webkit-transition: background 450ms;\n  transition: background 450ms;\n}\n/* Handles and cursors;\n */\n.noUi-draggable {\n  cursor: ew-resize;\n}\n.noUi-vertical .noUi-draggable {\n  cursor: ns-resize;\n}\n.noUi-handle {\n  border: 1px solid #D9D9D9;\n  border-radius: 3px;\n  background: #FFF;\n  cursor: default;\n  box-shadow: inset 0 0 1px #FFF, inset 0 1px 7px #EBEBEB, 0 3px 6px -3px #BBB;\n}\n.noUi-active {\n  box-shadow: inset 0 0 1px #FFF, inset 0 1px 7px #DDD, 0 3px 6px -3px #BBB;\n}\n/* Handle stripes;\n */\n.noUi-handle:before,\n.noUi-handle:after {\n  content: \"\";\n  display: block;\n  position: absolute;\n  height: 14px;\n  width: 1px;\n  background: #E8E7E6;\n  left: 14px;\n  top: 6px;\n}\n.noUi-handle:after {\n  left: 17px;\n}\n.noUi-vertical .noUi-handle:before,\n.noUi-vertical .noUi-handle:after {\n  width: 14px;\n  height: 1px;\n  left: 6px;\n  top: 14px;\n}\n.noUi-vertical .noUi-handle:after {\n  top: 17px;\n}\n/* Disabled state;\n */\n[disabled] .noUi-connect {\n  background: #B8B8B8;\n}\n[disabled].noUi-target,\n[disabled].noUi-handle,\n[disabled] .noUi-handle {\n  cursor: not-allowed;\n}\n/* Base;\n *\n */\n.noUi-pips,\n.noUi-pips * {\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\n.noUi-pips {\n  position: absolute;\n  color: #999;\n}\n/* Values;\n *\n */\n.noUi-value {\n  position: absolute;\n  text-align: center;\n}\n.noUi-value-sub {\n  color: #ccc;\n  font-size: 10px;\n}\n/* Markings;\n *\n */\n.noUi-marker {\n  position: absolute;\n  background: #CCC;\n}\n.noUi-marker-sub {\n  background: #AAA;\n}\n.noUi-marker-large {\n  background: #AAA;\n}\n/* Horizontal layout;\n *\n */\n.noUi-pips-horizontal {\n  padding: 10px 0;\n  height: 80px;\n  top: 100%;\n  left: 0;\n  width: 100%;\n}\n.noUi-value-horizontal {\n  -webkit-transform: translate3d(-50%, 50%, 0);\n  transform: translate3d(-50%, 50%, 0);\n}\n.noUi-marker-horizontal.noUi-marker {\n  margin-left: -1px;\n  width: 2px;\n  height: 5px;\n}\n.noUi-marker-horizontal.noUi-marker-sub {\n  height: 10px;\n}\n.noUi-marker-horizontal.noUi-marker-large {\n  height: 15px;\n}\n/* Vertical layout;\n *\n */\n.noUi-pips-vertical {\n  padding: 0 10px;\n  height: 100%;\n  top: 0;\n  left: 100%;\n}\n.noUi-value-vertical {\n  -webkit-transform: translate3d(0, 50%, 0);\n  transform: translate3d(0, 50%, 0);\n  padding-left: 25px;\n}\n.noUi-marker-vertical.noUi-marker {\n  width: 5px;\n  height: 2px;\n  margin-top: -1px;\n}\n.noUi-marker-vertical.noUi-marker-sub {\n  width: 10px;\n}\n.noUi-marker-vertical.noUi-marker-large {\n  width: 15px;\n}\n.noUi-tooltip {\n  display: block;\n  position: absolute;\n  border: 1px solid #D9D9D9;\n  border-radius: 3px;\n  background: #fff;\n  color: #000;\n  padding: 5px;\n  text-align: center;\n}\n.noUi-horizontal .noUi-tooltip {\n  -webkit-transform: translate(-50%, 0);\n  transform: translate(-50%, 0);\n  left: 50%;\n  bottom: 120%;\n}\n.noUi-vertical .noUi-tooltip {\n  -webkit-transform: translate(0, -50%);\n  transform: translate(0, -50%);\n  top: 50%;\n  right: 120%;\n}\n"
  },
  {
    "path": "lib/nouislider.js",
    "content": "/*! nouislider - 9.2.0 - 2017-01-11 10:35:34 */\r\n\r\n(function (factory) {\r\n\r\n    if ( typeof define === 'function' && define.amd ) {\r\n\r\n        // AMD. Register as an anonymous module.\r\n        define([], factory);\r\n\r\n    } else if ( typeof exports === 'object' ) {\r\n\r\n        // Node/CommonJS\r\n        module.exports = factory();\r\n\r\n    } else {\r\n\r\n        // Browser globals\r\n        window.noUiSlider = factory();\r\n    }\r\n\r\n}(function( ){\r\n\r\n\t'use strict';\r\n\r\n\tvar VERSION = '9.2.0';\r\n\r\n\r\n\t// Creates a node, adds it to target, returns the new node.\r\n\tfunction addNodeTo ( target, className ) {\r\n\t\tvar div = document.createElement('div');\r\n\t\taddClass(div, className);\r\n\t\ttarget.appendChild(div);\r\n\t\treturn div;\r\n\t}\r\n\r\n\t// Removes duplicates from an array.\r\n\tfunction unique ( array ) {\r\n\t\treturn array.filter(function(a){\r\n\t\t\treturn !this[a] ? this[a] = true : false;\r\n\t\t}, {});\r\n\t}\r\n\r\n\t// Round a value to the closest 'to'.\r\n\tfunction closest ( value, to ) {\r\n\t\treturn Math.round(value / to) * to;\r\n\t}\r\n\r\n\t// Current position of an element relative to the document.\r\n\tfunction offset ( elem, orientation ) {\r\n\r\n\tvar rect = elem.getBoundingClientRect(),\r\n\t\tdoc = elem.ownerDocument,\r\n\t\tdocElem = doc.documentElement,\r\n\t\tpageOffset = getPageOffset();\r\n\r\n\t\t// getBoundingClientRect contains left scroll in Chrome on Android.\r\n\t\t// I haven't found a feature detection that proves this. Worst case\r\n\t\t// scenario on mis-match: the 'tap' feature on horizontal sliders breaks.\r\n\t\tif ( /webkit.*Chrome.*Mobile/i.test(navigator.userAgent) ) {\r\n\t\t\tpageOffset.x = 0;\r\n\t\t}\r\n\r\n\t\treturn orientation ? (rect.top + pageOffset.y - docElem.clientTop) : (rect.left + pageOffset.x - docElem.clientLeft);\r\n\t}\r\n\r\n\t// Checks whether a value is numerical.\r\n\tfunction isNumeric ( a ) {\r\n\t\treturn typeof a === 'number' && !isNaN( a ) && isFinite( a );\r\n\t}\r\n\r\n\t// Sets a class and removes it after [duration] ms.\r\n\tfunction addClassFor ( element, className, duration ) {\r\n\t\tif (duration > 0) {\r\n\t\taddClass(element, className);\r\n\t\t\tsetTimeout(function(){\r\n\t\t\t\tremoveClass(element, className);\r\n\t\t\t}, duration);\r\n\t\t}\r\n\t}\r\n\r\n\t// Limits a value to 0 - 100\r\n\tfunction limit ( a ) {\r\n\t\treturn Math.max(Math.min(a, 100), 0);\r\n\t}\r\n\r\n\t// Wraps a variable as an array, if it isn't one yet.\r\n\t// Note that an input array is returned by reference!\r\n\tfunction asArray ( a ) {\r\n\t\treturn Array.isArray(a) ? a : [a];\r\n\t}\r\n\r\n\t// Counts decimals\r\n\tfunction countDecimals ( numStr ) {\r\n\t\tnumStr = String(numStr);\r\n\t\tvar pieces = numStr.split(\".\");\r\n\t\treturn pieces.length > 1 ? pieces[1].length : 0;\r\n\t}\r\n\r\n\t// http://youmightnotneedjquery.com/#add_class\r\n\tfunction addClass ( el, className ) {\r\n\t\tif ( el.classList ) {\r\n\t\t\tel.classList.add(className);\r\n\t\t} else {\r\n\t\t\tel.className += ' ' + className;\r\n\t\t}\r\n\t}\r\n\r\n\t// http://youmightnotneedjquery.com/#remove_class\r\n\tfunction removeClass ( el, className ) {\r\n\t\tif ( el.classList ) {\r\n\t\t\tel.classList.remove(className);\r\n\t\t} else {\r\n\t\t\tel.className = el.className.replace(new RegExp('(^|\\\\b)' + className.split(' ').join('|') + '(\\\\b|$)', 'gi'), ' ');\r\n\t\t}\r\n\t}\r\n\r\n\t// https://plainjs.com/javascript/attributes/adding-removing-and-testing-for-classes-9/\r\n\tfunction hasClass ( el, className ) {\r\n\t\treturn el.classList ? el.classList.contains(className) : new RegExp('\\\\b' + className + '\\\\b').test(el.className);\r\n\t}\r\n\r\n\t// https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY#Notes\r\n\tfunction getPageOffset ( ) {\r\n\r\n\t\tvar supportPageOffset = window.pageXOffset !== undefined,\r\n\t\t\tisCSS1Compat = ((document.compatMode || \"\") === \"CSS1Compat\"),\r\n\t\t\tx = supportPageOffset ? window.pageXOffset : isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft,\r\n\t\t\ty = supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;\r\n\r\n\t\treturn {\r\n\t\t\tx: x,\r\n\t\t\ty: y\r\n\t\t};\r\n\t}\r\n\r\n\t// we provide a function to compute constants instead\r\n\t// of accessing window.* as soon as the module needs it\r\n\t// so that we do not compute anything if not needed\r\n\tfunction getActions ( ) {\r\n\r\n\t\t// Determine the events to bind. IE11 implements pointerEvents without\r\n\t\t// a prefix, which breaks compatibility with the IE10 implementation.\r\n\t\treturn window.navigator.pointerEnabled ? {\r\n\t\t\tstart: 'pointerdown',\r\n\t\t\tmove: 'pointermove',\r\n\t\t\tend: 'pointerup'\r\n\t\t} : window.navigator.msPointerEnabled ? {\r\n\t\t\tstart: 'MSPointerDown',\r\n\t\t\tmove: 'MSPointerMove',\r\n\t\t\tend: 'MSPointerUp'\r\n\t\t} : {\r\n\t\t\tstart: 'mousedown touchstart',\r\n\t\t\tmove: 'mousemove touchmove',\r\n\t\t\tend: 'mouseup touchend'\r\n\t\t};\r\n\t}\r\n\r\n\r\n// Value calculation\r\n\r\n\t// Determine the size of a sub-range in relation to a full range.\r\n\tfunction subRangeRatio ( pa, pb ) {\r\n\t\treturn (100 / (pb - pa));\r\n\t}\r\n\r\n\t// (percentage) How many percent is this value of this range?\r\n\tfunction fromPercentage ( range, value ) {\r\n\t\treturn (value * 100) / ( range[1] - range[0] );\r\n\t}\r\n\r\n\t// (percentage) Where is this value on this range?\r\n\tfunction toPercentage ( range, value ) {\r\n\t\treturn fromPercentage( range, range[0] < 0 ?\r\n\t\t\tvalue + Math.abs(range[0]) :\r\n\t\t\t\tvalue - range[0] );\r\n\t}\r\n\r\n\t// (value) How much is this percentage on this range?\r\n\tfunction isPercentage ( range, value ) {\r\n\t\treturn ((value * ( range[1] - range[0] )) / 100) + range[0];\r\n\t}\r\n\r\n\r\n// Range conversion\r\n\r\n\tfunction getJ ( value, arr ) {\r\n\r\n\t\tvar j = 1;\r\n\r\n\t\twhile ( value >= arr[j] ){\r\n\t\t\tj += 1;\r\n\t\t}\r\n\r\n\t\treturn j;\r\n\t}\r\n\r\n\t// (percentage) Input a value, find where, on a scale of 0-100, it applies.\r\n\tfunction toStepping ( xVal, xPct, value ) {\r\n\r\n\t\tif ( value >= xVal.slice(-1)[0] ){\r\n\t\t\treturn 100;\r\n\t\t}\r\n\r\n\t\tvar j = getJ( value, xVal ), va, vb, pa, pb;\r\n\r\n\t\tva = xVal[j-1];\r\n\t\tvb = xVal[j];\r\n\t\tpa = xPct[j-1];\r\n\t\tpb = xPct[j];\r\n\r\n\t\treturn pa + (toPercentage([va, vb], value) / subRangeRatio (pa, pb));\r\n\t}\r\n\r\n\t// (value) Input a percentage, find where it is on the specified range.\r\n\tfunction fromStepping ( xVal, xPct, value ) {\r\n\r\n\t\t// There is no range group that fits 100\r\n\t\tif ( value >= 100 ){\r\n\t\t\treturn xVal.slice(-1)[0];\r\n\t\t}\r\n\r\n\t\tvar j = getJ( value, xPct ), va, vb, pa, pb;\r\n\r\n\t\tva = xVal[j-1];\r\n\t\tvb = xVal[j];\r\n\t\tpa = xPct[j-1];\r\n\t\tpb = xPct[j];\r\n\r\n\t\treturn isPercentage([va, vb], (value - pa) * subRangeRatio (pa, pb));\r\n\t}\r\n\r\n\t// (percentage) Get the step that applies at a certain value.\r\n\tfunction getStep ( xPct, xSteps, snap, value ) {\r\n\r\n\t\tif ( value === 100 ) {\r\n\t\t\treturn value;\r\n\t\t}\r\n\r\n\t\tvar j = getJ( value, xPct ), a, b;\r\n\r\n\t\t// If 'snap' is set, steps are used as fixed points on the slider.\r\n\t\tif ( snap ) {\r\n\r\n\t\t\ta = xPct[j-1];\r\n\t\t\tb = xPct[j];\r\n\r\n\t\t\t// Find the closest position, a or b.\r\n\t\t\tif ((value - a) > ((b-a)/2)){\r\n\t\t\t\treturn b;\r\n\t\t\t}\r\n\r\n\t\t\treturn a;\r\n\t\t}\r\n\r\n\t\tif ( !xSteps[j-1] ){\r\n\t\t\treturn value;\r\n\t\t}\r\n\r\n\t\treturn xPct[j-1] + closest(\r\n\t\t\tvalue - xPct[j-1],\r\n\t\t\txSteps[j-1]\r\n\t\t);\r\n\t}\r\n\r\n\r\n// Entry parsing\r\n\r\n\tfunction handleEntryPoint ( index, value, that ) {\r\n\r\n\t\tvar percentage;\r\n\r\n\t\t// Wrap numerical input in an array.\r\n\t\tif ( typeof value === \"number\" ) {\r\n\t\t\tvalue = [value];\r\n\t\t}\r\n\r\n\t\t// Reject any invalid input, by testing whether value is an array.\r\n\t\tif ( Object.prototype.toString.call( value ) !== '[object Array]' ){\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'range' contains invalid value.\");\r\n\t\t}\r\n\r\n\t\t// Covert min/max syntax to 0 and 100.\r\n\t\tif ( index === 'min' ) {\r\n\t\t\tpercentage = 0;\r\n\t\t} else if ( index === 'max' ) {\r\n\t\t\tpercentage = 100;\r\n\t\t} else {\r\n\t\t\tpercentage = parseFloat( index );\r\n\t\t}\r\n\r\n\t\t// Check for correct input.\r\n\t\tif ( !isNumeric( percentage ) || !isNumeric( value[0] ) ) {\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'range' value isn't numeric.\");\r\n\t\t}\r\n\r\n\t\t// Store values.\r\n\t\tthat.xPct.push( percentage );\r\n\t\tthat.xVal.push( value[0] );\r\n\r\n\t\t// NaN will evaluate to false too, but to keep\r\n\t\t// logging clear, set step explicitly. Make sure\r\n\t\t// not to override the 'step' setting with false.\r\n\t\tif ( !percentage ) {\r\n\t\t\tif ( !isNaN( value[1] ) ) {\r\n\t\t\t\tthat.xSteps[0] = value[1];\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tthat.xSteps.push( isNaN(value[1]) ? false : value[1] );\r\n\t\t}\r\n\r\n\t\tthat.xHighestCompleteStep.push(0);\r\n\t}\r\n\r\n\tfunction handleStepPoint ( i, n, that ) {\r\n\r\n\t\t// Ignore 'false' stepping.\r\n\t\tif ( !n ) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\t// Factor to range ratio\r\n\t\tthat.xSteps[i] = fromPercentage([\r\n\t\t\t that.xVal[i]\r\n\t\t\t,that.xVal[i+1]\r\n\t\t], n) / subRangeRatio (\r\n\t\t\tthat.xPct[i],\r\n\t\t\tthat.xPct[i+1] );\r\n\r\n\t\tvar totalSteps = (that.xVal[i+1] - that.xVal[i]) / that.xNumSteps[i];\r\n\t\tvar highestStep = Math.ceil(Number(totalSteps.toFixed(3)) - 1);\r\n\t\tvar step = that.xVal[i] + (that.xNumSteps[i] * highestStep);\r\n\r\n\t\tthat.xHighestCompleteStep[i] = step;\r\n\t}\r\n\r\n\r\n// Interface\r\n\r\n\t// The interface to Spectrum handles all direction-based\r\n\t// conversions, so the above values are unaware.\r\n\r\n\tfunction Spectrum ( entry, snap, direction, singleStep ) {\r\n\r\n\t\tthis.xPct = [];\r\n\t\tthis.xVal = [];\r\n\t\tthis.xSteps = [ singleStep || false ];\r\n\t\tthis.xNumSteps = [ false ];\r\n\t\tthis.xHighestCompleteStep = [];\r\n\r\n\t\tthis.snap = snap;\r\n\t\tthis.direction = direction;\r\n\r\n\t\tvar index, ordered = [ /* [0, 'min'], [1, '50%'], [2, 'max'] */ ];\r\n\r\n\t\t// Map the object keys to an array.\r\n\t\tfor ( index in entry ) {\r\n\t\t\tif ( entry.hasOwnProperty(index) ) {\r\n\t\t\t\tordered.push([entry[index], index]);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Sort all entries by value (numeric sort).\r\n\t\tif ( ordered.length && typeof ordered[0][0] === \"object\" ) {\r\n\t\t\tordered.sort(function(a, b) { return a[0][0] - b[0][0]; });\r\n\t\t} else {\r\n\t\t\tordered.sort(function(a, b) { return a[0] - b[0]; });\r\n\t\t}\r\n\r\n\r\n\t\t// Convert all entries to subranges.\r\n\t\tfor ( index = 0; index < ordered.length; index++ ) {\r\n\t\t\thandleEntryPoint(ordered[index][1], ordered[index][0], this);\r\n\t\t}\r\n\r\n\t\t// Store the actual step values.\r\n\t\t// xSteps is sorted in the same order as xPct and xVal.\r\n\t\tthis.xNumSteps = this.xSteps.slice(0);\r\n\r\n\t\t// Convert all numeric steps to the percentage of the subrange they represent.\r\n\t\tfor ( index = 0; index < this.xNumSteps.length; index++ ) {\r\n\t\t\thandleStepPoint(index, this.xNumSteps[index], this);\r\n\t\t}\r\n\t}\r\n\r\n\tSpectrum.prototype.getMargin = function ( value ) {\r\n\r\n\t\tvar step = this.xNumSteps[0];\r\n\r\n\t\tif ( step && ((value / step) % 1) !== 0 ) {\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'limit', 'margin' and 'padding' must be divisible by step.\");\r\n\t\t}\r\n\r\n\t\treturn this.xPct.length === 2 ? fromPercentage(this.xVal, value) : false;\r\n\t};\r\n\r\n\tSpectrum.prototype.toStepping = function ( value ) {\r\n\r\n\t\tvalue = toStepping( this.xVal, this.xPct, value );\r\n\r\n\t\treturn value;\r\n\t};\r\n\r\n\tSpectrum.prototype.fromStepping = function ( value ) {\r\n\r\n\t\treturn fromStepping( this.xVal, this.xPct, value );\r\n\t};\r\n\r\n\tSpectrum.prototype.getStep = function ( value ) {\r\n\r\n\t\tvalue = getStep(this.xPct, this.xSteps, this.snap, value );\r\n\r\n\t\treturn value;\r\n\t};\r\n\r\n\tSpectrum.prototype.getNearbySteps = function ( value ) {\r\n\r\n\t\tvar j = getJ(value, this.xPct);\r\n\r\n\t\treturn {\r\n\t\t\tstepBefore: { startValue: this.xVal[j-2], step: this.xNumSteps[j-2], highestStep: this.xHighestCompleteStep[j-2] },\r\n\t\t\tthisStep: { startValue: this.xVal[j-1], step: this.xNumSteps[j-1], highestStep: this.xHighestCompleteStep[j-1] },\r\n\t\t\tstepAfter: { startValue: this.xVal[j-0], step: this.xNumSteps[j-0], highestStep: this.xHighestCompleteStep[j-0] }\r\n\t\t};\r\n\t};\r\n\r\n\tSpectrum.prototype.countStepDecimals = function () {\r\n\t\tvar stepDecimals = this.xNumSteps.map(countDecimals);\r\n\t\treturn Math.max.apply(null, stepDecimals);\r\n \t};\r\n\r\n\t// Outside testing\r\n\tSpectrum.prototype.convert = function ( value ) {\r\n\t\treturn this.getStep(this.toStepping(value));\r\n\t};\r\n\r\n/*\tEvery input option is tested and parsed. This'll prevent\r\n\tendless validation in internal methods. These tests are\r\n\tstructured with an item for every option available. An\r\n\toption can be marked as required by setting the 'r' flag.\r\n\tThe testing function is provided with three arguments:\r\n\t\t- The provided value for the option;\r\n\t\t- A reference to the options object;\r\n\t\t- The name for the option;\r\n\r\n\tThe testing function returns false when an error is detected,\r\n\tor true when everything is OK. It can also modify the option\r\n\tobject, to make sure all values can be correctly looped elsewhere. */\r\n\r\n\tvar defaultFormatter = { 'to': function( value ){\r\n\t\treturn value !== undefined && value.toFixed(2);\r\n\t}, 'from': Number };\r\n\r\n\tfunction testStep ( parsed, entry ) {\r\n\r\n\t\tif ( !isNumeric( entry ) ) {\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'step' is not numeric.\");\r\n\t\t}\r\n\r\n\t\t// The step option can still be used to set stepping\r\n\t\t// for linear sliders. Overwritten if set in 'range'.\r\n\t\tparsed.singleStep = entry;\r\n\t}\r\n\r\n\tfunction testRange ( parsed, entry ) {\r\n\r\n\t\t// Filter incorrect input.\r\n\t\tif ( typeof entry !== 'object' || Array.isArray(entry) ) {\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'range' is not an object.\");\r\n\t\t}\r\n\r\n\t\t// Catch missing start or end.\r\n\t\tif ( entry.min === undefined || entry.max === undefined ) {\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): Missing 'min' or 'max' in 'range'.\");\r\n\t\t}\r\n\r\n\t\t// Catch equal start or end.\r\n\t\tif ( entry.min === entry.max ) {\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'range' 'min' and 'max' cannot be equal.\");\r\n\t\t}\r\n\r\n\t\tparsed.spectrum = new Spectrum(entry, parsed.snap, parsed.dir, parsed.singleStep);\r\n\t}\r\n\r\n\tfunction testStart ( parsed, entry ) {\r\n\r\n\t\tentry = asArray(entry);\r\n\r\n\t\t// Validate input. Values aren't tested, as the public .val method\r\n\t\t// will always provide a valid location.\r\n\t\tif ( !Array.isArray( entry ) || !entry.length ) {\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'start' option is incorrect.\");\r\n\t\t}\r\n\r\n\t\t// Store the number of handles.\r\n\t\tparsed.handles = entry.length;\r\n\r\n\t\t// When the slider is initialized, the .val method will\r\n\t\t// be called with the start options.\r\n\t\tparsed.start = entry;\r\n\t}\r\n\r\n\tfunction testSnap ( parsed, entry ) {\r\n\r\n\t\t// Enforce 100% stepping within subranges.\r\n\t\tparsed.snap = entry;\r\n\r\n\t\tif ( typeof entry !== 'boolean' ){\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'snap' option must be a boolean.\");\r\n\t\t}\r\n\t}\r\n\r\n\tfunction testAnimate ( parsed, entry ) {\r\n\r\n\t\t// Enforce 100% stepping within subranges.\r\n\t\tparsed.animate = entry;\r\n\r\n\t\tif ( typeof entry !== 'boolean' ){\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'animate' option must be a boolean.\");\r\n\t\t}\r\n\t}\r\n\r\n\tfunction testAnimationDuration ( parsed, entry ) {\r\n\r\n\t\tparsed.animationDuration = entry;\r\n\r\n\t\tif ( typeof entry !== 'number' ){\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'animationDuration' option must be a number.\");\r\n\t\t}\r\n\t}\r\n\r\n\tfunction testConnect ( parsed, entry ) {\r\n\r\n\t\tvar connect = [false];\r\n\t\tvar i;\r\n\r\n\t\t// Map legacy options\r\n\t\tif ( entry === 'lower' ) {\r\n\t\t\tentry = [true, false];\r\n\t\t}\r\n\r\n\t\telse if ( entry === 'upper' ) {\r\n\t\t\tentry = [false, true];\r\n\t\t}\r\n\r\n\t\t// Handle boolean options\r\n\t\tif ( entry === true || entry === false ) {\r\n\r\n\t\t\tfor ( i = 1; i < parsed.handles; i++ ) {\r\n\t\t\t\tconnect.push(entry);\r\n\t\t\t}\r\n\r\n\t\t\tconnect.push(false);\r\n\t\t}\r\n\r\n\t\t// Reject invalid input\r\n\t\telse if ( !Array.isArray( entry ) || !entry.length || entry.length !== parsed.handles + 1 ) {\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'connect' option doesn't match handle count.\");\r\n\t\t}\r\n\r\n\t\telse {\r\n\t\t\tconnect = entry;\r\n\t\t}\r\n\r\n\t\tparsed.connect = connect;\r\n\t}\r\n\r\n\tfunction testOrientation ( parsed, entry ) {\r\n\r\n\t\t// Set orientation to an a numerical value for easy\r\n\t\t// array selection.\r\n\t\tswitch ( entry ){\r\n\t\t  case 'horizontal':\r\n\t\t\tparsed.ort = 0;\r\n\t\t\tbreak;\r\n\t\t  case 'vertical':\r\n\t\t\tparsed.ort = 1;\r\n\t\t\tbreak;\r\n\t\t  default:\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'orientation' option is invalid.\");\r\n\t\t}\r\n\t}\r\n\r\n\tfunction testMargin ( parsed, entry ) {\r\n\r\n\t\tif ( !isNumeric(entry) ){\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'margin' option must be numeric.\");\r\n\t\t}\r\n\r\n\t\t// Issue #582\r\n\t\tif ( entry === 0 ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tparsed.margin = parsed.spectrum.getMargin(entry);\r\n\r\n\t\tif ( !parsed.margin ) {\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'margin' option is only supported on linear sliders.\");\r\n\t\t}\r\n\t}\r\n\r\n\tfunction testLimit ( parsed, entry ) {\r\n\r\n\t\tif ( !isNumeric(entry) ){\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'limit' option must be numeric.\");\r\n\t\t}\r\n\r\n\t\tparsed.limit = parsed.spectrum.getMargin(entry);\r\n\r\n\t\tif ( !parsed.limit || parsed.handles < 2 ) {\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'limit' option is only supported on linear sliders with 2 or more handles.\");\r\n\t\t}\r\n\t}\r\n\r\n\tfunction testPadding ( parsed, entry ) {\r\n\r\n\t\tif ( !isNumeric(entry) ){\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'padding' option must be numeric.\");\r\n\t\t}\r\n\r\n\t\tif ( entry === 0 ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tparsed.padding = parsed.spectrum.getMargin(entry);\r\n\r\n\t\tif ( !parsed.padding ) {\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'padding' option is only supported on linear sliders.\");\r\n\t\t}\r\n\r\n\t\tif ( parsed.padding < 0 ) {\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'padding' option must be a positive number.\");\r\n\t\t}\r\n\r\n\t\tif ( parsed.padding >= 50 ) {\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'padding' option must be less than half the range.\");\r\n\t\t}\r\n\t}\r\n\r\n\tfunction testDirection ( parsed, entry ) {\r\n\r\n\t\t// Set direction as a numerical value for easy parsing.\r\n\t\t// Invert connection for RTL sliders, so that the proper\r\n\t\t// handles get the connect/background classes.\r\n\t\tswitch ( entry ) {\r\n\t\t  case 'ltr':\r\n\t\t\tparsed.dir = 0;\r\n\t\t\tbreak;\r\n\t\t  case 'rtl':\r\n\t\t\tparsed.dir = 1;\r\n\t\t\tbreak;\r\n\t\t  default:\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'direction' option was not recognized.\");\r\n\t\t}\r\n\t}\r\n\r\n\tfunction testBehaviour ( parsed, entry ) {\r\n\r\n\t\t// Make sure the input is a string.\r\n\t\tif ( typeof entry !== 'string' ) {\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'behaviour' must be a string containing options.\");\r\n\t\t}\r\n\r\n\t\t// Check if the string contains any keywords.\r\n\t\t// None are required.\r\n\t\tvar tap = entry.indexOf('tap') >= 0;\r\n\t\tvar drag = entry.indexOf('drag') >= 0;\r\n\t\tvar fixed = entry.indexOf('fixed') >= 0;\r\n\t\tvar snap = entry.indexOf('snap') >= 0;\r\n\t\tvar hover = entry.indexOf('hover') >= 0;\r\n\r\n\t\tif ( fixed ) {\r\n\r\n\t\t\tif ( parsed.handles !== 2 ) {\r\n\t\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'fixed' behaviour must be used with 2 handles\");\r\n\t\t\t}\r\n\r\n\t\t\t// Use margin to enforce fixed state\r\n\t\t\ttestMargin(parsed, parsed.start[1] - parsed.start[0]);\r\n\t\t}\r\n\r\n\t\tparsed.events = {\r\n\t\t\ttap: tap || snap,\r\n\t\t\tdrag: drag,\r\n\t\t\tfixed: fixed,\r\n\t\t\tsnap: snap,\r\n\t\t\thover: hover\r\n\t\t};\r\n\t}\r\n\r\n\tfunction testTooltips ( parsed, entry ) {\r\n\r\n\t\tif ( entry === false ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\telse if ( entry === true ) {\r\n\r\n\t\t\tparsed.tooltips = [];\r\n\r\n\t\t\tfor ( var i = 0; i < parsed.handles; i++ ) {\r\n\t\t\t\tparsed.tooltips.push(true);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\telse {\r\n\r\n\t\t\tparsed.tooltips = asArray(entry);\r\n\r\n\t\t\tif ( parsed.tooltips.length !== parsed.handles ) {\r\n\t\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): must pass a formatter for all handles.\");\r\n\t\t\t}\r\n\r\n\t\t\tparsed.tooltips.forEach(function(formatter){\r\n\t\t\t\tif ( typeof formatter !== 'boolean' && (typeof formatter !== 'object' || typeof formatter.to !== 'function') ) {\r\n\t\t\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'tooltips' must be passed a formatter or 'false'.\");\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\tfunction testFormat ( parsed, entry ) {\r\n\r\n\t\tparsed.format = entry;\r\n\r\n\t\t// Any object with a to and from method is supported.\r\n\t\tif ( typeof entry.to === 'function' && typeof entry.from === 'function' ) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'format' requires 'to' and 'from' methods.\");\r\n\t}\r\n\r\n\tfunction testCssPrefix ( parsed, entry ) {\r\n\r\n\t\tif ( entry !== undefined && typeof entry !== 'string' && entry !== false ) {\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'cssPrefix' must be a string or `false`.\");\r\n\t\t}\r\n\r\n\t\tparsed.cssPrefix = entry;\r\n\t}\r\n\r\n\tfunction testCssClasses ( parsed, entry ) {\r\n\r\n\t\tif ( entry !== undefined && typeof entry !== 'object' ) {\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'cssClasses' must be an object.\");\r\n\t\t}\r\n\r\n\t\tif ( typeof parsed.cssPrefix === 'string' ) {\r\n\t\t\tparsed.cssClasses = {};\r\n\r\n\t\t\tfor ( var key in entry ) {\r\n\t\t\t\tif ( !entry.hasOwnProperty(key) ) { continue; }\r\n\r\n\t\t\t\tparsed.cssClasses[key] = parsed.cssPrefix + entry[key];\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tparsed.cssClasses = entry;\r\n\t\t}\r\n\t}\r\n\r\n\tfunction testUseRaf ( parsed, entry ) {\r\n\t\tif ( entry === true || entry === false ) {\r\n\t\t\tparsed.useRequestAnimationFrame = entry;\r\n\t\t} else {\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'useRequestAnimationFrame' option should be true (default) or false.\");\r\n\t\t}\r\n\t}\r\n\r\n\t// Test all developer settings and parse to assumption-safe values.\r\n\tfunction testOptions ( options ) {\r\n\r\n\t\t// To prove a fix for #537, freeze options here.\r\n\t\t// If the object is modified, an error will be thrown.\r\n\t\t// Object.freeze(options);\r\n\r\n\t\tvar parsed = {\r\n\t\t\tmargin: 0,\r\n\t\t\tlimit: 0,\r\n\t\t\tpadding: 0,\r\n\t\t\tanimate: true,\r\n\t\t\tanimationDuration: 300,\r\n\t\t\tformat: defaultFormatter\r\n\t\t};\r\n\r\n\t\t// Tests are executed in the order they are presented here.\r\n\t\tvar tests = {\r\n\t\t\t'step': { r: false, t: testStep },\r\n\t\t\t'start': { r: true, t: testStart },\r\n\t\t\t'connect': { r: true, t: testConnect },\r\n\t\t\t'direction': { r: true, t: testDirection },\r\n\t\t\t'snap': { r: false, t: testSnap },\r\n\t\t\t'animate': { r: false, t: testAnimate },\r\n\t\t\t'animationDuration': { r: false, t: testAnimationDuration },\r\n\t\t\t'range': { r: true, t: testRange },\r\n\t\t\t'orientation': { r: false, t: testOrientation },\r\n\t\t\t'margin': { r: false, t: testMargin },\r\n\t\t\t'limit': { r: false, t: testLimit },\r\n\t\t\t'padding': { r: false, t: testPadding },\r\n\t\t\t'behaviour': { r: true, t: testBehaviour },\r\n\t\t\t'format': { r: false, t: testFormat },\r\n\t\t\t'tooltips': { r: false, t: testTooltips },\r\n\t\t\t'cssPrefix': { r: false, t: testCssPrefix },\r\n\t\t\t'cssClasses': { r: false, t: testCssClasses },\r\n\t\t\t'useRequestAnimationFrame': { r: false, t: testUseRaf }\r\n\t\t};\r\n\r\n\t\tvar defaults = {\r\n\t\t\t'connect': false,\r\n\t\t\t'direction': 'ltr',\r\n\t\t\t'behaviour': 'tap',\r\n\t\t\t'orientation': 'horizontal',\r\n\t\t\t'cssPrefix' : 'noUi-',\r\n\t\t\t'cssClasses': {\r\n\t\t\t\ttarget: 'target',\r\n\t\t\t\tbase: 'base',\r\n\t\t\t\torigin: 'origin',\r\n\t\t\t\thandle: 'handle',\r\n\t\t\t\thandleLower: 'handle-lower',\r\n\t\t\t\thandleUpper: 'handle-upper',\r\n\t\t\t\thorizontal: 'horizontal',\r\n\t\t\t\tvertical: 'vertical',\r\n\t\t\t\tbackground: 'background',\r\n\t\t\t\tconnect: 'connect',\r\n\t\t\t\tltr: 'ltr',\r\n\t\t\t\trtl: 'rtl',\r\n\t\t\t\tdraggable: 'draggable',\r\n\t\t\t\tdrag: 'state-drag',\r\n\t\t\t\ttap: 'state-tap',\r\n\t\t\t\tactive: 'active',\r\n\t\t\t\ttooltip: 'tooltip',\r\n\t\t\t\tpips: 'pips',\r\n\t\t\t\tpipsHorizontal: 'pips-horizontal',\r\n\t\t\t\tpipsVertical: 'pips-vertical',\r\n\t\t\t\tmarker: 'marker',\r\n\t\t\t\tmarkerHorizontal: 'marker-horizontal',\r\n\t\t\t\tmarkerVertical: 'marker-vertical',\r\n\t\t\t\tmarkerNormal: 'marker-normal',\r\n\t\t\t\tmarkerLarge: 'marker-large',\r\n\t\t\t\tmarkerSub: 'marker-sub',\r\n\t\t\t\tvalue: 'value',\r\n\t\t\t\tvalueHorizontal: 'value-horizontal',\r\n\t\t\t\tvalueVertical: 'value-vertical',\r\n\t\t\t\tvalueNormal: 'value-normal',\r\n\t\t\t\tvalueLarge: 'value-large',\r\n\t\t\t\tvalueSub: 'value-sub'\r\n\t\t\t},\r\n\t\t\t'useRequestAnimationFrame': true\r\n\t\t};\r\n\r\n\t\t// Run all options through a testing mechanism to ensure correct\r\n\t\t// input. It should be noted that options might get modified to\r\n\t\t// be handled properly. E.g. wrapping integers in arrays.\r\n\t\tObject.keys(tests).forEach(function( name ){\r\n\r\n\t\t\t// If the option isn't set, but it is required, throw an error.\r\n\t\t\tif ( options[name] === undefined && defaults[name] === undefined ) {\r\n\r\n\t\t\t\tif ( tests[name].r ) {\r\n\t\t\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): '\" + name + \"' is required.\");\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\r\n\t\t\ttests[name].t( parsed, options[name] === undefined ? defaults[name] : options[name] );\r\n\t\t});\r\n\r\n\t\t// Forward pips options\r\n\t\tparsed.pips = options.pips;\r\n\r\n\t\tvar styles = [['left', 'top'], ['right', 'bottom']];\r\n\r\n\t\t// Pre-define the styles.\r\n\t\tparsed.style = styles[parsed.dir][parsed.ort];\r\n\t\tparsed.styleOposite = styles[parsed.dir?0:1][parsed.ort];\r\n\r\n\t\treturn parsed;\r\n\t}\r\n\r\n\r\nfunction closure ( target, options, originalOptions ){\r\n\r\n\tvar actions = getActions( );\r\n\r\n\t// All variables local to 'closure' are prefixed with 'scope_'\r\n\tvar scope_Target = target;\r\n\tvar scope_Locations = [];\r\n\tvar scope_Base;\r\n\tvar scope_Handles;\r\n\tvar scope_HandleNumbers = [];\r\n\tvar scope_ActiveHandle = false;\r\n\tvar scope_Connects;\r\n\tvar scope_Spectrum = options.spectrum;\r\n\tvar scope_Values = [];\r\n\tvar scope_Events = {};\r\n\tvar scope_Self;\r\n\r\n\r\n\t// Append a origin to the base\r\n\tfunction addOrigin ( base, handleNumber ) {\r\n\r\n\t\tvar origin = addNodeTo(base, options.cssClasses.origin);\r\n\t\tvar handle = addNodeTo(origin, options.cssClasses.handle);\r\n\r\n\t\thandle.setAttribute('data-handle', handleNumber);\r\n\r\n\t\tif ( handleNumber === 0 ) {\r\n\t\t\taddClass(handle, options.cssClasses.handleLower);\r\n\t\t}\r\n\r\n\t\telse if ( handleNumber === options.handles - 1 ) {\r\n\t\t\taddClass(handle, options.cssClasses.handleUpper);\r\n\t\t}\r\n\r\n\t\treturn origin;\r\n\t}\r\n\r\n\t// Insert nodes for connect elements\r\n\tfunction addConnect ( base, add ) {\r\n\r\n\t\tif ( !add ) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\treturn addNodeTo(base, options.cssClasses.connect);\r\n\t}\r\n\r\n\t// Add handles to the slider base.\r\n\tfunction addElements ( connectOptions, base ) {\r\n\r\n\t\tscope_Handles = [];\r\n\t\tscope_Connects = [];\r\n\r\n\t\tscope_Connects.push(addConnect(base, connectOptions[0]));\r\n\r\n\t\t// [::::O====O====O====]\r\n\t\t// connectOptions = [0, 1, 1, 1]\r\n\r\n\t\tfor ( var i = 0; i < options.handles; i++ ) {\r\n\t\t\t// Keep a list of all added handles.\r\n\t\t\tscope_Handles.push(addOrigin(base, i));\r\n\t\t\tscope_HandleNumbers[i] = i;\r\n\t\t\tscope_Connects.push(addConnect(base, connectOptions[i + 1]));\r\n\t\t}\r\n\t}\r\n\r\n\t// Initialize a single slider.\r\n\tfunction addSlider ( target ) {\r\n\r\n\t\t// Apply classes and data to the target.\r\n\t\taddClass(target, options.cssClasses.target);\r\n\r\n\t\tif ( options.dir === 0 ) {\r\n\t\t\taddClass(target, options.cssClasses.ltr);\r\n\t\t} else {\r\n\t\t\taddClass(target, options.cssClasses.rtl);\r\n\t\t}\r\n\r\n\t\tif ( options.ort === 0 ) {\r\n\t\t\taddClass(target, options.cssClasses.horizontal);\r\n\t\t} else {\r\n\t\t\taddClass(target, options.cssClasses.vertical);\r\n\t\t}\r\n\r\n\t\tscope_Base = addNodeTo(target, options.cssClasses.base);\r\n\t}\r\n\r\n\r\n\tfunction addTooltip ( handle, handleNumber ) {\r\n\r\n\t\tif ( !options.tooltips[handleNumber] ) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\treturn addNodeTo(handle.firstChild, options.cssClasses.tooltip);\r\n\t}\r\n\r\n\t// The tooltips option is a shorthand for using the 'update' event.\r\n\tfunction tooltips ( ) {\r\n\r\n\t\t// Tooltips are added with options.tooltips in original order.\r\n\t\tvar tips = scope_Handles.map(addTooltip);\r\n\r\n\t\tbindEvent('update', function(values, handleNumber, unencoded) {\r\n\r\n\t\t\tif ( !tips[handleNumber] ) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tvar formattedValue = values[handleNumber];\r\n\r\n\t\t\tif ( options.tooltips[handleNumber] !== true ) {\r\n\t\t\t\tformattedValue = options.tooltips[handleNumber].to(unencoded[handleNumber]);\r\n\t\t\t}\r\n\r\n\t\t\ttips[handleNumber].innerHTML = formattedValue;\r\n\t\t});\r\n\t}\r\n\r\n\r\n\tfunction getGroup ( mode, values, stepped ) {\r\n\r\n\t\t// Use the range.\r\n\t\tif ( mode === 'range' || mode === 'steps' ) {\r\n\t\t\treturn scope_Spectrum.xVal;\r\n\t\t}\r\n\r\n\t\tif ( mode === 'count' ) {\r\n\r\n\t\t\tif ( !values ) {\r\n\t\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): 'values' required for mode 'count'.\");\r\n\t\t\t}\r\n\r\n\t\t\t// Divide 0 - 100 in 'count' parts.\r\n\t\t\tvar spread = ( 100 / (values - 1) );\r\n\t\t\tvar v;\r\n\t\t\tvar i = 0;\r\n\r\n\t\t\tvalues = [];\r\n\r\n\t\t\t// List these parts and have them handled as 'positions'.\r\n\t\t\twhile ( (v = i++ * spread) <= 100 ) {\r\n\t\t\t\tvalues.push(v);\r\n\t\t\t}\r\n\r\n\t\t\tmode = 'positions';\r\n\t\t}\r\n\r\n\t\tif ( mode === 'positions' ) {\r\n\r\n\t\t\t// Map all percentages to on-range values.\r\n\t\t\treturn values.map(function( value ){\r\n\t\t\t\treturn scope_Spectrum.fromStepping( stepped ? scope_Spectrum.getStep( value ) : value );\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tif ( mode === 'values' ) {\r\n\r\n\t\t\t// If the value must be stepped, it needs to be converted to a percentage first.\r\n\t\t\tif ( stepped ) {\r\n\r\n\t\t\t\treturn values.map(function( value ){\r\n\r\n\t\t\t\t\t// Convert to percentage, apply step, return to value.\r\n\t\t\t\t\treturn scope_Spectrum.fromStepping( scope_Spectrum.getStep( scope_Spectrum.toStepping( value ) ) );\r\n\t\t\t\t});\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Otherwise, we can simply use the values.\r\n\t\t\treturn values;\r\n\t\t}\r\n\t}\r\n\r\n\tfunction generateSpread ( density, mode, group ) {\r\n\r\n\t\tfunction safeIncrement(value, increment) {\r\n\t\t\t// Avoid floating point variance by dropping the smallest decimal places.\r\n\t\t\treturn (value + increment).toFixed(7) / 1;\r\n\t\t}\r\n\r\n\t\tvar indexes = {};\r\n\t\tvar firstInRange = scope_Spectrum.xVal[0];\r\n\t\tvar lastInRange = scope_Spectrum.xVal[scope_Spectrum.xVal.length-1];\r\n\t\tvar ignoreFirst = false;\r\n\t\tvar ignoreLast = false;\r\n\t\tvar prevPct = 0;\r\n\r\n\t\t// Create a copy of the group, sort it and filter away all duplicates.\r\n\t\tgroup = unique(group.slice().sort(function(a, b){ return a - b; }));\r\n\r\n\t\t// Make sure the range starts with the first element.\r\n\t\tif ( group[0] !== firstInRange ) {\r\n\t\t\tgroup.unshift(firstInRange);\r\n\t\t\tignoreFirst = true;\r\n\t\t}\r\n\r\n\t\t// Likewise for the last one.\r\n\t\tif ( group[group.length - 1] !== lastInRange ) {\r\n\t\t\tgroup.push(lastInRange);\r\n\t\t\tignoreLast = true;\r\n\t\t}\r\n\r\n\t\tgroup.forEach(function ( current, index ) {\r\n\r\n\t\t\t// Get the current step and the lower + upper positions.\r\n\t\t\tvar step;\r\n\t\t\tvar i;\r\n\t\t\tvar q;\r\n\t\t\tvar low = current;\r\n\t\t\tvar high = group[index+1];\r\n\t\t\tvar newPct;\r\n\t\t\tvar pctDifference;\r\n\t\t\tvar pctPos;\r\n\t\t\tvar type;\r\n\t\t\tvar steps;\r\n\t\t\tvar realSteps;\r\n\t\t\tvar stepsize;\r\n\r\n\t\t\t// When using 'steps' mode, use the provided steps.\r\n\t\t\t// Otherwise, we'll step on to the next subrange.\r\n\t\t\tif ( mode === 'steps' ) {\r\n\t\t\t\tstep = scope_Spectrum.xNumSteps[ index ];\r\n\t\t\t}\r\n\r\n\t\t\t// Default to a 'full' step.\r\n\t\t\tif ( !step ) {\r\n\t\t\t\tstep = high-low;\r\n\t\t\t}\r\n\r\n\t\t\t// Low can be 0, so test for false. If high is undefined,\r\n\t\t\t// we are at the last subrange. Index 0 is already handled.\r\n\t\t\tif ( low === false || high === undefined ) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\t// Make sure step isn't 0, which would cause an infinite loop (#654)\r\n\t\t\tstep = Math.max(step, 0.0000001);\r\n\r\n\t\t\t// Find all steps in the subrange.\r\n\t\t\tfor ( i = low; i <= high; i = safeIncrement(i, step) ) {\r\n\r\n\t\t\t\t// Get the percentage value for the current step,\r\n\t\t\t\t// calculate the size for the subrange.\r\n\t\t\t\tnewPct = scope_Spectrum.toStepping( i );\r\n\t\t\t\tpctDifference = newPct - prevPct;\r\n\r\n\t\t\t\tsteps = pctDifference / density;\r\n\t\t\t\trealSteps = Math.round(steps);\r\n\r\n\t\t\t\t// This ratio represents the ammount of percentage-space a point indicates.\r\n\t\t\t\t// For a density 1 the points/percentage = 1. For density 2, that percentage needs to be re-devided.\r\n\t\t\t\t// Round the percentage offset to an even number, then divide by two\r\n\t\t\t\t// to spread the offset on both sides of the range.\r\n\t\t\t\tstepsize = pctDifference/realSteps;\r\n\r\n\t\t\t\t// Divide all points evenly, adding the correct number to this subrange.\r\n\t\t\t\t// Run up to <= so that 100% gets a point, event if ignoreLast is set.\r\n\t\t\t\tfor ( q = 1; q <= realSteps; q += 1 ) {\r\n\r\n\t\t\t\t\t// The ratio between the rounded value and the actual size might be ~1% off.\r\n\t\t\t\t\t// Correct the percentage offset by the number of points\r\n\t\t\t\t\t// per subrange. density = 1 will result in 100 points on the\r\n\t\t\t\t\t// full range, 2 for 50, 4 for 25, etc.\r\n\t\t\t\t\tpctPos = prevPct + ( q * stepsize );\r\n\t\t\t\t\tindexes[pctPos.toFixed(5)] = ['x', 0];\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Determine the point type.\r\n\t\t\t\ttype = (group.indexOf(i) > -1) ? 1 : ( mode === 'steps' ? 2 : 0 );\r\n\r\n\t\t\t\t// Enforce the 'ignoreFirst' option by overwriting the type for 0.\r\n\t\t\t\tif ( !index && ignoreFirst ) {\r\n\t\t\t\t\ttype = 0;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( !(i === high && ignoreLast)) {\r\n\t\t\t\t\t// Mark the 'type' of this point. 0 = plain, 1 = real value, 2 = step value.\r\n\t\t\t\t\tindexes[newPct.toFixed(5)] = [i, type];\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Update the percentage count.\r\n\t\t\t\tprevPct = newPct;\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\treturn indexes;\r\n\t}\r\n\r\n\tfunction addMarking ( spread, filterFunc, formatter ) {\r\n\r\n\t\tvar element = document.createElement('div');\r\n\t\tvar out = '';\r\n\t\tvar valueSizeClasses = [\r\n\t\t\toptions.cssClasses.valueNormal,\r\n\t\t\toptions.cssClasses.valueLarge,\r\n\t\t\toptions.cssClasses.valueSub\r\n\t\t];\r\n\t\tvar markerSizeClasses = [\r\n\t\t\toptions.cssClasses.markerNormal,\r\n\t\t\toptions.cssClasses.markerLarge,\r\n\t\t\toptions.cssClasses.markerSub\r\n\t\t];\r\n\t\tvar valueOrientationClasses = [\r\n\t\t\toptions.cssClasses.valueHorizontal,\r\n\t\t\toptions.cssClasses.valueVertical\r\n\t\t];\r\n\t\tvar markerOrientationClasses = [\r\n\t\t\toptions.cssClasses.markerHorizontal,\r\n\t\t\toptions.cssClasses.markerVertical\r\n\t\t];\r\n\r\n\t\taddClass(element, options.cssClasses.pips);\r\n\t\taddClass(element, options.ort === 0 ? options.cssClasses.pipsHorizontal : options.cssClasses.pipsVertical);\r\n\r\n\t\tfunction getClasses( type, source ){\r\n\t\t\tvar a = source === options.cssClasses.value;\r\n\t\t\tvar orientationClasses = a ? valueOrientationClasses : markerOrientationClasses;\r\n\t\t\tvar sizeClasses = a ? valueSizeClasses : markerSizeClasses;\r\n\r\n\t\t\treturn source + ' ' + orientationClasses[options.ort] + ' ' + sizeClasses[type];\r\n\t\t}\r\n\r\n\t\tfunction getTags( offset, source, values ) {\r\n\t\t\treturn 'class=\"' + getClasses(values[1], source) + '\" style=\"' + options.style + ': ' + offset + '%\"';\r\n\t\t}\r\n\r\n\t\tfunction addSpread ( offset, values ){\r\n\r\n\t\t\t// Apply the filter function, if it is set.\r\n\t\t\tvalues[1] = (values[1] && filterFunc) ? filterFunc(values[0], values[1]) : values[1];\r\n\r\n\t\t\t// Add a marker for every point\r\n\t\t\tout += '<div ' + getTags(offset, options.cssClasses.marker, values) + '></div>';\r\n\r\n\t\t\t// Values are only appended for points marked '1' or '2'.\r\n\t\t\tif ( values[1] ) {\r\n\t\t\t\tout += '<div ' + getTags(offset, options.cssClasses.value, values) + '>' + formatter.to(values[0]) + '</div>';\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Append all points.\r\n\t\tObject.keys(spread).forEach(function(a){\r\n\t\t\taddSpread(a, spread[a]);\r\n\t\t});\r\n\r\n\t\telement.innerHTML = out;\r\n\r\n\t\treturn element;\r\n\t}\r\n\r\n\tfunction pips ( grid ) {\r\n\r\n\t\tvar mode = grid.mode;\r\n\t\tvar density = grid.density || 1;\r\n\t\tvar filter = grid.filter || false;\r\n\t\tvar values = grid.values || false;\r\n\t\tvar stepped = grid.stepped || false;\r\n\t\tvar group = getGroup( mode, values, stepped );\r\n\t\tvar spread = generateSpread( density, mode, group );\r\n\t\tvar format = grid.format || {\r\n\t\t\tto: Math.round\r\n\t\t};\r\n\r\n\t\treturn scope_Target.appendChild(addMarking(\r\n\t\t\tspread,\r\n\t\t\tfilter,\r\n\t\t\tformat\r\n\t\t));\r\n\t}\r\n\r\n\r\n\t// Shorthand for base dimensions.\r\n\tfunction baseSize ( ) {\r\n\t\tvar rect = scope_Base.getBoundingClientRect(), alt = 'offset' + ['Width', 'Height'][options.ort];\r\n\t\treturn options.ort === 0 ? (rect.width||scope_Base[alt]) : (rect.height||scope_Base[alt]);\r\n\t}\r\n\r\n\t// Handler for attaching events trough a proxy.\r\n\tfunction attachEvent ( events, element, callback, data ) {\r\n\r\n\t\t// This function can be used to 'filter' events to the slider.\r\n\t\t// element is a node, not a nodeList\r\n\r\n\t\tvar method = function ( e ){\r\n\r\n\t\t\tif ( scope_Target.hasAttribute('disabled') ) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\r\n\t\t\t// Stop if an active 'tap' transition is taking place.\r\n\t\t\tif ( hasClass(scope_Target, options.cssClasses.tap) ) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\r\n\t\t\te = fixEvent(e, data.pageOffset);\r\n\r\n\t\t\t// Handle reject of multitouch\r\n\t\t\tif ( !e ) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\r\n\t\t\t// Ignore right or middle clicks on start #454\r\n\t\t\tif ( events === actions.start && e.buttons !== undefined && e.buttons > 1 ) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\r\n\t\t\t// Ignore right or middle clicks on start #454\r\n\t\t\tif ( data.hover && e.buttons ) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\r\n\t\t\te.calcPoint = e.points[ options.ort ];\r\n\r\n\t\t\t// Call the event handler with the event [ and additional data ].\r\n\t\t\tcallback ( e, data );\r\n\t\t};\r\n\r\n\t\tvar methods = [];\r\n\r\n\t\t// Bind a closure on the target for every event type.\r\n\t\tevents.split(' ').forEach(function( eventName ){\r\n\t\t\telement.addEventListener(eventName, method, false);\r\n\t\t\tmethods.push([eventName, method]);\r\n\t\t});\r\n\r\n\t\treturn methods;\r\n\t}\r\n\r\n\t// Provide a clean event with standardized offset values.\r\n\tfunction fixEvent ( e, pageOffset ) {\r\n\r\n\t\t// Prevent scrolling and panning on touch events, while\r\n\t\t// attempting to slide. The tap event also depends on this.\r\n\t\te.preventDefault();\r\n\r\n\t\t// Filter the event to register the type, which can be\r\n\t\t// touch, mouse or pointer. Offset changes need to be\r\n\t\t// made on an event specific basis.\r\n\t\tvar touch = e.type.indexOf('touch') === 0;\r\n\t\tvar mouse = e.type.indexOf('mouse') === 0;\r\n\t\tvar pointer = e.type.indexOf('pointer') === 0;\r\n\t\tvar x;\r\n\t\tvar y;\r\n\r\n\t\t// IE10 implemented pointer events with a prefix;\r\n\t\tif ( e.type.indexOf('MSPointer') === 0 ) {\r\n\t\t\tpointer = true;\r\n\t\t}\r\n\r\n\t\tif ( touch ) {\r\n\r\n\t\t\t// Fix bug when user touches with two or more fingers on mobile devices.\r\n\t\t\t// It's useful when you have two or more sliders on one page,\r\n\t\t\t// that can be touched simultaneously.\r\n\t\t\t// #649, #663, #668\r\n\t\t\tif ( e.touches.length > 1 ) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\r\n\t\t\t// noUiSlider supports one movement at a time,\r\n\t\t\t// so we can select the first 'changedTouch'.\r\n\t\t\tx = e.changedTouches[0].pageX;\r\n\t\t\ty = e.changedTouches[0].pageY;\r\n\t\t}\r\n\r\n\t\tpageOffset = pageOffset || getPageOffset();\r\n\r\n\t\tif ( mouse || pointer ) {\r\n\t\t\tx = e.clientX + pageOffset.x;\r\n\t\t\ty = e.clientY + pageOffset.y;\r\n\t\t}\r\n\r\n\t\te.pageOffset = pageOffset;\r\n\t\te.points = [x, y];\r\n\t\te.cursor = mouse || pointer; // Fix #435\r\n\r\n\t\treturn e;\r\n\t}\r\n\r\n\t// Translate a coordinate in the document to a percentage on the slider\r\n\tfunction calcPointToPercentage ( calcPoint ) {\r\n\t\tvar location = calcPoint - offset(scope_Base, options.ort);\r\n\t\tvar proposal = ( location * 100 ) / baseSize();\r\n\t\treturn options.dir ? 100 - proposal : proposal;\r\n\t}\r\n\r\n\t// Find handle closest to a certain percentage on the slider\r\n\tfunction getClosestHandle ( proposal ) {\r\n\r\n\t\tvar closest = 100;\r\n\t\tvar handleNumber = false;\r\n\r\n\t\tscope_Handles.forEach(function(handle, index){\r\n\r\n\t\t\t// Disabled handles are ignored\r\n\t\t\tif ( handle.hasAttribute('disabled') ) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tvar pos = Math.abs(scope_Locations[index] - proposal);\r\n\r\n\t\t\tif ( pos < closest ) {\r\n\t\t\t\thandleNumber = index;\r\n\t\t\t\tclosest = pos;\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\treturn handleNumber;\r\n\t}\r\n\r\n\t// Moves handle(s) by a percentage\r\n\t// (bool, % to move, [% where handle started, ...], [index in scope_Handles, ...])\r\n\tfunction moveHandles ( upward, proposal, locations, handleNumbers ) {\r\n\r\n\t\tvar proposals = locations.slice();\r\n\r\n\t\tvar b = [!upward, upward];\r\n\t\tvar f = [upward, !upward];\r\n\r\n\t\t// Copy handleNumbers so we don't change the dataset\r\n\t\thandleNumbers = handleNumbers.slice();\r\n\r\n\t\t// Check to see which handle is 'leading'.\r\n\t\t// If that one can't move the second can't either.\r\n\t\tif ( upward ) {\r\n\t\t\thandleNumbers.reverse();\r\n\t\t}\r\n\r\n\t\t// Step 1: get the maximum percentage that any of the handles can move\r\n\t\tif ( handleNumbers.length > 1 ) {\r\n\r\n\t\t\thandleNumbers.forEach(function(handleNumber, o) {\r\n\r\n\t\t\t\tvar to = checkHandlePosition(proposals, handleNumber, proposals[handleNumber] + proposal, b[o], f[o]);\r\n\r\n\t\t\t\t// Stop if one of the handles can't move.\r\n\t\t\t\tif ( to === false ) {\r\n\t\t\t\t\tproposal = 0;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tproposal = to - proposals[handleNumber];\r\n\t\t\t\t\tproposals[handleNumber] = to;\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\t// If using one handle, check backward AND forward\r\n\t\telse {\r\n\t\t\tb = f = [true];\r\n\t\t}\r\n\r\n\t\tvar state = false;\r\n\r\n\t\t// Step 2: Try to set the handles with the found percentage\r\n\t\thandleNumbers.forEach(function(handleNumber, o) {\r\n\t\t\tstate = setHandle(handleNumber, locations[handleNumber] + proposal, b[o], f[o]) || state;\r\n\t\t});\r\n\r\n\t\t// Step 3: If a handle moved, fire events\r\n\t\tif ( state ) {\r\n\t\t\thandleNumbers.forEach(function(handleNumber){\r\n\t\t\t\tfireEvent('update', handleNumber);\r\n\t\t\t\tfireEvent('slide', handleNumber);\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\t// External event handling\r\n\tfunction fireEvent ( eventName, handleNumber, tap ) {\r\n\r\n\t\tObject.keys(scope_Events).forEach(function( targetEvent ) {\r\n\r\n\t\t\tvar eventType = targetEvent.split('.')[0];\r\n\r\n\t\t\tif ( eventName === eventType ) {\r\n\t\t\t\tscope_Events[targetEvent].forEach(function( callback ) {\r\n\r\n\t\t\t\t\tcallback.call(\r\n\t\t\t\t\t\t// Use the slider public API as the scope ('this')\r\n\t\t\t\t\t\tscope_Self,\r\n\t\t\t\t\t\t// Return values as array, so arg_1[arg_2] is always valid.\r\n\t\t\t\t\t\tscope_Values.map(options.format.to),\r\n\t\t\t\t\t\t// Handle index, 0 or 1\r\n\t\t\t\t\t\thandleNumber,\r\n\t\t\t\t\t\t// Unformatted slider values\r\n\t\t\t\t\t\tscope_Values.slice(),\r\n\t\t\t\t\t\t// Event is fired by tap, true or false\r\n\t\t\t\t\t\ttap || false,\r\n\t\t\t\t\t\t// Left offset of the handle, in relation to the slider\r\n\t\t\t\t\t\tscope_Locations.slice()\r\n\t\t\t\t\t);\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\r\n\t// Fire 'end' when a mouse or pen leaves the document.\r\n\tfunction documentLeave ( event, data ) {\r\n\t\tif ( event.type === \"mouseout\" && event.target.nodeName === \"HTML\" && event.relatedTarget === null ){\r\n\t\t\teventEnd (event, data);\r\n\t\t}\r\n\t}\r\n\r\n\t// Handle movement on document for handle and range drag.\r\n\tfunction eventMove ( event, data ) {\r\n\r\n\t\t// Fix #498\r\n\t\t// Check value of .buttons in 'start' to work around a bug in IE10 mobile (data.buttonsProperty).\r\n\t\t// https://connect.microsoft.com/IE/feedback/details/927005/mobile-ie10-windows-phone-buttons-property-of-pointermove-event-always-zero\r\n\t\t// IE9 has .buttons and .which zero on mousemove.\r\n\t\t// Firefox breaks the spec MDN defines.\r\n\t\tif ( navigator.appVersion.indexOf(\"MSIE 9\") === -1 && event.buttons === 0 && data.buttonsProperty !== 0 ) {\r\n\t\t\treturn eventEnd(event, data);\r\n\t\t}\r\n\r\n\t\t// Check if we are moving up or down\r\n\t\tvar movement = (options.dir ? -1 : 1) * (event.calcPoint - data.startCalcPoint);\r\n\r\n\t\t// Convert the movement into a percentage of the slider width/height\r\n\t\tvar proposal = (movement * 100) / data.baseSize;\r\n\r\n\t\tmoveHandles(movement > 0, proposal, data.locations, data.handleNumbers);\r\n\t}\r\n\r\n\t// Unbind move events on document, call callbacks.\r\n\tfunction eventEnd ( event, data ) {\r\n\r\n\t\t// The handle is no longer active, so remove the class.\r\n\t\tif ( scope_ActiveHandle ) {\r\n\t\t\tremoveClass(scope_ActiveHandle, options.cssClasses.active);\r\n\t\t\tscope_ActiveHandle = false;\r\n\t\t}\r\n\r\n\t\t// Remove cursor styles and text-selection events bound to the body.\r\n\t\tif ( event.cursor ) {\r\n\t\t\tdocument.body.style.cursor = '';\r\n\t\t\tdocument.body.removeEventListener('selectstart', document.body.noUiListener);\r\n\t\t}\r\n\r\n\t\t// Unbind the move and end events, which are added on 'start'.\r\n\t\tdocument.documentElement.noUiListeners.forEach(function( c ) {\r\n\t\t\tdocument.documentElement.removeEventListener(c[0], c[1]);\r\n\t\t});\r\n\r\n\t\t// Remove dragging class.\r\n\t\tremoveClass(scope_Target, options.cssClasses.drag);\r\n\r\n\t\tsetZindex();\r\n\r\n\t\tdata.handleNumbers.forEach(function(handleNumber){\r\n\t\t\tfireEvent('set', handleNumber);\r\n\t\t\tfireEvent('change', handleNumber);\r\n\t\t\tfireEvent('end', handleNumber);\r\n\t\t});\r\n\t}\r\n\r\n\t// Bind move events on document.\r\n\tfunction eventStart ( event, data ) {\r\n\r\n\t\tif ( data.handleNumbers.length === 1 ) {\r\n\r\n\t\t\tvar handle = scope_Handles[data.handleNumbers[0]];\r\n\r\n\t\t\t// Ignore 'disabled' handles\r\n\t\t\tif ( handle.hasAttribute('disabled') ) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\r\n\t\t\t// Mark the handle as 'active' so it can be styled.\r\n\t\t\tscope_ActiveHandle = handle.children[0];\r\n\t\t\taddClass(scope_ActiveHandle, options.cssClasses.active);\r\n\t\t}\r\n\r\n\t\t// Fix #551, where a handle gets selected instead of dragged.\r\n\t\tevent.preventDefault();\r\n\r\n\t\t// A drag should never propagate up to the 'tap' event.\r\n\t\tevent.stopPropagation();\r\n\r\n\t\t// Attach the move and end events.\r\n\t\tvar moveEvent = attachEvent(actions.move, document.documentElement, eventMove, {\r\n\t\t\tstartCalcPoint: event.calcPoint,\r\n\t\t\tbaseSize: baseSize(),\r\n\t\t\tpageOffset: event.pageOffset,\r\n\t\t\thandleNumbers: data.handleNumbers,\r\n\t\t\tbuttonsProperty: event.buttons,\r\n\t\t\tlocations: scope_Locations.slice()\r\n\t\t});\r\n\r\n\t\tvar endEvent = attachEvent(actions.end, document.documentElement, eventEnd, {\r\n\t\t\thandleNumbers: data.handleNumbers\r\n\t\t});\r\n\r\n\t\tvar outEvent = attachEvent(\"mouseout\", document.documentElement, documentLeave, {\r\n\t\t\thandleNumbers: data.handleNumbers\r\n\t\t});\r\n\r\n\t\tdocument.documentElement.noUiListeners = moveEvent.concat(endEvent, outEvent);\r\n\r\n\t\t// Text selection isn't an issue on touch devices,\r\n\t\t// so adding cursor styles can be skipped.\r\n\t\tif ( event.cursor ) {\r\n\r\n\t\t\t// Prevent the 'I' cursor and extend the range-drag cursor.\r\n\t\t\tdocument.body.style.cursor = getComputedStyle(event.target).cursor;\r\n\r\n\t\t\t// Mark the target with a dragging state.\r\n\t\t\tif ( scope_Handles.length > 1 ) {\r\n\t\t\t\taddClass(scope_Target, options.cssClasses.drag);\r\n\t\t\t}\r\n\r\n\t\t\tvar f = function(){\r\n\t\t\t\treturn false;\r\n\t\t\t};\r\n\r\n\t\t\tdocument.body.noUiListener = f;\r\n\r\n\t\t\t// Prevent text selection when dragging the handles.\r\n\t\t\tdocument.body.addEventListener('selectstart', f, false);\r\n\t\t}\r\n\r\n\t\tdata.handleNumbers.forEach(function(handleNumber){\r\n\t\t\tfireEvent('start', handleNumber);\r\n\t\t});\r\n\t}\r\n\r\n\t// Move closest handle to tapped location.\r\n\tfunction eventTap ( event ) {\r\n\r\n\t\t// The tap event shouldn't propagate up\r\n\t\tevent.stopPropagation();\r\n\r\n\t\tvar proposal = calcPointToPercentage(event.calcPoint);\r\n\t\tvar handleNumber = getClosestHandle(proposal);\r\n\r\n\t\t// Tackle the case that all handles are 'disabled'.\r\n\t\tif ( handleNumber === false ) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\t// Flag the slider as it is now in a transitional state.\r\n\t\t// Transition takes a configurable amount of ms (default 300). Re-enable the slider after that.\r\n\t\tif ( !options.events.snap ) {\r\n\t\t\taddClassFor(scope_Target, options.cssClasses.tap, options.animationDuration);\r\n\t\t}\r\n\r\n\t\tsetHandle(handleNumber, proposal, true, true);\r\n\r\n\t\tsetZindex();\r\n\r\n\t\tfireEvent('slide', handleNumber, true);\r\n\t\tfireEvent('set', handleNumber, true);\r\n\t\tfireEvent('change', handleNumber, true);\r\n\t\tfireEvent('update', handleNumber, true);\r\n\r\n\t\tif ( options.events.snap ) {\r\n\t\t\teventStart(event, { handleNumbers: [handleNumber] });\r\n\t\t}\r\n\t}\r\n\r\n\t// Fires a 'hover' event for a hovered mouse/pen position.\r\n\tfunction eventHover ( event ) {\r\n\r\n\t\tvar proposal = calcPointToPercentage(event.calcPoint);\r\n\r\n\t\tvar to = scope_Spectrum.getStep(proposal);\r\n\t\tvar value = scope_Spectrum.fromStepping(to);\r\n\r\n\t\tObject.keys(scope_Events).forEach(function( targetEvent ) {\r\n\t\t\tif ( 'hover' === targetEvent.split('.')[0] ) {\r\n\t\t\t\tscope_Events[targetEvent].forEach(function( callback ) {\r\n\t\t\t\t\tcallback.call( scope_Self, value );\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\t// Attach events to several slider parts.\r\n\tfunction bindSliderEvents ( behaviour ) {\r\n\r\n\t\t// Attach the standard drag event to the handles.\r\n\t\tif ( !behaviour.fixed ) {\r\n\r\n\t\t\tscope_Handles.forEach(function( handle, index ){\r\n\r\n\t\t\t\t// These events are only bound to the visual handle\r\n\t\t\t\t// element, not the 'real' origin element.\r\n\t\t\t\tattachEvent ( actions.start, handle.children[0], eventStart, {\r\n\t\t\t\t\thandleNumbers: [index]\r\n\t\t\t\t});\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\t// Attach the tap event to the slider base.\r\n\t\tif ( behaviour.tap ) {\r\n\t\t\tattachEvent (actions.start, scope_Base, eventTap, {});\r\n\t\t}\r\n\r\n\t\t// Fire hover events\r\n\t\tif ( behaviour.hover ) {\r\n\t\t\tattachEvent (actions.move, scope_Base, eventHover, { hover: true });\r\n\t\t}\r\n\r\n\t\t// Make the range draggable.\r\n\t\tif ( behaviour.drag ){\r\n\r\n\t\t\tscope_Connects.forEach(function( connect, index ){\r\n\r\n\t\t\t\tif ( connect === false || index === 0 || index === scope_Connects.length - 1 ) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar handleBefore = scope_Handles[index - 1];\r\n\t\t\t\tvar handleAfter = scope_Handles[index];\r\n\t\t\t\tvar eventHolders = [connect];\r\n\r\n\t\t\t\taddClass(connect, options.cssClasses.draggable);\r\n\r\n\t\t\t\t// When the range is fixed, the entire range can\r\n\t\t\t\t// be dragged by the handles. The handle in the first\r\n\t\t\t\t// origin will propagate the start event upward,\r\n\t\t\t\t// but it needs to be bound manually on the other.\r\n\t\t\t\tif ( behaviour.fixed ) {\r\n\t\t\t\t\teventHolders.push(handleBefore.children[0]);\r\n\t\t\t\t\teventHolders.push(handleAfter.children[0]);\r\n\t\t\t\t}\r\n\r\n\t\t\t\teventHolders.forEach(function( eventHolder ) {\r\n\t\t\t\t\tattachEvent ( actions.start, eventHolder, eventStart, {\r\n\t\t\t\t\t\thandles: [handleBefore, handleAfter],\r\n\t\t\t\t\t\thandleNumbers: [index - 1, index]\r\n\t\t\t\t\t});\r\n\t\t\t\t});\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t// Split out the handle positioning logic so the Move event can use it, too\r\n\tfunction checkHandlePosition ( reference, handleNumber, to, lookBackward, lookForward ) {\r\n\r\n\t\t// For sliders with multiple handles, limit movement to the other handle.\r\n\t\t// Apply the margin option by adding it to the handle positions.\r\n\t\tif ( scope_Handles.length > 1 ) {\r\n\r\n\t\t\tif ( lookBackward && handleNumber > 0 ) {\r\n\t\t\t\tto = Math.max(to, reference[handleNumber - 1] + options.margin);\r\n\t\t\t}\r\n\r\n\t\t\tif ( lookForward && handleNumber < scope_Handles.length - 1 ) {\r\n\t\t\t\tto = Math.min(to, reference[handleNumber + 1] - options.margin);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// The limit option has the opposite effect, limiting handles to a\r\n\t\t// maximum distance from another. Limit must be > 0, as otherwise\r\n\t\t// handles would be unmoveable.\r\n\t\tif ( scope_Handles.length > 1 && options.limit ) {\r\n\r\n\t\t\tif ( lookBackward && handleNumber > 0 ) {\r\n\t\t\t\tto = Math.min(to, reference[handleNumber - 1] + options.limit);\r\n\t\t\t}\r\n\r\n\t\t\tif ( lookForward && handleNumber < scope_Handles.length - 1 ) {\r\n\t\t\t\tto = Math.max(to, reference[handleNumber + 1] - options.limit);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// The padding option keeps the handles a certain distance from the\r\n\t\t// edges of the slider. Padding must be > 0.\r\n\t\tif ( options.padding ) {\r\n\r\n\t\t\tif ( handleNumber === 0 ) {\r\n\t\t\t\tto = Math.max(to, options.padding);\r\n\t\t\t}\r\n\r\n\t\t\tif ( handleNumber === scope_Handles.length - 1 ) {\r\n\t\t\t\tto = Math.min(to, 100 - options.padding);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tto = scope_Spectrum.getStep(to);\r\n\r\n\t\t// Limit percentage to the 0 - 100 range\r\n\t\tto = limit(to);\r\n\r\n\t\t// Return false if handle can't move\r\n\t\tif ( to === reference[handleNumber] ) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\treturn to;\r\n\t}\r\n\r\n\tfunction toPct ( pct ) {\r\n\t\treturn pct + '%';\r\n\t}\r\n\r\n\t// Updates scope_Locations and scope_Values, updates visual state\r\n\tfunction updateHandlePosition ( handleNumber, to ) {\r\n\r\n\t\t// Update locations.\r\n\t\tscope_Locations[handleNumber] = to;\r\n\r\n\t\t// Convert the value to the slider stepping/range.\r\n\t\tscope_Values[handleNumber] = scope_Spectrum.fromStepping(to);\r\n\r\n\t\t// Called synchronously or on the next animationFrame\r\n\t\tvar stateUpdate = function() {\r\n\t\t\tscope_Handles[handleNumber].style[options.style] = toPct(to);\r\n\t\t\tupdateConnect(handleNumber);\r\n\t\t\tupdateConnect(handleNumber + 1);\r\n\t\t};\r\n\r\n\t\t// Set the handle to the new position.\r\n\t\t// Use requestAnimationFrame for efficient painting.\r\n\t\t// No significant effect in Chrome, Edge sees dramatic performace improvements.\r\n\t\t// Option to disable is useful for unit tests, and single-step debugging.\r\n\t\tif ( window.requestAnimationFrame && options.useRequestAnimationFrame ) {\r\n\t\t\twindow.requestAnimationFrame(stateUpdate);\r\n\t\t} else {\r\n\t\t\tstateUpdate();\r\n\t\t}\r\n\t}\r\n\r\n\tfunction setZindex ( ) {\r\n\r\n\t\tscope_HandleNumbers.forEach(function(handleNumber){\r\n\t\t\t// Handles before the slider middle are stacked later = higher,\r\n\t\t\t// Handles after the middle later is lower\r\n\t\t\t// [[7] [8] .......... | .......... [5] [4]\r\n\t\t\tvar dir = (scope_Locations[handleNumber] > 50 ? -1 : 1);\r\n\t\t\tvar zIndex = 3 + (scope_Handles.length + (dir * handleNumber));\r\n\t\t\tscope_Handles[handleNumber].childNodes[0].style.zIndex = zIndex;\r\n\t\t});\r\n\t}\r\n\r\n\t// Test suggested values and apply margin, step.\r\n\tfunction setHandle ( handleNumber, to, lookBackward, lookForward ) {\r\n\r\n\t\tto = checkHandlePosition(scope_Locations, handleNumber, to, lookBackward, lookForward);\r\n\r\n\t\tif ( to === false ) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tupdateHandlePosition(handleNumber, to);\r\n\r\n\t\treturn true;\r\n\t}\r\n\r\n\t// Updates style attribute for connect nodes\r\n\tfunction updateConnect ( index ) {\r\n\r\n\t\t// Skip connects set to false\r\n\t\tif ( !scope_Connects[index] ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tvar l = 0;\r\n\t\tvar h = 100;\r\n\r\n\t\tif ( index !== 0 ) {\r\n\t\t\tl = scope_Locations[index - 1];\r\n\t\t}\r\n\r\n\t\tif ( index !== scope_Connects.length - 1 ) {\r\n\t\t\th = scope_Locations[index];\r\n\t\t}\r\n\r\n\t\tscope_Connects[index].style[options.style] = toPct(l);\r\n\t\tscope_Connects[index].style[options.styleOposite] = toPct(100 - h);\r\n\t}\r\n\r\n\t// ...\r\n\tfunction setValue ( to, handleNumber ) {\r\n\r\n\t\t// Setting with null indicates an 'ignore'.\r\n\t\t// Inputting 'false' is invalid.\r\n\t\tif ( to === null || to === false ) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// If a formatted number was passed, attemt to decode it.\r\n\t\tif ( typeof to === 'number' ) {\r\n\t\t\tto = String(to);\r\n\t\t}\r\n\r\n\t\tto = options.format.from(to);\r\n\r\n\t\t// Request an update for all links if the value was invalid.\r\n\t\t// Do so too if setting the handle fails.\r\n\t\tif ( to !== false && !isNaN(to) ) {\r\n\t\t\tsetHandle(handleNumber, scope_Spectrum.toStepping(to), false, false);\r\n\t\t}\r\n\t}\r\n\r\n\t// Set the slider value.\r\n\tfunction valueSet ( input, fireSetEvent ) {\r\n\r\n\t\tvar values = asArray(input);\r\n\t\tvar isInit = scope_Locations[0] === undefined;\r\n\r\n\t\t// Event fires by default\r\n\t\tfireSetEvent = (fireSetEvent === undefined ? true : !!fireSetEvent);\r\n\r\n\t\tvalues.forEach(setValue);\r\n\r\n\t\t// Animation is optional.\r\n\t\t// Make sure the initial values were set before using animated placement.\r\n\t\tif ( options.animate && !isInit ) {\r\n\t\t\taddClassFor(scope_Target, options.cssClasses.tap, options.animationDuration);\r\n\t\t}\r\n\r\n\t\t// Now that all base values are set, apply constraints\r\n\t\tscope_HandleNumbers.forEach(function(handleNumber){\r\n\t\t\tsetHandle(handleNumber, scope_Locations[handleNumber], true, false);\r\n\t\t});\r\n\r\n\t\tsetZindex();\r\n\r\n\t\tscope_HandleNumbers.forEach(function(handleNumber){\r\n\r\n\t\t\tfireEvent('update', handleNumber);\r\n\r\n\t\t\t// Fire the event only for handles that received a new value, as per #579\r\n\t\t\tif ( values[handleNumber] !== null && fireSetEvent ) {\r\n\t\t\t\tfireEvent('set', handleNumber);\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\t// Reset slider to initial values\r\n\tfunction valueReset ( fireSetEvent ) {\r\n\t\tvalueSet(options.start, fireSetEvent);\r\n\t}\r\n\r\n\t// Get the slider value.\r\n\tfunction valueGet ( ) {\r\n\r\n\t\tvar values = scope_Values.map(options.format.to);\r\n\r\n\t\t// If only one handle is used, return a single value.\r\n\t\tif ( values.length === 1 ){\r\n\t\t\treturn values[0];\r\n\t\t}\r\n\r\n\t\treturn values;\r\n\t}\r\n\r\n\t// Removes classes from the root and empties it.\r\n\tfunction destroy ( ) {\r\n\r\n\t\tfor ( var key in options.cssClasses ) {\r\n\t\t\tif ( !options.cssClasses.hasOwnProperty(key) ) { continue; }\r\n\t\t\tremoveClass(scope_Target, options.cssClasses[key]);\r\n\t\t}\r\n\r\n\t\twhile (scope_Target.firstChild) {\r\n\t\t\tscope_Target.removeChild(scope_Target.firstChild);\r\n\t\t}\r\n\r\n\t\tdelete scope_Target.noUiSlider;\r\n\t}\r\n\r\n\t// Get the current step size for the slider.\r\n\tfunction getCurrentStep ( ) {\r\n\r\n\t\t// Check all locations, map them to their stepping point.\r\n\t\t// Get the step point, then find it in the input list.\r\n\t\treturn scope_Locations.map(function( location, index ){\r\n\r\n\t\t\tvar nearbySteps = scope_Spectrum.getNearbySteps( location );\r\n\t\t\tvar value = scope_Values[index];\r\n\t\t\tvar increment = nearbySteps.thisStep.step;\r\n\t\t\tvar decrement = null;\r\n\r\n\t\t\t// If the next value in this step moves into the next step,\r\n\t\t\t// the increment is the start of the next step - the current value\r\n\t\t\tif ( increment !== false ) {\r\n\t\t\t\tif ( value + increment > nearbySteps.stepAfter.startValue ) {\r\n\t\t\t\t\tincrement = nearbySteps.stepAfter.startValue - value;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\r\n\t\t\t// If the value is beyond the starting point\r\n\t\t\tif ( value > nearbySteps.thisStep.startValue ) {\r\n\t\t\t\tdecrement = nearbySteps.thisStep.step;\r\n\t\t\t}\r\n\r\n\t\t\telse if ( nearbySteps.stepBefore.step === false ) {\r\n\t\t\t\tdecrement = false;\r\n\t\t\t}\r\n\r\n\t\t\t// If a handle is at the start of a step, it always steps back into the previous step first\r\n\t\t\telse {\r\n\t\t\t\tdecrement = value - nearbySteps.stepBefore.highestStep;\r\n\t\t\t}\r\n\r\n\r\n\t\t\t// Now, if at the slider edges, there is not in/decrement\r\n\t\t\tif ( location === 100 ) {\r\n\t\t\t\tincrement = null;\r\n\t\t\t}\r\n\r\n\t\t\telse if ( location === 0 ) {\r\n\t\t\t\tdecrement = null;\r\n\t\t\t}\r\n\r\n\t\t\t// As per #391, the comparison for the decrement step can have some rounding issues.\r\n\t\t\tvar stepDecimals = scope_Spectrum.countStepDecimals();\r\n\r\n\t\t\t// Round per #391\r\n\t\t\tif ( increment !== null && increment !== false ) {\r\n\t\t\t\tincrement = Number(increment.toFixed(stepDecimals));\r\n\t\t\t}\r\n\r\n\t\t\tif ( decrement !== null && decrement !== false ) {\r\n\t\t\t\tdecrement = Number(decrement.toFixed(stepDecimals));\r\n\t\t\t}\r\n\r\n\t\t\treturn [decrement, increment];\r\n\t\t});\r\n\t}\r\n\r\n\t// Attach an event to this slider, possibly including a namespace\r\n\tfunction bindEvent ( namespacedEvent, callback ) {\r\n\t\tscope_Events[namespacedEvent] = scope_Events[namespacedEvent] || [];\r\n\t\tscope_Events[namespacedEvent].push(callback);\r\n\r\n\t\t// If the event bound is 'update,' fire it immediately for all handles.\r\n\t\tif ( namespacedEvent.split('.')[0] === 'update' ) {\r\n\t\t\tscope_Handles.forEach(function(a, index){\r\n\t\t\t\tfireEvent('update', index);\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\t// Undo attachment of event\r\n\tfunction removeEvent ( namespacedEvent ) {\r\n\r\n\t\tvar event = namespacedEvent && namespacedEvent.split('.')[0];\r\n\t\tvar namespace = event && namespacedEvent.substring(event.length);\r\n\r\n\t\tObject.keys(scope_Events).forEach(function( bind ){\r\n\r\n\t\t\tvar tEvent = bind.split('.')[0],\r\n\t\t\t\ttNamespace = bind.substring(tEvent.length);\r\n\r\n\t\t\tif ( (!event || event === tEvent) && (!namespace || namespace === tNamespace) ) {\r\n\t\t\t\tdelete scope_Events[bind];\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\t// Updateable: margin, limit, padding, step, range, animate, snap\r\n\tfunction updateOptions ( optionsToUpdate, fireSetEvent ) {\r\n\r\n\t\t// Spectrum is created using the range, snap, direction and step options.\r\n\t\t// 'snap' and 'step' can be updated, 'direction' cannot, due to event binding.\r\n\t\t// If 'snap' and 'step' are not passed, they should remain unchanged.\r\n\t\tvar v = valueGet();\r\n\r\n\t\tvar updateAble = ['margin', 'limit', 'padding', 'range', 'animate', 'snap', 'step', 'format'];\r\n\r\n\t\t// Only change options that we're actually passed to update.\r\n\t\tupdateAble.forEach(function(name){\r\n\t\t\tif ( optionsToUpdate[name] !== undefined ) {\r\n\t\t\t\toriginalOptions[name] = optionsToUpdate[name];\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tvar newOptions = testOptions(originalOptions);\r\n\r\n\t\t// Load new options into the slider state\r\n\t\tupdateAble.forEach(function(name){\r\n\t\t\tif ( optionsToUpdate[name] !== undefined ) {\r\n\t\t\t\toptions[name] = newOptions[name];\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\t// Save current spectrum direction as testOptions in testRange call\r\n\t\t// doesn't rely on current direction\r\n\t\tnewOptions.spectrum.direction = scope_Spectrum.direction;\r\n\t\tscope_Spectrum = newOptions.spectrum;\r\n\r\n\t\t// Limit, margin and padding depend on the spectrum but are stored outside of it. (#677)\r\n\t\toptions.margin = newOptions.margin;\r\n\t\toptions.limit = newOptions.limit;\r\n\t\toptions.padding = newOptions.padding;\r\n\r\n\t\t// Invalidate the current positioning so valueSet forces an update.\r\n\t\tscope_Locations = [];\r\n\t\tvalueSet(optionsToUpdate.start || v, fireSetEvent);\r\n\t}\r\n\r\n\t// Throw an error if the slider was already initialized.\r\n\tif ( scope_Target.noUiSlider ) {\r\n\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): Slider was already initialized.\");\r\n\t}\r\n\r\n\t// Create the base element, initialise HTML and set classes.\r\n\t// Add handles and connect elements.\r\n\taddSlider(scope_Target);\r\n\taddElements(options.connect, scope_Base);\r\n\r\n\tscope_Self = {\r\n\t\tdestroy: destroy,\r\n\t\tsteps: getCurrentStep,\r\n\t\ton: bindEvent,\r\n\t\toff: removeEvent,\r\n\t\tget: valueGet,\r\n\t\tset: valueSet,\r\n\t\treset: valueReset,\r\n\t\t// Exposed for unit testing, don't use this in your application.\r\n\t\t__moveHandles: function(a, b, c) { moveHandles(a, b, scope_Locations, c); },\r\n\t\toptions: originalOptions, // Issue #600, #678\r\n\t\tupdateOptions: updateOptions,\r\n\t\ttarget: scope_Target, // Issue #597\r\n\t\tpips: pips // Issue #594\r\n\t};\r\n\r\n\t// Attach user events.\r\n\tbindSliderEvents(options.events);\r\n\r\n\t// Use the public value method to set the start values.\r\n\tvalueSet(options.start);\r\n\r\n\tif ( options.pips ) {\r\n\t\tpips(options.pips);\r\n\t}\r\n\r\n\tif ( options.tooltips ) {\r\n\t\ttooltips();\r\n\t}\r\n\r\n\treturn scope_Self;\r\n\r\n}\r\n\r\n\r\n\t// Run the standard initializer\r\n\tfunction initialize ( target, originalOptions ) {\r\n\r\n\t\tif ( !target.nodeName ) {\r\n\t\t\tthrow new Error(\"noUiSlider (\" + VERSION + \"): create requires a single element.\");\r\n\t\t}\r\n\r\n\t\t// Test the options and create the slider environment;\r\n\t\tvar options = testOptions( originalOptions, target );\r\n\t\tvar api = closure( target, options, originalOptions );\r\n\r\n\t\ttarget.noUiSlider = api;\r\n\r\n\t\treturn api;\r\n\t}\r\n\r\n\t// Use an object instead of a function for future expansibility;\r\n\treturn {\r\n\t\tversion: VERSION,\r\n\t\tcreate: initialize\r\n\t};\r\n\r\n}));"
  },
  {
    "path": "lib/offset.js",
    "content": "/*\n Copyright (c) 2014-2017, Jan Bösenberg & Jürg Lehni\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in all\n copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n SOFTWARE.\n */\n\nvar Path = paper.Path;\nvar Segment = paper.Segment;\nvar Curve = paper.Curve;\nvar Line = paper.Line;\nvar Numerical = paper.Numerical;\n\nvar OffsetUtils =  {\n    offsetPath: function(path, offset, result) {\n        var outerPath = new Path({ insert: false }),\n            epsilon = Numerical.GEOMETRIC_EPSILON,\n            enforeArcs = true;\n        for (var i = 0; i < path.curves.length; i++) {\n            var curve = path.curves[i];\n            if (curve.hasLength(epsilon)) {\n                var segments = this.getOffsetSegments(curve, offset),\n                    start = segments[0];\n                if (outerPath.isEmpty()) {\n                    outerPath.addSegments(segments);\n                } else {\n                    var lastCurve = outerPath.lastCurve;\n                    if (!lastCurve.point2.isClose(start.point, epsilon)) {\n                        if (enforeArcs || lastCurve.getTangentAtTime(1).dot(start.point.subtract(curve.point1)) >= 0) {\n                            this.addRoundJoin(outerPath, start.point, curve.point1, Math.abs(offset));\n                        } else {\n                            // Connect points with a line\n                            outerPath.lineTo(start.point);\n                        }\n                    }\n                    outerPath.lastSegment.handleOut = start.handleOut;\n                    outerPath.addSegments(segments.slice(1));\n                }\n            }\n        }\n        if (path.isClosed()) {\n            if (!outerPath.lastSegment.point.isClose(outerPath.firstSegment.point, epsilon) && (enforeArcs ||\n                    outerPath.lastCurve.getTangentAtTime(1).dot(outerPath.firstSegment.point.subtract(path.firstSegment.point)) >= 0)) {\n                this.addRoundJoin(outerPath, outerPath.firstSegment.point, path.firstSegment.point, Math.abs(offset));\n            }\n            outerPath.closePath();\n        }\n        return outerPath;\n    },\n\n    joinOffsets: function (outerPath, innerPath, originPath, offset) {\n        function connect(path, dest, originSegment, offset, type, miterLimit,\n            addLine) {\n            var geomEpsilon = 1e-8;\n            var enforeArcs = true;\n            function fixHandles(seg) {\n                var handleIn = seg.handleIn,\n                    handleOut = seg.handleOut;\n                if (handleIn.length < handleOut.length) {\n                    seg.handleIn = handleIn.project(handleOut);\n                } else {\n                    seg.handleOut = handleOut.project(handleIn);\n                }\n            }\n\n            function addPoint(point) {\n                if (!point.equals(path.lastSegment.point)) {\n                    path.add(point);\n                }\n            }\n\n            var center = originSegment.point,\n                start = path.lastSegment,\n                pt1 = start.point,\n                pt2 = dest.point,\n                connected = false;\n\n            if (!pt1.isClose(pt2, geomEpsilon)) {\n                if (enforeArcs\n                        // decide if the join is inside or outside the stroke\n                        // by checking on which side of the line connecting pt1 \n                        // and pt2 the center lies.\n                        || new Line(pt1, pt2).getSignedDistance(center)\n                            * offset <= geomEpsilon) {\n                    // Calculate the through point based on the vectors from center\n                    // to pt1 / pt2\n                    var radius = Math.abs(offset);\n                    switch (type) {\n                    case 'round':\n                        // Try adding the vectors together to get the average vector\n                        // which can be normalized to radius length to get the\n                        // through point except if the two vectors have 180° between\n                        // them, in which case we can rotate one of them by 90°.\n                        var v1 = pt1.subtract(center),\n                            v2 = pt2.subtract(center),\n                            v = v1.add(v2),\n                            through = v.getLength() < geomEpsilon\n                                    ? v2.rotate(90).add(center)\n                                    : center.add(v.normalize(radius));\n                        path.arcTo(through, pt2);\n                        break;\n                    case 'miter':\n                        Path._addBevelJoin(originSegment, 'miter', radius, 4,\n                                null, null, addPoint);\n                        break;\n                    case 'square':\n                        Path._addSquareCap(originSegment, 'square', radius,\n                                null, null, addPoint);\n                        break;\n                    default: // 'bevel' / 'butt'\n                        path.lineTo(pt2);\n                    }\n                    connected = true;\n                } else if (addLine) {\n                    path.lineTo(pt2);\n                    connected = true;\n                }\n                if (connected) {\n                    fixHandles(start);\n                    var last = path.lastSegment;\n                    fixHandles(last);\n                    // Adjust handleOut, except for when connecting back to the\n                    // beginning on closed paths.\n                    if (dest !== path.firstSegment) {\n                        last.handleOut = dest.handleOut;\n                    }\n                }\n            } else {\n                if (dest !== path.firstSegment) {\n                    path.lastSegment.handleOut = dest.handleOut;\n                }\n            }\n            return connected;\n        }\n\n        outerPath.closed = innerPath.closed = false;\n        var path = outerPath,\n            open = !originPath.closed,\n            strokeCap = originPath.strokeCap;\n        path.reverse();\n        if (open) {\n            connect(path, innerPath.firstSegment, originPath.firstSegment,\n                    offset, strokeCap);\n        }\n        path.join(innerPath);\n        if (open) {\n            connect(path, path.firstSegment, originPath.lastSegment,\n                    offset, strokeCap);\n        }\n        path.closePath();\n        return path;\n    },\n\n    /**\n     * Creates an offset for the specified curve and returns the segments of\n     * that offset path.\n     *\n     * @param {Curve} curve the curve to be offset\n     * @param {Number} offset the offset distance\n     * @returns {Segment[]} an array of segments describing the offset path\n     */\n    getOffsetSegments: function(curve, offset) {\n        if (curve.isStraight()) {\n            var n = curve.getNormalAtTime(0.5).multiply(offset),\n                p1 = curve.point1.add(n),\n                p2 = curve.point2.add(n);\n            return [new Segment(p1), new Segment(p2)];\n        } else {\n            var curves = this.splitCurveForOffseting(curve),\n                segments = [];\n            for (var i = 0, l = curves.length; i < l; i++) {\n                var offsetCurves = this.getOffsetCurves(curves[i], offset, 0),\n                    prevSegment;\n                for (var j = 0, m = offsetCurves.length; j < m; j++) {\n                    var curve = offsetCurves[j],\n                        segment = curve.segment1;\n                    if (prevSegment) {\n                        prevSegment.handleOut = segment.handleOut;\n                    } else {\n                        segments.push(segment);\n                    }\n                    segments.push(prevSegment = curve.segment2);\n                }\n            }\n            return segments;\n        }\n    },\n\n    /**\n     * Approach for Curve Offsetting based on:\n     *   \"A New Shape Control and Classification for Cubic Bézier Curves\"\n     *   Shi-Nine Yang and Ming-Liang Huang\n     */\n    offsetCurve_middle: function(curve, offset) {\n        var v = curve.getValues(),\n            p1 = curve.point1.add(Curve.getNormal(v, 0).multiply(offset)),\n            p2 = curve.point2.add(Curve.getNormal(v, 1).multiply(offset)),\n            pt = Curve.getPoint(v, 0.5).add(\n                    Curve.getNormal(v, 0.5).multiply(offset)),\n            t1 = Curve.getTangent(v, 0),\n            t2 = Curve.getTangent(v, 1),\n            div = t1.cross(t2) * 3 / 4,\n            d = pt.multiply(2).subtract(p1.add(p2)),\n            a = d.cross(t2) / div,\n            b = d.cross(t1) / div;\n        return new Curve(p1, t1.multiply(a), t2.multiply(-b), p2);\n    },\n\n    offsetCurve_average: function(curve, offset) {\n        var v = curve.getValues(),\n            p1 = curve.point1.add(Curve.getNormal(v, 0).multiply(offset)),\n            p2 = curve.point2.add(Curve.getNormal(v, 1).multiply(offset)),\n            t = this.getAverageTangentTime(v),\n            u = 1 - t,\n            pt = Curve.getPoint(v, t).add(\n                    Curve.getNormal(v, t).multiply(offset)),\n            t1 = Curve.getTangent(v, 0),\n            t2 = Curve.getTangent(v, 1),\n            div = t1.cross(t2) * 3 * t * u,\n            v = pt.subtract(\n                    p1.multiply(u * u * (1 + 2 * t)).add(\n                    p2.multiply(t * t * (3 - 2 * t)))),\n            a = v.cross(t2) / (div * u),\n            b = v.cross(t1) / (div * t);\n        return new Curve(p1, t1.multiply(a), t2.multiply(-b), p2);\n    },\n\n    /**\n     * This algorithm simply scales the curve so its end points are at the\n     * calculated offsets of the original end points.\n     */\n    offsetCurve_simple: function (crv, dist) {\n        // calculate end points of offset curve\n        var p1 = crv.point1.add(crv.getNormalAtTime(0).multiply(dist));\n        var p4 = crv.point2.add(crv.getNormalAtTime(1).multiply(dist));\n        // get scale ratio\n        var pointDist = crv.point1.getDistance(crv.point2);\n        // TODO: Handle cases when pointDist == 0\n        var f = p1.getDistance(p4) / pointDist;\n        if (crv.point2.subtract(crv.point1).dot(p4.subtract(p1)) < 0) {\n            f = -f; // probably more correct than connecting with line\n        }\n        // Scale handles and generate offset curve\n        return new Curve(p1, crv.handle1.multiply(f), crv.handle2.multiply(f), p4);\n    },\n\n    getOffsetCurves: function(curve, offset, method) {\n        var errorThreshold = 0.01,\n            radius = Math.abs(offset),\n            offsetMethod = this['offsetCurve_' + (method || 'middle')],\n            that = this;\n\n        function offsetCurce(curve, curves, recursion) {\n            var offsetCurve = offsetMethod.call(that, curve, offset),\n                cv = curve.getValues(),\n                ov = offsetCurve.getValues(),\n                count = 16,\n                error = 0;\n            for (var i = 1; i < count; i++) {\n                var t = i / count,\n                    p = Curve.getPoint(cv, t),\n                    n = Curve.getNormal(cv, t),\n                    roots = Curve.getCurveLineIntersections(ov, p.x, p.y, n.x, n.y),\n                    dist = 2 * radius;\n                for (var j = 0, l = roots.length; j < l; j++) {\n                    var d = Curve.getPoint(ov, roots[j]).getDistance(p);\n                    if (d < dist)\n                        dist = d;\n                }\n                var err = Math.abs(radius - dist);\n                if (err > error)\n                    error = err;\n            }\n            if (error > errorThreshold && recursion++ < 8) {\n                if (error === radius) {\n                    // console.log(cv);\n                }\n                var curve2 = curve.divideAtTime(that.getAverageTangentTime(cv));\n                offsetCurce(curve, curves, recursion);\n                offsetCurce(curve2, curves, recursion);\n            } else {\n                curves.push(offsetCurve);\n            }\n            return curves;\n        }\n\n        return offsetCurce(curve, [], 0);\n    },\n\n    /**\n     * Split curve into sections that can then be treated individually by an\n     * offset algorithm.\n     */\n    splitCurveForOffseting: function(curve) {\n        var curves = [curve.clone()], // Clone so path is not modified.\n            that = this;\n        if (curve.isStraight())\n            return curves;\n\n        function splitAtRoots(index, roots) {\n            for (var i = 0, prevT, l = roots && roots.length; i < l; i++) {\n                var t = roots[i],\n                    curve = curves[index].divideAtTime(\n                            // Renormalize curve-time for multiple roots:\n                            i ? (t - prevT) / (1 - prevT) : t);\n                prevT = t;\n                if (curve)\n                    curves.splice(++index, 0, curve);\n            }\n        }\n\n        // Recursively splits the specified curve if the angle between the two\n        // handles is too large (we use 60° as a threshold).\n        function splitLargeAngles(index, recursion) {\n            var curve = curves[index],\n                v = curve.getValues(),\n                n1 = Curve.getNormal(v, 0),\n                n2 = Curve.getNormal(v, 1).negate(),\n                cos = n1.dot(n2);\n            if (cos > -0.5 && ++recursion < 4) {\n                curves.splice(index + 1, 0,\n                        curve.divideAtTime(that.getAverageTangentTime(v)));\n                splitLargeAngles(index + 1, recursion);\n                splitLargeAngles(index, recursion);\n            }\n        }\n\n        // Split curves at cusps and inflection points.\n        var info = curve.classify();\n        if (info.roots && info.type !== 'loop') {\n            splitAtRoots(0, info.roots);\n        }\n\n        // Split sub-curves at peaks.\n        for (var i = curves.length - 1; i >= 0; i--) {\n            splitAtRoots(i, Curve.getPeaks(curves[i].getValues()));\n        }\n\n        // Split sub-curves with too large angle between handles.\n        for (var i = curves.length - 1; i >= 0; i--) {\n            //splitLargeAngles(i, 0);\n        }\n        return curves;\n    },\n\n    /**\n     * Returns the first curve-time where the curve has its tangent in the same\n     * direction as the average of the tangents at its beginning and end.\n     */\n    getAverageTangentTime: function(v) {\n        var tan = Curve.getTangent(v, 0).add(Curve.getTangent(v, 1)),\n            tx = tan.x,\n            ty = tan.y,\n            abs = Math.abs,\n            flip = abs(ty) < abs(tx),\n            s = flip ? ty / tx : tx / ty,\n            ia = flip ? 1 : 0, // the abscissa index\n            io = ia ^ 1,       // the ordinate index\n            a0 = v[ia + 0], o0 = v[io + 0],\n            a1 = v[ia + 2], o1 = v[io + 2],\n            a2 = v[ia + 4], o2 = v[io + 4],\n            a3 = v[ia + 6], o3 = v[io + 6],\n            aA =     -a0 + 3 * a1 - 3 * a2 + a3,\n            aB =  3 * a0 - 6 * a1 + 3 * a2,\n            aC = -3 * a0 + 3 * a1,\n            oA =     -o0 + 3 * o1 - 3 * o2 + o3,\n            oB =  3 * o0 - 6 * o1 + 3 * o2,\n            oC = -3 * o0 + 3 * o1,\n            roots = [],\n            epsilon = Numerical.CURVETIME_EPSILON,\n            count = Numerical.solveQuadratic(\n                    3 * (aA - s * oA),\n                    2 * (aB - s * oB),\n                    aC - s * oC, roots,\n                    epsilon, 1 - epsilon);\n        // Fall back to 0.5, so we always have a place to split...\n        return count > 0 ? roots[0] : 0.5;\n    },\n\n    addRoundJoin: function(path, dest, center, radius) {\n        // return path.lineTo(dest);\n        var middle = path.lastSegment.point.add(dest).divide(2),\n            through = center.add(middle.subtract(center).normalize(radius));\n        path.arcTo(through, dest);\n    },\n};"
  },
  {
    "path": "lib/paper-full.js",
    "content": "/*!\n * Paper.js v0.11.3 - The Swiss Army Knife of Vector Graphics Scripting.\n * http://paperjs.org/\n *\n * Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey\n * http://scratchdisk.com/ & http://jonathanpuckey.com/\n *\n * Distributed under the MIT license. See LICENSE file for details.\n *\n * All rights reserved.\n *\n * Date: Sat Apr 22 20:01:34 2017 +0200\n *\n ***\n *\n * Straps.js - Class inheritance library with support for bean-style accessors\n *\n * Copyright (c) 2006 - 2016 Juerg Lehni\n * http://scratchdisk.com/\n *\n * Distributed under the MIT license.\n *\n ***\n *\n * Acorn.js\n * http://marijnhaverbeke.nl/acorn/\n *\n * Acorn is a tiny, fast JavaScript parser written in JavaScript,\n * created by Marijn Haverbeke and released under an MIT license.\n *\n */\n\nvar paper = function(self, undefined) {\n\nself = self || require('./node/self.js');\nvar window = self.window,\n\tdocument = self.document;\n\nvar Base = new function() {\n\tvar hidden = /^(statics|enumerable|beans|preserve)$/,\n\t\tarray = [],\n\t\tslice = array.slice,\n\t\tcreate = Object.create,\n\t\tdescribe = Object.getOwnPropertyDescriptor,\n\t\tdefine = Object.defineProperty,\n\n\t\tforEach = array.forEach || function(iter, bind) {\n\t\t\tfor (var i = 0, l = this.length; i < l; i++) {\n\t\t\t\titer.call(bind, this[i], i, this);\n\t\t\t}\n\t\t},\n\n\t\tforIn = function(iter, bind) {\n\t\t\tfor (var i in this) {\n\t\t\t\tif (this.hasOwnProperty(i))\n\t\t\t\t\titer.call(bind, this[i], i, this);\n\t\t\t}\n\t\t},\n\n\t\tset = Object.assign || function(dst) {\n\t\t\tfor (var i = 1, l = arguments.length; i < l; i++) {\n\t\t\t\tvar src = arguments[i];\n\t\t\t\tfor (var key in src) {\n\t\t\t\t\tif (src.hasOwnProperty(key))\n\t\t\t\t\t\tdst[key] = src[key];\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn dst;\n\t\t},\n\n\t\teach = function(obj, iter, bind) {\n\t\t\tif (obj) {\n\t\t\t\tvar desc = describe(obj, 'length');\n\t\t\t\t(desc && typeof desc.value === 'number' ? forEach : forIn)\n\t\t\t\t\t.call(obj, iter, bind = bind || obj);\n\t\t\t}\n\t\t\treturn bind;\n\t\t};\n\n\tfunction inject(dest, src, enumerable, beans, preserve) {\n\t\tvar beansNames = {};\n\n\t\tfunction field(name, val) {\n\t\t\tval = val || (val = describe(src, name))\n\t\t\t\t\t&& (val.get ? val : val.value);\n\t\t\tif (typeof val === 'string' && val[0] === '#')\n\t\t\t\tval = dest[val.substring(1)] || val;\n\t\t\tvar isFunc = typeof val === 'function',\n\t\t\t\tres = val,\n\t\t\t\tprev = preserve || isFunc && !val.base\n\t\t\t\t\t\t? (val && val.get ? name in dest : dest[name])\n\t\t\t\t\t\t: null,\n\t\t\t\tbean;\n\t\t\tif (!preserve || !prev) {\n\t\t\t\tif (isFunc && prev)\n\t\t\t\t\tval.base = prev;\n\t\t\t\tif (isFunc && beans !== false\n\t\t\t\t\t\t&& (bean = name.match(/^([gs]et|is)(([A-Z])(.*))$/)))\n\t\t\t\t\tbeansNames[bean[3].toLowerCase() + bean[4]] = bean[2];\n\t\t\t\tif (!res || isFunc || !res.get || typeof res.get !== 'function'\n\t\t\t\t\t\t|| !Base.isPlainObject(res)) {\n\t\t\t\t\tres = { value: res, writable: true };\n\t\t\t\t}\n\t\t\t\tif ((describe(dest, name)\n\t\t\t\t\t\t|| { configurable: true }).configurable) {\n\t\t\t\t\tres.configurable = true;\n\t\t\t\t\tres.enumerable = enumerable != null ? enumerable : !bean;\n\t\t\t\t}\n\t\t\t\tdefine(dest, name, res);\n\t\t\t}\n\t\t}\n\t\tif (src) {\n\t\t\tfor (var name in src) {\n\t\t\t\tif (src.hasOwnProperty(name) && !hidden.test(name))\n\t\t\t\t\tfield(name);\n\t\t\t}\n\t\t\tfor (var name in beansNames) {\n\t\t\t\tvar part = beansNames[name],\n\t\t\t\t\tset = dest['set' + part],\n\t\t\t\t\tget = dest['get' + part] || set && dest['is' + part];\n\t\t\t\tif (get && (beans === true || get.length === 0))\n\t\t\t\t\tfield(name, { get: get, set: set });\n\t\t\t}\n\t\t}\n\t\treturn dest;\n\t}\n\n\tfunction Base() {\n\t\tfor (var i = 0, l = arguments.length; i < l; i++) {\n\t\t\tvar src = arguments[i];\n\t\t\tif (src)\n\t\t\t\tset(this, src);\n\t\t}\n\t\treturn this;\n\t}\n\n\treturn inject(Base, {\n\t\tinject: function(src) {\n\t\t\tif (src) {\n\t\t\t\tvar statics = src.statics === true ? src : src.statics,\n\t\t\t\t\tbeans = src.beans,\n\t\t\t\t\tpreserve = src.preserve;\n\t\t\t\tif (statics !== src)\n\t\t\t\t\tinject(this.prototype, src, src.enumerable, beans, preserve);\n\t\t\t\tinject(this, statics, null, beans, preserve);\n\t\t\t}\n\t\t\tfor (var i = 1, l = arguments.length; i < l; i++)\n\t\t\t\tthis.inject(arguments[i]);\n\t\t\treturn this;\n\t\t},\n\n\t\textend: function() {\n\t\t\tvar base = this,\n\t\t\t\tctor,\n\t\t\t\tproto;\n\t\t\tfor (var i = 0, obj, l = arguments.length;\n\t\t\t\t\ti < l && !(ctor && proto); i++) {\n\t\t\t\tobj = arguments[i];\n\t\t\t\tctor = ctor || obj.initialize;\n\t\t\t\tproto = proto || obj.prototype;\n\t\t\t}\n\t\t\tctor = ctor || function() {\n\t\t\t\tbase.apply(this, arguments);\n\t\t\t};\n\t\t\tproto = ctor.prototype = proto || create(this.prototype);\n\t\t\tdefine(proto, 'constructor',\n\t\t\t\t\t{ value: ctor, writable: true, configurable: true });\n\t\t\tinject(ctor, this);\n\t\t\tif (arguments.length)\n\t\t\t\tthis.inject.apply(ctor, arguments);\n\t\t\tctor.base = base;\n\t\t\treturn ctor;\n\t\t}\n\t}).inject({\n\t\tenumerable: false,\n\n\t\tinitialize: Base,\n\n\t\tset: Base,\n\n\t\tinject: function() {\n\t\t\tfor (var i = 0, l = arguments.length; i < l; i++) {\n\t\t\t\tvar src = arguments[i];\n\t\t\t\tif (src) {\n\t\t\t\t\tinject(this, src, src.enumerable, src.beans, src.preserve);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\n\t\textend: function() {\n\t\t\tvar res = create(this);\n\t\t\treturn res.inject.apply(res, arguments);\n\t\t},\n\n\t\teach: function(iter, bind) {\n\t\t\treturn each(this, iter, bind);\n\t\t},\n\n\t\tclone: function() {\n\t\t\treturn new this.constructor(this);\n\t\t},\n\n\t\tstatics: {\n\t\t\tset: set,\n\t\t\teach: each,\n\t\t\tcreate: create,\n\t\t\tdefine: define,\n\t\t\tdescribe: describe,\n\n\t\t\tclone: function(obj) {\n\t\t\t\treturn set(new obj.constructor(), obj);\n\t\t\t},\n\n\t\t\tisPlainObject: function(obj) {\n\t\t\t\tvar ctor = obj != null && obj.constructor;\n\t\t\t\treturn ctor && (ctor === Object || ctor === Base\n\t\t\t\t\t\t|| ctor.name === 'Object');\n\t\t\t},\n\n\t\t\tpick: function(a, b) {\n\t\t\t\treturn a !== undefined ? a : b;\n\t\t\t},\n\n\t\t\tslice: function(list, begin, end) {\n\t\t\t\treturn slice.call(list, begin, end);\n\t\t\t}\n\t\t}\n\t});\n};\n\nif (typeof module !== 'undefined')\n\tmodule.exports = Base;\n\nBase.inject({\n\tenumerable: false,\n\n\ttoString: function() {\n\t\treturn this._id != null\n\t\t\t?  (this._class || 'Object') + (this._name\n\t\t\t\t? \" '\" + this._name + \"'\"\n\t\t\t\t: ' @' + this._id)\n\t\t\t: '{ ' + Base.each(this, function(value, key) {\n\t\t\t\tif (!/^_/.test(key)) {\n\t\t\t\t\tvar type = typeof value;\n\t\t\t\t\tthis.push(key + ': ' + (type === 'number'\n\t\t\t\t\t\t\t? Formatter.instance.number(value)\n\t\t\t\t\t\t\t: type === 'string' ? \"'\" + value + \"'\" : value));\n\t\t\t\t}\n\t\t\t}, []).join(', ') + ' }';\n\t},\n\n\tgetClassName: function() {\n\t\treturn this._class || '';\n\t},\n\n\timportJSON: function(json) {\n\t\treturn Base.importJSON(json, this);\n\t},\n\n\texportJSON: function(options) {\n\t\treturn Base.exportJSON(this, options);\n\t},\n\n\ttoJSON: function() {\n\t\treturn Base.serialize(this);\n\t},\n\n\tset: function(props, exclude) {\n\t\tif (props)\n\t\t\tBase.filter(this, props, exclude, this._prioritize);\n\t\treturn this;\n\t}\n}, {\n\nbeans: false,\nstatics: {\n\texports: {},\n\n\textend: function extend() {\n\t\tvar res = extend.base.apply(this, arguments),\n\t\t\tname = res.prototype._class;\n\t\tif (name && !Base.exports[name])\n\t\t\tBase.exports[name] = res;\n\t\treturn res;\n\t},\n\n\tequals: function(obj1, obj2) {\n\t\tif (obj1 === obj2)\n\t\t\treturn true;\n\t\tif (obj1 && obj1.equals)\n\t\t\treturn obj1.equals(obj2);\n\t\tif (obj2 && obj2.equals)\n\t\t\treturn obj2.equals(obj1);\n\t\tif (obj1 && obj2\n\t\t\t\t&& typeof obj1 === 'object' && typeof obj2 === 'object') {\n\t\t\tif (Array.isArray(obj1) && Array.isArray(obj2)) {\n\t\t\t\tvar length = obj1.length;\n\t\t\t\tif (length !== obj2.length)\n\t\t\t\t\treturn false;\n\t\t\t\twhile (length--) {\n\t\t\t\t\tif (!Base.equals(obj1[length], obj2[length]))\n\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tvar keys = Object.keys(obj1),\n\t\t\t\t\tlength = keys.length;\n\t\t\t\tif (length !== Object.keys(obj2).length)\n\t\t\t\t\treturn false;\n\t\t\t\twhile (length--) {\n\t\t\t\t\tvar key = keys[length];\n\t\t\t\t\tif (!(obj2.hasOwnProperty(key)\n\t\t\t\t\t\t\t&& Base.equals(obj1[key], obj2[key])))\n\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t},\n\n\tread: function(list, start, options, amount) {\n\t\tif (this === Base) {\n\t\t\tvar value = this.peek(list, start);\n\t\t\tlist.__index++;\n\t\t\treturn value;\n\t\t}\n\t\tvar proto = this.prototype,\n\t\t\treadIndex = proto._readIndex,\n\t\t\tbegin = start || readIndex && list.__index || 0,\n\t\t\tlength = list.length,\n\t\t\tobj = list[begin];\n\t\tamount = amount || length - begin;\n\t\tif (obj instanceof this\n\t\t\t|| options && options.readNull && obj == null && amount <= 1) {\n\t\t\tif (readIndex)\n\t\t\t\tlist.__index = begin + 1;\n\t\t\treturn obj && options && options.clone ? obj.clone() : obj;\n\t\t}\n\t\tobj = Base.create(proto);\n\t\tif (readIndex)\n\t\t\tobj.__read = true;\n\t\tobj = obj.initialize.apply(obj, begin > 0 || begin + amount < length\n\t\t\t\t? Base.slice(list, begin, begin + amount)\n\t\t\t\t: list) || obj;\n\t\tif (readIndex) {\n\t\t\tlist.__index = begin + obj.__read;\n\t\t\tvar filtered = obj.__filtered;\n\t\t\tif (filtered) {\n\t\t\t\tlist.__filtered = filtered;\n\t\t\t\tobj.__filtered = undefined;\n\t\t\t}\n\t\t\tobj.__read = undefined;\n\t\t}\n\t\treturn obj;\n\t},\n\n\tpeek: function(list, start) {\n\t\treturn list[list.__index = start || list.__index || 0];\n\t},\n\n\tremain: function(list) {\n\t\treturn list.length - (list.__index || 0);\n\t},\n\n\treadList: function(list, start, options, amount) {\n\t\tvar res = [],\n\t\t\tentry,\n\t\t\tbegin = start || 0,\n\t\t\tend = amount ? begin + amount : list.length;\n\t\tfor (var i = begin; i < end; i++) {\n\t\t\tres.push(Array.isArray(entry = list[i])\n\t\t\t\t\t? this.read(entry, 0, options)\n\t\t\t\t\t: this.read(list, i, options, 1));\n\t\t}\n\t\treturn res;\n\t},\n\n\treadNamed: function(list, name, start, options, amount) {\n\t\tvar value = this.getNamed(list, name),\n\t\t\thasObject = value !== undefined;\n\t\tif (hasObject) {\n\t\t\tvar filtered = list.__filtered;\n\t\t\tif (!filtered) {\n\t\t\t\tfiltered = list.__filtered = Base.create(list[0]);\n\t\t\t\tfiltered.__unfiltered = list[0];\n\t\t\t}\n\t\t\tfiltered[name] = undefined;\n\t\t}\n\t\tvar l = hasObject ? [value] : list,\n\t\t\tres = this.read(l, start, options, amount);\n\t\treturn res;\n\t},\n\n\tgetNamed: function(list, name) {\n\t\tvar arg = list[0];\n\t\tif (list._hasObject === undefined)\n\t\t\tlist._hasObject = list.length === 1 && Base.isPlainObject(arg);\n\t\tif (list._hasObject)\n\t\t\treturn name ? arg[name] : list.__filtered || arg;\n\t},\n\n\thasNamed: function(list, name) {\n\t\treturn !!this.getNamed(list, name);\n\t},\n\n\tfilter: function(dest, source, exclude, prioritize) {\n\t\tvar processed;\n\n\t\tfunction handleKey(key) {\n\t\t\tif (!(exclude && key in exclude) &&\n\t\t\t\t!(processed && key in processed)) {\n\t\t\t\tvar value = source[key];\n\t\t\t\tif (value !== undefined)\n\t\t\t\t\tdest[key] = value;\n\t\t\t}\n\t\t}\n\n\t\tif (prioritize) {\n\t\t\tvar keys = {};\n\t\t\tfor (var i = 0, key, l = prioritize.length; i < l; i++) {\n\t\t\t\tif ((key = prioritize[i]) in source) {\n\t\t\t\t\thandleKey(key);\n\t\t\t\t\tkeys[key] = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tprocessed = keys;\n\t\t}\n\n\t\tObject.keys(source.__unfiltered || source).forEach(handleKey);\n\t\treturn dest;\n\t},\n\n\tisPlainValue: function(obj, asString) {\n\t\treturn Base.isPlainObject(obj) || Array.isArray(obj)\n\t\t\t\t|| asString && typeof obj === 'string';\n\t},\n\n\tserialize: function(obj, options, compact, dictionary) {\n\t\toptions = options || {};\n\n\t\tvar isRoot = !dictionary,\n\t\t\tres;\n\t\tif (isRoot) {\n\t\t\toptions.formatter = new Formatter(options.precision);\n\t\t\tdictionary = {\n\t\t\t\tlength: 0,\n\t\t\t\tdefinitions: {},\n\t\t\t\treferences: {},\n\t\t\t\tadd: function(item, create) {\n\t\t\t\t\tvar id = '#' + item._id,\n\t\t\t\t\t\tref = this.references[id];\n\t\t\t\t\tif (!ref) {\n\t\t\t\t\t\tthis.length++;\n\t\t\t\t\t\tvar res = create.call(item),\n\t\t\t\t\t\t\tname = item._class;\n\t\t\t\t\t\tif (name && res[0] !== name)\n\t\t\t\t\t\t\tres.unshift(name);\n\t\t\t\t\t\tthis.definitions[id] = res;\n\t\t\t\t\t\tref = this.references[id] = [id];\n\t\t\t\t\t}\n\t\t\t\t\treturn ref;\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tif (obj && obj._serialize) {\n\t\t\tres = obj._serialize(options, dictionary);\n\t\t\tvar name = obj._class;\n\t\t\tif (name && !obj._compactSerialize && (isRoot || !compact)\n\t\t\t\t\t&& res[0] !== name) {\n\t\t\t\tres.unshift(name);\n\t\t\t}\n\t\t} else if (Array.isArray(obj)) {\n\t\t\tres = [];\n\t\t\tfor (var i = 0, l = obj.length; i < l; i++)\n\t\t\t\tres[i] = Base.serialize(obj[i], options, compact, dictionary);\n\t\t} else if (Base.isPlainObject(obj)) {\n\t\t\tres = {};\n\t\t\tvar keys = Object.keys(obj);\n\t\t\tfor (var i = 0, l = keys.length; i < l; i++) {\n\t\t\t\tvar key = keys[i];\n\t\t\t\tres[key] = Base.serialize(obj[key], options, compact,\n\t\t\t\t\t\tdictionary);\n\t\t\t}\n\t\t} else if (typeof obj === 'number') {\n\t\t\tres = options.formatter.number(obj, options.precision);\n\t\t} else {\n\t\t\tres = obj;\n\t\t}\n\t\treturn isRoot && dictionary.length > 0\n\t\t\t\t? [['dictionary', dictionary.definitions], res]\n\t\t\t\t: res;\n\t},\n\n\tdeserialize: function(json, create, _data, _setDictionary, _isRoot) {\n\t\tvar res = json,\n\t\t\tisFirst = !_data,\n\t\t\thasDictionary = isFirst && json && json.length\n\t\t\t\t&& json[0][0] === 'dictionary';\n\t\t_data = _data || {};\n\t\tif (Array.isArray(json)) {\n\t\t\tvar type = json[0],\n\t\t\t\tisDictionary = type === 'dictionary';\n\t\t\tif (json.length == 1 && /^#/.test(type)) {\n\t\t\t\treturn _data.dictionary[type];\n\t\t\t}\n\t\t\ttype = Base.exports[type];\n\t\t\tres = [];\n\t\t\tfor (var i = type ? 1 : 0, l = json.length; i < l; i++) {\n\t\t\t\tres.push(Base.deserialize(json[i], create, _data,\n\t\t\t\t\t\tisDictionary, hasDictionary));\n\t\t\t}\n\t\t\tif (type) {\n\t\t\t\tvar args = res;\n\t\t\t\tif (create) {\n\t\t\t\t\tres = create(type, args, isFirst || _isRoot);\n\t\t\t\t} else {\n\t\t\t\t\tres = Base.create(type.prototype);\n\t\t\t\t\ttype.apply(res, args);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (Base.isPlainObject(json)) {\n\t\t\tres = {};\n\t\t\tif (_setDictionary)\n\t\t\t\t_data.dictionary = res;\n\t\t\tfor (var key in json)\n\t\t\t\tres[key] = Base.deserialize(json[key], create, _data);\n\t\t}\n\t\treturn hasDictionary ? res[1] : res;\n\t},\n\n\texportJSON: function(obj, options) {\n\t\tvar json = Base.serialize(obj, options);\n\t\treturn options && options.asString == false\n\t\t\t\t? json\n\t\t\t\t: JSON.stringify(json);\n\t},\n\n\timportJSON: function(json, target) {\n\t\treturn Base.deserialize(\n\t\t\t\ttypeof json === 'string' ? JSON.parse(json) : json,\n\t\t\t\tfunction(ctor, args, isRoot) {\n\t\t\t\t\tvar useTarget = isRoot && target\n\t\t\t\t\t\t\t&& target.constructor === ctor,\n\t\t\t\t\t\tobj = useTarget ? target\n\t\t\t\t\t\t\t: Base.create(ctor.prototype);\n\t\t\t\t\tif (args.length === 1 && obj instanceof Item\n\t\t\t\t\t\t\t&& (useTarget || !(obj instanceof Layer))) {\n\t\t\t\t\t\tvar arg = args[0];\n\t\t\t\t\t\tif (Base.isPlainObject(arg))\n\t\t\t\t\t\t\targ.insert = false;\n\t\t\t\t\t}\n\t\t\t\t\t(useTarget ? obj.set : ctor).apply(obj, args);\n\t\t\t\t\tif (useTarget)\n\t\t\t\t\t\ttarget = null;\n\t\t\t\t\treturn obj;\n\t\t\t\t});\n\t},\n\n\tsplice: function(list, items, index, remove) {\n\t\tvar amount = items && items.length,\n\t\t\tappend = index === undefined;\n\t\tindex = append ? list.length : index;\n\t\tif (index > list.length)\n\t\t\tindex = list.length;\n\t\tfor (var i = 0; i < amount; i++)\n\t\t\titems[i]._index = index + i;\n\t\tif (append) {\n\t\t\tlist.push.apply(list, items);\n\t\t\treturn [];\n\t\t} else {\n\t\t\tvar args = [index, remove];\n\t\t\tif (items)\n\t\t\t\targs.push.apply(args, items);\n\t\t\tvar removed = list.splice.apply(list, args);\n\t\t\tfor (var i = 0, l = removed.length; i < l; i++)\n\t\t\t\tremoved[i]._index = undefined;\n\t\t\tfor (var i = index + amount, l = list.length; i < l; i++)\n\t\t\t\tlist[i]._index = i;\n\t\t\treturn removed;\n\t\t}\n\t},\n\n\tcapitalize: function(str) {\n\t\treturn str.replace(/\\b[a-z]/g, function(match) {\n\t\t\treturn match.toUpperCase();\n\t\t});\n\t},\n\n\tcamelize: function(str) {\n\t\treturn str.replace(/-(.)/g, function(match, chr) {\n\t\t\treturn chr.toUpperCase();\n\t\t});\n\t},\n\n\thyphenate: function(str) {\n\t\treturn str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();\n\t}\n}});\n\nvar Emitter = {\n\ton: function(type, func) {\n\t\tif (typeof type !== 'string') {\n\t\t\tBase.each(type, function(value, key) {\n\t\t\t\tthis.on(key, value);\n\t\t\t}, this);\n\t\t} else {\n\t\t\tvar types = this._eventTypes,\n\t\t\t\tentry = types && types[type],\n\t\t\t\thandlers = this._callbacks = this._callbacks || {};\n\t\t\thandlers = handlers[type] = handlers[type] || [];\n\t\t\tif (handlers.indexOf(func) === -1) {\n\t\t\t\thandlers.push(func);\n\t\t\t\tif (entry && entry.install && handlers.length === 1)\n\t\t\t\t\tentry.install.call(this, type);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t},\n\n\toff: function(type, func) {\n\t\tif (typeof type !== 'string') {\n\t\t\tBase.each(type, function(value, key) {\n\t\t\t\tthis.off(key, value);\n\t\t\t}, this);\n\t\t\treturn;\n\t\t}\n\t\tvar types = this._eventTypes,\n\t\t\tentry = types && types[type],\n\t\t\thandlers = this._callbacks && this._callbacks[type],\n\t\t\tindex;\n\t\tif (handlers) {\n\t\t\tif (!func || (index = handlers.indexOf(func)) !== -1\n\t\t\t\t\t&& handlers.length === 1) {\n\t\t\t\tif (entry && entry.uninstall)\n\t\t\t\t\tentry.uninstall.call(this, type);\n\t\t\t\tdelete this._callbacks[type];\n\t\t\t} else if (index !== -1) {\n\t\t\t\thandlers.splice(index, 1);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t},\n\n\tonce: function(type, func) {\n\t\treturn this.on(type, function() {\n\t\t\tfunc.apply(this, arguments);\n\t\t\tthis.off(type, func);\n\t\t});\n\t},\n\n\temit: function(type, event) {\n\t\tvar handlers = this._callbacks && this._callbacks[type];\n\t\tif (!handlers)\n\t\t\treturn false;\n\t\tvar args = Base.slice(arguments, 1),\n\t\t\tsetTarget = event && event.target && !event.currentTarget;\n\t\thandlers = handlers.slice();\n\t\tif (setTarget)\n\t\t\tevent.currentTarget = this;\n\t\tfor (var i = 0, l = handlers.length; i < l; i++) {\n\t\t\tif (handlers[i].apply(this, args) == false) {\n\t\t\t\tif (event && event.stop)\n\t\t\t\t\tevent.stop();\n\t\t\t\tbreak;\n\t\t   }\n\t\t}\n\t\tif (setTarget)\n\t\t\tdelete event.currentTarget;\n\t\treturn true;\n\t},\n\n\tresponds: function(type) {\n\t\treturn !!(this._callbacks && this._callbacks[type]);\n\t},\n\n\tattach: '#on',\n\tdetach: '#off',\n\tfire: '#emit',\n\n\t_installEvents: function(install) {\n\t\tvar types = this._eventTypes,\n\t\t\thandlers = this._callbacks,\n\t\t\tkey = install ? 'install' : 'uninstall';\n\t\tif (types) {\n\t\t\tfor (var type in handlers) {\n\t\t\t\tif (handlers[type].length > 0) {\n\t\t\t\t\tvar entry = types[type],\n\t\t\t\t\t\tfunc = entry && entry[key];\n\t\t\t\t\tif (func)\n\t\t\t\t\t\tfunc.call(this, type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tstatics: {\n\t\tinject: function inject(src) {\n\t\t\tvar events = src._events;\n\t\t\tif (events) {\n\t\t\t\tvar types = {};\n\t\t\t\tBase.each(events, function(entry, key) {\n\t\t\t\t\tvar isString = typeof entry === 'string',\n\t\t\t\t\t\tname = isString ? entry : key,\n\t\t\t\t\t\tpart = Base.capitalize(name),\n\t\t\t\t\t\ttype = name.substring(2).toLowerCase();\n\t\t\t\t\ttypes[type] = isString ? {} : entry;\n\t\t\t\t\tname = '_' + name;\n\t\t\t\t\tsrc['get' + part] = function() {\n\t\t\t\t\t\treturn this[name];\n\t\t\t\t\t};\n\t\t\t\t\tsrc['set' + part] = function(func) {\n\t\t\t\t\t\tvar prev = this[name];\n\t\t\t\t\t\tif (prev)\n\t\t\t\t\t\t\tthis.off(type, prev);\n\t\t\t\t\t\tif (func)\n\t\t\t\t\t\t\tthis.on(type, func);\n\t\t\t\t\t\tthis[name] = func;\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t\tsrc._eventTypes = types;\n\t\t\t}\n\t\t\treturn inject.base.apply(this, arguments);\n\t\t}\n\t}\n};\n\nvar PaperScope = Base.extend({\n\t_class: 'PaperScope',\n\n\tinitialize: function PaperScope() {\n\t\tpaper = this;\n\t\tthis.settings = new Base({\n\t\t\tapplyMatrix: true,\n\t\t\tinsertItems: true,\n\t\t\thandleSize: 4,\n\t\t\thitTolerance: 0\n\t\t});\n\t\tthis.project = null;\n\t\tthis.projects = [];\n\t\tthis.tools = [];\n\t\tthis._id = PaperScope._id++;\n\t\tPaperScope._scopes[this._id] = this;\n\t\tvar proto = PaperScope.prototype;\n\t\tif (!this.support) {\n\t\t\tvar ctx = CanvasProvider.getContext(1, 1) || {};\n\t\t\tproto.support = {\n\t\t\t\tnativeDash: 'setLineDash' in ctx || 'mozDash' in ctx,\n\t\t\t\tnativeBlendModes: BlendMode.nativeModes\n\t\t\t};\n\t\t\tCanvasProvider.release(ctx);\n\t\t}\n\t\tif (!this.agent) {\n\t\t\tvar user = self.navigator.userAgent.toLowerCase(),\n\t\t\t\tos = (/(darwin|win|mac|linux|freebsd|sunos)/.exec(user)||[])[0],\n\t\t\t\tplatform = os === 'darwin' ? 'mac' : os,\n\t\t\t\tagent = proto.agent = proto.browser = { platform: platform };\n\t\t\tif (platform)\n\t\t\t\tagent[platform] = true;\n\t\t\tuser.replace(\n\t\t\t\t/(opera|chrome|safari|webkit|firefox|msie|trident|atom|node)\\/?\\s*([.\\d]+)(?:.*version\\/([.\\d]+))?(?:.*rv\\:v?([.\\d]+))?/g,\n\t\t\t\tfunction(match, n, v1, v2, rv) {\n\t\t\t\t\tif (!agent.chrome) {\n\t\t\t\t\t\tvar v = n === 'opera' ? v2 :\n\t\t\t\t\t\t\t\t/^(node|trident)$/.test(n) ? rv : v1;\n\t\t\t\t\t\tagent.version = v;\n\t\t\t\t\t\tagent.versionNumber = parseFloat(v);\n\t\t\t\t\t\tn = n === 'trident' ? 'msie' : n;\n\t\t\t\t\t\tagent.name = n;\n\t\t\t\t\t\tagent[n] = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t\tif (agent.chrome)\n\t\t\t\tdelete agent.webkit;\n\t\t\tif (agent.atom)\n\t\t\t\tdelete agent.chrome;\n\t\t}\n\t},\n\n\tversion: \"0.11.3\",\n\n\tgetView: function() {\n\t\tvar project = this.project;\n\t\treturn project && project._view;\n\t},\n\n\tgetPaper: function() {\n\t\treturn this;\n\t},\n\n\texecute: function(code, options) {\n\t\tpaper.PaperScript.execute(code, this, options);\n\t\tView.updateFocus();\n\t},\n\n\tinstall: function(scope) {\n\t\tvar that = this;\n\t\tBase.each(['project', 'view', 'tool'], function(key) {\n\t\t\tBase.define(scope, key, {\n\t\t\t\tconfigurable: true,\n\t\t\t\tget: function() {\n\t\t\t\t\treturn that[key];\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t\tfor (var key in this)\n\t\t\tif (!/^_/.test(key) && this[key])\n\t\t\t\tscope[key] = this[key];\n\t},\n\n\tsetup: function(element) {\n\t\tpaper = this;\n\t\tthis.project = new Project(element);\n\t\treturn this;\n\t},\n\n\tcreateCanvas: function(width, height) {\n\t\treturn CanvasProvider.getCanvas(width, height);\n\t},\n\n\tactivate: function() {\n\t\tpaper = this;\n\t},\n\n\tclear: function() {\n\t\tvar projects = this.projects,\n\t\t\ttools = this.tools;\n\t\tfor (var i = projects.length - 1; i >= 0; i--)\n\t\t\tprojects[i].remove();\n\t\tfor (var i = tools.length - 1; i >= 0; i--)\n\t\t\ttools[i].remove();\n\t},\n\n\tremove: function() {\n\t\tthis.clear();\n\t\tdelete PaperScope._scopes[this._id];\n\t},\n\n\tstatics: new function() {\n\t\tfunction handleAttribute(name) {\n\t\t\tname += 'Attribute';\n\t\t\treturn function(el, attr) {\n\t\t\t\treturn el[name](attr) || el[name]('data-paper-' + attr);\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\t_scopes: {},\n\t\t\t_id: 0,\n\n\t\t\tget: function(id) {\n\t\t\t\treturn this._scopes[id] || null;\n\t\t\t},\n\n\t\t\tgetAttribute: handleAttribute('get'),\n\t\t\thasAttribute: handleAttribute('has')\n\t\t};\n\t}\n});\n\nvar PaperScopeItem = Base.extend(Emitter, {\n\n\tinitialize: function(activate) {\n\t\tthis._scope = paper;\n\t\tthis._index = this._scope[this._list].push(this) - 1;\n\t\tif (activate || !this._scope[this._reference])\n\t\t\tthis.activate();\n\t},\n\n\tactivate: function() {\n\t\tif (!this._scope)\n\t\t\treturn false;\n\t\tvar prev = this._scope[this._reference];\n\t\tif (prev && prev !== this)\n\t\t\tprev.emit('deactivate');\n\t\tthis._scope[this._reference] = this;\n\t\tthis.emit('activate', prev);\n\t\treturn true;\n\t},\n\n\tisActive: function() {\n\t\treturn this._scope[this._reference] === this;\n\t},\n\n\tremove: function() {\n\t\tif (this._index == null)\n\t\t\treturn false;\n\t\tBase.splice(this._scope[this._list], null, this._index, 1);\n\t\tif (this._scope[this._reference] == this)\n\t\t\tthis._scope[this._reference] = null;\n\t\tthis._scope = null;\n\t\treturn true;\n\t},\n\n\tgetView: function() {\n\t\treturn this._scope.getView();\n\t}\n});\n\nvar Formatter = Base.extend({\n\tinitialize: function(precision) {\n\t\tthis.precision = Base.pick(precision, 5);\n\t\tthis.multiplier = Math.pow(10, this.precision);\n\t},\n\n\tnumber: function(val) {\n\t\treturn this.precision < 16\n\t\t\t\t? Math.round(val * this.multiplier) / this.multiplier : val;\n\t},\n\n\tpair: function(val1, val2, separator) {\n\t\treturn this.number(val1) + (separator || ',') + this.number(val2);\n\t},\n\n\tpoint: function(val, separator) {\n\t\treturn this.number(val.x) + (separator || ',') + this.number(val.y);\n\t},\n\n\tsize: function(val, separator) {\n\t\treturn this.number(val.width) + (separator || ',')\n\t\t\t\t+ this.number(val.height);\n\t},\n\n\trectangle: function(val, separator) {\n\t\treturn this.point(val, separator) + (separator || ',')\n\t\t\t\t+ this.size(val, separator);\n\t}\n});\n\nFormatter.instance = new Formatter();\n\nvar Numerical = new function() {\n\n\tvar abscissas = [\n\t\t[  0.5773502691896257645091488],\n\t\t[0,0.7745966692414833770358531],\n\t\t[  0.3399810435848562648026658,0.8611363115940525752239465],\n\t\t[0,0.5384693101056830910363144,0.9061798459386639927976269],\n\t\t[  0.2386191860831969086305017,0.6612093864662645136613996,0.9324695142031520278123016],\n\t\t[0,0.4058451513773971669066064,0.7415311855993944398638648,0.9491079123427585245261897],\n\t\t[  0.1834346424956498049394761,0.5255324099163289858177390,0.7966664774136267395915539,0.9602898564975362316835609],\n\t\t[0,0.3242534234038089290385380,0.6133714327005903973087020,0.8360311073266357942994298,0.9681602395076260898355762],\n\t\t[  0.1488743389816312108848260,0.4333953941292471907992659,0.6794095682990244062343274,0.8650633666889845107320967,0.9739065285171717200779640],\n\t\t[0,0.2695431559523449723315320,0.5190961292068118159257257,0.7301520055740493240934163,0.8870625997680952990751578,0.9782286581460569928039380],\n\t\t[  0.1252334085114689154724414,0.3678314989981801937526915,0.5873179542866174472967024,0.7699026741943046870368938,0.9041172563704748566784659,0.9815606342467192506905491],\n\t\t[0,0.2304583159551347940655281,0.4484927510364468528779129,0.6423493394403402206439846,0.8015780907333099127942065,0.9175983992229779652065478,0.9841830547185881494728294],\n\t\t[  0.1080549487073436620662447,0.3191123689278897604356718,0.5152486363581540919652907,0.6872929048116854701480198,0.8272013150697649931897947,0.9284348836635735173363911,0.9862838086968123388415973],\n\t\t[0,0.2011940939974345223006283,0.3941513470775633698972074,0.5709721726085388475372267,0.7244177313601700474161861,0.8482065834104272162006483,0.9372733924007059043077589,0.9879925180204854284895657],\n\t\t[  0.0950125098376374401853193,0.2816035507792589132304605,0.4580167776572273863424194,0.6178762444026437484466718,0.7554044083550030338951012,0.8656312023878317438804679,0.9445750230732325760779884,0.9894009349916499325961542]\n\t];\n\n\tvar weights = [\n\t\t[1],\n\t\t[0.8888888888888888888888889,0.5555555555555555555555556],\n\t\t[0.6521451548625461426269361,0.3478548451374538573730639],\n\t\t[0.5688888888888888888888889,0.4786286704993664680412915,0.2369268850561890875142640],\n\t\t[0.4679139345726910473898703,0.3607615730481386075698335,0.1713244923791703450402961],\n\t\t[0.4179591836734693877551020,0.3818300505051189449503698,0.2797053914892766679014678,0.1294849661688696932706114],\n\t\t[0.3626837833783619829651504,0.3137066458778872873379622,0.2223810344533744705443560,0.1012285362903762591525314],\n\t\t[0.3302393550012597631645251,0.3123470770400028400686304,0.2606106964029354623187429,0.1806481606948574040584720,0.0812743883615744119718922],\n\t\t[0.2955242247147528701738930,0.2692667193099963550912269,0.2190863625159820439955349,0.1494513491505805931457763,0.0666713443086881375935688],\n\t\t[0.2729250867779006307144835,0.2628045445102466621806889,0.2331937645919904799185237,0.1862902109277342514260976,0.1255803694649046246346943,0.0556685671161736664827537],\n\t\t[0.2491470458134027850005624,0.2334925365383548087608499,0.2031674267230659217490645,0.1600783285433462263346525,0.1069393259953184309602547,0.0471753363865118271946160],\n\t\t[0.2325515532308739101945895,0.2262831802628972384120902,0.2078160475368885023125232,0.1781459807619457382800467,0.1388735102197872384636018,0.0921214998377284479144218,0.0404840047653158795200216],\n\t\t[0.2152638534631577901958764,0.2051984637212956039659241,0.1855383974779378137417166,0.1572031671581935345696019,0.1215185706879031846894148,0.0801580871597602098056333,0.0351194603317518630318329],\n\t\t[0.2025782419255612728806202,0.1984314853271115764561183,0.1861610000155622110268006,0.1662692058169939335532009,0.1395706779261543144478048,0.1071592204671719350118695,0.0703660474881081247092674,0.0307532419961172683546284],\n\t\t[0.1894506104550684962853967,0.1826034150449235888667637,0.1691565193950025381893121,0.1495959888165767320815017,0.1246289712555338720524763,0.0951585116824927848099251,0.0622535239386478928628438,0.0271524594117540948517806]\n\t];\n\n\tvar abs = Math.abs,\n\t\tsqrt = Math.sqrt,\n\t\tpow = Math.pow,\n\t\tlog2 = Math.log2 || function(x) {\n\t\t\treturn Math.log(x) * Math.LOG2E;\n\t\t},\n\t\tEPSILON = 1e-12,\n\t\tMACHINE_EPSILON = 1.12e-16;\n\n\tfunction clamp(value, min, max) {\n\t\treturn value < min ? min : value > max ? max : value;\n\t}\n\n\tfunction getDiscriminant(a, b, c) {\n\t\tfunction split(v) {\n\t\t\tvar x = v * 134217729,\n\t\t\t\ty = v - x,\n\t\t\t\thi = y + x,\n\t\t\t\tlo = v - hi;\n\t\t\treturn [hi, lo];\n\t\t}\n\n\t\tvar D = b * b - a * c,\n\t\t\tE = b * b + a * c;\n\t\tif (abs(D) * 3 < E) {\n\t\t\tvar ad = split(a),\n\t\t\t\tbd = split(b),\n\t\t\t\tcd = split(c),\n\t\t\t\tp = b * b,\n\t\t\t\tdp = (bd[0] * bd[0] - p + 2 * bd[0] * bd[1]) + bd[1] * bd[1],\n\t\t\t\tq = a * c,\n\t\t\t\tdq = (ad[0] * cd[0] - q + ad[0] * cd[1] + ad[1] * cd[0])\n\t\t\t\t\t\t+ ad[1] * cd[1];\n\t\t\tD = (p - q) + (dp - dq);\n\t\t}\n\t\treturn D;\n\t}\n\n\tfunction getNormalizationFactor() {\n\t\tvar norm = Math.max.apply(Math, arguments);\n\t\treturn norm && (norm < 1e-8 || norm > 1e8)\n\t\t\t\t? pow(2, -Math.round(log2(norm)))\n\t\t\t\t: 0;\n\t}\n\n\treturn {\n\t\tEPSILON: EPSILON,\n\t\tMACHINE_EPSILON: MACHINE_EPSILON,\n\t\tCURVETIME_EPSILON: 1e-8,\n\t\tGEOMETRIC_EPSILON: 1e-7,\n\t\tTRIGONOMETRIC_EPSILON: 1e-8,\n\t\tKAPPA: 4 * (sqrt(2) - 1) / 3,\n\n\t\tisZero: function(val) {\n\t\t\treturn val >= -EPSILON && val <= EPSILON;\n\t\t},\n\n\t\tclamp: clamp,\n\n\t\tintegrate: function(f, a, b, n) {\n\t\t\tvar x = abscissas[n - 2],\n\t\t\t\tw = weights[n - 2],\n\t\t\t\tA = (b - a) * 0.5,\n\t\t\t\tB = A + a,\n\t\t\t\ti = 0,\n\t\t\t\tm = (n + 1) >> 1,\n\t\t\t\tsum = n & 1 ? w[i++] * f(B) : 0;\n\t\t\twhile (i < m) {\n\t\t\t\tvar Ax = A * x[i];\n\t\t\t\tsum += w[i++] * (f(B + Ax) + f(B - Ax));\n\t\t\t}\n\t\t\treturn A * sum;\n\t\t},\n\n\t\tfindRoot: function(f, df, x, a, b, n, tolerance) {\n\t\t\tfor (var i = 0; i < n; i++) {\n\t\t\t\tvar fx = f(x),\n\t\t\t\t\tdx = fx / df(x),\n\t\t\t\t\tnx = x - dx;\n\t\t\t\tif (abs(dx) < tolerance) {\n\t\t\t\t\tx = nx;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (fx > 0) {\n\t\t\t\t\tb = x;\n\t\t\t\t\tx = nx <= a ? (a + b) * 0.5 : nx;\n\t\t\t\t} else {\n\t\t\t\t\ta = x;\n\t\t\t\t\tx = nx >= b ? (a + b) * 0.5 : nx;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn clamp(x, a, b);\n\t\t},\n\n\t\tsolveQuadratic: function(a, b, c, roots, min, max) {\n\t\t\tvar x1, x2 = Infinity;\n\t\t\tif (abs(a) < EPSILON) {\n\t\t\t\tif (abs(b) < EPSILON)\n\t\t\t\t\treturn abs(c) < EPSILON ? -1 : 0;\n\t\t\t\tx1 = -c / b;\n\t\t\t} else {\n\t\t\t\tb *= -0.5;\n\t\t\t\tvar D = getDiscriminant(a, b, c);\n\t\t\t\tif (D && abs(D) < MACHINE_EPSILON) {\n\t\t\t\t\tvar f = getNormalizationFactor(abs(a), abs(b), abs(c));\n\t\t\t\t\tif (f) {\n\t\t\t\t\t\ta *= f;\n\t\t\t\t\t\tb *= f;\n\t\t\t\t\t\tc *= f;\n\t\t\t\t\t\tD = getDiscriminant(a, b, c);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (D >= -MACHINE_EPSILON) {\n\t\t\t\t\tvar Q = D < 0 ? 0 : sqrt(D),\n\t\t\t\t\t\tR = b + (b < 0 ? -Q : Q);\n\t\t\t\t\tif (R === 0) {\n\t\t\t\t\t\tx1 = c / a;\n\t\t\t\t\t\tx2 = -x1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tx1 = R / a;\n\t\t\t\t\t\tx2 = c / R;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar count = 0,\n\t\t\t\tboundless = min == null,\n\t\t\t\tminB = min - EPSILON,\n\t\t\t\tmaxB = max + EPSILON;\n\t\t\tif (isFinite(x1) && (boundless || x1 > minB && x1 < maxB))\n\t\t\t\troots[count++] = boundless ? x1 : clamp(x1, min, max);\n\t\t\tif (x2 !== x1\n\t\t\t\t\t&& isFinite(x2) && (boundless || x2 > minB && x2 < maxB))\n\t\t\t\troots[count++] = boundless ? x2 : clamp(x2, min, max);\n\t\t\treturn count;\n\t\t},\n\n\t\tsolveCubic: function(a, b, c, d, roots, min, max) {\n\t\t\tvar f = getNormalizationFactor(abs(a), abs(b), abs(c), abs(d)),\n\t\t\t\tx, b1, c2, qd, q;\n\t\t\tif (f) {\n\t\t\t\ta *= f;\n\t\t\t\tb *= f;\n\t\t\t\tc *= f;\n\t\t\t\td *= f;\n\t\t\t}\n\n\t\t\tfunction evaluate(x0) {\n\t\t\t\tx = x0;\n\t\t\t\tvar tmp = a * x;\n\t\t\t\tb1 = tmp + b;\n\t\t\t\tc2 = b1 * x + c;\n\t\t\t\tqd = (tmp + b1) * x + c2;\n\t\t\t\tq = c2 * x + d;\n\t\t\t}\n\n\t\t\tif (abs(a) < EPSILON) {\n\t\t\t\ta = b;\n\t\t\t\tb1 = c;\n\t\t\t\tc2 = d;\n\t\t\t\tx = Infinity;\n\t\t\t} else if (abs(d) < EPSILON) {\n\t\t\t\tb1 = b;\n\t\t\t\tc2 = c;\n\t\t\t\tx = 0;\n\t\t\t} else {\n\t\t\t\tevaluate(-(b / a) / 3);\n\t\t\t\tvar t = q / a,\n\t\t\t\t\tr = pow(abs(t), 1/3),\n\t\t\t\t\ts = t < 0 ? -1 : 1,\n\t\t\t\t\ttd = -qd / a,\n\t\t\t\t\trd = td > 0 ? 1.324717957244746 * Math.max(r, sqrt(td)) : r,\n\t\t\t\t\tx0 = x - s * rd;\n\t\t\t\tif (x0 !== x) {\n\t\t\t\t\tdo {\n\t\t\t\t\t\tevaluate(x0);\n\t\t\t\t\t\tx0 = qd === 0 ? x : x - q / qd / (1 + MACHINE_EPSILON);\n\t\t\t\t\t} while (s * x0 > s * x);\n\t\t\t\t\tif (abs(a) * x * x > abs(d / x)) {\n\t\t\t\t\t\tc2 = -d / x;\n\t\t\t\t\t\tb1 = (c2 - c) / x;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar count = Numerical.solveQuadratic(a, b1, c2, roots, min, max),\n\t\t\t\tboundless = min == null;\n\t\t\tif (isFinite(x) && (count === 0\n\t\t\t\t\t|| count > 0 && x !== roots[0] && x !== roots[1])\n\t\t\t\t\t&& (boundless || x > min - EPSILON && x < max + EPSILON))\n\t\t\t\troots[count++] = boundless ? x : clamp(x, min, max);\n\t\t\treturn count;\n\t\t}\n\t};\n};\n\nvar UID = {\n\t_id: 1,\n\t_pools: {},\n\n\tget: function(name) {\n\t\tif (name) {\n\t\t\tvar pool = this._pools[name];\n\t\t\tif (!pool)\n\t\t\t\tpool = this._pools[name] = { _id: 1 };\n\t\t\treturn pool._id++;\n\t\t} else {\n\t\t\treturn this._id++;\n\t\t}\n\t}\n};\n\nvar Point = Base.extend({\n\t_class: 'Point',\n\t_readIndex: true,\n\n\tinitialize: function Point(arg0, arg1) {\n\t\tvar type = typeof arg0,\n\t\t\treading = this.__read,\n\t\t\tread = 0;\n\t\tif (type === 'number') {\n\t\t\tvar hasY = typeof arg1 === 'number';\n\t\t\tthis._set(arg0, hasY ? arg1 : arg0);\n\t\t\tif (reading)\n\t\t\t\tread = hasY ? 2 : 1;\n\t\t} else if (type === 'undefined' || arg0 === null) {\n\t\t\tthis._set(0, 0);\n\t\t\tif (reading)\n\t\t\t\tread = arg0 === null ? 1 : 0;\n\t\t} else {\n\t\t\tvar obj = type === 'string' ? arg0.split(/[\\s,]+/) || [] : arg0;\n\t\t\tread = 1;\n\t\t\tif (Array.isArray(obj)) {\n\t\t\t\tthis._set(+obj[0], +(obj.length > 1 ? obj[1] : obj[0]));\n\t\t\t} else if ('x' in obj) {\n\t\t\t\tthis._set(obj.x || 0, obj.y || 0);\n\t\t\t} else if ('width' in obj) {\n\t\t\t\tthis._set(obj.width || 0, obj.height || 0);\n\t\t\t} else if ('angle' in obj) {\n\t\t\t\tthis._set(obj.length || 0, 0);\n\t\t\t\tthis.setAngle(obj.angle || 0);\n\t\t\t} else {\n\t\t\t\tthis._set(0, 0);\n\t\t\t\tread = 0;\n\t\t\t}\n\t\t}\n\t\tif (reading)\n\t\t\tthis.__read = read;\n\t\treturn this;\n\t},\n\n\tset: '#initialize',\n\n\t_set: function(x, y) {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\treturn this;\n\t},\n\n\tequals: function(point) {\n\t\treturn this === point || point\n\t\t\t\t&& (this.x === point.x && this.y === point.y\n\t\t\t\t\t|| Array.isArray(point)\n\t\t\t\t\t\t&& this.x === point[0] && this.y === point[1])\n\t\t\t\t|| false;\n\t},\n\n\tclone: function() {\n\t\treturn new Point(this.x, this.y);\n\t},\n\n\ttoString: function() {\n\t\tvar f = Formatter.instance;\n\t\treturn '{ x: ' + f.number(this.x) + ', y: ' + f.number(this.y) + ' }';\n\t},\n\n\t_serialize: function(options) {\n\t\tvar f = options.formatter;\n\t\treturn [f.number(this.x), f.number(this.y)];\n\t},\n\n\tgetLength: function() {\n\t\treturn Math.sqrt(this.x * this.x + this.y * this.y);\n\t},\n\n\tsetLength: function(length) {\n\t\tif (this.isZero()) {\n\t\t\tvar angle = this._angle || 0;\n\t\t\tthis._set(\n\t\t\t\tMath.cos(angle) * length,\n\t\t\t\tMath.sin(angle) * length\n\t\t\t);\n\t\t} else {\n\t\t\tvar scale = length / this.getLength();\n\t\t\tif (Numerical.isZero(scale))\n\t\t\t\tthis.getAngle();\n\t\t\tthis._set(\n\t\t\t\tthis.x * scale,\n\t\t\t\tthis.y * scale\n\t\t\t);\n\t\t}\n\t},\n\tgetAngle: function() {\n\t\treturn this.getAngleInRadians.apply(this, arguments) * 180 / Math.PI;\n\t},\n\n\tsetAngle: function(angle) {\n\t\tthis.setAngleInRadians.call(this, angle * Math.PI / 180);\n\t},\n\n\tgetAngleInDegrees: '#getAngle',\n\tsetAngleInDegrees: '#setAngle',\n\n\tgetAngleInRadians: function() {\n\t\tif (!arguments.length) {\n\t\t\treturn this.isZero()\n\t\t\t\t\t? this._angle || 0\n\t\t\t\t\t: this._angle = Math.atan2(this.y, this.x);\n\t\t} else {\n\t\t\tvar point = Point.read(arguments),\n\t\t\t\tdiv = this.getLength() * point.getLength();\n\t\t\tif (Numerical.isZero(div)) {\n\t\t\t\treturn NaN;\n\t\t\t} else {\n\t\t\t\tvar a = this.dot(point) / div;\n\t\t\t\treturn Math.acos(a < -1 ? -1 : a > 1 ? 1 : a);\n\t\t\t}\n\t\t}\n\t},\n\n\tsetAngleInRadians: function(angle) {\n\t\tthis._angle = angle;\n\t\tif (!this.isZero()) {\n\t\t\tvar length = this.getLength();\n\t\t\tthis._set(\n\t\t\t\tMath.cos(angle) * length,\n\t\t\t\tMath.sin(angle) * length\n\t\t\t);\n\t\t}\n\t},\n\n\tgetQuadrant: function() {\n\t\treturn this.x >= 0 ? this.y >= 0 ? 1 : 4 : this.y >= 0 ? 2 : 3;\n\t}\n}, {\n\tbeans: false,\n\n\tgetDirectedAngle: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn Math.atan2(this.cross(point), this.dot(point)) * 180 / Math.PI;\n\t},\n\n\tgetDistance: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\tx = point.x - this.x,\n\t\t\ty = point.y - this.y,\n\t\t\td = x * x + y * y,\n\t\t\tsquared = Base.read(arguments);\n\t\treturn squared ? d : Math.sqrt(d);\n\t},\n\n\tnormalize: function(length) {\n\t\tif (length === undefined)\n\t\t\tlength = 1;\n\t\tvar current = this.getLength(),\n\t\t\tscale = current !== 0 ? length / current : 0,\n\t\t\tpoint = new Point(this.x * scale, this.y * scale);\n\t\tif (scale >= 0)\n\t\t\tpoint._angle = this._angle;\n\t\treturn point;\n\t},\n\n\trotate: function(angle, center) {\n\t\tif (angle === 0)\n\t\t\treturn this.clone();\n\t\tangle = angle * Math.PI / 180;\n\t\tvar point = center ? this.subtract(center) : this,\n\t\t\tsin = Math.sin(angle),\n\t\t\tcos = Math.cos(angle);\n\t\tpoint = new Point(\n\t\t\tpoint.x * cos - point.y * sin,\n\t\t\tpoint.x * sin + point.y * cos\n\t\t);\n\t\treturn center ? point.add(center) : point;\n\t},\n\n\ttransform: function(matrix) {\n\t\treturn matrix ? matrix._transformPoint(this) : this;\n\t},\n\n\tadd: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn new Point(this.x + point.x, this.y + point.y);\n\t},\n\n\tsubtract: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn new Point(this.x - point.x, this.y - point.y);\n\t},\n\n\tmultiply: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn new Point(this.x * point.x, this.y * point.y);\n\t},\n\n\tdivide: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn new Point(this.x / point.x, this.y / point.y);\n\t},\n\n\tmodulo: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn new Point(this.x % point.x, this.y % point.y);\n\t},\n\n\tnegate: function() {\n\t\treturn new Point(-this.x, -this.y);\n\t},\n\n\tisInside: function() {\n\t\treturn Rectangle.read(arguments).contains(this);\n\t},\n\n\tisClose: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\ttolerance = Base.read(arguments);\n\t\treturn this.getDistance(point) <= tolerance;\n\t},\n\n\tisCollinear: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn Point.isCollinear(this.x, this.y, point.x, point.y);\n\t},\n\n\tisColinear: '#isCollinear',\n\n\tisOrthogonal: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn Point.isOrthogonal(this.x, this.y, point.x, point.y);\n\t},\n\n\tisZero: function() {\n\t\tvar isZero = Numerical.isZero;\n\t\treturn isZero(this.x) && isZero(this.y);\n\t},\n\n\tisNaN: function() {\n\t\treturn isNaN(this.x) || isNaN(this.y);\n\t},\n\n\tisInQuadrant: function(q) {\n\t\treturn this.x * (q > 1 && q < 4 ? -1 : 1) >= 0\n\t\t\t&& this.y * (q > 2 ? -1 : 1) >= 0;\n\t},\n\n\tdot: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn this.x * point.x + this.y * point.y;\n\t},\n\n\tcross: function() {\n\t\tvar point = Point.read(arguments);\n\t\treturn this.x * point.y - this.y * point.x;\n\t},\n\n\tproject: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\tscale = point.isZero() ? 0 : this.dot(point) / point.dot(point);\n\t\treturn new Point(\n\t\t\tpoint.x * scale,\n\t\t\tpoint.y * scale\n\t\t);\n\t},\n\n\tstatics: {\n\t\tmin: function() {\n\t\t\tvar point1 = Point.read(arguments),\n\t\t\t\tpoint2 = Point.read(arguments);\n\t\t\treturn new Point(\n\t\t\t\tMath.min(point1.x, point2.x),\n\t\t\t\tMath.min(point1.y, point2.y)\n\t\t\t);\n\t\t},\n\n\t\tmax: function() {\n\t\t\tvar point1 = Point.read(arguments),\n\t\t\t\tpoint2 = Point.read(arguments);\n\t\t\treturn new Point(\n\t\t\t\tMath.max(point1.x, point2.x),\n\t\t\t\tMath.max(point1.y, point2.y)\n\t\t\t);\n\t\t},\n\n\t\trandom: function() {\n\t\t\treturn new Point(Math.random(), Math.random());\n\t\t},\n\n\t\tisCollinear: function(x1, y1, x2, y2) {\n\t\t\treturn Math.abs(x1 * y2 - y1 * x2)\n\t\t\t\t\t<= Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2))\n\t\t\t\t\t\t* 1e-8;\n\t\t},\n\n\t\tisOrthogonal: function(x1, y1, x2, y2) {\n\t\t\treturn Math.abs(x1 * x2 + y1 * y2)\n\t\t\t\t\t<= Math.sqrt((x1 * x1 + y1 * y1) * (x2 * x2 + y2 * y2))\n\t\t\t\t\t\t* 1e-8;\n\t\t}\n\t}\n}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) {\n\tvar op = Math[key];\n\tthis[key] = function() {\n\t\treturn new Point(op(this.x), op(this.y));\n\t};\n}, {}));\n\nvar LinkedPoint = Point.extend({\n\tinitialize: function Point(x, y, owner, setter) {\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t\tthis._owner = owner;\n\t\tthis._setter = setter;\n\t},\n\n\t_set: function(x, y, _dontNotify) {\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t\tif (!_dontNotify)\n\t\t\tthis._owner[this._setter](this);\n\t\treturn this;\n\t},\n\n\tgetX: function() {\n\t\treturn this._x;\n\t},\n\n\tsetX: function(x) {\n\t\tthis._x = x;\n\t\tthis._owner[this._setter](this);\n\t},\n\n\tgetY: function() {\n\t\treturn this._y;\n\t},\n\n\tsetY: function(y) {\n\t\tthis._y = y;\n\t\tthis._owner[this._setter](this);\n\t},\n\n\tisSelected: function() {\n\t\treturn !!(this._owner._selection & this._getSelection());\n\t},\n\n\tsetSelected: function(selected) {\n\t\tthis._owner.changeSelection(this._getSelection(), selected);\n\t},\n\n\t_getSelection: function() {\n\t\treturn this._setter === 'setPosition' ? 4 : 0;\n\t}\n});\n\nvar Size = Base.extend({\n\t_class: 'Size',\n\t_readIndex: true,\n\n\tinitialize: function Size(arg0, arg1) {\n\t\tvar type = typeof arg0,\n\t\t\treading = this.__read,\n\t\t\tread = 0;\n\t\tif (type === 'number') {\n\t\t\tvar hasHeight = typeof arg1 === 'number';\n\t\t\tthis._set(arg0, hasHeight ? arg1 : arg0);\n\t\t\tif (reading)\n\t\t\t\tread = hasHeight ? 2 : 1;\n\t\t} else if (type === 'undefined' || arg0 === null) {\n\t\t\tthis._set(0, 0);\n\t\t\tif (reading)\n\t\t\t\tread = arg0 === null ? 1 : 0;\n\t\t} else {\n\t\t\tvar obj = type === 'string' ? arg0.split(/[\\s,]+/) || [] : arg0;\n\t\t\tread = 1;\n\t\t\tif (Array.isArray(obj)) {\n\t\t\t\tthis._set(+obj[0], +(obj.length > 1 ? obj[1] : obj[0]));\n\t\t\t} else if ('width' in obj) {\n\t\t\t\tthis._set(obj.width || 0, obj.height || 0);\n\t\t\t} else if ('x' in obj) {\n\t\t\t\tthis._set(obj.x || 0, obj.y || 0);\n\t\t\t} else {\n\t\t\t\tthis._set(0, 0);\n\t\t\t\tread = 0;\n\t\t\t}\n\t\t}\n\t\tif (reading)\n\t\t\tthis.__read = read;\n\t\treturn this;\n\t},\n\n\tset: '#initialize',\n\n\t_set: function(width, height) {\n\t\tthis.width = width;\n\t\tthis.height = height;\n\t\treturn this;\n\t},\n\n\tequals: function(size) {\n\t\treturn size === this || size && (this.width === size.width\n\t\t\t\t&& this.height === size.height\n\t\t\t\t|| Array.isArray(size) && this.width === size[0]\n\t\t\t\t\t&& this.height === size[1]) || false;\n\t},\n\n\tclone: function() {\n\t\treturn new Size(this.width, this.height);\n\t},\n\n\ttoString: function() {\n\t\tvar f = Formatter.instance;\n\t\treturn '{ width: ' + f.number(this.width)\n\t\t\t\t+ ', height: ' + f.number(this.height) + ' }';\n\t},\n\n\t_serialize: function(options) {\n\t\tvar f = options.formatter;\n\t\treturn [f.number(this.width),\n\t\t\t\tf.number(this.height)];\n\t},\n\n\tadd: function() {\n\t\tvar size = Size.read(arguments);\n\t\treturn new Size(this.width + size.width, this.height + size.height);\n\t},\n\n\tsubtract: function() {\n\t\tvar size = Size.read(arguments);\n\t\treturn new Size(this.width - size.width, this.height - size.height);\n\t},\n\n\tmultiply: function() {\n\t\tvar size = Size.read(arguments);\n\t\treturn new Size(this.width * size.width, this.height * size.height);\n\t},\n\n\tdivide: function() {\n\t\tvar size = Size.read(arguments);\n\t\treturn new Size(this.width / size.width, this.height / size.height);\n\t},\n\n\tmodulo: function() {\n\t\tvar size = Size.read(arguments);\n\t\treturn new Size(this.width % size.width, this.height % size.height);\n\t},\n\n\tnegate: function() {\n\t\treturn new Size(-this.width, -this.height);\n\t},\n\n\tisZero: function() {\n\t\tvar isZero = Numerical.isZero;\n\t\treturn isZero(this.width) && isZero(this.height);\n\t},\n\n\tisNaN: function() {\n\t\treturn isNaN(this.width) || isNaN(this.height);\n\t},\n\n\tstatics: {\n\t\tmin: function(size1, size2) {\n\t\t\treturn new Size(\n\t\t\t\tMath.min(size1.width, size2.width),\n\t\t\t\tMath.min(size1.height, size2.height));\n\t\t},\n\n\t\tmax: function(size1, size2) {\n\t\t\treturn new Size(\n\t\t\t\tMath.max(size1.width, size2.width),\n\t\t\t\tMath.max(size1.height, size2.height));\n\t\t},\n\n\t\trandom: function() {\n\t\t\treturn new Size(Math.random(), Math.random());\n\t\t}\n\t}\n}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) {\n\tvar op = Math[key];\n\tthis[key] = function() {\n\t\treturn new Size(op(this.width), op(this.height));\n\t};\n}, {}));\n\nvar LinkedSize = Size.extend({\n\tinitialize: function Size(width, height, owner, setter) {\n\t\tthis._width = width;\n\t\tthis._height = height;\n\t\tthis._owner = owner;\n\t\tthis._setter = setter;\n\t},\n\n\t_set: function(width, height, _dontNotify) {\n\t\tthis._width = width;\n\t\tthis._height = height;\n\t\tif (!_dontNotify)\n\t\t\tthis._owner[this._setter](this);\n\t\treturn this;\n\t},\n\n\tgetWidth: function() {\n\t\treturn this._width;\n\t},\n\n\tsetWidth: function(width) {\n\t\tthis._width = width;\n\t\tthis._owner[this._setter](this);\n\t},\n\n\tgetHeight: function() {\n\t\treturn this._height;\n\t},\n\n\tsetHeight: function(height) {\n\t\tthis._height = height;\n\t\tthis._owner[this._setter](this);\n\t}\n});\n\nvar Rectangle = Base.extend({\n\t_class: 'Rectangle',\n\t_readIndex: true,\n\tbeans: true,\n\n\tinitialize: function Rectangle(arg0, arg1, arg2, arg3) {\n\t\tvar type = typeof arg0,\n\t\t\tread;\n\t\tif (type === 'number') {\n\t\t\tthis._set(arg0, arg1, arg2, arg3);\n\t\t\tread = 4;\n\t\t} else if (type === 'undefined' || arg0 === null) {\n\t\t\tthis._set(0, 0, 0, 0);\n\t\t\tread = arg0 === null ? 1 : 0;\n\t\t} else if (arguments.length === 1) {\n\t\t\tif (Array.isArray(arg0)) {\n\t\t\t\tthis._set.apply(this, arg0);\n\t\t\t\tread = 1;\n\t\t\t} else if (arg0.x !== undefined || arg0.width !== undefined) {\n\t\t\t\tthis._set(arg0.x || 0, arg0.y || 0,\n\t\t\t\t\t\targ0.width || 0, arg0.height || 0);\n\t\t\t\tread = 1;\n\t\t\t} else if (arg0.from === undefined && arg0.to === undefined) {\n\t\t\t\tthis._set(0, 0, 0, 0);\n\t\t\t\tBase.filter(this, arg0);\n\t\t\t\tread = 1;\n\t\t\t}\n\t\t}\n\t\tif (read === undefined) {\n\t\t\tvar frm = Point.readNamed(arguments, 'from'),\n\t\t\t\tnext = Base.peek(arguments),\n\t\t\t\tx = frm.x,\n\t\t\t\ty = frm.y,\n\t\t\t\twidth,\n\t\t\t\theight;\n\t\t\tif (next && next.x !== undefined\n\t\t\t\t\t|| Base.hasNamed(arguments, 'to')) {\n\t\t\t\tvar to = Point.readNamed(arguments, 'to');\n\t\t\t\twidth = to.x - x;\n\t\t\t\theight = to.y - y;\n\t\t\t\tif (width < 0) {\n\t\t\t\t\tx = to.x;\n\t\t\t\t\twidth = -width;\n\t\t\t\t}\n\t\t\t\tif (height < 0) {\n\t\t\t\t\ty = to.y;\n\t\t\t\t\theight = -height;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tvar size = Size.read(arguments);\n\t\t\t\twidth = size.width;\n\t\t\t\theight = size.height;\n\t\t\t}\n\t\t\tthis._set(x, y, width, height);\n\t\t\tread = arguments.__index;\n\t\t\tvar filtered = arguments.__filtered;\n\t\t\tif (filtered)\n\t\t\t\tthis.__filtered = filtered;\n\t\t}\n\t\tif (this.__read)\n\t\t\tthis.__read = read;\n\t\treturn this;\n\t},\n\n\tset: '#initialize',\n\n\t_set: function(x, y, width, height) {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\tthis.width = width;\n\t\tthis.height = height;\n\t\treturn this;\n\t},\n\n\tclone: function() {\n\t\treturn new Rectangle(this.x, this.y, this.width, this.height);\n\t},\n\n\tequals: function(rect) {\n\t\tvar rt = Base.isPlainValue(rect)\n\t\t\t\t? Rectangle.read(arguments)\n\t\t\t\t: rect;\n\t\treturn rt === this\n\t\t\t\t|| rt && this.x === rt.x && this.y === rt.y\n\t\t\t\t\t&& this.width === rt.width && this.height === rt.height\n\t\t\t\t|| false;\n\t},\n\n\ttoString: function() {\n\t\tvar f = Formatter.instance;\n\t\treturn '{ x: ' + f.number(this.x)\n\t\t\t\t+ ', y: ' + f.number(this.y)\n\t\t\t\t+ ', width: ' + f.number(this.width)\n\t\t\t\t+ ', height: ' + f.number(this.height)\n\t\t\t\t+ ' }';\n\t},\n\n\t_serialize: function(options) {\n\t\tvar f = options.formatter;\n\t\treturn [f.number(this.x),\n\t\t\t\tf.number(this.y),\n\t\t\t\tf.number(this.width),\n\t\t\t\tf.number(this.height)];\n\t},\n\n\tgetPoint: function(_dontLink) {\n\t\tvar ctor = _dontLink ? Point : LinkedPoint;\n\t\treturn new ctor(this.x, this.y, this, 'setPoint');\n\t},\n\n\tsetPoint: function() {\n\t\tvar point = Point.read(arguments);\n\t\tthis.x = point.x;\n\t\tthis.y = point.y;\n\t},\n\n\tgetSize: function(_dontLink) {\n\t\tvar ctor = _dontLink ? Size : LinkedSize;\n\t\treturn new ctor(this.width, this.height, this, 'setSize');\n\t},\n\n\t_fw: 1,\n\t_fh: 1,\n\n\tsetSize: function() {\n\t\tvar size = Size.read(arguments),\n\t\t\tsx = this._sx,\n\t\t\tsy = this._sy,\n\t\t\tw = size.width,\n\t\t\th = size.height;\n\t\tif (sx) {\n\t\t\tthis.x += (this.width - w) * sx;\n\t\t}\n\t\tif (sy) {\n\t\t\tthis.y += (this.height - h) * sy;\n\t\t}\n\t\tthis.width = w;\n\t\tthis.height = h;\n\t\tthis._fw = this._fh = 1;\n\t},\n\n\tgetLeft: function() {\n\t\treturn this.x;\n\t},\n\n\tsetLeft: function(left) {\n\t\tif (!this._fw) {\n\t\t\tvar amount = left - this.x;\n\t\t\tthis.width -= this._sx === 0.5 ? amount * 2 : amount;\n\t\t}\n\t\tthis.x = left;\n\t\tthis._sx = this._fw = 0;\n\t},\n\n\tgetTop: function() {\n\t\treturn this.y;\n\t},\n\n\tsetTop: function(top) {\n\t\tif (!this._fh) {\n\t\t\tvar amount = top - this.y;\n\t\t\tthis.height -= this._sy === 0.5 ? amount * 2 : amount;\n\t\t}\n\t\tthis.y = top;\n\t\tthis._sy = this._fh = 0;\n\t},\n\n\tgetRight: function() {\n\t\treturn this.x + this.width;\n\t},\n\n\tsetRight: function(right) {\n\t\tif (!this._fw) {\n\t\t\tvar amount = right - this.x;\n\t\t\tthis.width = this._sx === 0.5 ? amount * 2 : amount;\n\t\t}\n\t\tthis.x = right - this.width;\n\t\tthis._sx = 1;\n\t\tthis._fw = 0;\n\t},\n\n\tgetBottom: function() {\n\t\treturn this.y + this.height;\n\t},\n\n\tsetBottom: function(bottom) {\n\t\tif (!this._fh) {\n\t\t\tvar amount = bottom - this.y;\n\t\t\tthis.height = this._sy === 0.5 ? amount * 2 : amount;\n\t\t}\n\t\tthis.y = bottom - this.height;\n\t\tthis._sy = 1;\n\t\tthis._fh = 0;\n\t},\n\n\tgetCenterX: function() {\n\t\treturn this.x + this.width / 2;\n\t},\n\n\tsetCenterX: function(x) {\n\t\tif (this._fw || this._sx === 0.5) {\n\t\t\tthis.x = x - this.width / 2;\n\t\t} else {\n\t\t\tif (this._sx) {\n\t\t\t\tthis.x += (x - this.x) * 2 * this._sx;\n\t\t\t}\n\t\t\tthis.width = (x - this.x) * 2;\n\t\t}\n\t\tthis._sx = 0.5;\n\t\tthis._fw = 0;\n\t},\n\n\tgetCenterY: function() {\n\t\treturn this.y + this.height / 2;\n\t},\n\n\tsetCenterY: function(y) {\n\t\tif (this._fh || this._sy === 0.5) {\n\t\t\tthis.y = y - this.height / 2;\n\t\t} else {\n\t\t\tif (this._sy) {\n\t\t\t\tthis.y += (y - this.y) * 2 * this._sy;\n\t\t\t}\n\t\t\tthis.height = (y - this.y) * 2;\n\t\t}\n\t\tthis._sy = 0.5;\n\t\tthis._fh = 0;\n\t},\n\n\tgetCenter: function(_dontLink) {\n\t\tvar ctor = _dontLink ? Point : LinkedPoint;\n\t\treturn new ctor(this.getCenterX(), this.getCenterY(), this, 'setCenter');\n\t},\n\n\tsetCenter: function() {\n\t\tvar point = Point.read(arguments);\n\t\tthis.setCenterX(point.x);\n\t\tthis.setCenterY(point.y);\n\t\treturn this;\n\t},\n\n\tgetArea: function() {\n\t\treturn this.width * this.height;\n\t},\n\n\tisEmpty: function() {\n\t\treturn this.width === 0 || this.height === 0;\n\t},\n\n\tcontains: function(arg) {\n\t\treturn arg && arg.width !== undefined\n\t\t\t\t|| (Array.isArray(arg) ? arg : arguments).length === 4\n\t\t\t\t? this._containsRectangle(Rectangle.read(arguments))\n\t\t\t\t: this._containsPoint(Point.read(arguments));\n\t},\n\n\t_containsPoint: function(point) {\n\t\tvar x = point.x,\n\t\t\ty = point.y;\n\t\treturn x >= this.x && y >= this.y\n\t\t\t\t&& x <= this.x + this.width\n\t\t\t\t&& y <= this.y + this.height;\n\t},\n\n\t_containsRectangle: function(rect) {\n\t\tvar x = rect.x,\n\t\t\ty = rect.y;\n\t\treturn x >= this.x && y >= this.y\n\t\t\t\t&& x + rect.width <= this.x + this.width\n\t\t\t\t&& y + rect.height <= this.y + this.height;\n\t},\n\n\tintersects: function() {\n\t\tvar rect = Rectangle.read(arguments),\n\t\t\tepsilon = Base.read(arguments) || 0;\n\t\treturn rect.x + rect.width > this.x - epsilon\n\t\t\t\t&& rect.y + rect.height > this.y - epsilon\n\t\t\t\t&& rect.x < this.x + this.width + epsilon\n\t\t\t\t&& rect.y < this.y + this.height + epsilon;\n\t},\n\n\tintersect: function() {\n\t\tvar rect = Rectangle.read(arguments),\n\t\t\tx1 = Math.max(this.x, rect.x),\n\t\t\ty1 = Math.max(this.y, rect.y),\n\t\t\tx2 = Math.min(this.x + this.width, rect.x + rect.width),\n\t\t\ty2 = Math.min(this.y + this.height, rect.y + rect.height);\n\t\treturn new Rectangle(x1, y1, x2 - x1, y2 - y1);\n\t},\n\n\tunite: function() {\n\t\tvar rect = Rectangle.read(arguments),\n\t\t\tx1 = Math.min(this.x, rect.x),\n\t\t\ty1 = Math.min(this.y, rect.y),\n\t\t\tx2 = Math.max(this.x + this.width, rect.x + rect.width),\n\t\t\ty2 = Math.max(this.y + this.height, rect.y + rect.height);\n\t\treturn new Rectangle(x1, y1, x2 - x1, y2 - y1);\n\t},\n\n\tinclude: function() {\n\t\tvar point = Point.read(arguments);\n\t\tvar x1 = Math.min(this.x, point.x),\n\t\t\ty1 = Math.min(this.y, point.y),\n\t\t\tx2 = Math.max(this.x + this.width, point.x),\n\t\t\ty2 = Math.max(this.y + this.height, point.y);\n\t\treturn new Rectangle(x1, y1, x2 - x1, y2 - y1);\n\t},\n\n\texpand: function() {\n\t\tvar amount = Size.read(arguments),\n\t\t\thor = amount.width,\n\t\t\tver = amount.height;\n\t\treturn new Rectangle(this.x - hor / 2, this.y - ver / 2,\n\t\t\t\tthis.width + hor, this.height + ver);\n\t},\n\n\tscale: function(hor, ver) {\n\t\treturn this.expand(this.width * hor - this.width,\n\t\t\t\tthis.height * (ver === undefined ? hor : ver) - this.height);\n\t}\n}, Base.each([\n\t\t['Top', 'Left'], ['Top', 'Right'],\n\t\t['Bottom', 'Left'], ['Bottom', 'Right'],\n\t\t['Left', 'Center'], ['Top', 'Center'],\n\t\t['Right', 'Center'], ['Bottom', 'Center']\n\t],\n\tfunction(parts, index) {\n\t\tvar part = parts.join(''),\n\t\t\txFirst = /^[RL]/.test(part);\n\t\tif (index >= 4)\n\t\t\tparts[1] += xFirst ? 'Y' : 'X';\n\t\tvar x = parts[xFirst ? 0 : 1],\n\t\t\ty = parts[xFirst ? 1 : 0],\n\t\t\tgetX = 'get' + x,\n\t\t\tgetY = 'get' + y,\n\t\t\tsetX = 'set' + x,\n\t\t\tsetY = 'set' + y,\n\t\t\tget = 'get' + part,\n\t\t\tset = 'set' + part;\n\t\tthis[get] = function(_dontLink) {\n\t\t\tvar ctor = _dontLink ? Point : LinkedPoint;\n\t\t\treturn new ctor(this[getX](), this[getY](), this, set);\n\t\t};\n\t\tthis[set] = function() {\n\t\t\tvar point = Point.read(arguments);\n\t\t\tthis[setX](point.x);\n\t\t\tthis[setY](point.y);\n\t\t};\n\t}, {\n\t\tbeans: true\n\t}\n));\n\nvar LinkedRectangle = Rectangle.extend({\n\tinitialize: function Rectangle(x, y, width, height, owner, setter) {\n\t\tthis._set(x, y, width, height, true);\n\t\tthis._owner = owner;\n\t\tthis._setter = setter;\n\t},\n\n\t_set: function(x, y, width, height, _dontNotify) {\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t\tthis._width = width;\n\t\tthis._height = height;\n\t\tif (!_dontNotify)\n\t\t\tthis._owner[this._setter](this);\n\t\treturn this;\n\t}\n},\nnew function() {\n\tvar proto = Rectangle.prototype;\n\n\treturn Base.each(['x', 'y', 'width', 'height'], function(key) {\n\t\tvar part = Base.capitalize(key),\n\t\t\tinternal = '_' + key;\n\t\tthis['get' + part] = function() {\n\t\t\treturn this[internal];\n\t\t};\n\n\t\tthis['set' + part] = function(value) {\n\t\t\tthis[internal] = value;\n\t\t\tif (!this._dontNotify)\n\t\t\t\tthis._owner[this._setter](this);\n\t\t};\n\t}, Base.each(['Point', 'Size', 'Center',\n\t\t\t'Left', 'Top', 'Right', 'Bottom', 'CenterX', 'CenterY',\n\t\t\t'TopLeft', 'TopRight', 'BottomLeft', 'BottomRight',\n\t\t\t'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter'],\n\t\tfunction(key) {\n\t\t\tvar name = 'set' + key;\n\t\t\tthis[name] = function() {\n\t\t\t\tthis._dontNotify = true;\n\t\t\t\tproto[name].apply(this, arguments);\n\t\t\t\tthis._dontNotify = false;\n\t\t\t\tthis._owner[this._setter](this);\n\t\t\t};\n\t\t}, {\n\t\t\tisSelected: function() {\n\t\t\t\treturn !!(this._owner._selection & 2);\n\t\t\t},\n\n\t\t\tsetSelected: function(selected) {\n\t\t\t\tvar owner = this._owner;\n\t\t\t\tif (owner.changeSelection) {\n\t\t\t\t\towner.changeSelection(2, selected);\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t);\n});\n\nvar Matrix = Base.extend({\n\t_class: 'Matrix',\n\n\tinitialize: function Matrix(arg, _dontNotify) {\n\t\tvar count = arguments.length,\n\t\t\tok = true;\n\t\tif (count >= 6) {\n\t\t\tthis._set.apply(this, arguments);\n\t\t} else if (count === 1 || count === 2) {\n\t\t\tif (arg instanceof Matrix) {\n\t\t\t\tthis._set(arg._a, arg._b, arg._c, arg._d, arg._tx, arg._ty,\n\t\t\t\t\t\t_dontNotify);\n\t\t\t} else if (Array.isArray(arg)) {\n\t\t\t\tthis._set.apply(this,\n\t\t\t\t\t\t_dontNotify ? arg.concat([_dontNotify]) : arg);\n\t\t\t} else {\n\t\t\t\tok = false;\n\t\t\t}\n\t\t} else if (!count) {\n\t\t\tthis.reset();\n\t\t} else {\n\t\t\tok = false;\n\t\t}\n\t\tif (!ok) {\n\t\t\tthrow new Error('Unsupported matrix parameters');\n\t\t}\n\t\treturn this;\n\t},\n\n\tset: '#initialize',\n\n\t_set: function(a, b, c, d, tx, ty, _dontNotify) {\n\t\tthis._a = a;\n\t\tthis._b = b;\n\t\tthis._c = c;\n\t\tthis._d = d;\n\t\tthis._tx = tx;\n\t\tthis._ty = ty;\n\t\tif (!_dontNotify)\n\t\t\tthis._changed();\n\t\treturn this;\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\treturn Base.serialize(this.getValues(), options, true, dictionary);\n\t},\n\n\t_changed: function() {\n\t\tvar owner = this._owner;\n\t\tif (owner) {\n\t\t\tif (owner._applyMatrix) {\n\t\t\t\towner.transform(null, true);\n\t\t\t} else {\n\t\t\t\towner._changed(9);\n\t\t\t}\n\t\t}\n\t},\n\n\tclone: function() {\n\t\treturn new Matrix(this._a, this._b, this._c, this._d,\n\t\t\t\tthis._tx, this._ty);\n\t},\n\n\tequals: function(mx) {\n\t\treturn mx === this || mx && this._a === mx._a && this._b === mx._b\n\t\t\t\t&& this._c === mx._c && this._d === mx._d\n\t\t\t\t&& this._tx === mx._tx && this._ty === mx._ty;\n\t},\n\n\ttoString: function() {\n\t\tvar f = Formatter.instance;\n\t\treturn '[[' + [f.number(this._a), f.number(this._c),\n\t\t\t\t\tf.number(this._tx)].join(', ') + '], ['\n\t\t\t\t+ [f.number(this._b), f.number(this._d),\n\t\t\t\t\tf.number(this._ty)].join(', ') + ']]';\n\t},\n\n\treset: function(_dontNotify) {\n\t\tthis._a = this._d = 1;\n\t\tthis._b = this._c = this._tx = this._ty = 0;\n\t\tif (!_dontNotify)\n\t\t\tthis._changed();\n\t\treturn this;\n\t},\n\n\tapply: function(recursively, _setApplyMatrix) {\n\t\tvar owner = this._owner;\n\t\tif (owner) {\n\t\t\towner.transform(null, true, Base.pick(recursively, true),\n\t\t\t\t\t_setApplyMatrix);\n\t\t\treturn this.isIdentity();\n\t\t}\n\t\treturn false;\n\t},\n\n\ttranslate: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\tx = point.x,\n\t\t\ty = point.y;\n\t\tthis._tx += x * this._a + y * this._c;\n\t\tthis._ty += x * this._b + y * this._d;\n\t\tthis._changed();\n\t\treturn this;\n\t},\n\n\tscale: function() {\n\t\tvar scale = Point.read(arguments),\n\t\t\tcenter = Point.read(arguments, 0, { readNull: true });\n\t\tif (center)\n\t\t\tthis.translate(center);\n\t\tthis._a *= scale.x;\n\t\tthis._b *= scale.x;\n\t\tthis._c *= scale.y;\n\t\tthis._d *= scale.y;\n\t\tif (center)\n\t\t\tthis.translate(center.negate());\n\t\tthis._changed();\n\t\treturn this;\n\t},\n\n\trotate: function(angle ) {\n\t\tangle *= Math.PI / 180;\n\t\tvar center = Point.read(arguments, 1),\n\t\t\tx = center.x,\n\t\t\ty = center.y,\n\t\t\tcos = Math.cos(angle),\n\t\t\tsin = Math.sin(angle),\n\t\t\ttx = x - x * cos + y * sin,\n\t\t\tty = y - x * sin - y * cos,\n\t\t\ta = this._a,\n\t\t\tb = this._b,\n\t\t\tc = this._c,\n\t\t\td = this._d;\n\t\tthis._a = cos * a + sin * c;\n\t\tthis._b = cos * b + sin * d;\n\t\tthis._c = -sin * a + cos * c;\n\t\tthis._d = -sin * b + cos * d;\n\t\tthis._tx += tx * a + ty * c;\n\t\tthis._ty += tx * b + ty * d;\n\t\tthis._changed();\n\t\treturn this;\n\t},\n\n\tshear: function() {\n\t\tvar shear = Point.read(arguments),\n\t\t\tcenter = Point.read(arguments, 0, { readNull: true });\n\t\tif (center)\n\t\t\tthis.translate(center);\n\t\tvar a = this._a,\n\t\t\tb = this._b;\n\t\tthis._a += shear.y * this._c;\n\t\tthis._b += shear.y * this._d;\n\t\tthis._c += shear.x * a;\n\t\tthis._d += shear.x * b;\n\t\tif (center)\n\t\t\tthis.translate(center.negate());\n\t\tthis._changed();\n\t\treturn this;\n\t},\n\n\tskew: function() {\n\t\tvar skew = Point.read(arguments),\n\t\t\tcenter = Point.read(arguments, 0, { readNull: true }),\n\t\t\ttoRadians = Math.PI / 180,\n\t\t\tshear = new Point(Math.tan(skew.x * toRadians),\n\t\t\t\tMath.tan(skew.y * toRadians));\n\t\treturn this.shear(shear, center);\n\t},\n\n\tappend: function(mx, _dontNotify) {\n\t\tif (mx) {\n\t\t\tvar a1 = this._a,\n\t\t\t\tb1 = this._b,\n\t\t\t\tc1 = this._c,\n\t\t\t\td1 = this._d,\n\t\t\t\ta2 = mx._a,\n\t\t\t\tb2 = mx._c,\n\t\t\t\tc2 = mx._b,\n\t\t\t\td2 = mx._d,\n\t\t\t\ttx2 = mx._tx,\n\t\t\t\tty2 = mx._ty;\n\t\t\tthis._a = a2 * a1 + c2 * c1;\n\t\t\tthis._c = b2 * a1 + d2 * c1;\n\t\t\tthis._b = a2 * b1 + c2 * d1;\n\t\t\tthis._d = b2 * b1 + d2 * d1;\n\t\t\tthis._tx += tx2 * a1 + ty2 * c1;\n\t\t\tthis._ty += tx2 * b1 + ty2 * d1;\n\t\t\tif (!_dontNotify)\n\t\t\t\tthis._changed();\n\t\t}\n\t\treturn this;\n\t},\n\n\tprepend: function(mx, _dontNotify) {\n\t\tif (mx) {\n\t\t\tvar a1 = this._a,\n\t\t\t\tb1 = this._b,\n\t\t\t\tc1 = this._c,\n\t\t\t\td1 = this._d,\n\t\t\t\ttx1 = this._tx,\n\t\t\t\tty1 = this._ty,\n\t\t\t\ta2 = mx._a,\n\t\t\t\tb2 = mx._c,\n\t\t\t\tc2 = mx._b,\n\t\t\t\td2 = mx._d,\n\t\t\t\ttx2 = mx._tx,\n\t\t\t\tty2 = mx._ty;\n\t\t\tthis._a = a2 * a1 + b2 * b1;\n\t\t\tthis._c = a2 * c1 + b2 * d1;\n\t\t\tthis._b = c2 * a1 + d2 * b1;\n\t\t\tthis._d = c2 * c1 + d2 * d1;\n\t\t\tthis._tx = a2 * tx1 + b2 * ty1 + tx2;\n\t\t\tthis._ty = c2 * tx1 + d2 * ty1 + ty2;\n\t\t\tif (!_dontNotify)\n\t\t\t\tthis._changed();\n\t\t}\n\t\treturn this;\n\t},\n\n\tappended: function(mx) {\n\t\treturn this.clone().append(mx);\n\t},\n\n\tprepended: function(mx) {\n\t\treturn this.clone().prepend(mx);\n\t},\n\n\tinvert: function() {\n\t\tvar a = this._a,\n\t\t\tb = this._b,\n\t\t\tc = this._c,\n\t\t\td = this._d,\n\t\t\ttx = this._tx,\n\t\t\tty = this._ty,\n\t\t\tdet = a * d - b * c,\n\t\t\tres = null;\n\t\tif (det && !isNaN(det) && isFinite(tx) && isFinite(ty)) {\n\t\t\tthis._a = d / det;\n\t\t\tthis._b = -b / det;\n\t\t\tthis._c = -c / det;\n\t\t\tthis._d = a / det;\n\t\t\tthis._tx = (c * ty - d * tx) / det;\n\t\t\tthis._ty = (b * tx - a * ty) / det;\n\t\t\tres = this;\n\t\t}\n\t\treturn res;\n\t},\n\n\tinverted: function() {\n\t\treturn this.clone().invert();\n\t},\n\n\tconcatenate: '#append',\n\tpreConcatenate: '#prepend',\n\tchain: '#appended',\n\n\t_shiftless: function() {\n\t\treturn new Matrix(this._a, this._b, this._c, this._d, 0, 0);\n\t},\n\n\t_orNullIfIdentity: function() {\n\t\treturn this.isIdentity() ? null : this;\n\t},\n\n\tisIdentity: function() {\n\t\treturn this._a === 1 && this._b === 0 && this._c === 0 && this._d === 1\n\t\t\t\t&& this._tx === 0 && this._ty === 0;\n\t},\n\n\tisInvertible: function() {\n\t\tvar det = this._a * this._d - this._c * this._b;\n\t\treturn det && !isNaN(det) && isFinite(this._tx) && isFinite(this._ty);\n\t},\n\n\tisSingular: function() {\n\t\treturn !this.isInvertible();\n\t},\n\n\ttransform: function( src, dst, count) {\n\t\treturn arguments.length < 3\n\t\t\t? this._transformPoint(Point.read(arguments))\n\t\t\t: this._transformCoordinates(src, dst, count);\n\t},\n\n\t_transformPoint: function(point, dest, _dontNotify) {\n\t\tvar x = point.x,\n\t\t\ty = point.y;\n\t\tif (!dest)\n\t\t\tdest = new Point();\n\t\treturn dest._set(\n\t\t\t\tx * this._a + y * this._c + this._tx,\n\t\t\t\tx * this._b + y * this._d + this._ty,\n\t\t\t\t_dontNotify);\n\t},\n\n\t_transformCoordinates: function(src, dst, count) {\n\t\tfor (var i = 0, max = 2 * count; i < max; i += 2) {\n\t\t\tvar x = src[i],\n\t\t\t\ty = src[i + 1];\n\t\t\tdst[i] = x * this._a + y * this._c + this._tx;\n\t\t\tdst[i + 1] = x * this._b + y * this._d + this._ty;\n\t\t}\n\t\treturn dst;\n\t},\n\n\t_transformCorners: function(rect) {\n\t\tvar x1 = rect.x,\n\t\t\ty1 = rect.y,\n\t\t\tx2 = x1 + rect.width,\n\t\t\ty2 = y1 + rect.height,\n\t\t\tcoords = [ x1, y1, x2, y1, x2, y2, x1, y2 ];\n\t\treturn this._transformCoordinates(coords, coords, 4);\n\t},\n\n\t_transformBounds: function(bounds, dest, _dontNotify) {\n\t\tvar coords = this._transformCorners(bounds),\n\t\t\tmin = coords.slice(0, 2),\n\t\t\tmax = min.slice();\n\t\tfor (var i = 2; i < 8; i++) {\n\t\t\tvar val = coords[i],\n\t\t\t\tj = i & 1;\n\t\t\tif (val < min[j]) {\n\t\t\t\tmin[j] = val;\n\t\t\t} else if (val > max[j]) {\n\t\t\t\tmax[j] = val;\n\t\t\t}\n\t\t}\n\t\tif (!dest)\n\t\t\tdest = new Rectangle();\n\t\treturn dest._set(min[0], min[1], max[0] - min[0], max[1] - min[1],\n\t\t\t\t_dontNotify);\n\t},\n\n\tinverseTransform: function() {\n\t\treturn this._inverseTransform(Point.read(arguments));\n\t},\n\n\t_inverseTransform: function(point, dest, _dontNotify) {\n\t\tvar a = this._a,\n\t\t\tb = this._b,\n\t\t\tc = this._c,\n\t\t\td = this._d,\n\t\t\ttx = this._tx,\n\t\t\tty = this._ty,\n\t\t\tdet = a * d - b * c,\n\t\t\tres = null;\n\t\tif (det && !isNaN(det) && isFinite(tx) && isFinite(ty)) {\n\t\t\tvar x = point.x - this._tx,\n\t\t\t\ty = point.y - this._ty;\n\t\t\tif (!dest)\n\t\t\t\tdest = new Point();\n\t\t\tres = dest._set(\n\t\t\t\t\t(x * d - y * c) / det,\n\t\t\t\t\t(y * a - x * b) / det,\n\t\t\t\t\t_dontNotify);\n\t\t}\n\t\treturn res;\n\t},\n\n\tdecompose: function() {\n\t\tvar a = this._a,\n\t\t\tb = this._b,\n\t\t\tc = this._c,\n\t\t\td = this._d,\n\t\t\tdet = a * d - b * c,\n\t\t\tsqrt = Math.sqrt,\n\t\t\tatan2 = Math.atan2,\n\t\t\tdegrees = 180 / Math.PI,\n\t\t\trotate,\n\t\t\tscale,\n\t\t\tskew;\n\t\tif (a !== 0 || b !== 0) {\n\t\t\tvar r = sqrt(a * a + b * b);\n\t\t\trotate = Math.acos(a / r) * (b > 0 ? 1 : -1);\n\t\t\tscale = [r, det / r];\n\t\t\tskew = [atan2(a * c + b * d, r * r), 0];\n\t\t} else if (c !== 0 || d !== 0) {\n\t\t\tvar s = sqrt(c * c + d * d);\n\t\t\trotate = Math.asin(c / s)  * (d > 0 ? 1 : -1);\n\t\t\tscale = [det / s, s];\n\t\t\tskew = [0, atan2(a * c + b * d, s * s)];\n\t\t} else {\n\t\t\trotate = 0;\n\t\t\tskew = scale = [0, 0];\n\t\t}\n\t\treturn {\n\t\t\ttranslation: this.getTranslation(),\n\t\t\trotation: rotate * degrees,\n\t\t\tscaling: new Point(scale),\n\t\t\tskewing: new Point(skew[0] * degrees, skew[1] * degrees)\n\t\t};\n\t},\n\n\tgetValues: function() {\n\t\treturn [ this._a, this._b, this._c, this._d, this._tx, this._ty ];\n\t},\n\n\tgetTranslation: function() {\n\t\treturn new Point(this._tx, this._ty);\n\t},\n\n\tgetScaling: function() {\n\t\treturn (this.decompose() || {}).scaling;\n\t},\n\n\tgetRotation: function() {\n\t\treturn (this.decompose() || {}).rotation;\n\t},\n\n\tapplyToContext: function(ctx) {\n\t\tif (!this.isIdentity()) {\n\t\t\tctx.transform(this._a, this._b, this._c, this._d,\n\t\t\t\t\tthis._tx, this._ty);\n\t\t}\n\t}\n}, Base.each(['a', 'b', 'c', 'd', 'tx', 'ty'], function(key) {\n\tvar part = Base.capitalize(key),\n\t\tprop = '_' + key;\n\tthis['get' + part] = function() {\n\t\treturn this[prop];\n\t};\n\tthis['set' + part] = function(value) {\n\t\tthis[prop] = value;\n\t\tthis._changed();\n\t};\n}, {}));\n\nvar Line = Base.extend({\n\t_class: 'Line',\n\n\tinitialize: function Line(arg0, arg1, arg2, arg3, arg4) {\n\t\tvar asVector = false;\n\t\tif (arguments.length >= 4) {\n\t\t\tthis._px = arg0;\n\t\t\tthis._py = arg1;\n\t\t\tthis._vx = arg2;\n\t\t\tthis._vy = arg3;\n\t\t\tasVector = arg4;\n\t\t} else {\n\t\t\tthis._px = arg0.x;\n\t\t\tthis._py = arg0.y;\n\t\t\tthis._vx = arg1.x;\n\t\t\tthis._vy = arg1.y;\n\t\t\tasVector = arg2;\n\t\t}\n\t\tif (!asVector) {\n\t\t\tthis._vx -= this._px;\n\t\t\tthis._vy -= this._py;\n\t\t}\n\t},\n\n\tgetPoint: function() {\n\t\treturn new Point(this._px, this._py);\n\t},\n\n\tgetVector: function() {\n\t\treturn new Point(this._vx, this._vy);\n\t},\n\n\tgetLength: function() {\n\t\treturn this.getVector().getLength();\n\t},\n\n\tintersect: function(line, isInfinite) {\n\t\treturn Line.intersect(\n\t\t\t\tthis._px, this._py, this._vx, this._vy,\n\t\t\t\tline._px, line._py, line._vx, line._vy,\n\t\t\t\ttrue, isInfinite);\n\t},\n\n\tgetSide: function(point, isInfinite) {\n\t\treturn Line.getSide(\n\t\t\t\tthis._px, this._py, this._vx, this._vy,\n\t\t\t\tpoint.x, point.y, true, isInfinite);\n\t},\n\n\tgetDistance: function(point) {\n\t\treturn Math.abs(this.getSignedDistance(point));\n\t},\n\n\tgetSignedDistance: function(point) {\n\t\treturn Line.getSignedDistance(this._px, this._py, this._vx, this._vy,\n\t\t\t\tpoint.x, point.y, true);\n\t},\n\n\tisCollinear: function(line) {\n\t\treturn Point.isCollinear(this._vx, this._vy, line._vx, line._vy);\n\t},\n\n\tisOrthogonal: function(line) {\n\t\treturn Point.isOrthogonal(this._vx, this._vy, line._vx, line._vy);\n\t},\n\n\tstatics: {\n\t\tintersect: function(p1x, p1y, v1x, v1y, p2x, p2y, v2x, v2y, asVector,\n\t\t\t\tisInfinite) {\n\t\t\tif (!asVector) {\n\t\t\t\tv1x -= p1x;\n\t\t\t\tv1y -= p1y;\n\t\t\t\tv2x -= p2x;\n\t\t\t\tv2y -= p2y;\n\t\t\t}\n\t\t\tvar cross = v1x * v2y - v1y * v2x;\n\t\t\tif (!Numerical.isZero(cross)) {\n\t\t\t\tvar dx = p1x - p2x,\n\t\t\t\t\tdy = p1y - p2y,\n\t\t\t\t\tu1 = (v2x * dy - v2y * dx) / cross,\n\t\t\t\t\tu2 = (v1x * dy - v1y * dx) / cross,\n\t\t\t\t\tepsilon = 1e-12,\n\t\t\t\t\tuMin = -epsilon,\n\t\t\t\t\tuMax = 1 + epsilon;\n\t\t\t\tif (isInfinite\n\t\t\t\t\t\t|| uMin < u1 && u1 < uMax && uMin < u2 && u2 < uMax) {\n\t\t\t\t\tif (!isInfinite) {\n\t\t\t\t\t\tu1 = u1 <= 0 ? 0 : u1 >= 1 ? 1 : u1;\n\t\t\t\t\t}\n\t\t\t\t\treturn new Point(\n\t\t\t\t\t\t\tp1x + u1 * v1x,\n\t\t\t\t\t\t\tp1y + u1 * v1y);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tgetSide: function(px, py, vx, vy, x, y, asVector, isInfinite) {\n\t\t\tif (!asVector) {\n\t\t\t\tvx -= px;\n\t\t\t\tvy -= py;\n\t\t\t}\n\t\t\tvar v2x = x - px,\n\t\t\t\tv2y = y - py,\n\t\t\t\tccw = v2x * vy - v2y * vx;\n\t\t\tif (!isInfinite && Numerical.isZero(ccw)) {\n\t\t\t\tccw = (v2x * vx + v2x * vx) / (vx * vx + vy * vy);\n\t\t\t\tif (ccw >= 0 && ccw <= 1)\n\t\t\t\t\tccw = 0;\n\t\t\t}\n\t\t\treturn ccw < 0 ? -1 : ccw > 0 ? 1 : 0;\n\t\t},\n\n\t\tgetSignedDistance: function(px, py, vx, vy, x, y, asVector) {\n\t\t\tif (!asVector) {\n\t\t\t\tvx -= px;\n\t\t\t\tvy -= py;\n\t\t\t}\n\t\t\treturn vx === 0 ? vy > 0 ? x - px : px - x\n\t\t\t\t : vy === 0 ? vx < 0 ? y - py : py - y\n\t\t\t\t : ((x-px) * vy - (y-py) * vx) / Math.sqrt(vx * vx + vy * vy);\n\t\t},\n\n\t\tgetDistance: function(px, py, vx, vy, x, y, asVector) {\n\t\t\treturn Math.abs(\n\t\t\t\t\tLine.getSignedDistance(px, py, vx, vy, x, y, asVector));\n\t\t}\n\t}\n});\n\nvar Project = PaperScopeItem.extend({\n\t_class: 'Project',\n\t_list: 'projects',\n\t_reference: 'project',\n\t_compactSerialize: true,\n\n\tinitialize: function Project(element) {\n\t\tPaperScopeItem.call(this, true);\n\t\tthis._children = [];\n\t\tthis._namedChildren = {};\n\t\tthis._activeLayer = null;\n\t\tthis._currentStyle = new Style(null, null, this);\n\t\tthis._view = View.create(this,\n\t\t\t\telement || CanvasProvider.getCanvas(1, 1));\n\t\tthis._selectionItems = {};\n\t\tthis._selectionCount = 0;\n\t\tthis._updateVersion = 0;\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\treturn Base.serialize(this._children, options, true, dictionary);\n\t},\n\n\t_changed: function(flags, item) {\n\t\tif (flags & 1) {\n\t\t\tvar view = this._view;\n\t\t\tif (view) {\n\t\t\t\tview._needsUpdate = true;\n\t\t\t\tif (!view._requested && view._autoUpdate)\n\t\t\t\t\tview.requestUpdate();\n\t\t\t}\n\t\t}\n\t\tvar changes = this._changes;\n\t\tif (changes && item) {\n\t\t\tvar changesById = this._changesById,\n\t\t\t\tid = item._id,\n\t\t\t\tentry = changesById[id];\n\t\t\tif (entry) {\n\t\t\t\tentry.flags |= flags;\n\t\t\t} else {\n\t\t\t\tchanges.push(changesById[id] = { item: item, flags: flags });\n\t\t\t}\n\t\t}\n\t},\n\n\tclear: function() {\n\t\tvar children = this._children;\n\t\tfor (var i = children.length - 1; i >= 0; i--)\n\t\t\tchildren[i].remove();\n\t},\n\n\tisEmpty: function() {\n\t\treturn !this._children.length;\n\t},\n\n\tremove: function remove() {\n\t\tif (!remove.base.call(this))\n\t\t\treturn false;\n\t\tif (this._view)\n\t\t\tthis._view.remove();\n\t\treturn true;\n\t},\n\n\tgetView: function() {\n\t\treturn this._view;\n\t},\n\n\tgetCurrentStyle: function() {\n\t\treturn this._currentStyle;\n\t},\n\n\tsetCurrentStyle: function(style) {\n\t\tthis._currentStyle.set(style);\n\t},\n\n\tgetIndex: function() {\n\t\treturn this._index;\n\t},\n\n\tgetOptions: function() {\n\t\treturn this._scope.settings;\n\t},\n\n\tgetLayers: function() {\n\t\treturn this._children;\n\t},\n\n\tgetActiveLayer: function() {\n\t\treturn this._activeLayer || new Layer({ project: this, insert: true });\n\t},\n\n\tgetSymbolDefinitions: function() {\n\t\tvar definitions = [],\n\t\t\tids = {};\n\t\tthis.getItems({\n\t\t\tclass: SymbolItem,\n\t\t\tmatch: function(item) {\n\t\t\t\tvar definition = item._definition,\n\t\t\t\t\tid = definition._id;\n\t\t\t\tif (!ids[id]) {\n\t\t\t\t\tids[id] = true;\n\t\t\t\t\tdefinitions.push(definition);\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\treturn definitions;\n\t},\n\n\tgetSymbols: 'getSymbolDefinitions',\n\n\tgetSelectedItems: function() {\n\t\tvar selectionItems = this._selectionItems,\n\t\t\titems = [];\n\t\tfor (var id in selectionItems) {\n\t\t\tvar item = selectionItems[id],\n\t\t\t\tselection = item._selection;\n\t\t\tif ((selection & 1) && item.isInserted()) {\n\t\t\t\titems.push(item);\n\t\t\t} else if (!selection) {\n\t\t\t\tthis._updateSelection(item);\n\t\t\t}\n\t\t}\n\t\treturn items;\n\t},\n\n\t_updateSelection: function(item) {\n\t\tvar id = item._id,\n\t\t\tselectionItems = this._selectionItems;\n\t\tif (item._selection) {\n\t\t\tif (selectionItems[id] !== item) {\n\t\t\t\tthis._selectionCount++;\n\t\t\t\tselectionItems[id] = item;\n\t\t\t}\n\t\t} else if (selectionItems[id] === item) {\n\t\t\tthis._selectionCount--;\n\t\t\tdelete selectionItems[id];\n\t\t}\n\t},\n\n\tselectAll: function() {\n\t\tvar children = this._children;\n\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\tchildren[i].setFullySelected(true);\n\t},\n\n\tdeselectAll: function() {\n\t\tvar selectionItems = this._selectionItems;\n\t\tfor (var i in selectionItems)\n\t\t\tselectionItems[i].setFullySelected(false);\n\t},\n\n\taddLayer: function(layer) {\n\t\treturn this.insertLayer(undefined, layer);\n\t},\n\n\tinsertLayer: function(index, layer) {\n\t\tif (layer instanceof Layer) {\n\t\t\tlayer._remove(false, true);\n\t\t\tBase.splice(this._children, [layer], index, 0);\n\t\t\tlayer._setProject(this, true);\n\t\t\tvar name = layer._name;\n\t\t\tif (name)\n\t\t\t\tlayer.setName(name);\n\t\t\tif (this._changes)\n\t\t\t\tlayer._changed(5);\n\t\t\tif (!this._activeLayer)\n\t\t\t\tthis._activeLayer = layer;\n\t\t} else {\n\t\t\tlayer = null;\n\t\t}\n\t\treturn layer;\n\t},\n\n\t_insertItem: function(index, item, _created) {\n\t\titem = this.insertLayer(index, item)\n\t\t\t\t|| (this._activeLayer || this._insertItem(undefined,\n\t\t\t\t\t\tnew Layer(Item.NO_INSERT), true))\n\t\t\t\t\t\t.insertChild(index, item);\n\t\tif (_created && item.activate)\n\t\t\titem.activate();\n\t\treturn item;\n\t},\n\n\tgetItems: function(options) {\n\t\treturn Item._getItems(this, options);\n\t},\n\n\tgetItem: function(options) {\n\t\treturn Item._getItems(this, options, null, null, true)[0] || null;\n\t},\n\n\timportJSON: function(json) {\n\t\tthis.activate();\n\t\tvar layer = this._activeLayer;\n\t\treturn Base.importJSON(json, layer && layer.isEmpty() && layer);\n\t},\n\n\tremoveOn: function(type) {\n\t\tvar sets = this._removeSets;\n\t\tif (sets) {\n\t\t\tif (type === 'mouseup')\n\t\t\t\tsets.mousedrag = null;\n\t\t\tvar set = sets[type];\n\t\t\tif (set) {\n\t\t\t\tfor (var id in set) {\n\t\t\t\t\tvar item = set[id];\n\t\t\t\t\tfor (var key in sets) {\n\t\t\t\t\t\tvar other = sets[key];\n\t\t\t\t\t\tif (other && other != set)\n\t\t\t\t\t\t\tdelete other[item._id];\n\t\t\t\t\t}\n\t\t\t\t\titem.remove();\n\t\t\t\t}\n\t\t\t\tsets[type] = null;\n\t\t\t}\n\t\t}\n\t},\n\n\tdraw: function(ctx, matrix, pixelRatio) {\n\t\tthis._updateVersion++;\n\t\tctx.save();\n\t\tmatrix.applyToContext(ctx);\n\t\tvar children = this._children,\n\t\t\tparam = new Base({\n\t\t\t\toffset: new Point(0, 0),\n\t\t\t\tpixelRatio: pixelRatio,\n\t\t\t\tviewMatrix: matrix.isIdentity() ? null : matrix,\n\t\t\t\tmatrices: [new Matrix()],\n\t\t\t\tupdateMatrix: true\n\t\t\t});\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tchildren[i].draw(ctx, param);\n\t\t}\n\t\tctx.restore();\n\n\t\tif (this._selectionCount > 0) {\n\t\t\tctx.save();\n\t\t\tctx.strokeWidth = 1;\n\t\t\tvar items = this._selectionItems,\n\t\t\t\tsize = this._scope.settings.handleSize,\n\t\t\t\tversion = this._updateVersion;\n\t\t\tfor (var id in items) {\n\t\t\t\titems[id]._drawSelection(ctx, matrix, size, items, version);\n\t\t\t}\n\t\t\tctx.restore();\n\t\t}\n\t}\n});\n\nvar Item = Base.extend(Emitter, {\n\tstatics: {\n\t\textend: function extend(src) {\n\t\t\tif (src._serializeFields)\n\t\t\t\tsrc._serializeFields = Base.set({},\n\t\t\t\t\tthis.prototype._serializeFields, src._serializeFields);\n\t\t\treturn extend.base.apply(this, arguments);\n\t\t},\n\n\t\tNO_INSERT: { insert: false }\n\t},\n\n\t_class: 'Item',\n\t_name: null,\n\t_applyMatrix: true,\n\t_canApplyMatrix: true,\n\t_canScaleStroke: false,\n\t_pivot: null,\n\t_visible: true,\n\t_blendMode: 'normal',\n\t_opacity: 1,\n\t_locked: false,\n\t_guide: false,\n\t_clipMask: false,\n\t_selection: 0,\n\t_selectBounds: true,\n\t_selectChildren: false,\n\t_serializeFields: {\n\t\tname: null,\n\t\tapplyMatrix: null,\n\t\tmatrix: new Matrix(),\n\t\tpivot: null,\n\t\tvisible: true,\n\t\tblendMode: 'normal',\n\t\topacity: 1,\n\t\tlocked: false,\n\t\tguide: false,\n\t\tclipMask: false,\n\t\tselected: false,\n\t\tdata: {}\n\t},\n\t_prioritize: ['applyMatrix']\n},\nnew function() {\n\tvar handlers = ['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onClick',\n\t\t\t'onDoubleClick', 'onMouseMove', 'onMouseEnter', 'onMouseLeave'];\n\treturn Base.each(handlers,\n\t\tfunction(name) {\n\t\t\tthis._events[name] = {\n\t\t\t\tinstall: function(type) {\n\t\t\t\t\tthis.getView()._countItemEvent(type, 1);\n\t\t\t\t},\n\n\t\t\t\tuninstall: function(type) {\n\t\t\t\t\tthis.getView()._countItemEvent(type, -1);\n\t\t\t\t}\n\t\t\t};\n\t\t}, {\n\t\t\t_events: {\n\t\t\t\tonFrame: {\n\t\t\t\t\tinstall: function() {\n\t\t\t\t\t\tthis.getView()._animateItem(this, true);\n\t\t\t\t\t},\n\n\t\t\t\t\tuninstall: function() {\n\t\t\t\t\t\tthis.getView()._animateItem(this, false);\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tonLoad: {},\n\t\t\t\tonError: {}\n\t\t\t},\n\t\t\tstatics: {\n\t\t\t\t_itemHandlers: handlers\n\t\t\t}\n\t\t}\n\t);\n}, {\n\tinitialize: function Item() {\n\t},\n\n\t_initialize: function(props, point) {\n\t\tvar hasProps = props && Base.isPlainObject(props),\n\t\t\tinternal = hasProps && props.internal === true,\n\t\t\tmatrix = this._matrix = new Matrix(),\n\t\t\tproject = hasProps && props.project || paper.project,\n\t\t\tsettings = paper.settings;\n\t\tthis._id = internal ? null : UID.get();\n\t\tthis._parent = this._index = null;\n\t\tthis._applyMatrix = this._canApplyMatrix && settings.applyMatrix;\n\t\tif (point)\n\t\t\tmatrix.translate(point);\n\t\tmatrix._owner = this;\n\t\tthis._style = new Style(project._currentStyle, this, project);\n\t\tif (internal || hasProps && props.insert == false\n\t\t\t|| !settings.insertItems && !(hasProps && props.insert === true)) {\n\t\t\tthis._setProject(project);\n\t\t} else {\n\t\t\t(hasProps && props.parent || project)\n\t\t\t\t\t._insertItem(undefined, this, true);\n\t\t}\n\t\tif (hasProps && props !== Item.NO_INSERT) {\n\t\t\tthis.set(props, {\n\t\t\t\tinternal: true, insert: true, project: true, parent: true\n\t\t\t});\n\t\t}\n\t\treturn hasProps;\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\tvar props = {},\n\t\t\tthat = this;\n\n\t\tfunction serialize(fields) {\n\t\t\tfor (var key in fields) {\n\t\t\t\tvar value = that[key];\n\t\t\t\tif (!Base.equals(value, key === 'leading'\n\t\t\t\t\t\t? fields.fontSize * 1.2 : fields[key])) {\n\t\t\t\t\tprops[key] = Base.serialize(value, options,\n\t\t\t\t\t\t\tkey !== 'data', dictionary);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tserialize(this._serializeFields);\n\t\tif (!(this instanceof Group))\n\t\t\tserialize(this._style._defaults);\n\t\treturn [ this._class, props ];\n\t},\n\n\t_changed: function(flags) {\n\t\tvar symbol = this._symbol,\n\t\t\tcacheParent = this._parent || symbol,\n\t\t\tproject = this._project;\n\t\tif (flags & 8) {\n\t\t\tthis._bounds = this._position = this._decomposed =\n\t\t\t\t\tthis._globalMatrix = undefined;\n\t\t}\n\t\tif (cacheParent\n\t\t\t\t&& (flags & 40)) {\n\t\t\tItem._clearBoundsCache(cacheParent);\n\t\t}\n\t\tif (flags & 2) {\n\t\t\tItem._clearBoundsCache(this);\n\t\t}\n\t\tif (project)\n\t\t\tproject._changed(flags, this);\n\t\tif (symbol)\n\t\t\tsymbol._changed(flags);\n\t},\n\n\tgetId: function() {\n\t\treturn this._id;\n\t},\n\n\tgetName: function() {\n\t\treturn this._name;\n\t},\n\n\tsetName: function(name) {\n\n\t\tif (this._name)\n\t\t\tthis._removeNamed();\n\t\tif (name === (+name) + '')\n\t\t\tthrow new Error(\n\t\t\t\t\t'Names consisting only of numbers are not supported.');\n\t\tvar owner = this._getOwner();\n\t\tif (name && owner) {\n\t\t\tvar children = owner._children,\n\t\t\t\tnamedChildren = owner._namedChildren;\n\t\t\t(namedChildren[name] = namedChildren[name] || []).push(this);\n\t\t\tif (!(name in children))\n\t\t\t\tchildren[name] = this;\n\t\t}\n\t\tthis._name = name || undefined;\n\t\tthis._changed(128);\n\t},\n\n\tgetStyle: function() {\n\t\treturn this._style;\n\t},\n\n\tsetStyle: function(style) {\n\t\tthis.getStyle().set(style);\n\t}\n}, Base.each(['locked', 'visible', 'blendMode', 'opacity', 'guide'],\n\tfunction(name) {\n\t\tvar part = Base.capitalize(name),\n\t\t\tkey = '_' + name,\n\t\t\tflags = {\n\t\t\t\tlocked: 128,\n\t\t\t\tvisible: 137\n\t\t\t};\n\t\tthis['get' + part] = function() {\n\t\t\treturn this[key];\n\t\t};\n\t\tthis['set' + part] = function(value) {\n\t\t\tif (value != this[key]) {\n\t\t\t\tthis[key] = value;\n\t\t\t\tthis._changed(flags[name] || 129);\n\t\t\t}\n\t\t};\n\t},\n{}), {\n\tbeans: true,\n\n\tgetSelection: function() {\n\t\treturn this._selection;\n\t},\n\n\tsetSelection: function(selection) {\n\t\tif (selection !== this._selection) {\n\t\t\tthis._selection = selection;\n\t\t\tvar project = this._project;\n\t\t\tif (project) {\n\t\t\t\tproject._updateSelection(this);\n\t\t\t\tthis._changed(129);\n\t\t\t}\n\t\t}\n\t},\n\n\tchangeSelection: function(flag, selected) {\n\t\tvar selection = this._selection;\n\t\tthis.setSelection(selected ? selection | flag : selection & ~flag);\n\t},\n\n\tisSelected: function() {\n\t\tif (this._selectChildren) {\n\t\t\tvar children = this._children;\n\t\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\t\tif (children[i].isSelected())\n\t\t\t\t\treturn true;\n\t\t}\n\t\treturn !!(this._selection & 1);\n\t},\n\n\tsetSelected: function(selected) {\n\t\tif (this._selectChildren) {\n\t\t\tvar children = this._children;\n\t\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\t\tchildren[i].setSelected(selected);\n\t\t}\n\t\tthis.changeSelection(1, selected);\n\t},\n\n\tisFullySelected: function() {\n\t\tvar children = this._children,\n\t\t\tselected = !!(this._selection & 1);\n\t\tif (children && selected) {\n\t\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\t\tif (!children[i].isFullySelected())\n\t\t\t\t\treturn false;\n\t\t\treturn true;\n\t\t}\n\t\treturn selected;\n\t},\n\n\tsetFullySelected: function(selected) {\n\t\tvar children = this._children;\n\t\tif (children) {\n\t\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\t\tchildren[i].setFullySelected(selected);\n\t\t}\n\t\tthis.changeSelection(1, selected);\n\t},\n\n\tisClipMask: function() {\n\t\treturn this._clipMask;\n\t},\n\n\tsetClipMask: function(clipMask) {\n\t\tif (this._clipMask != (clipMask = !!clipMask)) {\n\t\t\tthis._clipMask = clipMask;\n\t\t\tif (clipMask) {\n\t\t\t\tthis.setFillColor(null);\n\t\t\t\tthis.setStrokeColor(null);\n\t\t\t}\n\t\t\tthis._changed(129);\n\t\t\tif (this._parent)\n\t\t\t\tthis._parent._changed(1024);\n\t\t}\n\t},\n\n\tgetData: function() {\n\t\tif (!this._data)\n\t\t\tthis._data = {};\n\t\treturn this._data;\n\t},\n\n\tsetData: function(data) {\n\t\tthis._data = data;\n\t},\n\n\tgetPosition: function(_dontLink) {\n\t\tvar position = this._position,\n\t\t\tctor = _dontLink ? Point : LinkedPoint;\n\t\tif (!position) {\n\t\t\tvar pivot = this._pivot;\n\t\t\tposition = this._position = pivot\n\t\t\t\t\t? this._matrix._transformPoint(pivot)\n\t\t\t\t\t: this.getBounds().getCenter(true);\n\t\t}\n\t\treturn new ctor(position.x, position.y, this, 'setPosition');\n\t},\n\n\tsetPosition: function() {\n\t\tthis.translate(Point.read(arguments).subtract(this.getPosition(true)));\n\t},\n\n\tgetPivot: function() {\n\t\tvar pivot = this._pivot;\n\t\treturn pivot\n\t\t\t\t? new LinkedPoint(pivot.x, pivot.y, this, 'setPivot')\n\t\t\t\t: null;\n\t},\n\n\tsetPivot: function() {\n\t\tthis._pivot = Point.read(arguments, 0, { clone: true, readNull: true });\n\t\tthis._position = undefined;\n\t}\n}, Base.each({\n\t\tgetStrokeBounds: { stroke: true },\n\t\tgetHandleBounds: { handle: true },\n\t\tgetInternalBounds: { internal: true }\n\t},\n\tfunction(options, key) {\n\t\tthis[key] = function(matrix) {\n\t\t\treturn this.getBounds(matrix, options);\n\t\t};\n\t},\n{\n\tbeans: true,\n\n\tgetBounds: function(matrix, options) {\n\t\tvar hasMatrix = options || matrix instanceof Matrix,\n\t\t\topts = Base.set({}, hasMatrix ? options : matrix,\n\t\t\t\t\tthis._boundsOptions);\n\t\tif (!opts.stroke || this.getStrokeScaling())\n\t\t\topts.cacheItem = this;\n\t\tvar rect = this._getCachedBounds(hasMatrix && matrix, opts).rect;\n\t\treturn !arguments.length\n\t\t\t\t? new LinkedRectangle(rect.x, rect.y, rect.width, rect.height,\n\t\t\t\t\tthis, 'setBounds')\n\t\t\t\t: rect;\n\t},\n\n\tsetBounds: function() {\n\t\tvar rect = Rectangle.read(arguments),\n\t\t\tbounds = this.getBounds(),\n\t\t\t_matrix = this._matrix,\n\t\t\tmatrix = new Matrix(),\n\t\t\tcenter = rect.getCenter();\n\t\tmatrix.translate(center);\n\t\tif (rect.width != bounds.width || rect.height != bounds.height) {\n\t\t\tif (!_matrix.isInvertible()) {\n\t\t\t\t_matrix.set(_matrix._backup\n\t\t\t\t\t\t|| new Matrix().translate(_matrix.getTranslation()));\n\t\t\t\tbounds = this.getBounds();\n\t\t\t}\n\t\t\tmatrix.scale(\n\t\t\t\t\tbounds.width !== 0 ? rect.width / bounds.width : 0,\n\t\t\t\t\tbounds.height !== 0 ? rect.height / bounds.height : 0);\n\t\t}\n\t\tcenter = bounds.getCenter();\n\t\tmatrix.translate(-center.x, -center.y);\n\t\tthis.transform(matrix);\n\t},\n\n\t_getBounds: function(matrix, options) {\n\t\tvar children = this._children;\n\t\tif (!children || !children.length)\n\t\t\treturn new Rectangle();\n\t\tItem._updateBoundsCache(this, options.cacheItem);\n\t\treturn Item._getBounds(children, matrix, options);\n\t},\n\n\t_getBoundsCacheKey: function(options, internal) {\n\t\treturn [\n\t\t\toptions.stroke ? 1 : 0,\n\t\t\toptions.handle ? 1 : 0,\n\t\t\tinternal ? 1 : 0\n\t\t].join('');\n\t},\n\n\t_getCachedBounds: function(matrix, options, noInternal) {\n\t\tmatrix = matrix && matrix._orNullIfIdentity();\n\t\tvar internal = options.internal && !noInternal,\n\t\t\tcacheItem = options.cacheItem,\n\t\t\t_matrix = internal ? null : this._matrix._orNullIfIdentity(),\n\t\t\tcacheKey = cacheItem && (!matrix || matrix.equals(_matrix))\n\t\t\t\t&& this._getBoundsCacheKey(options, internal),\n\t\t\tbounds = this._bounds;\n\t\tItem._updateBoundsCache(this._parent || this._symbol, cacheItem);\n\t\tif (cacheKey && bounds && cacheKey in bounds) {\n\t\t\tvar cached = bounds[cacheKey];\n\t\t\treturn {\n\t\t\t\trect: cached.rect.clone(),\n\t\t\t\tnonscaling: cached.nonscaling\n\t\t\t};\n\t\t}\n\t\tvar res = this._getBounds(matrix || _matrix, options),\n\t\t\trect = res.rect || res,\n\t\t\tstyle = this._style,\n\t\t\tnonscaling = res.nonscaling || style.hasStroke()\n\t\t\t\t&& !style.getStrokeScaling();\n\t\tif (cacheKey) {\n\t\t\tif (!bounds) {\n\t\t\t\tthis._bounds = bounds = {};\n\t\t\t}\n\t\t\tvar cached = bounds[cacheKey] = {\n\t\t\t\trect: rect.clone(),\n\t\t\t\tnonscaling: nonscaling,\n\t\t\t\tinternal: internal\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\trect: rect,\n\t\t\tnonscaling: nonscaling\n\t\t};\n\t},\n\n\t_getStrokeMatrix: function(matrix, options) {\n\t\tvar parent = this.getStrokeScaling() ? null\n\t\t\t\t: options && options.internal ? this\n\t\t\t\t\t: this._parent || this._symbol && this._symbol._item,\n\t\t\tmx = parent ? parent.getViewMatrix().invert() : matrix;\n\t\treturn mx && mx._shiftless();\n\t},\n\n\tstatics: {\n\t\t_updateBoundsCache: function(parent, item) {\n\t\t\tif (parent && item) {\n\t\t\t\tvar id = item._id,\n\t\t\t\t\tref = parent._boundsCache = parent._boundsCache || {\n\t\t\t\t\t\tids: {},\n\t\t\t\t\t\tlist: []\n\t\t\t\t\t};\n\t\t\t\tif (!ref.ids[id]) {\n\t\t\t\t\tref.list.push(item);\n\t\t\t\t\tref.ids[id] = item;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_clearBoundsCache: function(item) {\n\t\t\tvar cache = item._boundsCache;\n\t\t\tif (cache) {\n\t\t\t\titem._bounds = item._position = item._boundsCache = undefined;\n\t\t\t\tfor (var i = 0, list = cache.list, l = list.length; i < l; i++){\n\t\t\t\t\tvar other = list[i];\n\t\t\t\t\tif (other !== item) {\n\t\t\t\t\t\tother._bounds = other._position = undefined;\n\t\t\t\t\t\tif (other._boundsCache)\n\t\t\t\t\t\t\tItem._clearBoundsCache(other);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_getBounds: function(items, matrix, options) {\n\t\t\tvar x1 = Infinity,\n\t\t\t\tx2 = -x1,\n\t\t\t\ty1 = x1,\n\t\t\t\ty2 = x2,\n\t\t\t\tnonscaling = false;\n\t\t\toptions = options || {};\n\t\t\tfor (var i = 0, l = items.length; i < l; i++) {\n\t\t\t\tvar item = items[i];\n\t\t\t\tif (item._visible && !item.isEmpty()) {\n\t\t\t\t\tvar bounds = item._getCachedBounds(\n\t\t\t\t\t\tmatrix && matrix.appended(item._matrix), options, true),\n\t\t\t\t\t\trect = bounds.rect;\n\t\t\t\t\tx1 = Math.min(rect.x, x1);\n\t\t\t\t\ty1 = Math.min(rect.y, y1);\n\t\t\t\t\tx2 = Math.max(rect.x + rect.width, x2);\n\t\t\t\t\ty2 = Math.max(rect.y + rect.height, y2);\n\t\t\t\t\tif (bounds.nonscaling)\n\t\t\t\t\t\tnonscaling = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn {\n\t\t\t\trect: isFinite(x1)\n\t\t\t\t\t? new Rectangle(x1, y1, x2 - x1, y2 - y1)\n\t\t\t\t\t: new Rectangle(),\n\t\t\t\tnonscaling: nonscaling\n\t\t\t};\n\t\t}\n\t}\n\n}), {\n\tbeans: true,\n\n\t_decompose: function() {\n\t\treturn this._applyMatrix\n\t\t\t? null\n\t\t\t: this._decomposed || (this._decomposed = this._matrix.decompose());\n\t},\n\n\tgetRotation: function() {\n\t\tvar decomposed = this._decompose();\n\t\treturn decomposed ? decomposed.rotation : 0;\n\t},\n\n\tsetRotation: function(rotation) {\n\t\tvar current = this.getRotation();\n\t\tif (current != null && rotation != null) {\n\t\t\tvar decomposed = this._decomposed;\n\t\t\tthis.rotate(rotation - current);\n\t\t\tif (decomposed) {\n\t\t\t\tdecomposed.rotation = rotation;\n\t\t\t\tthis._decomposed = decomposed;\n\t\t\t}\n\t\t}\n\t},\n\n\tgetScaling: function() {\n\t\tvar decomposed = this._decompose(),\n\t\t\ts = decomposed && decomposed.scaling;\n\t\treturn new LinkedPoint(s ? s.x : 1, s ? s.y : 1, this, 'setScaling');\n\t},\n\n\tsetScaling: function() {\n\t\tvar current = this.getScaling(),\n\t\t\tscaling = Point.read(arguments, 0, { clone: true, readNull: true });\n\t\tif (current && scaling && !current.equals(scaling)) {\n\t\t\tvar rotation = this.getRotation(),\n\t\t\t\tdecomposed = this._decomposed,\n\t\t\t\tmatrix = new Matrix(),\n\t\t\t\tcenter = this.getPosition(true);\n\t\t\tmatrix.translate(center);\n\t\t\tif (rotation)\n\t\t\t\tmatrix.rotate(rotation);\n\t\t\tmatrix.scale(scaling.x / current.x, scaling.y / current.y);\n\t\t\tif (rotation)\n\t\t\t\tmatrix.rotate(-rotation);\n\t\t\tmatrix.translate(center.negate());\n\t\t\tthis.transform(matrix);\n\t\t\tif (decomposed) {\n\t\t\t\tdecomposed.scaling = scaling;\n\t\t\t\tthis._decomposed = decomposed;\n\t\t\t}\n\t\t}\n\t},\n\n\tgetMatrix: function() {\n\t\treturn this._matrix;\n\t},\n\n\tsetMatrix: function() {\n\t\tvar matrix = this._matrix;\n\t\tmatrix.initialize.apply(matrix, arguments);\n\t},\n\n\tgetGlobalMatrix: function(_dontClone) {\n\t\tvar matrix = this._globalMatrix,\n\t\t\tupdateVersion = this._project._updateVersion;\n\t\tif (matrix && matrix._updateVersion !== updateVersion)\n\t\t\tmatrix = null;\n\t\tif (!matrix) {\n\t\t\tmatrix = this._globalMatrix = this._matrix.clone();\n\t\t\tvar parent = this._parent;\n\t\t\tif (parent)\n\t\t\t\tmatrix.prepend(parent.getGlobalMatrix(true));\n\t\t\tmatrix._updateVersion = updateVersion;\n\t\t}\n\t\treturn _dontClone ? matrix : matrix.clone();\n\t},\n\n\tgetViewMatrix: function() {\n\t\treturn this.getGlobalMatrix().prepend(this.getView()._matrix);\n\t},\n\n\tgetApplyMatrix: function() {\n\t\treturn this._applyMatrix;\n\t},\n\n\tsetApplyMatrix: function(apply) {\n\t\tif (this._applyMatrix = this._canApplyMatrix && !!apply)\n\t\t\tthis.transform(null, true);\n\t},\n\n\tgetTransformContent: '#getApplyMatrix',\n\tsetTransformContent: '#setApplyMatrix',\n}, {\n\tgetProject: function() {\n\t\treturn this._project;\n\t},\n\n\t_setProject: function(project, installEvents) {\n\t\tif (this._project !== project) {\n\t\t\tif (this._project)\n\t\t\t\tthis._installEvents(false);\n\t\t\tthis._project = project;\n\t\t\tvar children = this._children;\n\t\t\tfor (var i = 0, l = children && children.length; i < l; i++)\n\t\t\t\tchildren[i]._setProject(project);\n\t\t\tinstallEvents = true;\n\t\t}\n\t\tif (installEvents)\n\t\t\tthis._installEvents(true);\n\t},\n\n\tgetView: function() {\n\t\treturn this._project._view;\n\t},\n\n\t_installEvents: function _installEvents(install) {\n\t\t_installEvents.base.call(this, install);\n\t\tvar children = this._children;\n\t\tfor (var i = 0, l = children && children.length; i < l; i++)\n\t\t\tchildren[i]._installEvents(install);\n\t},\n\n\tgetLayer: function() {\n\t\tvar parent = this;\n\t\twhile (parent = parent._parent) {\n\t\t\tif (parent instanceof Layer)\n\t\t\t\treturn parent;\n\t\t}\n\t\treturn null;\n\t},\n\n\tgetParent: function() {\n\t\treturn this._parent;\n\t},\n\n\tsetParent: function(item) {\n\t\treturn item.addChild(this);\n\t},\n\n\t_getOwner: '#getParent',\n\n\tgetChildren: function() {\n\t\treturn this._children;\n\t},\n\n\tsetChildren: function(items) {\n\t\tthis.removeChildren();\n\t\tthis.addChildren(items);\n\t},\n\n\tgetFirstChild: function() {\n\t\treturn this._children && this._children[0] || null;\n\t},\n\n\tgetLastChild: function() {\n\t\treturn this._children && this._children[this._children.length - 1]\n\t\t\t\t|| null;\n\t},\n\n\tgetNextSibling: function() {\n\t\tvar owner = this._getOwner();\n\t\treturn owner && owner._children[this._index + 1] || null;\n\t},\n\n\tgetPreviousSibling: function() {\n\t\tvar owner = this._getOwner();\n\t\treturn owner && owner._children[this._index - 1] || null;\n\t},\n\n\tgetIndex: function() {\n\t\treturn this._index;\n\t},\n\n\tequals: function(item) {\n\t\treturn item === this || item && this._class === item._class\n\t\t\t\t&& this._style.equals(item._style)\n\t\t\t\t&& this._matrix.equals(item._matrix)\n\t\t\t\t&& this._locked === item._locked\n\t\t\t\t&& this._visible === item._visible\n\t\t\t\t&& this._blendMode === item._blendMode\n\t\t\t\t&& this._opacity === item._opacity\n\t\t\t\t&& this._clipMask === item._clipMask\n\t\t\t\t&& this._guide === item._guide\n\t\t\t\t&& this._equals(item)\n\t\t\t\t|| false;\n\t},\n\n\t_equals: function(item) {\n\t\treturn Base.equals(this._children, item._children);\n\t},\n\n\tclone: function(options) {\n\t\tvar copy = new this.constructor(Item.NO_INSERT),\n\t\t\tchildren = this._children,\n\t\t\tinsert = Base.pick(options ? options.insert : undefined,\n\t\t\t\t\toptions === undefined || options === true),\n\t\t\tdeep = Base.pick(options ? options.deep : undefined, true);\n\t\tif (children)\n\t\t\tcopy.copyAttributes(this);\n\t\tif (!children || deep)\n\t\t\tcopy.copyContent(this);\n\t\tif (!children)\n\t\t\tcopy.copyAttributes(this);\n\t\tif (insert)\n\t\t\tcopy.insertAbove(this);\n\t\tvar name = this._name,\n\t\t\tparent = this._parent;\n\t\tif (name && parent) {\n\t\t\tvar children = parent._children,\n\t\t\t\torig = name,\n\t\t\t\ti = 1;\n\t\t\twhile (children[name])\n\t\t\t\tname = orig + ' ' + (i++);\n\t\t\tif (name !== orig)\n\t\t\t\tcopy.setName(name);\n\t\t}\n\t\treturn copy;\n\t},\n\n\tcopyContent: function(source) {\n\t\tvar children = source._children;\n\t\tfor (var i = 0, l = children && children.length; i < l; i++) {\n\t\t\tthis.addChild(children[i].clone(false), true);\n\t\t}\n\t},\n\n\tcopyAttributes: function(source, excludeMatrix) {\n\t\tthis.setStyle(source._style);\n\t\tvar keys = ['_locked', '_visible', '_blendMode', '_opacity',\n\t\t\t\t'_clipMask', '_guide'];\n\t\tfor (var i = 0, l = keys.length; i < l; i++) {\n\t\t\tvar key = keys[i];\n\t\t\tif (source.hasOwnProperty(key))\n\t\t\t\tthis[key] = source[key];\n\t\t}\n\t\tif (!excludeMatrix)\n\t\t\tthis._matrix.set(source._matrix, true);\n\t\tthis.setApplyMatrix(source._applyMatrix);\n\t\tthis.setPivot(source._pivot);\n\t\tthis.setSelection(source._selection);\n\t\tvar data = source._data,\n\t\t\tname = source._name;\n\t\tthis._data = data ? Base.clone(data) : null;\n\t\tif (name)\n\t\t\tthis.setName(name);\n\t},\n\n\trasterize: function(resolution, insert) {\n\t\tvar bounds = this.getStrokeBounds(),\n\t\t\tscale = (resolution || this.getView().getResolution()) / 72,\n\t\t\ttopLeft = bounds.getTopLeft().floor(),\n\t\t\tbottomRight = bounds.getBottomRight().ceil(),\n\t\t\tsize = new Size(bottomRight.subtract(topLeft)),\n\t\t\traster = new Raster(Item.NO_INSERT);\n\t\tif (!size.isZero()) {\n\t\t\tvar canvas = CanvasProvider.getCanvas(size.multiply(scale)),\n\t\t\t\tctx = canvas.getContext('2d'),\n\t\t\t\tmatrix = new Matrix().scale(scale).translate(topLeft.negate());\n\t\t\tctx.save();\n\t\t\tmatrix.applyToContext(ctx);\n\t\t\tthis.draw(ctx, new Base({ matrices: [matrix] }));\n\t\t\tctx.restore();\n\t\t\traster.setCanvas(canvas);\n\t\t}\n\t\traster.transform(new Matrix().translate(topLeft.add(size.divide(2)))\n\t\t\t\t.scale(1 / scale));\n\t\tif (insert === undefined || insert)\n\t\t\traster.insertAbove(this);\n\t\treturn raster;\n\t},\n\n\tcontains: function() {\n\t\treturn !!this._contains(\n\t\t\t\tthis._matrix._inverseTransform(Point.read(arguments)));\n\t},\n\n\t_contains: function(point) {\n\t\tvar children = this._children;\n\t\tif (children) {\n\t\t\tfor (var i = children.length - 1; i >= 0; i--) {\n\t\t\t\tif (children[i].contains(point))\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t\treturn point.isInside(this.getInternalBounds());\n\t},\n\n\tisInside: function() {\n\t\treturn Rectangle.read(arguments).contains(this.getBounds());\n\t},\n\n\t_asPathItem: function() {\n\t\treturn new Path.Rectangle({\n\t\t\trectangle: this.getInternalBounds(),\n\t\t\tmatrix: this._matrix,\n\t\t\tinsert: false,\n\t\t});\n\t},\n\n\tintersects: function(item, _matrix) {\n\t\tif (!(item instanceof Item))\n\t\t\treturn false;\n\t\treturn this._asPathItem().getIntersections(item._asPathItem(), null,\n\t\t\t\t_matrix, true).length > 0;\n\t}\n},\nnew function() {\n\tfunction hitTest() {\n\t\treturn this._hitTest(\n\t\t\t\tPoint.read(arguments),\n\t\t\t\tHitResult.getOptions(arguments));\n\t}\n\n\tfunction hitTestAll() {\n\t\tvar point = Point.read(arguments),\n\t\t\toptions = HitResult.getOptions(arguments),\n\t\t\tall = [];\n\t\tthis._hitTest(point, Base.set({ all: all }, options));\n\t\treturn all;\n\t}\n\n\tfunction hitTestChildren(point, options, viewMatrix, _exclude) {\n\t\tvar children = this._children;\n\t\tif (children) {\n\t\t\tfor (var i = children.length - 1; i >= 0; i--) {\n\t\t\t\tvar child = children[i];\n\t\t\t\tvar res = child !== _exclude && child._hitTest(point, options,\n\t\t\t\t\t\tviewMatrix);\n\t\t\t\tif (res && !options.all)\n\t\t\t\t\treturn res;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tProject.inject({\n\t\thitTest: hitTest,\n\t\thitTestAll: hitTestAll,\n\t\t_hitTest: hitTestChildren\n\t});\n\n\treturn {\n\t\thitTest: hitTest,\n\t\thitTestAll: hitTestAll,\n\t\t_hitTestChildren: hitTestChildren,\n\t};\n}, {\n\n\t_hitTest: function(point, options, parentViewMatrix) {\n\t\tif (this._locked || !this._visible || this._guide && !options.guides\n\t\t\t\t|| this.isEmpty()) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar matrix = this._matrix,\n\t\t\tviewMatrix = parentViewMatrix\n\t\t\t\t\t? parentViewMatrix.appended(matrix)\n\t\t\t\t\t: this.getGlobalMatrix().prepend(this.getView()._matrix),\n\t\t\ttolerance = Math.max(options.tolerance, 1e-12),\n\t\t\ttolerancePadding = options._tolerancePadding = new Size(\n\t\t\t\t\tPath._getStrokePadding(tolerance,\n\t\t\t\t\t\tmatrix._shiftless().invert()));\n\t\tpoint = matrix._inverseTransform(point);\n\t\tif (!point || !this._children &&\n\t\t\t!this.getBounds({ internal: true, stroke: true, handle: true })\n\t\t\t\t.expand(tolerancePadding.multiply(2))._containsPoint(point)) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar checkSelf = !(options.guides && !this._guide\n\t\t\t\t|| options.selected && !this.isSelected()\n\t\t\t\t|| options.type && options.type !== Base.hyphenate(this._class)\n\t\t\t\t|| options.class && !(this instanceof options.class)),\n\t\t\tmatch = options.match,\n\t\t\tthat = this,\n\t\t\tbounds,\n\t\t\tres;\n\n\t\tfunction filter(hit) {\n\t\t\tif (hit && match && !match(hit))\n\t\t\t\thit = null;\n\t\t\tif (hit && options.all)\n\t\t\t\toptions.all.push(hit);\n\t\t\treturn hit;\n\t\t}\n\n\t\tfunction checkPoint(type, part) {\n\t\t\tvar pt = part ? bounds['get' + part]() : that.getPosition();\n\t\t\tif (point.subtract(pt).divide(tolerancePadding).length <= 1) {\n\t\t\t\treturn new HitResult(type, that, {\n\t\t\t\t\tname: part ? Base.hyphenate(part) : type,\n\t\t\t\t\tpoint: pt\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tvar checkPosition = options.position,\n\t\t\tcheckCenter = options.center,\n\t\t\tcheckBounds = options.bounds;\n\t\tif (checkSelf && this._parent\n\t\t\t\t&& (checkPosition || checkCenter || checkBounds)) {\n\t\t\tif (checkCenter || checkBounds) {\n\t\t\t\tbounds = this.getInternalBounds();\n\t\t\t}\n\t\t\tres = checkPosition && checkPoint('position') ||\n\t\t\t\t\tcheckCenter && checkPoint('center', 'Center');\n\t\t\tif (!res && checkBounds) {\n\t\t\t\tvar points = [\n\t\t\t\t\t'TopLeft', 'TopRight', 'BottomLeft', 'BottomRight',\n\t\t\t\t\t'LeftCenter', 'TopCenter', 'RightCenter', 'BottomCenter'\n\t\t\t\t];\n\t\t\t\tfor (var i = 0; i < 8 && !res; i++) {\n\t\t\t\t\tres = checkPoint('bounds', points[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tres = filter(res);\n\t\t}\n\n\t\tif (!res) {\n\t\t\tres = this._hitTestChildren(point, options, viewMatrix)\n\t\t\t\t|| checkSelf\n\t\t\t\t\t&& filter(this._hitTestSelf(point, options, viewMatrix,\n\t\t\t\t\t\tthis.getStrokeScaling() ? null\n\t\t\t\t\t\t\t: viewMatrix._shiftless().invert()))\n\t\t\t\t|| null;\n\t\t}\n\t\tif (res && res.point) {\n\t\t\tres.point = matrix.transform(res.point);\n\t\t}\n\t\treturn res;\n\t},\n\n\t_hitTestSelf: function(point, options) {\n\t\tif (options.fill && this.hasFill() && this._contains(point))\n\t\t\treturn new HitResult('fill', this);\n\t},\n\n\tmatches: function(name, compare) {\n\t\tfunction matchObject(obj1, obj2) {\n\t\t\tfor (var i in obj1) {\n\t\t\t\tif (obj1.hasOwnProperty(i)) {\n\t\t\t\t\tvar val1 = obj1[i],\n\t\t\t\t\t\tval2 = obj2[i];\n\t\t\t\t\tif (Base.isPlainObject(val1) && Base.isPlainObject(val2)) {\n\t\t\t\t\t\tif (!matchObject(val1, val2))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t} else if (!Base.equals(val1, val2)) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\tvar type = typeof name;\n\t\tif (type === 'object') {\n\t\t\tfor (var key in name) {\n\t\t\t\tif (name.hasOwnProperty(key) && !this.matches(key, name[key]))\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn true;\n\t\t} else if (type === 'function') {\n\t\t\treturn name(this);\n\t\t} else if (name === 'match') {\n\t\t\treturn compare(this);\n\t\t} else {\n\t\t\tvar value = /^(empty|editable)$/.test(name)\n\t\t\t\t\t? this['is' + Base.capitalize(name)]()\n\t\t\t\t\t: name === 'type'\n\t\t\t\t\t\t? Base.hyphenate(this._class)\n\t\t\t\t\t\t: this[name];\n\t\t\tif (name === 'class') {\n\t\t\t\tif (typeof compare === 'function')\n\t\t\t\t\treturn this instanceof compare;\n\t\t\t\tvalue = this._class;\n\t\t\t}\n\t\t\tif (typeof compare === 'function') {\n\t\t\t\treturn !!compare(value);\n\t\t\t} else if (compare) {\n\t\t\t\tif (compare.test) {\n\t\t\t\t\treturn compare.test(value);\n\t\t\t\t} else if (Base.isPlainObject(compare)) {\n\t\t\t\t\treturn matchObject(compare, value);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn Base.equals(value, compare);\n\t\t}\n\t},\n\n\tgetItems: function(options) {\n\t\treturn Item._getItems(this, options, this._matrix);\n\t},\n\n\tgetItem: function(options) {\n\t\treturn Item._getItems(this, options, this._matrix, null, true)[0]\n\t\t\t\t|| null;\n\t},\n\n\tstatics: {\n\t\t_getItems: function _getItems(item, options, matrix, param, firstOnly) {\n\t\t\tif (!param) {\n\t\t\t\tvar obj = typeof options === 'object' && options,\n\t\t\t\t\toverlapping = obj && obj.overlapping,\n\t\t\t\t\tinside = obj && obj.inside,\n\t\t\t\t\tbounds = overlapping || inside,\n\t\t\t\t\trect = bounds && Rectangle.read([bounds]);\n\t\t\t\tparam = {\n\t\t\t\t\titems: [],\n\t\t\t\t\trecursive: obj && obj.recursive !== false,\n\t\t\t\t\tinside: !!inside,\n\t\t\t\t\toverlapping: !!overlapping,\n\t\t\t\t\trect: rect,\n\t\t\t\t\tpath: overlapping && new Path.Rectangle({\n\t\t\t\t\t\trectangle: rect,\n\t\t\t\t\t\tinsert: false\n\t\t\t\t\t})\n\t\t\t\t};\n\t\t\t\tif (obj) {\n\t\t\t\t\toptions = Base.filter({}, options, {\n\t\t\t\t\t\trecursive: true, inside: true, overlapping: true\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar children = item._children,\n\t\t\t\titems = param.items,\n\t\t\t\trect = param.rect;\n\t\t\tmatrix = rect && (matrix || new Matrix());\n\t\t\tfor (var i = 0, l = children && children.length; i < l; i++) {\n\t\t\t\tvar child = children[i],\n\t\t\t\t\tchildMatrix = matrix && matrix.appended(child._matrix),\n\t\t\t\t\tadd = true;\n\t\t\t\tif (rect) {\n\t\t\t\t\tvar bounds = child.getBounds(childMatrix);\n\t\t\t\t\tif (!rect.intersects(bounds))\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tif (!(rect.contains(bounds)\n\t\t\t\t\t\t\t|| param.overlapping && (bounds.contains(rect)\n\t\t\t\t\t\t\t\t|| param.path.intersects(child, childMatrix))))\n\t\t\t\t\t\tadd = false;\n\t\t\t\t}\n\t\t\t\tif (add && child.matches(options)) {\n\t\t\t\t\titems.push(child);\n\t\t\t\t\tif (firstOnly)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (param.recursive !== false) {\n\t\t\t\t\t_getItems(child, options, childMatrix, param, firstOnly);\n\t\t\t\t}\n\t\t\t\tif (firstOnly && items.length > 0)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\treturn items;\n\t\t}\n\t}\n}, {\n\n\timportJSON: function(json) {\n\t\tvar res = Base.importJSON(json, this);\n\t\treturn res !== this ? this.addChild(res) : res;\n\t},\n\n\taddChild: function(item) {\n\t\treturn this.insertChild(undefined, item);\n\t},\n\n\tinsertChild: function(index, item) {\n\t\tvar res = item ? this.insertChildren(index, [item]) : null;\n\t\treturn res && res[0];\n\t},\n\n\taddChildren: function(items) {\n\t\treturn this.insertChildren(this._children.length, items);\n\t},\n\n\tinsertChildren: function(index, items) {\n\t\tvar children = this._children;\n\t\tif (children && items && items.length > 0) {\n\t\t\titems = Base.slice(items);\n\t\t\tvar inserted = {};\n\t\t\tfor (var i = items.length - 1; i >= 0; i--) {\n\t\t\t\tvar item = items[i],\n\t\t\t\t\tid = item && item._id;\n\t\t\t\tif (!item || inserted[id]) {\n\t\t\t\t\titems.splice(i, 1);\n\t\t\t\t} else {\n\t\t\t\t\titem._remove(false, true);\n\t\t\t\t\tinserted[id] = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tBase.splice(children, items, index, 0);\n\t\t\tvar project = this._project,\n\t\t\t\tnotifySelf = project._changes;\n\t\t\tfor (var i = 0, l = items.length; i < l; i++) {\n\t\t\t\tvar item = items[i],\n\t\t\t\t\tname = item._name;\n\t\t\t\titem._parent = this;\n\t\t\t\titem._setProject(project, true);\n\t\t\t\tif (name)\n\t\t\t\t\titem.setName(name);\n\t\t\t\tif (notifySelf)\n\t\t\t\t\titem._changed(5);\n\t\t\t}\n\t\t\tthis._changed(11);\n\t\t} else {\n\t\t\titems = null;\n\t\t}\n\t\treturn items;\n\t},\n\n\t_insertItem: '#insertChild',\n\n\t_insertAt: function(item, offset) {\n\t\tvar owner = item && item._getOwner(),\n\t\t\tres = item !== this && owner ? this : null;\n\t\tif (res) {\n\t\t\tres._remove(false, true);\n\t\t\towner._insertItem(item._index + offset, res);\n\t\t}\n\t\treturn res;\n\t},\n\n\tinsertAbove: function(item) {\n\t\treturn this._insertAt(item, 1);\n\t},\n\n\tinsertBelow: function(item) {\n\t\treturn this._insertAt(item, 0);\n\t},\n\n\tsendToBack: function() {\n\t\tvar owner = this._getOwner();\n\t\treturn owner ? owner._insertItem(0, this) : null;\n\t},\n\n\tbringToFront: function() {\n\t\tvar owner = this._getOwner();\n\t\treturn owner ? owner._insertItem(undefined, this) : null;\n\t},\n\n\tappendTop: '#addChild',\n\n\tappendBottom: function(item) {\n\t\treturn this.insertChild(0, item);\n\t},\n\n\tmoveAbove: '#insertAbove',\n\n\tmoveBelow: '#insertBelow',\n\n\taddTo: function(owner) {\n\t\treturn owner._insertItem(undefined, this);\n\t},\n\n\tcopyTo: function(owner) {\n\t\treturn this.clone(false).addTo(owner);\n\t},\n\n\treduce: function(options) {\n\t\tvar children = this._children;\n\t\tif (children && children.length === 1) {\n\t\t\tvar child = children[0].reduce(options);\n\t\t\tif (this._parent) {\n\t\t\t\tchild.insertAbove(this);\n\t\t\t\tthis.remove();\n\t\t\t} else {\n\t\t\t\tchild.remove();\n\t\t\t}\n\t\t\treturn child;\n\t\t}\n\t\treturn this;\n\t},\n\n\t_removeNamed: function() {\n\t\tvar owner = this._getOwner();\n\t\tif (owner) {\n\t\t\tvar children = owner._children,\n\t\t\t\tnamedChildren = owner._namedChildren,\n\t\t\t\tname = this._name,\n\t\t\t\tnamedArray = namedChildren[name],\n\t\t\t\tindex = namedArray ? namedArray.indexOf(this) : -1;\n\t\t\tif (index !== -1) {\n\t\t\t\tif (children[name] == this)\n\t\t\t\t\tdelete children[name];\n\t\t\t\tnamedArray.splice(index, 1);\n\t\t\t\tif (namedArray.length) {\n\t\t\t\t\tchildren[name] = namedArray[0];\n\t\t\t\t} else {\n\t\t\t\t\tdelete namedChildren[name];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t_remove: function(notifySelf, notifyParent) {\n\t\tvar owner = this._getOwner(),\n\t\t\tproject = this._project,\n\t\t\tindex = this._index;\n\t\tif (owner) {\n\t\t\tif (this._name)\n\t\t\t\tthis._removeNamed();\n\t\t\tif (index != null) {\n\t\t\t\tif (project._activeLayer === this)\n\t\t\t\t\tproject._activeLayer = this.getNextSibling()\n\t\t\t\t\t\t\t|| this.getPreviousSibling();\n\t\t\t\tBase.splice(owner._children, null, index, 1);\n\t\t\t}\n\t\t\tthis._installEvents(false);\n\t\t\tif (notifySelf && project._changes)\n\t\t\t\tthis._changed(5);\n\t\t\tif (notifyParent)\n\t\t\t\towner._changed(11, this);\n\t\t\tthis._parent = null;\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t},\n\n\tremove: function() {\n\t\treturn this._remove(true, true);\n\t},\n\n\treplaceWith: function(item) {\n\t\tvar ok = item && item.insertBelow(this);\n\t\tif (ok)\n\t\t\tthis.remove();\n\t\treturn ok;\n\t},\n\n\tremoveChildren: function(start, end) {\n\t\tif (!this._children)\n\t\t\treturn null;\n\t\tstart = start || 0;\n\t\tend = Base.pick(end, this._children.length);\n\t\tvar removed = Base.splice(this._children, null, start, end - start);\n\t\tfor (var i = removed.length - 1; i >= 0; i--) {\n\t\t\tremoved[i]._remove(true, false);\n\t\t}\n\t\tif (removed.length > 0)\n\t\t\tthis._changed(11);\n\t\treturn removed;\n\t},\n\n\tclear: '#removeChildren',\n\n\treverseChildren: function() {\n\t\tif (this._children) {\n\t\t\tthis._children.reverse();\n\t\t\tfor (var i = 0, l = this._children.length; i < l; i++)\n\t\t\t\tthis._children[i]._index = i;\n\t\t\tthis._changed(11);\n\t\t}\n\t},\n\n\tisEmpty: function() {\n\t\tvar children = this._children;\n\t\treturn !children || !children.length;\n\t},\n\n\tisEditable: function() {\n\t\tvar item = this;\n\t\twhile (item) {\n\t\t\tif (!item._visible || item._locked)\n\t\t\t\treturn false;\n\t\t\titem = item._parent;\n\t\t}\n\t\treturn true;\n\t},\n\n\thasFill: function() {\n\t\treturn this.getStyle().hasFill();\n\t},\n\n\thasStroke: function() {\n\t\treturn this.getStyle().hasStroke();\n\t},\n\n\thasShadow: function() {\n\t\treturn this.getStyle().hasShadow();\n\t},\n\n\t_getOrder: function(item) {\n\t\tfunction getList(item) {\n\t\t\tvar list = [];\n\t\t\tdo {\n\t\t\t\tlist.unshift(item);\n\t\t\t} while (item = item._parent);\n\t\t\treturn list;\n\t\t}\n\t\tvar list1 = getList(this),\n\t\t\tlist2 = getList(item);\n\t\tfor (var i = 0, l = Math.min(list1.length, list2.length); i < l; i++) {\n\t\t\tif (list1[i] != list2[i]) {\n\t\t\t\treturn list1[i]._index < list2[i]._index ? 1 : -1;\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t},\n\n\thasChildren: function() {\n\t\treturn this._children && this._children.length > 0;\n\t},\n\n\tisInserted: function() {\n\t\treturn this._parent ? this._parent.isInserted() : false;\n\t},\n\n\tisAbove: function(item) {\n\t\treturn this._getOrder(item) === -1;\n\t},\n\n\tisBelow: function(item) {\n\t\treturn this._getOrder(item) === 1;\n\t},\n\n\tisParent: function(item) {\n\t\treturn this._parent === item;\n\t},\n\n\tisChild: function(item) {\n\t\treturn item && item._parent === this;\n\t},\n\n\tisDescendant: function(item) {\n\t\tvar parent = this;\n\t\twhile (parent = parent._parent) {\n\t\t\tif (parent === item)\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t},\n\n\tisAncestor: function(item) {\n\t\treturn item ? item.isDescendant(this) : false;\n\t},\n\n\tisSibling: function(item) {\n\t\treturn this._parent === item._parent;\n\t},\n\n\tisGroupedWith: function(item) {\n\t\tvar parent = this._parent;\n\t\twhile (parent) {\n\t\t\tif (parent._parent\n\t\t\t\t&& /^(Group|Layer|CompoundPath)$/.test(parent._class)\n\t\t\t\t&& item.isDescendant(parent))\n\t\t\t\t\treturn true;\n\t\t\tparent = parent._parent;\n\t\t}\n\t\treturn false;\n\t},\n\n}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) {\n\tvar rotate = key === 'rotate';\n\tthis[key] = function() {\n\t\tvar value = (rotate ? Base : Point).read(arguments),\n\t\t\tcenter = Point.read(arguments, 0, { readNull: true });\n\t\treturn this.transform(new Matrix()[key](value,\n\t\t\t\tcenter || this.getPosition(true)));\n\t};\n}, {\n\ttranslate: function() {\n\t\tvar mx = new Matrix();\n\t\treturn this.transform(mx.translate.apply(mx, arguments));\n\t},\n\n\ttransform: function(matrix, _applyMatrix, _applyRecursively,\n\t\t\t_setApplyMatrix) {\n\t\tvar _matrix = this._matrix,\n\t\t\ttransform = matrix && !matrix.isIdentity(),\n\t\t\tapplyMatrix = (_applyMatrix || this._applyMatrix)\n\t\t\t\t\t&& ((!_matrix.isIdentity() || transform)\n\t\t\t\t\t\t|| _applyMatrix && _applyRecursively && this._children);\n\t\tif (!transform && !applyMatrix)\n\t\t\treturn this;\n\t\tif (transform) {\n\t\t\tif (!matrix.isInvertible() && _matrix.isInvertible())\n\t\t\t\t_matrix._backup = _matrix.getValues();\n\t\t\t_matrix.prepend(matrix, true);\n\t\t\tvar style = this._style,\n\t\t\t\tfillColor = style.getFillColor(true),\n\t\t\t\tstrokeColor = style.getStrokeColor(true);\n\t\t\tif (fillColor)\n\t\t\t\tfillColor.transform(matrix);\n\t\t\tif (strokeColor)\n\t\t\t\tstrokeColor.transform(matrix);\n\t\t}\n\t\tif (applyMatrix && (applyMatrix = this._transformContent(_matrix,\n\t\t\t\t_applyRecursively, _setApplyMatrix))) {\n\t\t\tvar pivot = this._pivot;\n\t\t\tif (pivot)\n\t\t\t\t_matrix._transformPoint(pivot, pivot, true);\n\t\t\t_matrix.reset(true);\n\t\t\tif (_setApplyMatrix && this._canApplyMatrix)\n\t\t\t\tthis._applyMatrix = true;\n\t\t}\n\t\tvar bounds = this._bounds,\n\t\t\tposition = this._position;\n\t\tif (transform || applyMatrix) {\n\t\t\tthis._changed(9);\n\t\t}\n\t\tvar decomp = transform && bounds && matrix.decompose();\n\t\tif (decomp && decomp.skewing.isZero() && decomp.rotation % 90 === 0) {\n\t\t\tfor (var key in bounds) {\n\t\t\t\tvar cache = bounds[key];\n\t\t\t\tif (cache.nonscaling) {\n\t\t\t\t\tdelete bounds[key];\n\t\t\t\t} else if (applyMatrix || !cache.internal) {\n\t\t\t\t\tvar rect = cache.rect;\n\t\t\t\t\tmatrix._transformBounds(rect, rect);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._bounds = bounds;\n\t\t\tvar cached = bounds[this._getBoundsCacheKey(\n\t\t\t\t\tthis._boundsOptions || {})];\n\t\t\tif (cached) {\n\t\t\t\tthis._position = cached.rect.getCenter(true);\n\t\t\t}\n\t\t} else if (transform && position && this._pivot) {\n\t\t\tthis._position = matrix._transformPoint(position, position);\n\t\t}\n\t\treturn this;\n\t},\n\n\t_transformContent: function(matrix, applyRecursively, setApplyMatrix) {\n\t\tvar children = this._children;\n\t\tif (children) {\n\t\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\t\tchildren[i].transform(matrix, true, applyRecursively,\n\t\t\t\t\t\tsetApplyMatrix);\n\t\t\treturn true;\n\t\t}\n\t},\n\n\tglobalToLocal: function() {\n\t\treturn this.getGlobalMatrix(true)._inverseTransform(\n\t\t\t\tPoint.read(arguments));\n\t},\n\n\tlocalToGlobal: function() {\n\t\treturn this.getGlobalMatrix(true)._transformPoint(\n\t\t\t\tPoint.read(arguments));\n\t},\n\n\tparentToLocal: function() {\n\t\treturn this._matrix._inverseTransform(Point.read(arguments));\n\t},\n\n\tlocalToParent: function() {\n\t\treturn this._matrix._transformPoint(Point.read(arguments));\n\t},\n\n\tfitBounds: function(rectangle, fill) {\n\t\trectangle = Rectangle.read(arguments);\n\t\tvar bounds = this.getBounds(),\n\t\t\titemRatio = bounds.height / bounds.width,\n\t\t\trectRatio = rectangle.height / rectangle.width,\n\t\t\tscale = (fill ? itemRatio > rectRatio : itemRatio < rectRatio)\n\t\t\t\t\t? rectangle.width / bounds.width\n\t\t\t\t\t: rectangle.height / bounds.height,\n\t\t\tnewBounds = new Rectangle(new Point(),\n\t\t\t\t\tnew Size(bounds.width * scale, bounds.height * scale));\n\t\tnewBounds.setCenter(rectangle.getCenter());\n\t\tthis.setBounds(newBounds);\n\t}\n}), {\n\n\t_setStyles: function(ctx, param, viewMatrix) {\n\t\tvar style = this._style,\n\t\t\tmatrix = this._matrix;\n\t\tif (style.hasFill()) {\n\t\t\tctx.fillStyle = style.getFillColor().toCanvasStyle(ctx, matrix);\n\t\t}\n\t\tif (style.hasStroke()) {\n\t\t\tctx.strokeStyle = style.getStrokeColor().toCanvasStyle(ctx, matrix);\n\t\t\tctx.lineWidth = style.getStrokeWidth();\n\t\t\tvar strokeJoin = style.getStrokeJoin(),\n\t\t\t\tstrokeCap = style.getStrokeCap(),\n\t\t\t\tmiterLimit = style.getMiterLimit();\n\t\t\tif (strokeJoin)\n\t\t\t\tctx.lineJoin = strokeJoin;\n\t\t\tif (strokeCap)\n\t\t\t\tctx.lineCap = strokeCap;\n\t\t\tif (miterLimit)\n\t\t\t\tctx.miterLimit = miterLimit;\n\t\t\tif (paper.support.nativeDash) {\n\t\t\t\tvar dashArray = style.getDashArray(),\n\t\t\t\t\tdashOffset = style.getDashOffset();\n\t\t\t\tif (dashArray && dashArray.length) {\n\t\t\t\t\tif ('setLineDash' in ctx) {\n\t\t\t\t\t\tctx.setLineDash(dashArray);\n\t\t\t\t\t\tctx.lineDashOffset = dashOffset;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tctx.mozDash = dashArray;\n\t\t\t\t\t\tctx.mozDashOffset = dashOffset;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (style.hasShadow()) {\n\t\t\tvar pixelRatio = param.pixelRatio || 1,\n\t\t\t\tmx = viewMatrix._shiftless().prepend(\n\t\t\t\t\tnew Matrix().scale(pixelRatio, pixelRatio)),\n\t\t\t\tblur = mx.transform(new Point(style.getShadowBlur(), 0)),\n\t\t\t\toffset = mx.transform(this.getShadowOffset());\n\t\t\tctx.shadowColor = style.getShadowColor().toCanvasStyle(ctx);\n\t\t\tctx.shadowBlur = blur.getLength();\n\t\t\tctx.shadowOffsetX = offset.x;\n\t\t\tctx.shadowOffsetY = offset.y;\n\t\t}\n\t},\n\n\tdraw: function(ctx, param, parentStrokeMatrix) {\n\t\tvar updateVersion = this._updateVersion = this._project._updateVersion;\n\t\tif (!this._visible || this._opacity === 0)\n\t\t\treturn;\n\t\tvar matrices = param.matrices,\n\t\t\tviewMatrix = param.viewMatrix,\n\t\t\tmatrix = this._matrix,\n\t\t\tglobalMatrix = matrices[matrices.length - 1].appended(matrix);\n\t\tif (!globalMatrix.isInvertible())\n\t\t\treturn;\n\n\t\tviewMatrix = viewMatrix ? viewMatrix.appended(globalMatrix)\n\t\t\t\t: globalMatrix;\n\n\t\tmatrices.push(globalMatrix);\n\t\tif (param.updateMatrix) {\n\t\t\tglobalMatrix._updateVersion = updateVersion;\n\t\t\tthis._globalMatrix = globalMatrix;\n\t\t}\n\n\t\tvar blendMode = this._blendMode,\n\t\t\topacity = this._opacity,\n\t\t\tnormalBlend = blendMode === 'normal',\n\t\t\tnativeBlend = BlendMode.nativeModes[blendMode],\n\t\t\tdirect = normalBlend && opacity === 1\n\t\t\t\t\t|| param.dontStart\n\t\t\t\t\t|| param.clip\n\t\t\t\t\t|| (nativeBlend || normalBlend && opacity < 1)\n\t\t\t\t\t\t&& this._canComposite(),\n\t\t\tpixelRatio = param.pixelRatio || 1,\n\t\t\tmainCtx, itemOffset, prevOffset;\n\t\tif (!direct) {\n\t\t\tvar bounds = this.getStrokeBounds(viewMatrix);\n\t\t\tif (!bounds.width || !bounds.height)\n\t\t\t\treturn;\n\t\t\tprevOffset = param.offset;\n\t\t\titemOffset = param.offset = bounds.getTopLeft().floor();\n\t\t\tmainCtx = ctx;\n\t\t\tctx = CanvasProvider.getContext(bounds.getSize().ceil().add(1)\n\t\t\t\t\t.multiply(pixelRatio));\n\t\t\tif (pixelRatio !== 1)\n\t\t\t\tctx.scale(pixelRatio, pixelRatio);\n\t\t}\n\t\tctx.save();\n\t\tvar strokeMatrix = parentStrokeMatrix\n\t\t\t\t? parentStrokeMatrix.appended(matrix)\n\t\t\t\t: this._canScaleStroke && !this.getStrokeScaling(true)\n\t\t\t\t\t&& viewMatrix,\n\t\t\tclip = !direct && param.clipItem,\n\t\t\ttransform = !strokeMatrix || clip;\n\t\tif (direct) {\n\t\t\tctx.globalAlpha = opacity;\n\t\t\tif (nativeBlend)\n\t\t\t\tctx.globalCompositeOperation = blendMode;\n\t\t} else if (transform) {\n\t\t\tctx.translate(-itemOffset.x, -itemOffset.y);\n\t\t}\n\t\tif (transform) {\n\t\t\t(direct ? matrix : viewMatrix).applyToContext(ctx);\n\t\t}\n\t\tif (clip) {\n\t\t\tparam.clipItem.draw(ctx, param.extend({ clip: true }));\n\t\t}\n\t\tif (strokeMatrix) {\n\t\t\tctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);\n\t\t\tvar offset = param.offset;\n\t\t\tif (offset)\n\t\t\t\tctx.translate(-offset.x, -offset.y);\n\t\t}\n\t\tthis._draw(ctx, param, viewMatrix, strokeMatrix);\n\t\tctx.restore();\n\t\tmatrices.pop();\n\t\tif (param.clip && !param.dontFinish)\n\t\t\tctx.clip();\n\t\tif (!direct) {\n\t\t\tBlendMode.process(blendMode, ctx, mainCtx, opacity,\n\t\t\t\t\titemOffset.subtract(prevOffset).multiply(pixelRatio));\n\t\t\tCanvasProvider.release(ctx);\n\t\t\tparam.offset = prevOffset;\n\t\t}\n\t},\n\n\t_isUpdated: function(updateVersion) {\n\t\tvar parent = this._parent;\n\t\tif (parent instanceof CompoundPath)\n\t\t\treturn parent._isUpdated(updateVersion);\n\t\tvar updated = this._updateVersion === updateVersion;\n\t\tif (!updated && parent && parent._visible\n\t\t\t\t&& parent._isUpdated(updateVersion)) {\n\t\t\tthis._updateVersion = updateVersion;\n\t\t\tupdated = true;\n\t\t}\n\t\treturn updated;\n\t},\n\n\t_drawSelection: function(ctx, matrix, size, selectionItems, updateVersion) {\n\t\tvar selection = this._selection,\n\t\t\titemSelected = selection & 1,\n\t\t\tboundsSelected = selection & 2\n\t\t\t\t\t|| itemSelected && this._selectBounds,\n\t\t\tpositionSelected = selection & 4;\n\t\tif (!this._drawSelected)\n\t\t\titemSelected = false;\n\t\tif ((itemSelected || boundsSelected || positionSelected)\n\t\t\t\t&& this._isUpdated(updateVersion)) {\n\t\t\tvar layer,\n\t\t\t\tcolor = this.getSelectedColor(true) || (layer = this.getLayer())\n\t\t\t\t\t&& layer.getSelectedColor(true),\n\t\t\t\tmx = matrix.appended(this.getGlobalMatrix(true)),\n\t\t\t\thalf = size / 2;\n\t\t\tctx.strokeStyle = ctx.fillStyle = color\n\t\t\t\t\t? color.toCanvasStyle(ctx) : '#009dec';\n\t\t\tif (itemSelected)\n\t\t\t\tthis._drawSelected(ctx, mx, selectionItems);\n\t\t\tif (positionSelected) {\n\t\t\t\tvar point = this.getPosition(true),\n\t\t\t\t\tx = point.x,\n\t\t\t\t\ty = point.y;\n\t\t\t\tctx.beginPath();\n\t\t\t\tctx.arc(x, y, half, 0, Math.PI * 2, true);\n\t\t\t\tctx.stroke();\n\t\t\t\tvar deltas = [[0, -1], [1, 0], [0, 1], [-1, 0]],\n\t\t\t\t\tstart = half,\n\t\t\t\t\tend = size + 1;\n\t\t\t\tfor (var i = 0; i < 4; i++) {\n\t\t\t\t\tvar delta = deltas[i],\n\t\t\t\t\t\tdx = delta[0],\n\t\t\t\t\t\tdy = delta[1];\n\t\t\t\t\tctx.moveTo(x + dx * start, y + dy * start);\n\t\t\t\t\tctx.lineTo(x + dx * end, y + dy * end);\n\t\t\t\t\tctx.stroke();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (boundsSelected) {\n\t\t\t\tvar coords = mx._transformCorners(this.getInternalBounds());\n\t\t\t\tctx.beginPath();\n\t\t\t\tfor (var i = 0; i < 8; i++) {\n\t\t\t\t\tctx[!i ? 'moveTo' : 'lineTo'](coords[i], coords[++i]);\n\t\t\t\t}\n\t\t\t\tctx.closePath();\n\t\t\t\tctx.stroke();\n\t\t\t\tfor (var i = 0; i < 8; i++) {\n\t\t\t\t\tctx.fillRect(coords[i] - half, coords[++i] - half,\n\t\t\t\t\t\t\tsize, size);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t_canComposite: function() {\n\t\treturn false;\n\t}\n}, Base.each(['down', 'drag', 'up', 'move'], function(key) {\n\tthis['removeOn' + Base.capitalize(key)] = function() {\n\t\tvar hash = {};\n\t\thash[key] = true;\n\t\treturn this.removeOn(hash);\n\t};\n}, {\n\n\tremoveOn: function(obj) {\n\t\tfor (var name in obj) {\n\t\t\tif (obj[name]) {\n\t\t\t\tvar key = 'mouse' + name,\n\t\t\t\t\tproject = this._project,\n\t\t\t\t\tsets = project._removeSets = project._removeSets || {};\n\t\t\t\tsets[key] = sets[key] || {};\n\t\t\t\tsets[key][this._id] = this;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n}));\n\nvar Group = Item.extend({\n\t_class: 'Group',\n\t_selectBounds: false,\n\t_selectChildren: true,\n\t_serializeFields: {\n\t\tchildren: []\n\t},\n\n\tinitialize: function Group(arg) {\n\t\tthis._children = [];\n\t\tthis._namedChildren = {};\n\t\tif (!this._initialize(arg))\n\t\t\tthis.addChildren(Array.isArray(arg) ? arg : arguments);\n\t},\n\n\t_changed: function _changed(flags) {\n\t\t_changed.base.call(this, flags);\n\t\tif (flags & 1026) {\n\t\t\tthis._clipItem = undefined;\n\t\t}\n\t},\n\n\t_getClipItem: function() {\n\t\tvar clipItem = this._clipItem;\n\t\tif (clipItem === undefined) {\n\t\t\tclipItem = null;\n\t\t\tvar children = this._children;\n\t\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\t\tif (children[i]._clipMask) {\n\t\t\t\t\tclipItem = children[i];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._clipItem = clipItem;\n\t\t}\n\t\treturn clipItem;\n\t},\n\n\tisClipped: function() {\n\t\treturn !!this._getClipItem();\n\t},\n\n\tsetClipped: function(clipped) {\n\t\tvar child = this.getFirstChild();\n\t\tif (child)\n\t\t\tchild.setClipMask(clipped);\n\t},\n\n\t_getBounds: function _getBounds(matrix, options) {\n\t\tvar clipItem = this._getClipItem();\n\t\treturn clipItem\n\t\t\t? clipItem._getCachedBounds(\n\t\t\t\tmatrix && matrix.appended(clipItem._matrix),\n\t\t\t\tBase.set({}, options, { stroke: false }))\n\t\t\t: _getBounds.base.call(this, matrix, options);\n\t},\n\n\t_hitTestChildren: function _hitTestChildren(point, options, viewMatrix) {\n\t\tvar clipItem = this._getClipItem();\n\t\treturn (!clipItem || clipItem.contains(point))\n\t\t\t\t&& _hitTestChildren.base.call(this, point, options, viewMatrix,\n\t\t\t\t\tclipItem);\n\t},\n\n\t_draw: function(ctx, param) {\n\t\tvar clip = param.clip,\n\t\t\tclipItem = !clip && this._getClipItem();\n\t\tparam = param.extend({ clipItem: clipItem, clip: false });\n\t\tif (clip) {\n\t\t\tctx.beginPath();\n\t\t\tparam.dontStart = param.dontFinish = true;\n\t\t} else if (clipItem) {\n\t\t\tclipItem.draw(ctx, param.extend({ clip: true }));\n\t\t}\n\t\tvar children = this._children;\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tvar item = children[i];\n\t\t\tif (item !== clipItem)\n\t\t\t\titem.draw(ctx, param);\n\t\t}\n\t}\n});\n\nvar Layer = Group.extend({\n\t_class: 'Layer',\n\n\tinitialize: function Layer() {\n\t\tGroup.apply(this, arguments);\n\t},\n\n\t_getOwner: function() {\n\t\treturn this._parent || this._index != null && this._project;\n\t},\n\n\tisInserted: function isInserted() {\n\t\treturn this._parent ? isInserted.base.call(this) : this._index != null;\n\t},\n\n\tactivate: function() {\n\t\tthis._project._activeLayer = this;\n\t},\n\n\t_hitTestSelf: function() {\n\t}\n});\n\nvar Shape = Item.extend({\n\t_class: 'Shape',\n\t_applyMatrix: false,\n\t_canApplyMatrix: false,\n\t_canScaleStroke: true,\n\t_serializeFields: {\n\t\ttype: null,\n\t\tsize: null,\n\t\tradius: null\n\t},\n\n\tinitialize: function Shape(props, point) {\n\t\tthis._initialize(props, point);\n\t},\n\n\t_equals: function(item) {\n\t\treturn this._type === item._type\n\t\t\t&& this._size.equals(item._size)\n\t\t\t&& Base.equals(this._radius, item._radius);\n\t},\n\n\tcopyContent: function(source) {\n\t\tthis.setType(source._type);\n\t\tthis.setSize(source._size);\n\t\tthis.setRadius(source._radius);\n\t},\n\n\tgetType: function() {\n\t\treturn this._type;\n\t},\n\n\tsetType: function(type) {\n\t\tthis._type = type;\n\t},\n\n\tgetShape: '#getType',\n\tsetShape: '#setType',\n\n\tgetSize: function() {\n\t\tvar size = this._size;\n\t\treturn new LinkedSize(size.width, size.height, this, 'setSize');\n\t},\n\n\tsetSize: function() {\n\t\tvar size = Size.read(arguments);\n\t\tif (!this._size) {\n\t\t\tthis._size = size.clone();\n\t\t} else if (!this._size.equals(size)) {\n\t\t\tvar type = this._type,\n\t\t\t\twidth = size.width,\n\t\t\t\theight = size.height;\n\t\t\tif (type === 'rectangle') {\n\t\t\t\tthis._radius.set(Size.min(this._radius, size.divide(2)));\n\t\t\t} else if (type === 'circle') {\n\t\t\t\twidth = height = (width + height) / 2;\n\t\t\t\tthis._radius = width / 2;\n\t\t\t} else if (type === 'ellipse') {\n\t\t\t\tthis._radius._set(width / 2, height / 2);\n\t\t\t}\n\t\t\tthis._size._set(width, height);\n\t\t\tthis._changed(9);\n\t\t}\n\t},\n\n\tgetRadius: function() {\n\t\tvar rad = this._radius;\n\t\treturn this._type === 'circle'\n\t\t\t\t? rad\n\t\t\t\t: new LinkedSize(rad.width, rad.height, this, 'setRadius');\n\t},\n\n\tsetRadius: function(radius) {\n\t\tvar type = this._type;\n\t\tif (type === 'circle') {\n\t\t\tif (radius === this._radius)\n\t\t\t\treturn;\n\t\t\tvar size = radius * 2;\n\t\t\tthis._radius = radius;\n\t\t\tthis._size._set(size, size);\n\t\t} else {\n\t\t\tradius = Size.read(arguments);\n\t\t\tif (!this._radius) {\n\t\t\t\tthis._radius = radius.clone();\n\t\t\t} else {\n\t\t\t\tif (this._radius.equals(radius))\n\t\t\t\t\treturn;\n\t\t\t\tthis._radius.set(radius);\n\t\t\t\tif (type === 'rectangle') {\n\t\t\t\t\tvar size = Size.max(this._size, radius.multiply(2));\n\t\t\t\t\tthis._size.set(size);\n\t\t\t\t} else if (type === 'ellipse') {\n\t\t\t\t\tthis._size._set(radius.width * 2, radius.height * 2);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis._changed(9);\n\t},\n\n\tisEmpty: function() {\n\t\treturn false;\n\t},\n\n\ttoPath: function(insert) {\n\t\tvar path = new Path[Base.capitalize(this._type)]({\n\t\t\tcenter: new Point(),\n\t\t\tsize: this._size,\n\t\t\tradius: this._radius,\n\t\t\tinsert: false\n\t\t});\n\t\tpath.copyAttributes(this);\n\t\tif (paper.settings.applyMatrix)\n\t\t\tpath.setApplyMatrix(true);\n\t\tif (insert === undefined || insert)\n\t\t\tpath.insertAbove(this);\n\t\treturn path;\n\t},\n\n\ttoShape: '#clone',\n\n\t_asPathItem: function() {\n\t\treturn this.toPath(false);\n\t},\n\n\t_draw: function(ctx, param, viewMatrix, strokeMatrix) {\n\t\tvar style = this._style,\n\t\t\thasFill = style.hasFill(),\n\t\t\thasStroke = style.hasStroke(),\n\t\t\tdontPaint = param.dontFinish || param.clip,\n\t\t\tuntransformed = !strokeMatrix;\n\t\tif (hasFill || hasStroke || dontPaint) {\n\t\t\tvar type = this._type,\n\t\t\t\tradius = this._radius,\n\t\t\t\tisCircle = type === 'circle';\n\t\t\tif (!param.dontStart)\n\t\t\t\tctx.beginPath();\n\t\t\tif (untransformed && isCircle) {\n\t\t\t\tctx.arc(0, 0, radius, 0, Math.PI * 2, true);\n\t\t\t} else {\n\t\t\t\tvar rx = isCircle ? radius : radius.width,\n\t\t\t\t\try = isCircle ? radius : radius.height,\n\t\t\t\t\tsize = this._size,\n\t\t\t\t\twidth = size.width,\n\t\t\t\t\theight = size.height;\n\t\t\t\tif (untransformed && type === 'rectangle' && rx === 0 && ry === 0) {\n\t\t\t\t\tctx.rect(-width / 2, -height / 2, width, height);\n\t\t\t\t} else {\n\t\t\t\t\tvar x = width / 2,\n\t\t\t\t\t\ty = height / 2,\n\t\t\t\t\t\tkappa = 1 - 0.5522847498307936,\n\t\t\t\t\t\tcx = rx * kappa,\n\t\t\t\t\t\tcy = ry * kappa,\n\t\t\t\t\t\tc = [\n\t\t\t\t\t\t\t-x, -y + ry,\n\t\t\t\t\t\t\t-x, -y + cy,\n\t\t\t\t\t\t\t-x + cx, -y,\n\t\t\t\t\t\t\t-x + rx, -y,\n\t\t\t\t\t\t\tx - rx, -y,\n\t\t\t\t\t\t\tx - cx, -y,\n\t\t\t\t\t\t\tx, -y + cy,\n\t\t\t\t\t\t\tx, -y + ry,\n\t\t\t\t\t\t\tx, y - ry,\n\t\t\t\t\t\t\tx, y - cy,\n\t\t\t\t\t\t\tx - cx, y,\n\t\t\t\t\t\t\tx - rx, y,\n\t\t\t\t\t\t\t-x + rx, y,\n\t\t\t\t\t\t\t-x + cx, y,\n\t\t\t\t\t\t\t-x, y - cy,\n\t\t\t\t\t\t\t-x, y - ry\n\t\t\t\t\t\t];\n\t\t\t\t\tif (strokeMatrix)\n\t\t\t\t\t\tstrokeMatrix.transform(c, c, 32);\n\t\t\t\t\tctx.moveTo(c[0], c[1]);\n\t\t\t\t\tctx.bezierCurveTo(c[2], c[3], c[4], c[5], c[6], c[7]);\n\t\t\t\t\tif (x !== rx)\n\t\t\t\t\t\tctx.lineTo(c[8], c[9]);\n\t\t\t\t\tctx.bezierCurveTo(c[10], c[11], c[12], c[13], c[14], c[15]);\n\t\t\t\t\tif (y !== ry)\n\t\t\t\t\t\tctx.lineTo(c[16], c[17]);\n\t\t\t\t\tctx.bezierCurveTo(c[18], c[19], c[20], c[21], c[22], c[23]);\n\t\t\t\t\tif (x !== rx)\n\t\t\t\t\t\tctx.lineTo(c[24], c[25]);\n\t\t\t\t\tctx.bezierCurveTo(c[26], c[27], c[28], c[29], c[30], c[31]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tctx.closePath();\n\t\t}\n\t\tif (!dontPaint && (hasFill || hasStroke)) {\n\t\t\tthis._setStyles(ctx, param, viewMatrix);\n\t\t\tif (hasFill) {\n\t\t\t\tctx.fill(style.getFillRule());\n\t\t\t\tctx.shadowColor = 'rgba(0,0,0,0)';\n\t\t\t}\n\t\t\tif (hasStroke)\n\t\t\t\tctx.stroke();\n\t\t}\n\t},\n\n\t_canComposite: function() {\n\t\treturn !(this.hasFill() && this.hasStroke());\n\t},\n\n\t_getBounds: function(matrix, options) {\n\t\tvar rect = new Rectangle(this._size).setCenter(0, 0),\n\t\t\tstyle = this._style,\n\t\t\tstrokeWidth = options.stroke && style.hasStroke()\n\t\t\t\t\t&& style.getStrokeWidth();\n\t\tif (matrix)\n\t\t\trect = matrix._transformBounds(rect);\n\t\treturn strokeWidth\n\t\t\t\t? rect.expand(Path._getStrokePadding(strokeWidth,\n\t\t\t\t\tthis._getStrokeMatrix(matrix, options)))\n\t\t\t\t: rect;\n\t}\n},\nnew function() {\n\tfunction getCornerCenter(that, point, expand) {\n\t\tvar radius = that._radius;\n\t\tif (!radius.isZero()) {\n\t\t\tvar halfSize = that._size.divide(2);\n\t\t\tfor (var q = 1; q <= 4; q++) {\n\t\t\t\tvar dir = new Point(q > 1 && q < 4 ? -1 : 1, q > 2 ? -1 : 1),\n\t\t\t\t\tcorner = dir.multiply(halfSize),\n\t\t\t\t\tcenter = corner.subtract(dir.multiply(radius)),\n\t\t\t\t\trect = new Rectangle(\n\t\t\t\t\t\t\texpand ? corner.add(dir.multiply(expand)) : corner,\n\t\t\t\t\t\t\tcenter);\n\t\t\t\tif (rect.contains(point))\n\t\t\t\t\treturn { point: center, quadrant: q };\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction isOnEllipseStroke(point, radius, padding, quadrant) {\n\t\tvar vector = point.divide(radius);\n\t\treturn (!quadrant || vector.isInQuadrant(quadrant)) &&\n\t\t\t\tvector.subtract(vector.normalize()).multiply(radius)\n\t\t\t\t\t.divide(padding).length <= 1;\n\t}\n\n\treturn {\n\t\t_contains: function _contains(point) {\n\t\t\tif (this._type === 'rectangle') {\n\t\t\t\tvar center = getCornerCenter(this, point);\n\t\t\t\treturn center\n\t\t\t\t\t\t? point.subtract(center.point).divide(this._radius)\n\t\t\t\t\t\t\t.getLength() <= 1\n\t\t\t\t\t\t: _contains.base.call(this, point);\n\t\t\t} else {\n\t\t\t\treturn point.divide(this.size).getLength() <= 0.5;\n\t\t\t}\n\t\t},\n\n\t\t_hitTestSelf: function _hitTestSelf(point, options, viewMatrix,\n\t\t\t\tstrokeMatrix) {\n\t\t\tvar hit = false,\n\t\t\t\tstyle = this._style,\n\t\t\t\thitStroke = options.stroke && style.hasStroke(),\n\t\t\t\thitFill = options.fill && style.hasFill();\n\t\t\tif (hitStroke || hitFill) {\n\t\t\t\tvar type = this._type,\n\t\t\t\t\tradius = this._radius,\n\t\t\t\t\tstrokeRadius = hitStroke ? style.getStrokeWidth() / 2 : 0,\n\t\t\t\t\tstrokePadding = options._tolerancePadding.add(\n\t\t\t\t\t\tPath._getStrokePadding(strokeRadius,\n\t\t\t\t\t\t\t!style.getStrokeScaling() && strokeMatrix));\n\t\t\t\tif (type === 'rectangle') {\n\t\t\t\t\tvar padding = strokePadding.multiply(2),\n\t\t\t\t\t\tcenter = getCornerCenter(this, point, padding);\n\t\t\t\t\tif (center) {\n\t\t\t\t\t\thit = isOnEllipseStroke(point.subtract(center.point),\n\t\t\t\t\t\t\t\tradius, strokePadding, center.quadrant);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar rect = new Rectangle(this._size).setCenter(0, 0),\n\t\t\t\t\t\t\touter = rect.expand(padding),\n\t\t\t\t\t\t\tinner = rect.expand(padding.negate());\n\t\t\t\t\t\thit = outer._containsPoint(point)\n\t\t\t\t\t\t\t\t&& !inner._containsPoint(point);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\thit = isOnEllipseStroke(point, radius, strokePadding);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn hit ? new HitResult(hitStroke ? 'stroke' : 'fill', this)\n\t\t\t\t\t: _hitTestSelf.base.apply(this, arguments);\n\t\t}\n\t};\n}, {\n\nstatics: new function() {\n\tfunction createShape(type, point, size, radius, args) {\n\t\tvar item = new Shape(Base.getNamed(args), point);\n\t\titem._type = type;\n\t\titem._size = size;\n\t\titem._radius = radius;\n\t\treturn item;\n\t}\n\n\treturn {\n\t\tCircle: function() {\n\t\t\tvar center = Point.readNamed(arguments, 'center'),\n\t\t\t\tradius = Base.readNamed(arguments, 'radius');\n\t\t\treturn createShape('circle', center, new Size(radius * 2), radius,\n\t\t\t\t\targuments);\n\t\t},\n\n\t\tRectangle: function() {\n\t\t\tvar rect = Rectangle.readNamed(arguments, 'rectangle'),\n\t\t\t\tradius = Size.min(Size.readNamed(arguments, 'radius'),\n\t\t\t\t\t\trect.getSize(true).divide(2));\n\t\t\treturn createShape('rectangle', rect.getCenter(true),\n\t\t\t\t\trect.getSize(true), radius, arguments);\n\t\t},\n\n\t\tEllipse: function() {\n\t\t\tvar ellipse = Shape._readEllipse(arguments),\n\t\t\t\tradius = ellipse.radius;\n\t\t\treturn createShape('ellipse', ellipse.center, radius.multiply(2),\n\t\t\t\t\tradius, arguments);\n\t\t},\n\n\t\t_readEllipse: function(args) {\n\t\t\tvar center,\n\t\t\t\tradius;\n\t\t\tif (Base.hasNamed(args, 'radius')) {\n\t\t\t\tcenter = Point.readNamed(args, 'center');\n\t\t\t\tradius = Size.readNamed(args, 'radius');\n\t\t\t} else {\n\t\t\t\tvar rect = Rectangle.readNamed(args, 'rectangle');\n\t\t\t\tcenter = rect.getCenter(true);\n\t\t\t\tradius = rect.getSize(true).divide(2);\n\t\t\t}\n\t\t\treturn { center: center, radius: radius };\n\t\t}\n\t};\n}});\n\nvar Raster = Item.extend({\n\t_class: 'Raster',\n\t_applyMatrix: false,\n\t_canApplyMatrix: false,\n\t_boundsOptions: { stroke: false, handle: false },\n\t_serializeFields: {\n\t\tcrossOrigin: null,\n\t\tsource: null\n\t},\n\t_prioritize: ['crossOrigin'],\n\n\tinitialize: function Raster(object, position) {\n\t\tif (!this._initialize(object,\n\t\t\t\tposition !== undefined && Point.read(arguments, 1))) {\n\t\t\tvar image = typeof object === 'string'\n\t\t\t\t\t? document.getElementById(object) : object;\n\t\t\tif (image) {\n\t\t\t\tthis.setImage(image);\n\t\t\t} else {\n\t\t\t\tthis.setSource(object);\n\t\t\t}\n\t\t}\n\t\tif (!this._size) {\n\t\t\tthis._size = new Size();\n\t\t\tthis._loaded = false;\n\t\t}\n\t},\n\n\t_equals: function(item) {\n\t\treturn this.getSource() === item.getSource();\n\t},\n\n\tcopyContent: function(source) {\n\t\tvar image = source._image,\n\t\t\tcanvas = source._canvas;\n\t\tif (image) {\n\t\t\tthis._setImage(image);\n\t\t} else if (canvas) {\n\t\t\tvar copyCanvas = CanvasProvider.getCanvas(source._size);\n\t\t\tcopyCanvas.getContext('2d').drawImage(canvas, 0, 0);\n\t\t\tthis._setImage(copyCanvas);\n\t\t}\n\t\tthis._crossOrigin = source._crossOrigin;\n\t},\n\n\tgetSize: function() {\n\t\tvar size = this._size;\n\t\treturn new LinkedSize(size ? size.width : 0, size ? size.height : 0,\n\t\t\t\tthis, 'setSize');\n\t},\n\n\tsetSize: function() {\n\t\tvar size = Size.read(arguments);\n\t\tif (!size.equals(this._size)) {\n\t\t\tif (size.width > 0 && size.height > 0) {\n\t\t\t\tvar element = this.getElement();\n\t\t\t\tthis._setImage(CanvasProvider.getCanvas(size));\n\t\t\t\tif (element)\n\t\t\t\t\tthis.getContext(true).drawImage(element, 0, 0,\n\t\t\t\t\t\t\tsize.width, size.height);\n\t\t\t} else {\n\t\t\t\tif (this._canvas)\n\t\t\t\t\tCanvasProvider.release(this._canvas);\n\t\t\t\tthis._size = size.clone();\n\t\t\t}\n\t\t}\n\t},\n\n\tgetWidth: function() {\n\t\treturn this._size ? this._size.width : 0;\n\t},\n\n\tsetWidth: function(width) {\n\t\tthis.setSize(width, this.getHeight());\n\t},\n\n\tgetHeight: function() {\n\t\treturn this._size ? this._size.height : 0;\n\t},\n\n\tsetHeight: function(height) {\n\t\tthis.setSize(this.getWidth(), height);\n\t},\n\n\tgetLoaded: function() {\n\t\treturn this._loaded;\n\t},\n\n\tisEmpty: function() {\n\t\tvar size = this._size;\n\t\treturn !size || size.width === 0 && size.height === 0;\n\t},\n\n\tgetResolution: function() {\n\t\tvar matrix = this._matrix,\n\t\t\torig = new Point(0, 0).transform(matrix),\n\t\t\tu = new Point(1, 0).transform(matrix).subtract(orig),\n\t\t\tv = new Point(0, 1).transform(matrix).subtract(orig);\n\t\treturn new Size(\n\t\t\t72 / u.getLength(),\n\t\t\t72 / v.getLength()\n\t\t);\n\t},\n\n\tgetPpi: '#getResolution',\n\n\tgetImage: function() {\n\t\treturn this._image;\n\t},\n\n\tsetImage: function(image) {\n\t\tvar that = this;\n\n\t\tfunction emit(event) {\n\t\t\tvar view = that.getView(),\n\t\t\t\ttype = event && event.type || 'load';\n\t\t\tif (view && that.responds(type)) {\n\t\t\t\tpaper = view._scope;\n\t\t\t\tthat.emit(type, new Event(event));\n\t\t\t}\n\t\t}\n\n\t\tthis._setImage(image);\n\t\tif (this._loaded) {\n\t\t\tsetTimeout(emit, 0);\n\t\t} else if (image) {\n\t\t\tDomEvent.add(image, {\n\t\t\t\tload: function(event) {\n\t\t\t\t\tthat._setImage(image);\n\t\t\t\t\temit(event);\n\t\t\t\t},\n\t\t\t\terror: emit\n\t\t\t});\n\t\t}\n\t},\n\n\t_setImage: function(image) {\n\t\tif (this._canvas)\n\t\t\tCanvasProvider.release(this._canvas);\n\t\tif (image && image.getContext) {\n\t\t\tthis._image = null;\n\t\t\tthis._canvas = image;\n\t\t\tthis._loaded = true;\n\t\t} else {\n\t\t\tthis._image = image;\n\t\t\tthis._canvas = null;\n\t\t\tthis._loaded = !!(image && image.src && image.complete);\n\t\t}\n\t\tthis._size = new Size(\n\t\t\t\timage ? image.naturalWidth || image.width : 0,\n\t\t\t\timage ? image.naturalHeight || image.height : 0);\n\t\tthis._context = null;\n\t\tthis._changed(521);\n\t},\n\n\tgetCanvas: function() {\n\t\tif (!this._canvas) {\n\t\t\tvar ctx = CanvasProvider.getContext(this._size);\n\t\t\ttry {\n\t\t\t\tif (this._image)\n\t\t\t\t\tctx.drawImage(this._image, 0, 0);\n\t\t\t\tthis._canvas = ctx.canvas;\n\t\t\t} catch (e) {\n\t\t\t\tCanvasProvider.release(ctx);\n\t\t\t}\n\t\t}\n\t\treturn this._canvas;\n\t},\n\n\tsetCanvas: '#setImage',\n\n\tgetContext: function(modify) {\n\t\tif (!this._context)\n\t\t\tthis._context = this.getCanvas().getContext('2d');\n\t\tif (modify) {\n\t\t\tthis._image = null;\n\t\t\tthis._changed(513);\n\t\t}\n\t\treturn this._context;\n\t},\n\n\tsetContext: function(context) {\n\t\tthis._context = context;\n\t},\n\n\tgetSource: function() {\n\t\tvar image = this._image;\n\t\treturn image && image.src || this.toDataURL();\n\t},\n\n\tsetSource: function(src) {\n\t\tvar image = new self.Image(),\n\t\t\tcrossOrigin = this._crossOrigin;\n\t\tif (crossOrigin)\n\t\t\timage.crossOrigin = crossOrigin;\n\t\timage.src = src;\n\t\tthis.setImage(image);\n\t},\n\n\tgetCrossOrigin: function() {\n\t\tvar image = this._image;\n\t\treturn image && image.crossOrigin || this._crossOrigin || '';\n\t},\n\n\tsetCrossOrigin: function(crossOrigin) {\n\t\tthis._crossOrigin = crossOrigin;\n\t\tvar image = this._image;\n\t\tif (image)\n\t\t\timage.crossOrigin = crossOrigin;\n\t},\n\n\tgetElement: function() {\n\t\treturn this._canvas || this._loaded && this._image;\n\t}\n}, {\n\tbeans: false,\n\n\tgetSubCanvas: function() {\n\t\tvar rect = Rectangle.read(arguments),\n\t\t\tctx = CanvasProvider.getContext(rect.getSize());\n\t\tctx.drawImage(this.getCanvas(), rect.x, rect.y,\n\t\t\t\trect.width, rect.height, 0, 0, rect.width, rect.height);\n\t\treturn ctx.canvas;\n\t},\n\n\tgetSubRaster: function() {\n\t\tvar rect = Rectangle.read(arguments),\n\t\t\traster = new Raster(Item.NO_INSERT);\n\t\traster._setImage(this.getSubCanvas(rect));\n\t\traster.translate(rect.getCenter().subtract(this.getSize().divide(2)));\n\t\traster._matrix.prepend(this._matrix);\n\t\traster.insertAbove(this);\n\t\treturn raster;\n\t},\n\n\ttoDataURL: function() {\n\t\tvar image = this._image,\n\t\t\tsrc = image && image.src;\n\t\tif (/^data:/.test(src))\n\t\t\treturn src;\n\t\tvar canvas = this.getCanvas();\n\t\treturn canvas ? canvas.toDataURL.apply(canvas, arguments) : null;\n\t},\n\n\tdrawImage: function(image ) {\n\t\tvar point = Point.read(arguments, 1);\n\t\tthis.getContext(true).drawImage(image, point.x, point.y);\n\t},\n\n\tgetAverageColor: function(object) {\n\t\tvar bounds, path;\n\t\tif (!object) {\n\t\t\tbounds = this.getBounds();\n\t\t} else if (object instanceof PathItem) {\n\t\t\tpath = object;\n\t\t\tbounds = object.getBounds();\n\t\t} else if (typeof object === 'object') {\n\t\t\tif ('width' in object) {\n\t\t\t\tbounds = new Rectangle(object);\n\t\t\t} else if ('x' in object) {\n\t\t\t\tbounds = new Rectangle(object.x - 0.5, object.y - 0.5, 1, 1);\n\t\t\t}\n\t\t}\n\t\tif (!bounds)\n\t\t\treturn null;\n\t\tvar sampleSize = 32,\n\t\t\twidth = Math.min(bounds.width, sampleSize),\n\t\t\theight = Math.min(bounds.height, sampleSize);\n\t\tvar ctx = Raster._sampleContext;\n\t\tif (!ctx) {\n\t\t\tctx = Raster._sampleContext = CanvasProvider.getContext(\n\t\t\t\t\tnew Size(sampleSize));\n\t\t} else {\n\t\t\tctx.clearRect(0, 0, sampleSize + 1, sampleSize + 1);\n\t\t}\n\t\tctx.save();\n\t\tvar matrix = new Matrix()\n\t\t\t\t.scale(width / bounds.width, height / bounds.height)\n\t\t\t\t.translate(-bounds.x, -bounds.y);\n\t\tmatrix.applyToContext(ctx);\n\t\tif (path)\n\t\t\tpath.draw(ctx, new Base({ clip: true, matrices: [matrix] }));\n\t\tthis._matrix.applyToContext(ctx);\n\t\tvar element = this.getElement(),\n\t\t\tsize = this._size;\n\t\tif (element)\n\t\t\tctx.drawImage(element, -size.width / 2, -size.height / 2);\n\t\tctx.restore();\n\t\tvar pixels = ctx.getImageData(0.5, 0.5, Math.ceil(width),\n\t\t\t\tMath.ceil(height)).data,\n\t\t\tchannels = [0, 0, 0],\n\t\t\ttotal = 0;\n\t\tfor (var i = 0, l = pixels.length; i < l; i += 4) {\n\t\t\tvar alpha = pixels[i + 3];\n\t\t\ttotal += alpha;\n\t\t\talpha /= 255;\n\t\t\tchannels[0] += pixels[i] * alpha;\n\t\t\tchannels[1] += pixels[i + 1] * alpha;\n\t\t\tchannels[2] += pixels[i + 2] * alpha;\n\t\t}\n\t\tfor (var i = 0; i < 3; i++)\n\t\t\tchannels[i] /= total;\n\t\treturn total ? Color.read(channels) : null;\n\t},\n\n\tgetPixel: function() {\n\t\tvar point = Point.read(arguments);\n\t\tvar data = this.getContext().getImageData(point.x, point.y, 1, 1).data;\n\t\treturn new Color('rgb', [data[0] / 255, data[1] / 255, data[2] / 255],\n\t\t\t\tdata[3] / 255);\n\t},\n\n\tsetPixel: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\tcolor = Color.read(arguments),\n\t\t\tcomponents = color._convert('rgb'),\n\t\t\talpha = color._alpha,\n\t\t\tctx = this.getContext(true),\n\t\t\timageData = ctx.createImageData(1, 1),\n\t\t\tdata = imageData.data;\n\t\tdata[0] = components[0] * 255;\n\t\tdata[1] = components[1] * 255;\n\t\tdata[2] = components[2] * 255;\n\t\tdata[3] = alpha != null ? alpha * 255 : 255;\n\t\tctx.putImageData(imageData, point.x, point.y);\n\t},\n\n\tcreateImageData: function() {\n\t\tvar size = Size.read(arguments);\n\t\treturn this.getContext().createImageData(size.width, size.height);\n\t},\n\n\tgetImageData: function() {\n\t\tvar rect = Rectangle.read(arguments);\n\t\tif (rect.isEmpty())\n\t\t\trect = new Rectangle(this._size);\n\t\treturn this.getContext().getImageData(rect.x, rect.y,\n\t\t\t\trect.width, rect.height);\n\t},\n\n\tsetImageData: function(data ) {\n\t\tvar point = Point.read(arguments, 1);\n\t\tthis.getContext(true).putImageData(data, point.x, point.y);\n\t},\n\n\t_getBounds: function(matrix, options) {\n\t\tvar rect = new Rectangle(this._size).setCenter(0, 0);\n\t\treturn matrix ? matrix._transformBounds(rect) : rect;\n\t},\n\n\t_hitTestSelf: function(point) {\n\t\tif (this._contains(point)) {\n\t\t\tvar that = this;\n\t\t\treturn new HitResult('pixel', that, {\n\t\t\t\toffset: point.add(that._size.divide(2)).round(),\n\t\t\t\tcolor: {\n\t\t\t\t\tget: function() {\n\t\t\t\t\t\treturn that.getPixel(this.offset);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t},\n\n\t_draw: function(ctx) {\n\t\tvar element = this.getElement();\n\t\tif (element) {\n\t\t\tctx.globalAlpha = this._opacity;\n\t\t\tctx.drawImage(element,\n\t\t\t\t\t-this._size.width / 2, -this._size.height / 2);\n\t\t}\n\t},\n\n\t_canComposite: function() {\n\t\treturn true;\n\t}\n});\n\nvar SymbolItem = Item.extend({\n\t_class: 'SymbolItem',\n\t_applyMatrix: false,\n\t_canApplyMatrix: false,\n\t_boundsOptions: { stroke: true },\n\t_serializeFields: {\n\t\tsymbol: null\n\t},\n\n\tinitialize: function SymbolItem(arg0, arg1) {\n\t\tif (!this._initialize(arg0,\n\t\t\t\targ1 !== undefined && Point.read(arguments, 1)))\n\t\t\tthis.setDefinition(arg0 instanceof SymbolDefinition ?\n\t\t\t\t\targ0 : new SymbolDefinition(arg0));\n\t},\n\n\t_equals: function(item) {\n\t\treturn this._definition === item._definition;\n\t},\n\n\tcopyContent: function(source) {\n\t\tthis.setDefinition(source._definition);\n\t},\n\n\tgetDefinition: function() {\n\t\treturn this._definition;\n\t},\n\n\tsetDefinition: function(definition) {\n\t\tthis._definition = definition;\n\t\tthis._changed(9);\n\t},\n\n\tgetSymbol: '#getDefinition',\n\tsetSymbol: '#setDefinition',\n\n\tisEmpty: function() {\n\t\treturn this._definition._item.isEmpty();\n\t},\n\n\t_getBounds: function(matrix, options) {\n\t\tvar item = this._definition._item;\n\t\treturn item._getCachedBounds(item._matrix.prepended(matrix), options);\n\t},\n\n\t_hitTestSelf: function(point, options, viewMatrix) {\n\t\tvar res = this._definition._item._hitTest(point, options, viewMatrix);\n\t\tif (res)\n\t\t\tres.item = this;\n\t\treturn res;\n\t},\n\n\t_draw: function(ctx, param) {\n\t\tthis._definition._item.draw(ctx, param);\n\t}\n\n});\n\nvar SymbolDefinition = Base.extend({\n\t_class: 'SymbolDefinition',\n\n\tinitialize: function SymbolDefinition(item, dontCenter) {\n\t\tthis._id = UID.get();\n\t\tthis.project = paper.project;\n\t\tif (item)\n\t\t\tthis.setItem(item, dontCenter);\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\treturn dictionary.add(this, function() {\n\t\t\treturn Base.serialize([this._class, this._item],\n\t\t\t\t\toptions, false, dictionary);\n\t\t});\n\t},\n\n\t_changed: function(flags) {\n\t\tif (flags & 8)\n\t\t\tItem._clearBoundsCache(this);\n\t\tif (flags & 1)\n\t\t\tthis.project._changed(flags);\n\t},\n\n\tgetItem: function() {\n\t\treturn this._item;\n\t},\n\n\tsetItem: function(item, _dontCenter) {\n\t\tif (item._symbol)\n\t\t\titem = item.clone();\n\t\tif (this._item)\n\t\t\tthis._item._symbol = null;\n\t\tthis._item = item;\n\t\titem.remove();\n\t\titem.setSelected(false);\n\t\tif (!_dontCenter)\n\t\t\titem.setPosition(new Point());\n\t\titem._symbol = this;\n\t\tthis._changed(9);\n\t},\n\n\tgetDefinition: '#getItem',\n\tsetDefinition: '#setItem',\n\n\tplace: function(position) {\n\t\treturn new SymbolItem(this, position);\n\t},\n\n\tclone: function() {\n\t\treturn new SymbolDefinition(this._item.clone(false));\n\t},\n\n\tequals: function(symbol) {\n\t\treturn symbol === this\n\t\t\t\t|| symbol && this._item.equals(symbol._item)\n\t\t\t\t|| false;\n\t}\n});\n\nvar HitResult = Base.extend({\n\t_class: 'HitResult',\n\n\tinitialize: function HitResult(type, item, values) {\n\t\tthis.type = type;\n\t\tthis.item = item;\n\t\tif (values)\n\t\t\tthis.inject(values);\n\t},\n\n\tstatics: {\n\t\tgetOptions: function(args) {\n\t\t\tvar options = args && Base.read(args);\n\t\t\treturn Base.set({\n\t\t\t\ttype: null,\n\t\t\t\ttolerance: paper.settings.hitTolerance,\n\t\t\t\tfill: !options,\n\t\t\t\tstroke: !options,\n\t\t\t\tsegments: !options,\n\t\t\t\thandles: false,\n\t\t\t\tends: false,\n\t\t\t\tposition: false,\n\t\t\t\tcenter: false,\n\t\t\t\tbounds: false,\n\t\t\t\tguides: false,\n\t\t\t\tselected: false\n\t\t\t}, options);\n\t\t}\n\t}\n});\n\nvar Segment = Base.extend({\n\t_class: 'Segment',\n\tbeans: true,\n\t_selection: 0,\n\n\tinitialize: function Segment(arg0, arg1, arg2, arg3, arg4, arg5) {\n\t\tvar count = arguments.length,\n\t\t\tpoint, handleIn, handleOut, selection;\n\t\tif (count > 0) {\n\t\t\tif (arg0 == null || typeof arg0 === 'object') {\n\t\t\t\tif (count === 1 && arg0 && 'point' in arg0) {\n\t\t\t\t\tpoint = arg0.point;\n\t\t\t\t\thandleIn = arg0.handleIn;\n\t\t\t\t\thandleOut = arg0.handleOut;\n\t\t\t\t\tselection = arg0.selection;\n\t\t\t\t} else {\n\t\t\t\t\tpoint = arg0;\n\t\t\t\t\thandleIn = arg1;\n\t\t\t\t\thandleOut = arg2;\n\t\t\t\t\tselection = arg3;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tpoint = [ arg0, arg1 ];\n\t\t\t\thandleIn = arg2 !== undefined ? [ arg2, arg3 ] : null;\n\t\t\t\thandleOut = arg4 !== undefined ? [ arg4, arg5 ] : null;\n\t\t\t}\n\t\t}\n\t\tnew SegmentPoint(point, this, '_point');\n\t\tnew SegmentPoint(handleIn, this, '_handleIn');\n\t\tnew SegmentPoint(handleOut, this, '_handleOut');\n\t\tif (selection)\n\t\t\tthis.setSelection(selection);\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\tvar point = this._point,\n\t\t\tselection = this._selection,\n\t\t\tobj = selection || this.hasHandles()\n\t\t\t\t\t? [point, this._handleIn, this._handleOut]\n\t\t\t\t\t: point;\n\t\tif (selection)\n\t\t\tobj.push(selection);\n\t\treturn Base.serialize(obj, options, true, dictionary);\n\t},\n\n\t_changed: function(point) {\n\t\tvar path = this._path;\n\t\tif (!path)\n\t\t\treturn;\n\t\tvar curves = path._curves,\n\t\t\tindex = this._index,\n\t\t\tcurve;\n\t\tif (curves) {\n\t\t\tif ((!point || point === this._point || point === this._handleIn)\n\t\t\t\t\t&& (curve = index > 0 ? curves[index - 1] : path._closed\n\t\t\t\t\t\t? curves[curves.length - 1] : null))\n\t\t\t\tcurve._changed();\n\t\t\tif ((!point || point === this._point || point === this._handleOut)\n\t\t\t\t\t&& (curve = curves[index]))\n\t\t\t\tcurve._changed();\n\t\t}\n\t\tpath._changed(25);\n\t},\n\n\tgetPoint: function() {\n\t\treturn this._point;\n\t},\n\n\tsetPoint: function() {\n\t\tthis._point.set(Point.read(arguments));\n\t},\n\n\tgetHandleIn: function() {\n\t\treturn this._handleIn;\n\t},\n\n\tsetHandleIn: function() {\n\t\tthis._handleIn.set(Point.read(arguments));\n\t},\n\n\tgetHandleOut: function() {\n\t\treturn this._handleOut;\n\t},\n\n\tsetHandleOut: function() {\n\t\tthis._handleOut.set(Point.read(arguments));\n\t},\n\n\thasHandles: function() {\n\t\treturn !this._handleIn.isZero() || !this._handleOut.isZero();\n\t},\n\n\tisSmooth: function() {\n\t\tvar handleIn = this._handleIn,\n\t\t\thandleOut = this._handleOut;\n\t\treturn !handleIn.isZero() && !handleOut.isZero()\n\t\t\t\t&& handleIn.isCollinear(handleOut);\n\t},\n\n\tclearHandles: function() {\n\t\tthis._handleIn._set(0, 0);\n\t\tthis._handleOut._set(0, 0);\n\t},\n\n\tgetSelection: function() {\n\t\treturn this._selection;\n\t},\n\n\tsetSelection: function(selection) {\n\t\tvar oldSelection = this._selection,\n\t\t\tpath = this._path;\n\t\tthis._selection = selection = selection || 0;\n\t\tif (path && selection !== oldSelection) {\n\t\t\tpath._updateSelection(this, oldSelection, selection);\n\t\t\tpath._changed(129);\n\t\t}\n\t},\n\n\tchangeSelection: function(flag, selected) {\n\t\tvar selection = this._selection;\n\t\tthis.setSelection(selected ? selection | flag : selection & ~flag);\n\t},\n\n\tisSelected: function() {\n\t\treturn !!(this._selection & 7);\n\t},\n\n\tsetSelected: function(selected) {\n\t\tthis.changeSelection(7, selected);\n\t},\n\n\tgetIndex: function() {\n\t\treturn this._index !== undefined ? this._index : null;\n\t},\n\n\tgetPath: function() {\n\t\treturn this._path || null;\n\t},\n\n\tgetCurve: function() {\n\t\tvar path = this._path,\n\t\t\tindex = this._index;\n\t\tif (path) {\n\t\t\tif (index > 0 && !path._closed\n\t\t\t\t\t&& index === path._segments.length - 1)\n\t\t\t\tindex--;\n\t\t\treturn path.getCurves()[index] || null;\n\t\t}\n\t\treturn null;\n\t},\n\n\tgetLocation: function() {\n\t\tvar curve = this.getCurve();\n\t\treturn curve\n\t\t\t\t? new CurveLocation(curve, this === curve._segment1 ? 0 : 1)\n\t\t\t\t: null;\n\t},\n\n\tgetNext: function() {\n\t\tvar segments = this._path && this._path._segments;\n\t\treturn segments && (segments[this._index + 1]\n\t\t\t\t|| this._path._closed && segments[0]) || null;\n\t},\n\n\tsmooth: function(options, _first, _last) {\n\t\tvar opts = options || {},\n\t\t\ttype = opts.type,\n\t\t\tfactor = opts.factor,\n\t\t\tprev = this.getPrevious(),\n\t\t\tnext = this.getNext(),\n\t\t\tp0 = (prev || this)._point,\n\t\t\tp1 = this._point,\n\t\t\tp2 = (next || this)._point,\n\t\t\td1 = p0.getDistance(p1),\n\t\t\td2 = p1.getDistance(p2);\n\t\tif (!type || type === 'catmull-rom') {\n\t\t\tvar a = factor === undefined ? 0.5 : factor,\n\t\t\t\td1_a = Math.pow(d1, a),\n\t\t\t\td1_2a = d1_a * d1_a,\n\t\t\t\td2_a = Math.pow(d2, a),\n\t\t\t\td2_2a = d2_a * d2_a;\n\t\t\tif (!_first && prev) {\n\t\t\t\tvar A = 2 * d2_2a + 3 * d2_a * d1_a + d1_2a,\n\t\t\t\t\tN = 3 * d2_a * (d2_a + d1_a);\n\t\t\t\tthis.setHandleIn(N !== 0\n\t\t\t\t\t? new Point(\n\t\t\t\t\t\t(d2_2a * p0._x + A * p1._x - d1_2a * p2._x) / N - p1._x,\n\t\t\t\t\t\t(d2_2a * p0._y + A * p1._y - d1_2a * p2._y) / N - p1._y)\n\t\t\t\t\t: new Point());\n\t\t\t}\n\t\t\tif (!_last && next) {\n\t\t\t\tvar A = 2 * d1_2a + 3 * d1_a * d2_a + d2_2a,\n\t\t\t\t\tN = 3 * d1_a * (d1_a + d2_a);\n\t\t\t\tthis.setHandleOut(N !== 0\n\t\t\t\t\t? new Point(\n\t\t\t\t\t\t(d1_2a * p2._x + A * p1._x - d2_2a * p0._x) / N - p1._x,\n\t\t\t\t\t\t(d1_2a * p2._y + A * p1._y - d2_2a * p0._y) / N - p1._y)\n\t\t\t\t\t: new Point());\n\t\t\t}\n\t\t} else if (type === 'geometric') {\n\t\t\tif (prev && next) {\n\t\t\t\tvar vector = p0.subtract(p2),\n\t\t\t\t\tt = factor === undefined ? 0.4 : factor,\n\t\t\t\t\tk = t * d1 / (d1 + d2);\n\t\t\t\tif (!_first)\n\t\t\t\t\tthis.setHandleIn(vector.multiply(k));\n\t\t\t\tif (!_last)\n\t\t\t\t\tthis.setHandleOut(vector.multiply(k - t));\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new Error('Smoothing method \\'' + type + '\\' not supported.');\n\t\t}\n\t},\n\n\tgetPrevious: function() {\n\t\tvar segments = this._path && this._path._segments;\n\t\treturn segments && (segments[this._index - 1]\n\t\t\t\t|| this._path._closed && segments[segments.length - 1]) || null;\n\t},\n\n\tisFirst: function() {\n\t\treturn !this._index;\n\t},\n\n\tisLast: function() {\n\t\tvar path = this._path;\n\t\treturn path && this._index === path._segments.length - 1 || false;\n\t},\n\n\treverse: function() {\n\t\tvar handleIn = this._handleIn,\n\t\t\thandleOut = this._handleOut,\n\t\t\ttmp = handleIn.clone();\n\t\thandleIn.set(handleOut);\n\t\thandleOut.set(tmp);\n\t},\n\n\treversed: function() {\n\t\treturn new Segment(this._point, this._handleOut, this._handleIn);\n\t},\n\n\tremove: function() {\n\t\treturn this._path ? !!this._path.removeSegment(this._index) : false;\n\t},\n\n\tclone: function() {\n\t\treturn new Segment(this._point, this._handleIn, this._handleOut);\n\t},\n\n\tequals: function(segment) {\n\t\treturn segment === this || segment && this._class === segment._class\n\t\t\t\t&& this._point.equals(segment._point)\n\t\t\t\t&& this._handleIn.equals(segment._handleIn)\n\t\t\t\t&& this._handleOut.equals(segment._handleOut)\n\t\t\t\t|| false;\n\t},\n\n\ttoString: function() {\n\t\tvar parts = [ 'point: ' + this._point ];\n\t\tif (!this._handleIn.isZero())\n\t\t\tparts.push('handleIn: ' + this._handleIn);\n\t\tif (!this._handleOut.isZero())\n\t\t\tparts.push('handleOut: ' + this._handleOut);\n\t\treturn '{ ' + parts.join(', ') + ' }';\n\t},\n\n\ttransform: function(matrix) {\n\t\tthis._transformCoordinates(matrix, new Array(6), true);\n\t\tthis._changed();\n\t},\n\n\tinterpolate: function(from, to, factor) {\n\t\tvar u = 1 - factor,\n\t\t\tv = factor,\n\t\t\tpoint1 = from._point,\n\t\t\tpoint2 = to._point,\n\t\t\thandleIn1 = from._handleIn,\n\t\t\thandleIn2 = to._handleIn,\n\t\t\thandleOut2 = to._handleOut,\n\t\t\thandleOut1 = from._handleOut;\n\t\tthis._point._set(\n\t\t\t\tu * point1._x + v * point2._x,\n\t\t\t\tu * point1._y + v * point2._y, true);\n\t\tthis._handleIn._set(\n\t\t\t\tu * handleIn1._x + v * handleIn2._x,\n\t\t\t\tu * handleIn1._y + v * handleIn2._y, true);\n\t\tthis._handleOut._set(\n\t\t\t\tu * handleOut1._x + v * handleOut2._x,\n\t\t\t\tu * handleOut1._y + v * handleOut2._y, true);\n\t\tthis._changed();\n\t},\n\n\t_transformCoordinates: function(matrix, coords, change) {\n\t\tvar point = this._point,\n\t\t\thandleIn = !change || !this._handleIn.isZero()\n\t\t\t\t\t? this._handleIn : null,\n\t\t\thandleOut = !change || !this._handleOut.isZero()\n\t\t\t\t\t? this._handleOut : null,\n\t\t\tx = point._x,\n\t\t\ty = point._y,\n\t\t\ti = 2;\n\t\tcoords[0] = x;\n\t\tcoords[1] = y;\n\t\tif (handleIn) {\n\t\t\tcoords[i++] = handleIn._x + x;\n\t\t\tcoords[i++] = handleIn._y + y;\n\t\t}\n\t\tif (handleOut) {\n\t\t\tcoords[i++] = handleOut._x + x;\n\t\t\tcoords[i++] = handleOut._y + y;\n\t\t}\n\t\tif (matrix) {\n\t\t\tmatrix._transformCoordinates(coords, coords, i / 2);\n\t\t\tx = coords[0];\n\t\t\ty = coords[1];\n\t\t\tif (change) {\n\t\t\t\tpoint._x = x;\n\t\t\t\tpoint._y = y;\n\t\t\t\ti = 2;\n\t\t\t\tif (handleIn) {\n\t\t\t\t\thandleIn._x = coords[i++] - x;\n\t\t\t\t\thandleIn._y = coords[i++] - y;\n\t\t\t\t}\n\t\t\t\tif (handleOut) {\n\t\t\t\t\thandleOut._x = coords[i++] - x;\n\t\t\t\t\thandleOut._y = coords[i++] - y;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!handleIn) {\n\t\t\t\t\tcoords[i++] = x;\n\t\t\t\t\tcoords[i++] = y;\n\t\t\t\t}\n\t\t\t\tif (!handleOut) {\n\t\t\t\t\tcoords[i++] = x;\n\t\t\t\t\tcoords[i++] = y;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn coords;\n\t}\n});\n\nvar SegmentPoint = Point.extend({\n\tinitialize: function SegmentPoint(point, owner, key) {\n\t\tvar x, y,\n\t\t\tselected;\n\t\tif (!point) {\n\t\t\tx = y = 0;\n\t\t} else if ((x = point[0]) !== undefined) {\n\t\t\ty = point[1];\n\t\t} else {\n\t\t\tvar pt = point;\n\t\t\tif ((x = pt.x) === undefined) {\n\t\t\t\tpt = Point.read(arguments);\n\t\t\t\tx = pt.x;\n\t\t\t}\n\t\t\ty = pt.y;\n\t\t\tselected = pt.selected;\n\t\t}\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t\tthis._owner = owner;\n\t\towner[key] = this;\n\t\tif (selected)\n\t\t\tthis.setSelected(true);\n\t},\n\n\t_set: function(x, y) {\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t\tthis._owner._changed(this);\n\t\treturn this;\n\t},\n\n\tgetX: function() {\n\t\treturn this._x;\n\t},\n\n\tsetX: function(x) {\n\t\tthis._x = x;\n\t\tthis._owner._changed(this);\n\t},\n\n\tgetY: function() {\n\t\treturn this._y;\n\t},\n\n\tsetY: function(y) {\n\t\tthis._y = y;\n\t\tthis._owner._changed(this);\n\t},\n\n\tisZero: function() {\n\t\tvar isZero = Numerical.isZero;\n\t\treturn isZero(this._x) && isZero(this._y);\n\t},\n\n\tisSelected: function() {\n\t\treturn !!(this._owner._selection & this._getSelection());\n\t},\n\n\tsetSelected: function(selected) {\n\t\tthis._owner.changeSelection(this._getSelection(), selected);\n\t},\n\n\t_getSelection: function() {\n\t\tvar owner = this._owner;\n\t\treturn this === owner._point ? 1\n\t\t\t: this === owner._handleIn ? 2\n\t\t\t: this === owner._handleOut ? 4\n\t\t\t: 0;\n\t}\n});\n\nvar Curve = Base.extend({\n\t_class: 'Curve',\n\tbeans: true,\n\n\tinitialize: function Curve(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) {\n\t\tvar count = arguments.length,\n\t\t\tseg1, seg2,\n\t\t\tpoint1, point2,\n\t\t\thandle1, handle2;\n\t\tif (count === 3) {\n\t\t\tthis._path = arg0;\n\t\t\tseg1 = arg1;\n\t\t\tseg2 = arg2;\n\t\t} else if (!count) {\n\t\t\tseg1 = new Segment();\n\t\t\tseg2 = new Segment();\n\t\t} else if (count === 1) {\n\t\t\tif ('segment1' in arg0) {\n\t\t\t\tseg1 = new Segment(arg0.segment1);\n\t\t\t\tseg2 = new Segment(arg0.segment2);\n\t\t\t} else if ('point1' in arg0) {\n\t\t\t\tpoint1 = arg0.point1;\n\t\t\t\thandle1 = arg0.handle1;\n\t\t\t\thandle2 = arg0.handle2;\n\t\t\t\tpoint2 = arg0.point2;\n\t\t\t} else if (Array.isArray(arg0)) {\n\t\t\t\tpoint1 = [arg0[0], arg0[1]];\n\t\t\t\tpoint2 = [arg0[6], arg0[7]];\n\t\t\t\thandle1 = [arg0[2] - arg0[0], arg0[3] - arg0[1]];\n\t\t\t\thandle2 = [arg0[4] - arg0[6], arg0[5] - arg0[7]];\n\t\t\t}\n\t\t} else if (count === 2) {\n\t\t\tseg1 = new Segment(arg0);\n\t\t\tseg2 = new Segment(arg1);\n\t\t} else if (count === 4) {\n\t\t\tpoint1 = arg0;\n\t\t\thandle1 = arg1;\n\t\t\thandle2 = arg2;\n\t\t\tpoint2 = arg3;\n\t\t} else if (count === 8) {\n\t\t\tpoint1 = [arg0, arg1];\n\t\t\tpoint2 = [arg6, arg7];\n\t\t\thandle1 = [arg2 - arg0, arg3 - arg1];\n\t\t\thandle2 = [arg4 - arg6, arg5 - arg7];\n\t\t}\n\t\tthis._segment1 = seg1 || new Segment(point1, null, handle1);\n\t\tthis._segment2 = seg2 || new Segment(point2, handle2, null);\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\treturn Base.serialize(this.hasHandles()\n\t\t\t\t? [this.getPoint1(), this.getHandle1(), this.getHandle2(),\n\t\t\t\t\tthis.getPoint2()]\n\t\t\t\t: [this.getPoint1(), this.getPoint2()],\n\t\t\t\toptions, true, dictionary);\n\t},\n\n\t_changed: function() {\n\t\tthis._length = this._bounds = undefined;\n\t},\n\n\tclone: function() {\n\t\treturn new Curve(this._segment1, this._segment2);\n\t},\n\n\ttoString: function() {\n\t\tvar parts = [ 'point1: ' + this._segment1._point ];\n\t\tif (!this._segment1._handleOut.isZero())\n\t\t\tparts.push('handle1: ' + this._segment1._handleOut);\n\t\tif (!this._segment2._handleIn.isZero())\n\t\t\tparts.push('handle2: ' + this._segment2._handleIn);\n\t\tparts.push('point2: ' + this._segment2._point);\n\t\treturn '{ ' + parts.join(', ') + ' }';\n\t},\n\n\tclassify: function() {\n\t\treturn Curve.classify(this.getValues());\n\t},\n\n\tremove: function() {\n\t\tvar removed = false;\n\t\tif (this._path) {\n\t\t\tvar segment2 = this._segment2,\n\t\t\t\thandleOut = segment2._handleOut;\n\t\t\tremoved = segment2.remove();\n\t\t\tif (removed)\n\t\t\t\tthis._segment1._handleOut.set(handleOut);\n\t\t}\n\t\treturn removed;\n\t},\n\n\tgetPoint1: function() {\n\t\treturn this._segment1._point;\n\t},\n\n\tsetPoint1: function() {\n\t\tthis._segment1._point.set(Point.read(arguments));\n\t},\n\n\tgetPoint2: function() {\n\t\treturn this._segment2._point;\n\t},\n\n\tsetPoint2: function() {\n\t\tthis._segment2._point.set(Point.read(arguments));\n\t},\n\n\tgetHandle1: function() {\n\t\treturn this._segment1._handleOut;\n\t},\n\n\tsetHandle1: function() {\n\t\tthis._segment1._handleOut.set(Point.read(arguments));\n\t},\n\n\tgetHandle2: function() {\n\t\treturn this._segment2._handleIn;\n\t},\n\n\tsetHandle2: function() {\n\t\tthis._segment2._handleIn.set(Point.read(arguments));\n\t},\n\n\tgetSegment1: function() {\n\t\treturn this._segment1;\n\t},\n\n\tgetSegment2: function() {\n\t\treturn this._segment2;\n\t},\n\n\tgetPath: function() {\n\t\treturn this._path;\n\t},\n\n\tgetIndex: function() {\n\t\treturn this._segment1._index;\n\t},\n\n\tgetNext: function() {\n\t\tvar curves = this._path && this._path._curves;\n\t\treturn curves && (curves[this._segment1._index + 1]\n\t\t\t\t|| this._path._closed && curves[0]) || null;\n\t},\n\n\tgetPrevious: function() {\n\t\tvar curves = this._path && this._path._curves;\n\t\treturn curves && (curves[this._segment1._index - 1]\n\t\t\t\t|| this._path._closed && curves[curves.length - 1]) || null;\n\t},\n\n\tisFirst: function() {\n\t\treturn !this._segment1._index;\n\t},\n\n\tisLast: function() {\n\t\tvar path = this._path;\n\t\treturn path && this._segment1._index === path._curves.length - 1\n\t\t\t\t|| false;\n\t},\n\n\tisSelected: function() {\n\t\treturn this.getPoint1().isSelected()\n\t\t\t\t&& this.getHandle2().isSelected()\n\t\t\t\t&& this.getHandle2().isSelected()\n\t\t\t\t&& this.getPoint2().isSelected();\n\t},\n\n\tsetSelected: function(selected) {\n\t\tthis.getPoint1().setSelected(selected);\n\t\tthis.getHandle1().setSelected(selected);\n\t\tthis.getHandle2().setSelected(selected);\n\t\tthis.getPoint2().setSelected(selected);\n\t},\n\n\tgetValues: function(matrix) {\n\t\treturn Curve.getValues(this._segment1, this._segment2, matrix);\n\t},\n\n\tgetPoints: function() {\n\t\tvar coords = this.getValues(),\n\t\t\tpoints = [];\n\t\tfor (var i = 0; i < 8; i += 2)\n\t\t\tpoints.push(new Point(coords[i], coords[i + 1]));\n\t\treturn points;\n\t}\n}, {\n\tgetLength: function() {\n\t\tif (this._length == null)\n\t\t\tthis._length = Curve.getLength(this.getValues(), 0, 1);\n\t\treturn this._length;\n\t},\n\n\tgetArea: function() {\n\t\treturn Curve.getArea(this.getValues());\n\t},\n\n\tgetLine: function() {\n\t\treturn new Line(this._segment1._point, this._segment2._point);\n\t},\n\n\tgetPart: function(from, to) {\n\t\treturn new Curve(Curve.getPart(this.getValues(), from, to));\n\t},\n\n\tgetPartLength: function(from, to) {\n\t\treturn Curve.getLength(this.getValues(), from, to);\n\t},\n\n\tdivideAt: function(location) {\n\t\treturn this.divideAtTime(location && location.curve === this\n\t\t\t\t? location.time : this.getTimeAt(location));\n\t},\n\n\tdivideAtTime: function(time, _setHandles) {\n\t\tvar tMin = 1e-8,\n\t\t\ttMax = 1 - tMin,\n\t\t\tres = null;\n\t\tif (time >= tMin && time <= tMax) {\n\t\t\tvar parts = Curve.subdivide(this.getValues(), time),\n\t\t\t\tleft = parts[0],\n\t\t\t\tright = parts[1],\n\t\t\t\tsetHandles = _setHandles || this.hasHandles(),\n\t\t\t\tseg1 = this._segment1,\n\t\t\t\tseg2 = this._segment2,\n\t\t\t\tpath = this._path;\n\t\t\tif (setHandles) {\n\t\t\t\tseg1._handleOut._set(left[2] - left[0], left[3] - left[1]);\n\t\t\t\tseg2._handleIn._set(right[4] - right[6],right[5] - right[7]);\n\t\t\t}\n\t\t\tvar x = left[6], y = left[7],\n\t\t\t\tsegment = new Segment(new Point(x, y),\n\t\t\t\t\t\tsetHandles && new Point(left[4] - x, left[5] - y),\n\t\t\t\t\t\tsetHandles && new Point(right[2] - x, right[3] - y));\n\t\t\tif (path) {\n\t\t\t\tpath.insert(seg1._index + 1, segment);\n\t\t\t\tres = this.getNext();\n\t\t\t} else {\n\t\t\t\tthis._segment2 = segment;\n\t\t\t\tthis._changed();\n\t\t\t\tres = new Curve(segment, seg2);\n\t\t\t}\n\t\t}\n\t\treturn res;\n\t},\n\n\tsplitAt: function(location) {\n\t\tvar path = this._path;\n\t\treturn path ? path.splitAt(location) : null;\n\t},\n\n\tsplitAtTime: function(time) {\n\t\treturn this.splitAt(this.getLocationAtTime(time));\n\t},\n\n\tdivide: function(offset, isTime) {\n\t\treturn this.divideAtTime(offset === undefined ? 0.5 : isTime ? offset\n\t\t\t\t: this.getTimeAt(offset));\n\t},\n\n\tsplit: function(offset, isTime) {\n\t\treturn this.splitAtTime(offset === undefined ? 0.5 : isTime ? offset\n\t\t\t\t: this.getTimeAt(offset));\n\t},\n\n\treversed: function() {\n\t\treturn new Curve(this._segment2.reversed(), this._segment1.reversed());\n\t},\n\n\tclearHandles: function() {\n\t\tthis._segment1._handleOut._set(0, 0);\n\t\tthis._segment2._handleIn._set(0, 0);\n\t},\n\nstatics: {\n\tgetValues: function(segment1, segment2, matrix, straight) {\n\t\tvar p1 = segment1._point,\n\t\t\th1 = segment1._handleOut,\n\t\t\th2 = segment2._handleIn,\n\t\t\tp2 = segment2._point,\n\t\t\tx1 = p1.x, y1 = p1.y,\n\t\t\tx2 = p2.x, y2 = p2.y,\n\t\t\tvalues = straight\n\t\t\t\t? [ x1, y1, x1, y1, x2, y2, x2, y2 ]\n\t\t\t\t: [\n\t\t\t\t\tx1, y1,\n\t\t\t\t\tx1 + h1._x, y1 + h1._y,\n\t\t\t\t\tx2 + h2._x, y2 + h2._y,\n\t\t\t\t\tx2, y2\n\t\t\t\t];\n\t\tif (matrix)\n\t\t\tmatrix._transformCoordinates(values, values, 4);\n\t\treturn values;\n\t},\n\n\tsubdivide: function(v, t) {\n\t\tvar x0 = v[0], y0 = v[1],\n\t\t\tx1 = v[2], y1 = v[3],\n\t\t\tx2 = v[4], y2 = v[5],\n\t\t\tx3 = v[6], y3 = v[7];\n\t\tif (t === undefined)\n\t\t\tt = 0.5;\n\t\tvar u = 1 - t,\n\t\t\tx4 = u * x0 + t * x1, y4 = u * y0 + t * y1,\n\t\t\tx5 = u * x1 + t * x2, y5 = u * y1 + t * y2,\n\t\t\tx6 = u * x2 + t * x3, y6 = u * y2 + t * y3,\n\t\t\tx7 = u * x4 + t * x5, y7 = u * y4 + t * y5,\n\t\t\tx8 = u * x5 + t * x6, y8 = u * y5 + t * y6,\n\t\t\tx9 = u * x7 + t * x8, y9 = u * y7 + t * y8;\n\t\treturn [\n\t\t\t[x0, y0, x4, y4, x7, y7, x9, y9],\n\t\t\t[x9, y9, x8, y8, x6, y6, x3, y3]\n\t\t];\n\t},\n\n\tgetMonoCurves: function(v, dir) {\n\t\tvar curves = [],\n\t\t\tio = dir ? 0 : 1,\n\t\t\to0 = v[io + 0],\n\t\t\to1 = v[io + 2],\n\t\t\to2 = v[io + 4],\n\t\t\to3 = v[io + 6];\n\t\tif ((o0 >= o1) === (o1 >= o2) && (o1 >= o2) === (o2 >= o3)\n\t\t\t\t|| Curve.isStraight(v)) {\n\t\t\tcurves.push(v);\n\t\t} else {\n\t\t\tvar a = 3 * (o1 - o2) - o0 + o3,\n\t\t\t\tb = 2 * (o0 + o2) - 4 * o1,\n\t\t\t\tc = o1 - o0,\n\t\t\t\ttMin = 1e-8,\n\t\t\t\ttMax = 1 - tMin,\n\t\t\t\troots = [],\n\t\t\t\tn = Numerical.solveQuadratic(a, b, c, roots, tMin, tMax);\n\t\t\tif (!n) {\n\t\t\t\tcurves.push(v);\n\t\t\t} else {\n\t\t\t\troots.sort();\n\t\t\t\tvar t = roots[0],\n\t\t\t\t\tparts = Curve.subdivide(v, t);\n\t\t\t\tcurves.push(parts[0]);\n\t\t\t\tif (n > 1) {\n\t\t\t\t\tt = (roots[1] - t) / (1 - t);\n\t\t\t\t\tparts = Curve.subdivide(parts[1], t);\n\t\t\t\t\tcurves.push(parts[0]);\n\t\t\t\t}\n\t\t\t\tcurves.push(parts[1]);\n\t\t\t}\n\t\t}\n\t\treturn curves;\n\t},\n\n\tsolveCubic: function (v, coord, val, roots, min, max) {\n\t\tvar v0 = v[coord],\n\t\t\tv1 = v[coord + 2],\n\t\t\tv2 = v[coord + 4],\n\t\t\tv3 = v[coord + 6],\n\t\t\tres = 0;\n\t\tif (  !(v0 < val && v3 < val && v1 < val && v2 < val ||\n\t\t\t\tv0 > val && v3 > val && v1 > val && v2 > val)) {\n\t\t\tvar c = 3 * (v1 - v0),\n\t\t\t\tb = 3 * (v2 - v1) - c,\n\t\t\t\ta = v3 - v0 - c - b;\n\t\t\tres = Numerical.solveCubic(a, b, c, v0 - val, roots, min, max);\n\t\t}\n\t\treturn res;\n\t},\n\n\tgetTimeOf: function(v, point) {\n\t\tvar p0 = new Point(v[0], v[1]),\n\t\t\tp3 = new Point(v[6], v[7]),\n\t\t\tepsilon = 1e-12,\n\t\t\tgeomEpsilon = 1e-7,\n\t\t\tt = point.isClose(p0, epsilon) ? 0\n\t\t\t  : point.isClose(p3, epsilon) ? 1\n\t\t\t  : null;\n\t\tif (t === null) {\n\t\t\tvar coords = [point.x, point.y],\n\t\t\t\troots = [];\n\t\t\tfor (var c = 0; c < 2; c++) {\n\t\t\t\tvar count = Curve.solveCubic(v, c, coords[c], roots, 0, 1);\n\t\t\t\tfor (var i = 0; i < count; i++) {\n\t\t\t\t\tvar u = roots[i];\n\t\t\t\t\tif (point.isClose(Curve.getPoint(v, u), geomEpsilon))\n\t\t\t\t\t\treturn u;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn point.isClose(p0, geomEpsilon) ? 0\n\t\t\t : point.isClose(p3, geomEpsilon) ? 1\n\t\t\t : null;\n\t},\n\n\tgetNearestTime: function(v, point) {\n\t\tif (Curve.isStraight(v)) {\n\t\t\tvar x0 = v[0], y0 = v[1],\n\t\t\t\tx3 = v[6], y3 = v[7],\n\t\t\t\tvx = x3 - x0, vy = y3 - y0,\n\t\t\t\tdet = vx * vx + vy * vy;\n\t\t\tif (det === 0)\n\t\t\t\treturn 0;\n\t\t\tvar u = ((point.x - x0) * vx + (point.y - y0) * vy) / det;\n\t\t\treturn u < 1e-12 ? 0\n\t\t\t\t : u > 0.999999999999 ? 1\n\t\t\t\t : Curve.getTimeOf(v,\n\t\t\t\t\tnew Point(x0 + u * vx, y0 + u * vy));\n\t\t}\n\n\t\tvar count = 100,\n\t\t\tminDist = Infinity,\n\t\t\tminT = 0;\n\n\t\tfunction refine(t) {\n\t\t\tif (t >= 0 && t <= 1) {\n\t\t\t\tvar dist = point.getDistance(Curve.getPoint(v, t), true);\n\t\t\t\tif (dist < minDist) {\n\t\t\t\t\tminDist = dist;\n\t\t\t\t\tminT = t;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (var i = 0; i <= count; i++)\n\t\t\trefine(i / count);\n\n\t\tvar step = 1 / (count * 2);\n\t\twhile (step > 1e-8) {\n\t\t\tif (!refine(minT - step) && !refine(minT + step))\n\t\t\t\tstep /= 2;\n\t\t}\n\t\treturn minT;\n\t},\n\n\tgetPart: function(v, from, to) {\n\t\tvar flip = from > to;\n\t\tif (flip) {\n\t\t\tvar tmp = from;\n\t\t\tfrom = to;\n\t\t\tto = tmp;\n\t\t}\n\t\tif (from > 0)\n\t\t\tv = Curve.subdivide(v, from)[1];\n\t\tif (to < 1)\n\t\t\tv = Curve.subdivide(v, (to - from) / (1 - from))[0];\n\t\treturn flip\n\t\t\t\t? [v[6], v[7], v[4], v[5], v[2], v[3], v[0], v[1]]\n\t\t\t\t: v;\n\t},\n\n\tisFlatEnough: function(v, flatness) {\n\t\tvar x0 = v[0], y0 = v[1],\n\t\t\tx1 = v[2], y1 = v[3],\n\t\t\tx2 = v[4], y2 = v[5],\n\t\t\tx3 = v[6], y3 = v[7],\n\t\t\tux = 3 * x1 - 2 * x0 - x3,\n\t\t\tuy = 3 * y1 - 2 * y0 - y3,\n\t\t\tvx = 3 * x2 - 2 * x3 - x0,\n\t\t\tvy = 3 * y2 - 2 * y3 - y0;\n\t\treturn Math.max(ux * ux, vx * vx) + Math.max(uy * uy, vy * vy)\n\t\t\t\t<= 16 * flatness * flatness;\n\t},\n\n\tgetArea: function(v) {\n\t\tvar x0 = v[0], y0 = v[1],\n\t\t\tx1 = v[2], y1 = v[3],\n\t\t\tx2 = v[4], y2 = v[5],\n\t\t\tx3 = v[6], y3 = v[7];\n\t\treturn 3 * ((y3 - y0) * (x1 + x2) - (x3 - x0) * (y1 + y2)\n\t\t\t\t+ y1 * (x0 - x2) - x1 * (y0 - y2)\n\t\t\t\t+ y3 * (x2 + x0 / 3) - x3 * (y2 + y0 / 3)) / 20;\n\t},\n\n\tgetBounds: function(v) {\n\t\tvar min = v.slice(0, 2),\n\t\t\tmax = min.slice(),\n\t\t\troots = [0, 0];\n\t\tfor (var i = 0; i < 2; i++)\n\t\t\tCurve._addBounds(v[i], v[i + 2], v[i + 4], v[i + 6],\n\t\t\t\t\ti, 0, min, max, roots);\n\t\treturn new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);\n\t},\n\n\t_addBounds: function(v0, v1, v2, v3, coord, padding, min, max, roots) {\n\t\tfunction add(value, padding) {\n\t\t\tvar left = value - padding,\n\t\t\t\tright = value + padding;\n\t\t\tif (left < min[coord])\n\t\t\t\tmin[coord] = left;\n\t\t\tif (right > max[coord])\n\t\t\t\tmax[coord] = right;\n\t\t}\n\n\t\tpadding /= 2;\n\t\tvar minPad = min[coord] - padding,\n\t\t\tmaxPad = max[coord] + padding;\n\t\tif (    v0 < minPad || v1 < minPad || v2 < minPad || v3 < minPad ||\n\t\t\t\tv0 > maxPad || v1 > maxPad || v2 > maxPad || v3 > maxPad) {\n\t\t\tif (v1 < v0 != v1 < v3 && v2 < v0 != v2 < v3) {\n\t\t\t\tadd(v0, padding);\n\t\t\t\tadd(v3, padding);\n\t\t\t} else {\n\t\t\t\tvar a = 3 * (v1 - v2) - v0 + v3,\n\t\t\t\t\tb = 2 * (v0 + v2) - 4 * v1,\n\t\t\t\t\tc = v1 - v0,\n\t\t\t\t\tcount = Numerical.solveQuadratic(a, b, c, roots),\n\t\t\t\t\ttMin = 1e-8,\n\t\t\t\t\ttMax = 1 - tMin;\n\t\t\t\tadd(v3, 0);\n\t\t\t\tfor (var i = 0; i < count; i++) {\n\t\t\t\t\tvar t = roots[i],\n\t\t\t\t\t\tu = 1 - t;\n\t\t\t\t\tif (tMin <= t && t <= tMax)\n\t\t\t\t\t\tadd(u * u * u * v0\n\t\t\t\t\t\t\t+ 3 * u * u * t * v1\n\t\t\t\t\t\t\t+ 3 * u * t * t * v2\n\t\t\t\t\t\t\t+ t * t * t * v3,\n\t\t\t\t\t\t\tpadding);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}}, Base.each(\n\t['getBounds', 'getStrokeBounds', 'getHandleBounds'],\n\tfunction(name) {\n\t\tthis[name] = function() {\n\t\t\tif (!this._bounds)\n\t\t\t\tthis._bounds = {};\n\t\t\tvar bounds = this._bounds[name];\n\t\t\tif (!bounds) {\n\t\t\t\tbounds = this._bounds[name] = Path[name](\n\t\t\t\t\t\t[this._segment1, this._segment2], false, this._path);\n\t\t\t}\n\t\t\treturn bounds.clone();\n\t\t};\n\t},\n{\n\n}), Base.each({\n\tisStraight: function(p1, h1, h2, p2) {\n\t\tif (h1.isZero() && h2.isZero()) {\n\t\t\treturn true;\n\t\t} else {\n\t\t\tvar v = p2.subtract(p1);\n\t\t\tif (v.isZero()) {\n\t\t\t\treturn false;\n\t\t\t} else if (v.isCollinear(h1) && v.isCollinear(h2)) {\n\t\t\t\tvar l = new Line(p1, p2),\n\t\t\t\t\tepsilon = 1e-7;\n\t\t\t\tif (l.getDistance(p1.add(h1)) < epsilon &&\n\t\t\t\t\tl.getDistance(p2.add(h2)) < epsilon) {\n\t\t\t\t\tvar div = v.dot(v),\n\t\t\t\t\t\ts1 = v.dot(h1) / div,\n\t\t\t\t\t\ts2 = v.dot(h2) / div;\n\t\t\t\t\treturn s1 >= 0 && s1 <= 1 && s2 <= 0 && s2 >= -1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t},\n\n\tisLinear: function(p1, h1, h2, p2) {\n\t\tvar third = p2.subtract(p1).divide(3);\n\t\treturn h1.equals(third) && h2.negate().equals(third);\n\t}\n}, function(test, name) {\n\tthis[name] = function(epsilon) {\n\t\tvar seg1 = this._segment1,\n\t\t\tseg2 = this._segment2;\n\t\treturn test(seg1._point, seg1._handleOut, seg2._handleIn, seg2._point,\n\t\t\t\tepsilon);\n\t};\n\n\tthis.statics[name] = function(v, epsilon) {\n\t\tvar x0 = v[0], y0 = v[1],\n\t\t\tx3 = v[6], y3 = v[7];\n\t\treturn test(\n\t\t\t\tnew Point(x0, y0),\n\t\t\t\tnew Point(v[2] - x0, v[3] - y0),\n\t\t\t\tnew Point(v[4] - x3, v[5] - y3),\n\t\t\t\tnew Point(x3, y3), epsilon);\n\t};\n}, {\n\tstatics: {},\n\n\thasHandles: function() {\n\t\treturn !this._segment1._handleOut.isZero()\n\t\t\t\t|| !this._segment2._handleIn.isZero();\n\t},\n\n\thasLength: function(epsilon) {\n\t\treturn (!this.getPoint1().equals(this.getPoint2()) || this.hasHandles())\n\t\t\t\t&& this.getLength() > (epsilon || 0);\n\t},\n\n\tisCollinear: function(curve) {\n\t\treturn curve && this.isStraight() && curve.isStraight()\n\t\t\t\t&& this.getLine().isCollinear(curve.getLine());\n\t},\n\n\tisHorizontal: function() {\n\t\treturn this.isStraight() && Math.abs(this.getTangentAtTime(0.5).y)\n\t\t\t\t< 1e-8;\n\t},\n\n\tisVertical: function() {\n\t\treturn this.isStraight() && Math.abs(this.getTangentAtTime(0.5).x)\n\t\t\t\t< 1e-8;\n\t}\n}), {\n\tbeans: false,\n\n\tgetLocationAt: function(offset, _isTime) {\n\t\treturn this.getLocationAtTime(\n\t\t\t\t_isTime ? offset : this.getTimeAt(offset));\n\t},\n\n\tgetLocationAtTime: function(t) {\n\t\treturn t != null && t >= 0 && t <= 1\n\t\t\t\t? new CurveLocation(this, t)\n\t\t\t\t: null;\n\t},\n\n\tgetTimeAt: function(offset, start) {\n\t\treturn Curve.getTimeAt(this.getValues(), offset, start);\n\t},\n\n\tgetParameterAt: '#getTimeAt',\n\n\tgetOffsetAtTime: function(t) {\n\t\treturn this.getPartLength(0, t);\n\t},\n\n\tgetLocationOf: function() {\n\t\treturn this.getLocationAtTime(this.getTimeOf(Point.read(arguments)));\n\t},\n\n\tgetOffsetOf: function() {\n\t\tvar loc = this.getLocationOf.apply(this, arguments);\n\t\treturn loc ? loc.getOffset() : null;\n\t},\n\n\tgetTimeOf: function() {\n\t\treturn Curve.getTimeOf(this.getValues(), Point.read(arguments));\n\t},\n\n\tgetParameterOf: '#getTimeOf',\n\n\tgetNearestLocation: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\tvalues = this.getValues(),\n\t\t\tt = Curve.getNearestTime(values, point),\n\t\t\tpt = Curve.getPoint(values, t);\n\t\treturn new CurveLocation(this, t, pt, null, point.getDistance(pt));\n\t},\n\n\tgetNearestPoint: function() {\n\t\tvar loc = this.getNearestLocation.apply(this, arguments);\n\t\treturn loc ? loc.getPoint() : loc;\n\t}\n\n},\nnew function() {\n\tvar methods = ['getPoint', 'getTangent', 'getNormal', 'getWeightedTangent',\n\t\t'getWeightedNormal', 'getCurvature'];\n\treturn Base.each(methods,\n\t\tfunction(name) {\n\t\t\tthis[name + 'At'] = function(location, _isTime) {\n\t\t\t\tvar values = this.getValues();\n\t\t\t\treturn Curve[name](values, _isTime ? location\n\t\t\t\t\t\t: Curve.getTimeAt(values, location));\n\t\t\t};\n\n\t\t\tthis[name + 'AtTime'] = function(time) {\n\t\t\t\treturn Curve[name](this.getValues(), time);\n\t\t\t};\n\t\t}, {\n\t\t\tstatics: {\n\t\t\t\t_evaluateMethods: methods\n\t\t\t}\n\t\t}\n\t);\n},\nnew function() {\n\n\tfunction getLengthIntegrand(v) {\n\t\tvar x0 = v[0], y0 = v[1],\n\t\t\tx1 = v[2], y1 = v[3],\n\t\t\tx2 = v[4], y2 = v[5],\n\t\t\tx3 = v[6], y3 = v[7],\n\n\t\t\tax = 9 * (x1 - x2) + 3 * (x3 - x0),\n\t\t\tbx = 6 * (x0 + x2) - 12 * x1,\n\t\t\tcx = 3 * (x1 - x0),\n\n\t\t\tay = 9 * (y1 - y2) + 3 * (y3 - y0),\n\t\t\tby = 6 * (y0 + y2) - 12 * y1,\n\t\t\tcy = 3 * (y1 - y0);\n\n\t\treturn function(t) {\n\t\t\tvar dx = (ax * t + bx) * t + cx,\n\t\t\t\tdy = (ay * t + by) * t + cy;\n\t\t\treturn Math.sqrt(dx * dx + dy * dy);\n\t\t};\n\t}\n\n\tfunction getIterations(a, b) {\n\t\treturn Math.max(2, Math.min(16, Math.ceil(Math.abs(b - a) * 32)));\n\t}\n\n\tfunction evaluate(v, t, type, normalized) {\n\t\tif (t == null || t < 0 || t > 1)\n\t\t\treturn null;\n\t\tvar x0 = v[0], y0 = v[1],\n\t\t\tx1 = v[2], y1 = v[3],\n\t\t\tx2 = v[4], y2 = v[5],\n\t\t\tx3 = v[6], y3 = v[7],\n\t\t\tisZero = Numerical.isZero;\n\t\tif (isZero(x1 - x0) && isZero(y1 - y0)) {\n\t\t\tx1 = x0;\n\t\t\ty1 = y0;\n\t\t}\n\t\tif (isZero(x2 - x3) && isZero(y2 - y3)) {\n\t\t\tx2 = x3;\n\t\t\ty2 = y3;\n\t\t}\n\t\tvar cx = 3 * (x1 - x0),\n\t\t\tbx = 3 * (x2 - x1) - cx,\n\t\t\tax = x3 - x0 - cx - bx,\n\t\t\tcy = 3 * (y1 - y0),\n\t\t\tby = 3 * (y2 - y1) - cy,\n\t\t\tay = y3 - y0 - cy - by,\n\t\t\tx, y;\n\t\tif (type === 0) {\n\t\t\tx = t === 0 ? x0 : t === 1 ? x3\n\t\t\t\t\t: ((ax * t + bx) * t + cx) * t + x0;\n\t\t\ty = t === 0 ? y0 : t === 1 ? y3\n\t\t\t\t\t: ((ay * t + by) * t + cy) * t + y0;\n\t\t} else {\n\t\t\tvar tMin = 1e-8,\n\t\t\t\ttMax = 1 - tMin;\n\t\t\tif (t < tMin) {\n\t\t\t\tx = cx;\n\t\t\t\ty = cy;\n\t\t\t} else if (t > tMax) {\n\t\t\t\tx = 3 * (x3 - x2);\n\t\t\t\ty = 3 * (y3 - y2);\n\t\t\t} else {\n\t\t\t\tx = (3 * ax * t + 2 * bx) * t + cx;\n\t\t\t\ty = (3 * ay * t + 2 * by) * t + cy;\n\t\t\t}\n\t\t\tif (normalized) {\n\t\t\t\tif (x === 0 && y === 0 && (t < tMin || t > tMax)) {\n\t\t\t\t\tx = x2 - x1;\n\t\t\t\t\ty = y2 - y1;\n\t\t\t\t}\n\t\t\t\tvar len = Math.sqrt(x * x + y * y);\n\t\t\t\tif (len) {\n\t\t\t\t\tx /= len;\n\t\t\t\t\ty /= len;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (type === 3) {\n\t\t\t\tvar x2 = 6 * ax * t + 2 * bx,\n\t\t\t\t\ty2 = 6 * ay * t + 2 * by,\n\t\t\t\t\td = Math.pow(x * x + y * y, 3 / 2);\n\t\t\t\tx = d !== 0 ? (x * y2 - y * x2) / d : 0;\n\t\t\t\ty = 0;\n\t\t\t}\n\t\t}\n\t\treturn type === 2 ? new Point(y, -x) : new Point(x, y);\n\t}\n\n\treturn { statics: {\n\n\t\tclassify: function(v) {\n\n\t\t\tvar x0 = v[0], y0 = v[1],\n\t\t\t\tx1 = v[2], y1 = v[3],\n\t\t\t\tx2 = v[4], y2 = v[5],\n\t\t\t\tx3 = v[6], y3 = v[7],\n\t\t\t\ta1 = x0 * (y3 - y2) + y0 * (x2 - x3) + x3 * y2 - y3 * x2,\n\t\t\t\ta2 = x1 * (y0 - y3) + y1 * (x3 - x0) + x0 * y3 - y0 * x3,\n\t\t\t\ta3 = x2 * (y1 - y0) + y2 * (x0 - x1) + x1 * y0 - y1 * x0,\n\t\t\t\td3 = 3 * a3,\n\t\t\t\td2 = d3 - a2,\n\t\t\t\td1 = d2 - a2 + a1,\n\t\t\t\tl = Math.sqrt(d1 * d1 + d2 * d2 + d3 * d3),\n\t\t\t\ts = l !== 0 ? 1 / l : 0,\n\t\t\t\tisZero = Numerical.isZero,\n\t\t\t\tserpentine = 'serpentine';\n\t\t\td1 *= s;\n\t\t\td2 *= s;\n\t\t\td3 *= s;\n\n\t\t\tfunction type(type, t1, t2) {\n\t\t\t\tvar hasRoots = t1 !== undefined,\n\t\t\t\t\tt1Ok = hasRoots && t1 > 0 && t1 < 1,\n\t\t\t\t\tt2Ok = hasRoots && t2 > 0 && t2 < 1;\n\t\t\t\tif (hasRoots && (!(t1Ok || t2Ok)\n\t\t\t\t\t\t|| type === 'loop' && !(t1Ok && t2Ok))) {\n\t\t\t\t\ttype = 'arch';\n\t\t\t\t\tt1Ok = t2Ok = false;\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\ttype: type,\n\t\t\t\t\troots: t1Ok || t2Ok\n\t\t\t\t\t\t\t? t1Ok && t2Ok\n\t\t\t\t\t\t\t\t? t1 < t2 ? [t1, t2] : [t2, t1]\n\t\t\t\t\t\t\t\t: [t1Ok ? t1 : t2]\n\t\t\t\t\t\t\t: null\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (isZero(d1)) {\n\t\t\t\treturn isZero(d2)\n\t\t\t\t\t\t? type(isZero(d3) ? 'line' : 'quadratic')\n\t\t\t\t\t\t: type(serpentine, d3 / (3 * d2));\n\t\t\t}\n\t\t\tvar d = 3 * d2 * d2 - 4 * d1 * d3;\n\t\t\tif (isZero(d)) {\n\t\t\t\treturn type('cusp', d2 / (2 * d1));\n\t\t\t}\n\t\t\tvar f1 = d > 0 ? Math.sqrt(d / 3) : Math.sqrt(-d),\n\t\t\t\tf2 = 2 * d1;\n\t\t\treturn type(d > 0 ? serpentine : 'loop',\n\t\t\t\t\t(d2 + f1) / f2,\n\t\t\t\t\t(d2 - f1) / f2);\n\t\t},\n\n\t\tgetLength: function(v, a, b, ds) {\n\t\t\tif (a === undefined)\n\t\t\t\ta = 0;\n\t\t\tif (b === undefined)\n\t\t\t\tb = 1;\n\t\t\tif (Curve.isStraight(v)) {\n\t\t\t\tvar c = v;\n\t\t\t\tif (b < 1) {\n\t\t\t\t\tc = Curve.subdivide(c, b)[0];\n\t\t\t\t\ta /= b;\n\t\t\t\t}\n\t\t\t\tif (a > 0) {\n\t\t\t\t\tc = Curve.subdivide(c, a)[1];\n\t\t\t\t}\n\t\t\t\tvar dx = c[6] - c[0],\n\t\t\t\t\tdy = c[7] - c[1];\n\t\t\t\treturn Math.sqrt(dx * dx + dy * dy);\n\t\t\t}\n\t\t\treturn Numerical.integrate(ds || getLengthIntegrand(v), a, b,\n\t\t\t\t\tgetIterations(a, b));\n\t\t},\n\n\t\tgetTimeAt: function(v, offset, start) {\n\t\t\tif (start === undefined)\n\t\t\t\tstart = offset < 0 ? 1 : 0;\n\t\t\tif (offset === 0)\n\t\t\t\treturn start;\n\t\t\tvar abs = Math.abs,\n\t\t\t\tepsilon = 1e-12,\n\t\t\t\tforward = offset > 0,\n\t\t\t\ta = forward ? start : 0,\n\t\t\t\tb = forward ? 1 : start,\n\t\t\t\tds = getLengthIntegrand(v),\n\t\t\t\trangeLength = Curve.getLength(v, a, b, ds),\n\t\t\t\tdiff = abs(offset) - rangeLength;\n\t\t\tif (abs(diff) < epsilon) {\n\t\t\t\treturn forward ? b : a;\n\t\t\t} else if (diff > epsilon) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tvar guess = offset / rangeLength,\n\t\t\t\tlength = 0;\n\t\t\tfunction f(t) {\n\t\t\t\tlength += Numerical.integrate(ds, start, t,\n\t\t\t\t\t\tgetIterations(start, t));\n\t\t\t\tstart = t;\n\t\t\t\treturn length - offset;\n\t\t\t}\n\t\t\treturn Numerical.findRoot(f, ds, start + guess, a, b, 32,\n\t\t\t\t\t1e-12);\n\t\t},\n\n\t\tgetPoint: function(v, t) {\n\t\t\treturn evaluate(v, t, 0, false);\n\t\t},\n\n\t\tgetTangent: function(v, t) {\n\t\t\treturn evaluate(v, t, 1, true);\n\t\t},\n\n\t\tgetWeightedTangent: function(v, t) {\n\t\t\treturn evaluate(v, t, 1, false);\n\t\t},\n\n\t\tgetNormal: function(v, t) {\n\t\t\treturn evaluate(v, t, 2, true);\n\t\t},\n\n\t\tgetWeightedNormal: function(v, t) {\n\t\t\treturn evaluate(v, t, 2, false);\n\t\t},\n\n\t\tgetCurvature: function(v, t) {\n\t\t\treturn evaluate(v, t, 3, false).x;\n\t\t},\n\n\t\tgetPeaks: function(v) {\n\t\t\tvar x0 = v[0], y0 = v[1],\n\t\t\t\tx1 = v[2], y1 = v[3],\n\t\t\t\tx2 = v[4], y2 = v[5],\n\t\t\t\tx3 = v[6], y3 = v[7],\n\t\t\t\tax =     -x0 + 3 * x1 - 3 * x2 + x3,\n\t\t\t\tbx =  3 * x0 - 6 * x1 + 3 * x2,\n\t\t\t\tcx = -3 * x0 + 3 * x1,\n\t\t\t\tay =     -y0 + 3 * y1 - 3 * y2 + y3,\n\t\t\t\tby =  3 * y0 - 6 * y1 + 3 * y2,\n\t\t\t\tcy = -3 * y0 + 3 * y1,\n\t\t\t\ttMin = 1e-8,\n\t\t\t\ttMax = 1 - tMin,\n\t\t\t\troots = [];\n\t\t\tNumerical.solveCubic(\n\t\t\t\t\t9 * (ax * ax + ay * ay),\n\t\t\t\t\t9 * (ax * bx + by * ay),\n\t\t\t\t\t2 * (bx * bx + by * by) + 3 * (cx * ax + cy * ay),\n\t\t\t\t\t(cx * bx + by * cy),\n\t\t\t\t\troots, tMin, tMax);\n\t\t\treturn roots.sort();\n\t\t}\n\t}};\n},\nnew function() {\n\n\tfunction addLocation(locations, include, c1, t1, c2, t2, overlap) {\n\t\tvar excludeStart = !overlap && c1.getPrevious() === c2,\n\t\t\texcludeEnd = !overlap && c1 !== c2 && c1.getNext() === c2,\n\t\t\ttMin = 1e-8,\n\t\t\ttMax = 1 - tMin;\n\t\tif (t1 !== null && t1 >= (excludeStart ? tMin : 0) &&\n\t\t\tt1 <= (excludeEnd ? tMax : 1)) {\n\t\t\tif (t2 !== null && t2 >= (excludeEnd ? tMin : 0) &&\n\t\t\t\tt2 <= (excludeStart ? tMax : 1)) {\n\t\t\t\tvar loc1 = new CurveLocation(c1, t1, null, overlap),\n\t\t\t\t\tloc2 = new CurveLocation(c2, t2, null, overlap);\n\t\t\t\tloc1._intersection = loc2;\n\t\t\t\tloc2._intersection = loc1;\n\t\t\t\tif (!include || include(loc1)) {\n\t\t\t\t\tCurveLocation.insert(locations, loc1, true);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction addCurveIntersections(v1, v2, c1, c2, locations, include, flip,\n\t\t\trecursion, calls, tMin, tMax, uMin, uMax) {\n\t\tif (++calls >= 4096 || ++recursion >= 40)\n\t\t\treturn calls;\n\t\tvar fatLineEpsilon = 1e-9,\n\t\t\tq0x = v2[0], q0y = v2[1], q3x = v2[6], q3y = v2[7],\n\t\t\tgetSignedDistance = Line.getSignedDistance,\n\t\t\td1 = getSignedDistance(q0x, q0y, q3x, q3y, v2[2], v2[3]),\n\t\t\td2 = getSignedDistance(q0x, q0y, q3x, q3y, v2[4], v2[5]),\n\t\t\tfactor = d1 * d2 > 0 ? 3 / 4 : 4 / 9,\n\t\t\tdMin = factor * Math.min(0, d1, d2),\n\t\t\tdMax = factor * Math.max(0, d1, d2),\n\t\t\tdp0 = getSignedDistance(q0x, q0y, q3x, q3y, v1[0], v1[1]),\n\t\t\tdp1 = getSignedDistance(q0x, q0y, q3x, q3y, v1[2], v1[3]),\n\t\t\tdp2 = getSignedDistance(q0x, q0y, q3x, q3y, v1[4], v1[5]),\n\t\t\tdp3 = getSignedDistance(q0x, q0y, q3x, q3y, v1[6], v1[7]),\n\t\t\thull = getConvexHull(dp0, dp1, dp2, dp3),\n\t\t\ttop = hull[0],\n\t\t\tbottom = hull[1],\n\t\t\ttMinClip,\n\t\t\ttMaxClip;\n\t\tif (d1 === 0 && d2 === 0\n\t\t\t\t&& dp0 === 0 && dp1 === 0 && dp2 === 0 && dp3 === 0\n\t\t\t|| (tMinClip = clipConvexHull(top, bottom, dMin, dMax)) == null\n\t\t\t|| (tMaxClip = clipConvexHull(top.reverse(), bottom.reverse(),\n\t\t\t\tdMin, dMax)) == null)\n\t\t\treturn calls;\n\t\tvar tMinNew = tMin + (tMax - tMin) * tMinClip,\n\t\t\ttMaxNew = tMin + (tMax - tMin) * tMaxClip;\n\t\tif (Math.max(uMax - uMin, tMaxNew - tMinNew) < fatLineEpsilon) {\n\t\t\tvar t = (tMinNew + tMaxNew) / 2,\n\t\t\t\tu = (uMin + uMax) / 2;\n\t\t\taddLocation(locations, include,\n\t\t\t\t\tflip ? c2 : c1, flip ? u : t,\n\t\t\t\t\tflip ? c1 : c2, flip ? t : u);\n\t\t} else {\n\t\t\tv1 = Curve.getPart(v1, tMinClip, tMaxClip);\n\t\t\tif (tMaxClip - tMinClip > 0.8) {\n\t\t\t\tif (tMaxNew - tMinNew > uMax - uMin) {\n\t\t\t\t\tvar parts = Curve.subdivide(v1, 0.5),\n\t\t\t\t\t\tt = (tMinNew + tMaxNew) / 2;\n\t\t\t\t\tcalls = addCurveIntersections(\n\t\t\t\t\t\t\tv2, parts[0], c2, c1, locations, include, !flip,\n\t\t\t\t\t\t\trecursion, calls, uMin, uMax, tMinNew, t);\n\t\t\t\t\tcalls = addCurveIntersections(\n\t\t\t\t\t\t\tv2, parts[1], c2, c1, locations, include, !flip,\n\t\t\t\t\t\t\trecursion, calls, uMin, uMax, t, tMaxNew);\n\t\t\t\t} else {\n\t\t\t\t\tvar parts = Curve.subdivide(v2, 0.5),\n\t\t\t\t\t\tu = (uMin + uMax) / 2;\n\t\t\t\t\tcalls = addCurveIntersections(\n\t\t\t\t\t\t\tparts[0], v1, c2, c1, locations, include, !flip,\n\t\t\t\t\t\t\trecursion, calls, uMin, u, tMinNew, tMaxNew);\n\t\t\t\t\tcalls = addCurveIntersections(\n\t\t\t\t\t\t\tparts[1], v1, c2, c1, locations, include, !flip,\n\t\t\t\t\t\t\trecursion, calls, u, uMax, tMinNew, tMaxNew);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (uMax - uMin >= fatLineEpsilon) {\n\t\t\t\t\tcalls = addCurveIntersections(\n\t\t\t\t\t\t\tv2, v1, c2, c1, locations, include, !flip,\n\t\t\t\t\t\t\trecursion, calls, uMin, uMax, tMinNew, tMaxNew);\n\t\t\t\t} else {\n\t\t\t\t\tcalls = addCurveIntersections(\n\t\t\t\t\t\t\tv1, v2, c1, c2, locations, include, flip,\n\t\t\t\t\t\t\trecursion, calls, tMinNew, tMaxNew, uMin, uMax);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn calls;\n\t}\n\n\tfunction getConvexHull(dq0, dq1, dq2, dq3) {\n\t\tvar p0 = [ 0, dq0 ],\n\t\t\tp1 = [ 1 / 3, dq1 ],\n\t\t\tp2 = [ 2 / 3, dq2 ],\n\t\t\tp3 = [ 1, dq3 ],\n\t\t\tdist1 = dq1 - (2 * dq0 + dq3) / 3,\n\t\t\tdist2 = dq2 - (dq0 + 2 * dq3) / 3,\n\t\t\thull;\n\t\tif (dist1 * dist2 < 0) {\n\t\t\thull = [[p0, p1, p3], [p0, p2, p3]];\n\t\t} else {\n\t\t\tvar distRatio = dist1 / dist2;\n\t\t\thull = [\n\t\t\t\tdistRatio >= 2 ? [p0, p1, p3]\n\t\t\t\t: distRatio <= 0.5 ? [p0, p2, p3]\n\t\t\t\t: [p0, p1, p2, p3],\n\t\t\t\t[p0, p3]\n\t\t\t];\n\t\t}\n\t\treturn (dist1 || dist2) < 0 ? hull.reverse() : hull;\n\t}\n\n\tfunction clipConvexHull(hullTop, hullBottom, dMin, dMax) {\n\t\tif (hullTop[0][1] < dMin) {\n\t\t\treturn clipConvexHullPart(hullTop, true, dMin);\n\t\t} else if (hullBottom[0][1] > dMax) {\n\t\t\treturn clipConvexHullPart(hullBottom, false, dMax);\n\t\t} else {\n\t\t\treturn hullTop[0][0];\n\t\t}\n\t}\n\n\tfunction clipConvexHullPart(part, top, threshold) {\n\t\tvar px = part[0][0],\n\t\t\tpy = part[0][1];\n\t\tfor (var i = 1, l = part.length; i < l; i++) {\n\t\t\tvar qx = part[i][0],\n\t\t\t\tqy = part[i][1];\n\t\t\tif (top ? qy >= threshold : qy <= threshold) {\n\t\t\t\treturn qy === threshold ? qx\n\t\t\t\t\t\t: px + (threshold - py) * (qx - px) / (qy - py);\n\t\t\t}\n\t\t\tpx = qx;\n\t\t\tpy = qy;\n\t\t}\n\t\treturn null;\n\t}\n\n\tfunction getCurveLineIntersections(v, px, py, vx, vy) {\n\t\tvar isZero = Numerical.isZero;\n\t\tif (isZero(vx) && isZero(vy)) {\n\t\t\tvar t = Curve.getTimeOf(v, new Point(px, py));\n\t\t\treturn t === null ? [] : [t];\n\t\t}\n\t\tvar angle = Math.atan2(-vy, vx),\n\t\t\tsin = Math.sin(angle),\n\t\t\tcos = Math.cos(angle),\n\t\t\trv = [],\n\t\t\troots = [];\n\t\tfor (var i = 0; i < 8; i += 2) {\n\t\t\tvar x = v[i] - px,\n\t\t\t\ty = v[i + 1] - py;\n\t\t\trv.push(\n\t\t\t\tx * cos - y * sin,\n\t\t\t\tx * sin + y * cos);\n\t\t}\n\t\tCurve.solveCubic(rv, 1, 0, roots, 0, 1);\n\t\treturn roots;\n\t}\n\n\tfunction addCurveLineIntersections(v1, v2, c1, c2, locations, include,\n\t\t\tflip) {\n\t\tvar x1 = v2[0], y1 = v2[1],\n\t\t\tx2 = v2[6], y2 = v2[7],\n\t\t\troots = getCurveLineIntersections(v1, x1, y1, x2 - x1, y2 - y1);\n\t\tfor (var i = 0, l = roots.length; i < l; i++) {\n\t\t\tvar t1 = roots[i],\n\t\t\t\tp1 = Curve.getPoint(v1, t1),\n\t\t\t\tt2 = Curve.getTimeOf(v2, p1);\n\t\t\tif (t2 !== null) {\n\t\t\t\taddLocation(locations, include,\n\t\t\t\t\t\tflip ? c2 : c1, flip ? t2 : t1,\n\t\t\t\t\t\tflip ? c1 : c2, flip ? t1 : t2);\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction addLineIntersection(v1, v2, c1, c2, locations, include) {\n\t\tvar pt = Line.intersect(\n\t\t\t\tv1[0], v1[1], v1[6], v1[7],\n\t\t\t\tv2[0], v2[1], v2[6], v2[7]);\n\t\tif (pt) {\n\t\t\taddLocation(locations, include,\n\t\t\t\t\tc1, Curve.getTimeOf(v1, pt),\n\t\t\t\t\tc2, Curve.getTimeOf(v2, pt));\n\t\t}\n\t}\n\n\tfunction getCurveIntersections(v1, v2, c1, c2, locations, include) {\n\t\tvar epsilon = 1e-12,\n\t\t\tmin = Math.min,\n\t\t\tmax = Math.max;\n\n\t\tif (max(v1[0], v1[2], v1[4], v1[6]) + epsilon >\n\t\t\tmin(v2[0], v2[2], v2[4], v2[6]) &&\n\t\t\tmin(v1[0], v1[2], v1[4], v1[6]) - epsilon <\n\t\t\tmax(v2[0], v2[2], v2[4], v2[6]) &&\n\t\t\tmax(v1[1], v1[3], v1[5], v1[7]) + epsilon >\n\t\t\tmin(v2[1], v2[3], v2[5], v2[7]) &&\n\t\t\tmin(v1[1], v1[3], v1[5], v1[7]) - epsilon <\n\t\t\tmax(v2[1], v2[3], v2[5], v2[7])) {\n\t\t\tvar overlaps = getOverlaps(v1, v2);\n\t\t\tif (overlaps) {\n\t\t\t\tfor (var i = 0; i < 2; i++) {\n\t\t\t\t\tvar overlap = overlaps[i];\n\t\t\t\t\taddLocation(locations, include,\n\t\t\t\t\t\t\tc1, overlap[0],\n\t\t\t\t\t\t\tc2, overlap[1], true);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tvar straight1 = Curve.isStraight(v1),\n\t\t\t\t\tstraight2 = Curve.isStraight(v2),\n\t\t\t\t\tstraight = straight1 && straight2,\n\t\t\t\t\tflip = straight1 && !straight2,\n\t\t\t\t\tbefore = locations.length;\n\t\t\t\t(straight\n\t\t\t\t\t? addLineIntersection\n\t\t\t\t\t: straight1 || straight2\n\t\t\t\t\t\t? addCurveLineIntersections\n\t\t\t\t\t\t: addCurveIntersections)(\n\t\t\t\t\t\t\tflip ? v2 : v1, flip ? v1 : v2,\n\t\t\t\t\t\t\tflip ? c2 : c1, flip ? c1 : c2,\n\t\t\t\t\t\t\tlocations, include, flip,\n\t\t\t\t\t\t\t0, 0, 0, 1, 0, 1);\n\t\t\t\tif (!straight || locations.length === before) {\n\t\t\t\t\tfor (var i = 0; i < 4; i++) {\n\t\t\t\t\t\tvar t1 = i >> 1,\n\t\t\t\t\t\t\tt2 = i & 1,\n\t\t\t\t\t\t\ti1 = t1 * 6,\n\t\t\t\t\t\t\ti2 = t2 * 6,\n\t\t\t\t\t\t\tp1 = new Point(v1[i1], v1[i1 + 1]),\n\t\t\t\t\t\t\tp2 = new Point(v2[i2], v2[i2 + 1]);\n\t\t\t\t\t\tif (p1.isClose(p2, epsilon)) {\n\t\t\t\t\t\t\taddLocation(locations, include,\n\t\t\t\t\t\t\t\t\tc1, t1,\n\t\t\t\t\t\t\t\t\tc2, t2);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn locations;\n\t}\n\n\tfunction getLoopIntersection(v1, c1, locations, include) {\n\t\tvar info = Curve.classify(v1);\n\t\tif (info.type === 'loop') {\n\t\t\tvar roots = info.roots;\n\t\t\taddLocation(locations, include,\n\t\t\t\t\tc1, roots[0],\n\t\t\t\t\tc1, roots[1]);\n\t\t}\n\t  return locations;\n\t}\n\n\tfunction getIntersections(curves1, curves2, include, matrix1, matrix2,\n\t\t\t_returnFirst) {\n\t\tvar self = !curves2;\n\t\tif (self)\n\t\t\tcurves2 = curves1;\n\t\tvar length1 = curves1.length,\n\t\t\tlength2 = curves2.length,\n\t\t\tvalues2 = [],\n\t\t\tarrays = [],\n\t\t\tlocations,\n\t\t\tcurrent;\n\t\tfor (var i = 0; i < length2; i++)\n\t\t\tvalues2[i] = curves2[i].getValues(matrix2);\n\t\tfor (var i = 0; i < length1; i++) {\n\t\t\tvar curve1 = curves1[i],\n\t\t\t\tvalues1 = self ? values2[i] : curve1.getValues(matrix1),\n\t\t\t\tpath1 = curve1.getPath();\n\t\t\tif (path1 !== current) {\n\t\t\t\tcurrent = path1;\n\t\t\t\tlocations = [];\n\t\t\t\tarrays.push(locations);\n\t\t\t}\n\t\t\tif (self) {\n\t\t\t\tgetLoopIntersection(values1, curve1, locations, include);\n\t\t\t}\n\t\t\tfor (var j = self ? i + 1 : 0; j < length2; j++) {\n\t\t\t\tif (_returnFirst && locations.length)\n\t\t\t\t\treturn locations;\n\t\t\t\tgetCurveIntersections(values1, values2[j], curve1, curves2[j],\n\t\t\t\t\t\tlocations, include);\n\t\t\t}\n\t\t}\n\t\tlocations = [];\n\t\tfor (var i = 0, l = arrays.length; i < l; i++) {\n\t\t\tlocations.push.apply(locations, arrays[i]);\n\t\t}\n\t\treturn locations;\n\t}\n\n\tfunction getOverlaps(v1, v2) {\n\n\t\tfunction getSquaredLineLength(v) {\n\t\t\tvar x = v[6] - v[0],\n\t\t\t\ty = v[7] - v[1];\n\t\t\treturn x * x + y * y;\n\t\t}\n\n\t\tvar abs = Math.abs,\n\t\t\tgetDistance = Line.getDistance,\n\t\t\ttimeEpsilon = 1e-8,\n\t\t\tgeomEpsilon = 1e-7,\n\t\t\tstraight1 = Curve.isStraight(v1),\n\t\t\tstraight2 = Curve.isStraight(v2),\n\t\t\tstraightBoth = straight1 && straight2,\n\t\t\tflip = getSquaredLineLength(v1) < getSquaredLineLength(v2),\n\t\t\tl1 = flip ? v2 : v1,\n\t\t\tl2 = flip ? v1 : v2,\n\t\t\tpx = l1[0], py = l1[1],\n\t\t\tvx = l1[6] - px, vy = l1[7] - py;\n\t\tif (getDistance(px, py, vx, vy, l2[0], l2[1], true) < geomEpsilon &&\n\t\t\tgetDistance(px, py, vx, vy, l2[6], l2[7], true) < geomEpsilon) {\n\t\t\tif (!straightBoth &&\n\t\t\t\tgetDistance(px, py, vx, vy, l1[2], l1[3], true) < geomEpsilon &&\n\t\t\t\tgetDistance(px, py, vx, vy, l1[4], l1[5], true) < geomEpsilon &&\n\t\t\t\tgetDistance(px, py, vx, vy, l2[2], l2[3], true) < geomEpsilon &&\n\t\t\t\tgetDistance(px, py, vx, vy, l2[4], l2[5], true) < geomEpsilon) {\n\t\t\t\tstraight1 = straight2 = straightBoth = true;\n\t\t\t}\n\t\t} else if (straightBoth) {\n\t\t\treturn null;\n\t\t}\n\t\tif (straight1 ^ straight2) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar v = [v1, v2],\n\t\t\tpairs = [];\n\t\tfor (var i = 0; i < 4 && pairs.length < 2; i++) {\n\t\t\tvar i1 = i & 1,\n\t\t\t\ti2 = i1 ^ 1,\n\t\t\t\tt1 = i >> 1,\n\t\t\t\tt2 = Curve.getTimeOf(v[i1], new Point(\n\t\t\t\t\tv[i2][t1 ? 6 : 0],\n\t\t\t\t\tv[i2][t1 ? 7 : 1]));\n\t\t\tif (t2 != null) {\n\t\t\t\tvar pair = i1 ? [t1, t2] : [t2, t1];\n\t\t\t\tif (!pairs.length ||\n\t\t\t\t\tabs(pair[0] - pairs[0][0]) > timeEpsilon &&\n\t\t\t\t\tabs(pair[1] - pairs[0][1]) > timeEpsilon) {\n\t\t\t\t\tpairs.push(pair);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (i > 2 && !pairs.length)\n\t\t\t\tbreak;\n\t\t}\n\t\tif (pairs.length !== 2) {\n\t\t\tpairs = null;\n\t\t} else if (!straightBoth) {\n\t\t\tvar o1 = Curve.getPart(v1, pairs[0][0], pairs[1][0]),\n\t\t\t\to2 = Curve.getPart(v2, pairs[0][1], pairs[1][1]);\n\t\t\tif (abs(o2[2] - o1[2]) > geomEpsilon ||\n\t\t\t\tabs(o2[3] - o1[3]) > geomEpsilon ||\n\t\t\t\tabs(o2[4] - o1[4]) > geomEpsilon ||\n\t\t\t\tabs(o2[5] - o1[5]) > geomEpsilon)\n\t\t\t\tpairs = null;\n\t\t}\n\t\treturn pairs;\n\t}\n\n\treturn {\n\t\tgetIntersections: function(curve) {\n\t\t\tvar v1 = this.getValues(),\n\t\t\t\tv2 = curve && curve !== this && curve.getValues();\n\t\t\treturn v2 ? getCurveIntersections(v1, v2, this, curve, [])\n\t\t\t\t\t  : getLoopIntersection(v1, this, []);\n\t\t},\n\n\t\tstatics: {\n\t\t\tgetOverlaps: getOverlaps,\n\t\t\tgetIntersections: getIntersections,\n\t\t\tgetCurveLineIntersections: getCurveLineIntersections\n\t\t}\n\t};\n});\n\nvar CurveLocation = Base.extend({\n\t_class: 'CurveLocation',\n\n\tinitialize: function CurveLocation(curve, time, point, _overlap, _distance) {\n\t\tif (time >= 0.99999999) {\n\t\t\tvar next = curve.getNext();\n\t\t\tif (next) {\n\t\t\t\ttime = 0;\n\t\t\t\tcurve = next;\n\t\t\t}\n\t\t}\n\t\tthis._setCurve(curve);\n\t\tthis._time = time;\n\t\tthis._point = point || curve.getPointAtTime(time);\n\t\tthis._overlap = _overlap;\n\t\tthis._distance = _distance;\n\t\tthis._intersection = this._next = this._previous = null;\n\t},\n\n\t_setCurve: function(curve) {\n\t\tvar path = curve._path;\n\t\tthis._path = path;\n\t\tthis._version = path ? path._version : 0;\n\t\tthis._curve = curve;\n\t\tthis._segment = null;\n\t\tthis._segment1 = curve._segment1;\n\t\tthis._segment2 = curve._segment2;\n\t},\n\n\t_setSegment: function(segment) {\n\t\tthis._setCurve(segment.getCurve());\n\t\tthis._segment = segment;\n\t\tthis._time = segment === this._segment1 ? 0 : 1;\n\t\tthis._point = segment._point.clone();\n\t},\n\n\tgetSegment: function() {\n\t\tvar segment = this._segment;\n\t\tif (!segment) {\n\t\t\tvar curve = this.getCurve(),\n\t\t\t\ttime = this.getTime();\n\t\t\tif (time === 0) {\n\t\t\t\tsegment = curve._segment1;\n\t\t\t} else if (time === 1) {\n\t\t\t\tsegment = curve._segment2;\n\t\t\t} else if (time != null) {\n\t\t\t\tsegment = curve.getPartLength(0, time)\n\t\t\t\t\t< curve.getPartLength(time, 1)\n\t\t\t\t\t\t? curve._segment1\n\t\t\t\t\t\t: curve._segment2;\n\t\t\t}\n\t\t\tthis._segment = segment;\n\t\t}\n\t\treturn segment;\n\t},\n\n\tgetCurve: function() {\n\t\tvar path = this._path,\n\t\t\tthat = this;\n\t\tif (path && path._version !== this._version) {\n\t\t\tthis._time = this._offset = this._curveOffset = this._curve = null;\n\t\t}\n\n\t\tfunction trySegment(segment) {\n\t\t\tvar curve = segment && segment.getCurve();\n\t\t\tif (curve && (that._time = curve.getTimeOf(that._point)) != null) {\n\t\t\t\tthat._setCurve(curve);\n\t\t\t\treturn curve;\n\t\t\t}\n\t\t}\n\n\t\treturn this._curve\n\t\t\t|| trySegment(this._segment)\n\t\t\t|| trySegment(this._segment1)\n\t\t\t|| trySegment(this._segment2.getPrevious());\n\t},\n\n\tgetPath: function() {\n\t\tvar curve = this.getCurve();\n\t\treturn curve && curve._path;\n\t},\n\n\tgetIndex: function() {\n\t\tvar curve = this.getCurve();\n\t\treturn curve && curve.getIndex();\n\t},\n\n\tgetTime: function() {\n\t\tvar curve = this.getCurve(),\n\t\t\ttime = this._time;\n\t\treturn curve && time == null\n\t\t\t? this._time = curve.getTimeOf(this._point)\n\t\t\t: time;\n\t},\n\n\tgetParameter: '#getTime',\n\n\tgetPoint: function() {\n\t\treturn this._point;\n\t},\n\n\tgetOffset: function() {\n\t\tvar offset = this._offset;\n\t\tif (offset == null) {\n\t\t\toffset = 0;\n\t\t\tvar path = this.getPath(),\n\t\t\t\tindex = this.getIndex();\n\t\t\tif (path && index != null) {\n\t\t\t\tvar curves = path.getCurves();\n\t\t\t\tfor (var i = 0; i < index; i++)\n\t\t\t\t\toffset += curves[i].getLength();\n\t\t\t}\n\t\t\tthis._offset = offset += this.getCurveOffset();\n\t\t}\n\t\treturn offset;\n\t},\n\n\tgetCurveOffset: function() {\n\t\tvar offset = this._curveOffset;\n\t\tif (offset == null) {\n\t\t\tvar curve = this.getCurve(),\n\t\t\t\ttime = this.getTime();\n\t\t\tthis._curveOffset = offset = time != null && curve\n\t\t\t\t\t&& curve.getPartLength(0, time);\n\t\t}\n\t\treturn offset;\n\t},\n\n\tgetIntersection: function() {\n\t\treturn this._intersection;\n\t},\n\n\tgetDistance: function() {\n\t\treturn this._distance;\n\t},\n\n\tdivide: function() {\n\t\tvar curve = this.getCurve(),\n\t\t\tres = curve && curve.divideAtTime(this.getTime());\n\t\tif (res) {\n\t\t\tthis._setSegment(res._segment1);\n\t\t}\n\t\treturn res;\n\t},\n\n\tsplit: function() {\n\t\tvar curve = this.getCurve(),\n\t\t\tpath = curve._path,\n\t\t\tres = curve && curve.splitAtTime(this.getTime());\n\t\tif (res) {\n\t\t\tthis._setSegment(path.getLastSegment());\n\t\t}\n\t\treturn  res;\n\t},\n\n\tequals: function(loc, _ignoreOther) {\n\t\tvar res = this === loc;\n\t\tif (!res && loc instanceof CurveLocation) {\n\t\t\tvar c1 = this.getCurve(),\n\t\t\t\tc2 = loc.getCurve(),\n\t\t\t\tp1 = c1._path,\n\t\t\t\tp2 = c2._path;\n\t\t\tif (p1 === p2) {\n\t\t\t\tvar abs = Math.abs,\n\t\t\t\t\tepsilon = 1e-7,\n\t\t\t\t\tdiff = abs(this.getOffset() - loc.getOffset()),\n\t\t\t\t\ti1 = !_ignoreOther && this._intersection,\n\t\t\t\t\ti2 = !_ignoreOther && loc._intersection;\n\t\t\t\tres = (diff < epsilon\n\t\t\t\t\t\t|| p1 && abs(p1.getLength() - diff) < epsilon)\n\t\t\t\t\t&& (!i1 && !i2 || i1 && i2 && i1.equals(i2, true));\n\t\t\t}\n\t\t}\n\t\treturn res;\n\t},\n\n\ttoString: function() {\n\t\tvar parts = [],\n\t\t\tpoint = this.getPoint(),\n\t\t\tf = Formatter.instance;\n\t\tif (point)\n\t\t\tparts.push('point: ' + point);\n\t\tvar index = this.getIndex();\n\t\tif (index != null)\n\t\t\tparts.push('index: ' + index);\n\t\tvar time = this.getTime();\n\t\tif (time != null)\n\t\t\tparts.push('time: ' + f.number(time));\n\t\tif (this._distance != null)\n\t\t\tparts.push('distance: ' + f.number(this._distance));\n\t\treturn '{ ' + parts.join(', ') + ' }';\n\t},\n\n\tisTouching: function() {\n\t\tvar inter = this._intersection;\n\t\tif (inter && this.getTangent().isCollinear(inter.getTangent())) {\n\t\t\tvar curve1 = this.getCurve(),\n\t\t\t\tcurve2 = inter.getCurve();\n\t\t\treturn !(curve1.isStraight() && curve2.isStraight()\n\t\t\t\t\t&& curve1.getLine().intersect(curve2.getLine()));\n\t\t}\n\t\treturn false;\n\t},\n\n\tisCrossing: function() {\n\t\tvar inter = this._intersection;\n\t\tif (!inter)\n\t\t\treturn false;\n\t\tvar t1 = this.getTime(),\n\t\t\tt2 = inter.getTime(),\n\t\t\ttMin = 1e-8,\n\t\t\ttMax = 1 - tMin,\n\t\t\tt1Inside = t1 >= tMin && t1 <= tMax,\n\t\t\tt2Inside = t2 >= tMin && t2 <= tMax;\n\t\tif (t1Inside && t2Inside)\n\t\t\treturn !this.isTouching();\n\t\tvar c2 = this.getCurve(),\n\t\t\tc1 = t1 < tMin ? c2.getPrevious() : c2,\n\t\t\tc4 = inter.getCurve(),\n\t\t\tc3 = t2 < tMin ? c4.getPrevious() : c4;\n\t\tif (t1 > tMax)\n\t\t\tc2 = c2.getNext();\n\t\tif (t2 > tMax)\n\t\t\tc4 = c4.getNext();\n\t\tif (!c1 || !c2 || !c3 || !c4)\n\t\t\treturn false;\n\n\t\tvar offsets = [];\n\n\t\tfunction addOffsets(curve, end) {\n\t\t\tvar v = curve.getValues(),\n\t\t\t\troots = Curve.classify(v).roots || Curve.getPeaks(v),\n\t\t\t\tcount = roots.length,\n\t\t\t\tt = end && count > 1 ? roots[count - 1]\n\t\t\t\t\t\t: count > 0 ? roots[0]\n\t\t\t\t\t\t: 0.5;\n\t\t\toffsets.push(Curve.getLength(v, end ? t : 0, end ? 1 : t) / 2);\n\t\t}\n\n\t\tfunction isInRange(angle, min, max) {\n\t\t\treturn min < max\n\t\t\t\t\t? angle > min && angle < max\n\t\t\t\t\t: angle > min || angle < max;\n\t\t}\n\n\t\tif (!t1Inside) {\n\t\t\taddOffsets(c1, true);\n\t\t\taddOffsets(c2, false);\n\t\t}\n\t\tif (!t2Inside) {\n\t\t\taddOffsets(c3, true);\n\t\t\taddOffsets(c4, false);\n\t\t}\n\t\tvar pt = this.getPoint(),\n\t\t\toffset = Math.min.apply(Math, offsets),\n\t\t\tv2 = t1Inside ? c2.getTangentAtTime(t1)\n\t\t\t\t\t: c2.getPointAt(offset).subtract(pt),\n\t\t\tv1 = t1Inside ? v2.negate()\n\t\t\t\t\t: c1.getPointAt(-offset).subtract(pt),\n\t\t\tv4 = t2Inside ? c4.getTangentAtTime(t2)\n\t\t\t\t\t: c4.getPointAt(offset).subtract(pt),\n\t\t\tv3 = t2Inside ? v4.negate()\n\t\t\t\t\t: c3.getPointAt(-offset).subtract(pt),\n\t\t\ta1 = v1.getAngle(),\n\t\t\ta2 = v2.getAngle(),\n\t\t\ta3 = v3.getAngle(),\n\t\t\ta4 = v4.getAngle();\n\t\treturn !!(t1Inside\n\t\t\t\t? (isInRange(a1, a3, a4) ^ isInRange(a2, a3, a4)) &&\n\t\t\t\t  (isInRange(a1, a4, a3) ^ isInRange(a2, a4, a3))\n\t\t\t\t: (isInRange(a3, a1, a2) ^ isInRange(a4, a1, a2)) &&\n\t\t\t\t  (isInRange(a3, a2, a1) ^ isInRange(a4, a2, a1)));\n\t},\n\n\thasOverlap: function() {\n\t\treturn !!this._overlap;\n\t}\n}, Base.each(Curve._evaluateMethods, function(name) {\n\tvar get = name + 'At';\n\tthis[name] = function() {\n\t\tvar curve = this.getCurve(),\n\t\t\ttime = this.getTime();\n\t\treturn time != null && curve && curve[get](time, true);\n\t};\n}, {\n\tpreserve: true\n}),\nnew function() {\n\n\tfunction insert(locations, loc, merge) {\n\t\tvar length = locations.length,\n\t\t\tl = 0,\n\t\t\tr = length - 1;\n\n\t\tfunction search(index, dir) {\n\t\t\tfor (var i = index + dir; i >= -1 && i <= length; i += dir) {\n\t\t\t\tvar loc2 = locations[((i % length) + length) % length];\n\t\t\t\tif (!loc.getPoint().isClose(loc2.getPoint(),\n\t\t\t\t\t\t1e-7))\n\t\t\t\t\tbreak;\n\t\t\t\tif (loc.equals(loc2))\n\t\t\t\t\treturn loc2;\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\twhile (l <= r) {\n\t\t\tvar m = (l + r) >>> 1,\n\t\t\t\tloc2 = locations[m],\n\t\t\t\tfound;\n\t\t\tif (merge && (found = loc.equals(loc2) ? loc2\n\t\t\t\t\t: (search(m, -1) || search(m, 1)))) {\n\t\t\t\tif (loc._overlap) {\n\t\t\t\t\tfound._overlap = found._intersection._overlap = true;\n\t\t\t\t}\n\t\t\t\treturn found;\n\t\t\t}\n\t\tvar path1 = loc.getPath(),\n\t\t\tpath2 = loc2.getPath(),\n\t\t\tdiff = path1 !== path2\n\t\t\t\t? path1._id - path2._id\n\t\t\t\t: (loc.getIndex() + loc.getTime())\n\t\t\t\t- (loc2.getIndex() + loc2.getTime());\n\t\t\tif (diff < 0) {\n\t\t\t\tr = m - 1;\n\t\t\t} else {\n\t\t\t\tl = m + 1;\n\t\t\t}\n\t\t}\n\t\tlocations.splice(l, 0, loc);\n\t\treturn loc;\n\t}\n\n\treturn { statics: {\n\t\tinsert: insert,\n\n\t\texpand: function(locations) {\n\t\t\tvar expanded = locations.slice();\n\t\t\tfor (var i = locations.length - 1; i >= 0; i--) {\n\t\t\t\tinsert(expanded, locations[i]._intersection, false);\n\t\t\t}\n\t\t\treturn expanded;\n\t\t}\n\t}};\n});\n\nvar PathItem = Item.extend({\n\t_class: 'PathItem',\n\t_selectBounds: false,\n\t_canScaleStroke: true,\n\tbeans: true,\n\n\tinitialize: function PathItem() {\n\t},\n\n\tstatics: {\n\t\tcreate: function(arg) {\n\t\t\tvar data,\n\t\t\t\tsegments,\n\t\t\t\tcompound;\n\t\t\tif (Base.isPlainObject(arg)) {\n\t\t\t\tsegments = arg.segments;\n\t\t\t\tdata = arg.pathData;\n\t\t\t} else if (Array.isArray(arg)) {\n\t\t\t\tsegments = arg;\n\t\t\t} else if (typeof arg === 'string') {\n\t\t\t\tdata = arg;\n\t\t\t}\n\t\t\tif (segments) {\n\t\t\t\tvar first = segments[0];\n\t\t\t\tcompound = first && Array.isArray(first[0]);\n\t\t\t} else if (data) {\n\t\t\t\tcompound = (data.match(/m/gi) || []).length > 1\n\t\t\t\t\t\t|| /z\\s*\\S+/i.test(data);\n\t\t\t}\n\t\t\tvar ctor = compound ? CompoundPath : Path;\n\t\t\treturn new ctor(arg);\n\t\t}\n\t},\n\n\t_asPathItem: function() {\n\t\treturn this;\n\t},\n\n\tisClockwise: function() {\n\t\treturn this.getArea() >= 0;\n\t},\n\n\tsetClockwise: function(clockwise) {\n\t\tif (this.isClockwise() != (clockwise = !!clockwise))\n\t\t\tthis.reverse();\n\t},\n\n\tsetPathData: function(data) {\n\n\t\tvar parts = data && data.match(/[mlhvcsqtaz][^mlhvcsqtaz]*/ig),\n\t\t\tcoords,\n\t\t\trelative = false,\n\t\t\tprevious,\n\t\t\tcontrol,\n\t\t\tcurrent = new Point(),\n\t\t\tstart = new Point();\n\n\t\tfunction getCoord(index, coord) {\n\t\t\tvar val = +coords[index];\n\t\t\tif (relative)\n\t\t\t\tval += current[coord];\n\t\t\treturn val;\n\t\t}\n\n\t\tfunction getPoint(index) {\n\t\t\treturn new Point(\n\t\t\t\tgetCoord(index, 'x'),\n\t\t\t\tgetCoord(index + 1, 'y')\n\t\t\t);\n\t\t}\n\n\t\tthis.clear();\n\n\t\tfor (var i = 0, l = parts && parts.length; i < l; i++) {\n\t\t\tvar part = parts[i],\n\t\t\t\tcommand = part[0],\n\t\t\t\tlower = command.toLowerCase();\n\t\t\tcoords = part.match(/[+-]?(?:\\d*\\.\\d+|\\d+\\.?)(?:[eE][+-]?\\d+)?/g);\n\t\t\tvar length = coords && coords.length;\n\t\t\trelative = command === lower;\n\t\t\tif (previous === 'z' && !/[mz]/.test(lower))\n\t\t\t\tthis.moveTo(current);\n\t\t\tswitch (lower) {\n\t\t\tcase 'm':\n\t\t\tcase 'l':\n\t\t\t\tvar move = lower === 'm';\n\t\t\t\tfor (var j = 0; j < length; j += 2) {\n\t\t\t\t\tthis[move ? 'moveTo' : 'lineTo'](current = getPoint(j));\n\t\t\t\t\tif (move) {\n\t\t\t\t\t\tstart = current;\n\t\t\t\t\t\tmove = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontrol = current;\n\t\t\t\tbreak;\n\t\t\tcase 'h':\n\t\t\tcase 'v':\n\t\t\t\tvar coord = lower === 'h' ? 'x' : 'y';\n\t\t\t\tcurrent = current.clone();\n\t\t\t\tfor (var j = 0; j < length; j++) {\n\t\t\t\t\tcurrent[coord] = getCoord(j, coord);\n\t\t\t\t\tthis.lineTo(current);\n\t\t\t\t}\n\t\t\t\tcontrol = current;\n\t\t\t\tbreak;\n\t\t\tcase 'c':\n\t\t\t\tfor (var j = 0; j < length; j += 6) {\n\t\t\t\t\tthis.cubicCurveTo(\n\t\t\t\t\t\t\tgetPoint(j),\n\t\t\t\t\t\t\tcontrol = getPoint(j + 2),\n\t\t\t\t\t\t\tcurrent = getPoint(j + 4));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 's':\n\t\t\t\tfor (var j = 0; j < length; j += 4) {\n\t\t\t\t\tthis.cubicCurveTo(\n\t\t\t\t\t\t\t/[cs]/.test(previous)\n\t\t\t\t\t\t\t\t\t? current.multiply(2).subtract(control)\n\t\t\t\t\t\t\t\t\t: current,\n\t\t\t\t\t\t\tcontrol = getPoint(j),\n\t\t\t\t\t\t\tcurrent = getPoint(j + 2));\n\t\t\t\t\tprevious = lower;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'q':\n\t\t\t\tfor (var j = 0; j < length; j += 4) {\n\t\t\t\t\tthis.quadraticCurveTo(\n\t\t\t\t\t\t\tcontrol = getPoint(j),\n\t\t\t\t\t\t\tcurrent = getPoint(j + 2));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 't':\n\t\t\t\tfor (var j = 0; j < length; j += 2) {\n\t\t\t\t\tthis.quadraticCurveTo(\n\t\t\t\t\t\t\tcontrol = (/[qt]/.test(previous)\n\t\t\t\t\t\t\t\t\t? current.multiply(2).subtract(control)\n\t\t\t\t\t\t\t\t\t: current),\n\t\t\t\t\t\t\tcurrent = getPoint(j));\n\t\t\t\t\tprevious = lower;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'a':\n\t\t\t\tfor (var j = 0; j < length; j += 7) {\n\t\t\t\t\tthis.arcTo(current = getPoint(j + 5),\n\t\t\t\t\t\t\tnew Size(+coords[j], +coords[j + 1]),\n\t\t\t\t\t\t\t+coords[j + 2], +coords[j + 4], +coords[j + 3]);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'z':\n\t\t\t\tthis.closePath(1e-12);\n\t\t\t\tcurrent = start;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tprevious = lower;\n\t\t}\n\t},\n\n\t_canComposite: function() {\n\t\treturn !(this.hasFill() && this.hasStroke());\n\t},\n\n\t_contains: function(point) {\n\t\tvar winding = point.isInside(\n\t\t\t\tthis.getBounds({ internal: true, handle: true }))\n\t\t\t\t\t? this._getWinding(point)\n\t\t\t\t\t: {};\n\t\treturn winding.onPath || !!(this.getFillRule() === 'evenodd'\n\t\t\t\t? winding.windingL & 1 || winding.windingR & 1\n\t\t\t\t: winding.winding);\n\t},\n\n\tgetIntersections: function(path, include, _matrix, _returnFirst) {\n\t\tvar self = this === path || !path,\n\t\t\tmatrix1 = this._matrix._orNullIfIdentity(),\n\t\t\tmatrix2 = self ? matrix1\n\t\t\t\t: (_matrix || path._matrix)._orNullIfIdentity();\n\t\treturn self || this.getBounds(matrix1).intersects(\n\t\t\t\tpath.getBounds(matrix2), 1e-12)\n\t\t\t\t? Curve.getIntersections(\n\t\t\t\t\t\tthis.getCurves(), !self && path.getCurves(), include,\n\t\t\t\t\t\tmatrix1, matrix2, _returnFirst)\n\t\t\t\t: [];\n\t},\n\n\tgetCrossings: function(path) {\n\t\treturn this.getIntersections(path, function(inter) {\n\t\t\treturn inter.hasOverlap() || inter.isCrossing();\n\t\t});\n\t},\n\n\tgetNearestLocation: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\tcurves = this.getCurves(),\n\t\t\tminDist = Infinity,\n\t\t\tminLoc = null;\n\t\tfor (var i = 0, l = curves.length; i < l; i++) {\n\t\t\tvar loc = curves[i].getNearestLocation(point);\n\t\t\tif (loc._distance < minDist) {\n\t\t\t\tminDist = loc._distance;\n\t\t\t\tminLoc = loc;\n\t\t\t}\n\t\t}\n\t\treturn minLoc;\n\t},\n\n\tgetNearestPoint: function() {\n\t\tvar loc = this.getNearestLocation.apply(this, arguments);\n\t\treturn loc ? loc.getPoint() : loc;\n\t},\n\n\tinterpolate: function(from, to, factor) {\n\t\tvar isPath = !this._children,\n\t\t\tname = isPath ? '_segments' : '_children',\n\t\t\titemsFrom = from[name],\n\t\t\titemsTo = to[name],\n\t\t\titems = this[name];\n\t\tif (!itemsFrom || !itemsTo || itemsFrom.length !== itemsTo.length) {\n\t\t\tthrow new Error('Invalid operands in interpolate() call: ' +\n\t\t\t\t\tfrom + ', ' + to);\n\t\t}\n\t\tvar current = items.length,\n\t\t\tlength = itemsTo.length;\n\t\tif (current < length) {\n\t\t\tvar ctor = isPath ? Segment : Path;\n\t\t\tfor (var i = current; i < length; i++) {\n\t\t\t\tthis.add(new ctor());\n\t\t\t}\n\t\t} else if (current > length) {\n\t\t\tthis[isPath ? 'removeSegments' : 'removeChildren'](length, current);\n\t\t}\n\t\tfor (var i = 0; i < length; i++) {\n\t\t\titems[i].interpolate(itemsFrom[i], itemsTo[i], factor);\n\t\t}\n\t\tif (isPath) {\n\t\t\tthis.setClosed(from._closed);\n\t\t\tthis._changed(9);\n\t\t}\n\t},\n\n\tcompare: function(path) {\n\t\tvar ok = false;\n\t\tif (path) {\n\t\t\tvar paths1 = this._children || [this],\n\t\t\t\tpaths2 = path._children ? path._children.slice() : [path],\n\t\t\t\tlength1 = paths1.length,\n\t\t\t\tlength2 = paths2.length,\n\t\t\t\tmatched = [],\n\t\t\t\tcount = 0;\n\t\t\tok = true;\n\t\t\tfor (var i1 = length1 - 1; i1 >= 0 && ok; i1--) {\n\t\t\t\tvar path1 = paths1[i1];\n\t\t\t\tok = false;\n\t\t\t\tfor (var i2 = length2 - 1; i2 >= 0 && !ok; i2--) {\n\t\t\t\t\tif (path1.compare(paths2[i2])) {\n\t\t\t\t\t\tif (!matched[i2]) {\n\t\t\t\t\t\t\tmatched[i2] = true;\n\t\t\t\t\t\t\tcount++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tok = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tok = ok && count === length2;\n\t\t}\n\t\treturn ok;\n\t},\n\n});\n\nvar Path = PathItem.extend({\n\t_class: 'Path',\n\t_serializeFields: {\n\t\tsegments: [],\n\t\tclosed: false\n\t},\n\n\tinitialize: function Path(arg) {\n\t\tthis._closed = false;\n\t\tthis._segments = [];\n\t\tthis._version = 0;\n\t\tvar segments = Array.isArray(arg)\n\t\t\t? typeof arg[0] === 'object'\n\t\t\t\t? arg\n\t\t\t\t: arguments\n\t\t\t: arg && (arg.size === undefined && (arg.x !== undefined\n\t\t\t\t\t|| arg.point !== undefined))\n\t\t\t\t? arguments\n\t\t\t\t: null;\n\t\tif (segments && segments.length > 0) {\n\t\t\tthis.setSegments(segments);\n\t\t} else {\n\t\t\tthis._curves = undefined;\n\t\t\tthis._segmentSelection = 0;\n\t\t\tif (!segments && typeof arg === 'string') {\n\t\t\t\tthis.setPathData(arg);\n\t\t\t\targ = null;\n\t\t\t}\n\t\t}\n\t\tthis._initialize(!segments && arg);\n\t},\n\n\t_equals: function(item) {\n\t\treturn this._closed === item._closed\n\t\t\t\t&& Base.equals(this._segments, item._segments);\n\t},\n\n\tcopyContent: function(source) {\n\t\tthis.setSegments(source._segments);\n\t\tthis._closed = source._closed;\n\t},\n\n\t_changed: function _changed(flags) {\n\t\t_changed.base.call(this, flags);\n\t\tif (flags & 8) {\n\t\t\tthis._length = this._area = undefined;\n\t\t\tif (flags & 16) {\n\t\t\t\tthis._version++;\n\t\t\t} else if (this._curves) {\n\t\t\t   for (var i = 0, l = this._curves.length; i < l; i++)\n\t\t\t\t\tthis._curves[i]._changed();\n\t\t\t}\n\t\t} else if (flags & 32) {\n\t\t\tthis._bounds = undefined;\n\t\t}\n\t},\n\n\tgetStyle: function() {\n\t\tvar parent = this._parent;\n\t\treturn (parent instanceof CompoundPath ? parent : this)._style;\n\t},\n\n\tgetSegments: function() {\n\t\treturn this._segments;\n\t},\n\n\tsetSegments: function(segments) {\n\t\tvar fullySelected = this.isFullySelected(),\n\t\t\tlength = segments && segments.length;\n\t\tthis._segments.length = 0;\n\t\tthis._segmentSelection = 0;\n\t\tthis._curves = undefined;\n\t\tif (length) {\n\t\t\tvar last = segments[length - 1];\n\t\t\tif (typeof last === 'boolean') {\n\t\t\t\tthis.setClosed(last);\n\t\t\t\tlength--;\n\t\t\t}\n\t\t\tthis._add(Segment.readList(segments, 0, {}, length));\n\t\t}\n\t\tif (fullySelected)\n\t\t\tthis.setFullySelected(true);\n\t},\n\n\tgetFirstSegment: function() {\n\t\treturn this._segments[0];\n\t},\n\n\tgetLastSegment: function() {\n\t\treturn this._segments[this._segments.length - 1];\n\t},\n\n\tgetCurves: function() {\n\t\tvar curves = this._curves,\n\t\t\tsegments = this._segments;\n\t\tif (!curves) {\n\t\t\tvar length = this._countCurves();\n\t\t\tcurves = this._curves = new Array(length);\n\t\t\tfor (var i = 0; i < length; i++)\n\t\t\t\tcurves[i] = new Curve(this, segments[i],\n\t\t\t\t\tsegments[i + 1] || segments[0]);\n\t\t}\n\t\treturn curves;\n\t},\n\n\tgetFirstCurve: function() {\n\t\treturn this.getCurves()[0];\n\t},\n\n\tgetLastCurve: function() {\n\t\tvar curves = this.getCurves();\n\t\treturn curves[curves.length - 1];\n\t},\n\n\tisClosed: function() {\n\t\treturn this._closed;\n\t},\n\n\tsetClosed: function(closed) {\n\t\tif (this._closed != (closed = !!closed)) {\n\t\t\tthis._closed = closed;\n\t\t\tif (this._curves) {\n\t\t\t\tvar length = this._curves.length = this._countCurves();\n\t\t\t\tif (closed)\n\t\t\t\t\tthis._curves[length - 1] = new Curve(this,\n\t\t\t\t\t\tthis._segments[length - 1], this._segments[0]);\n\t\t\t}\n\t\t\tthis._changed(25);\n\t\t}\n\t}\n}, {\n\tbeans: true,\n\n\tgetPathData: function(_matrix, _precision) {\n\t\tvar segments = this._segments,\n\t\t\tlength = segments.length,\n\t\t\tf = new Formatter(_precision),\n\t\t\tcoords = new Array(6),\n\t\t\tfirst = true,\n\t\t\tcurX, curY,\n\t\t\tprevX, prevY,\n\t\t\tinX, inY,\n\t\t\toutX, outY,\n\t\t\tparts = [];\n\n\t\tfunction addSegment(segment, skipLine) {\n\t\t\tsegment._transformCoordinates(_matrix, coords);\n\t\t\tcurX = coords[0];\n\t\t\tcurY = coords[1];\n\t\t\tif (first) {\n\t\t\t\tparts.push('M' + f.pair(curX, curY));\n\t\t\t\tfirst = false;\n\t\t\t} else {\n\t\t\t\tinX = coords[2];\n\t\t\t\tinY = coords[3];\n\t\t\t\tif (inX === curX && inY === curY\n\t\t\t\t\t\t&& outX === prevX && outY === prevY) {\n\t\t\t\t\tif (!skipLine) {\n\t\t\t\t\t\tvar dx = curX - prevX,\n\t\t\t\t\t\t\tdy = curY - prevY;\n\t\t\t\t\t\tparts.push(\n\t\t\t\t\t\t\t  dx === 0 ? 'v' + f.number(dy)\n\t\t\t\t\t\t\t: dy === 0 ? 'h' + f.number(dx)\n\t\t\t\t\t\t\t: 'l' + f.pair(dx, dy));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tparts.push('c' + f.pair(outX - prevX, outY - prevY)\n\t\t\t\t\t\t\t + ' ' + f.pair( inX - prevX,  inY - prevY)\n\t\t\t\t\t\t\t + ' ' + f.pair(curX - prevX, curY - prevY));\n\t\t\t\t}\n\t\t\t}\n\t\t\tprevX = curX;\n\t\t\tprevY = curY;\n\t\t\toutX = coords[4];\n\t\t\toutY = coords[5];\n\t\t}\n\n\t\tif (!length)\n\t\t\treturn '';\n\n\t\tfor (var i = 0; i < length; i++)\n\t\t\taddSegment(segments[i]);\n\t\tif (this._closed && length > 0) {\n\t\t\taddSegment(segments[0], true);\n\t\t\tparts.push('z');\n\t\t}\n\t\treturn parts.join('');\n\t},\n\n\tisEmpty: function() {\n\t\treturn !this._segments.length;\n\t},\n\n\t_transformContent: function(matrix) {\n\t\tvar segments = this._segments,\n\t\t\tcoords = new Array(6);\n\t\tfor (var i = 0, l = segments.length; i < l; i++)\n\t\t\tsegments[i]._transformCoordinates(matrix, coords, true);\n\t\treturn true;\n\t},\n\n\t_add: function(segs, index) {\n\t\tvar segments = this._segments,\n\t\t\tcurves = this._curves,\n\t\t\tamount = segs.length,\n\t\t\tappend = index == null,\n\t\t\tindex = append ? segments.length : index;\n\t\tfor (var i = 0; i < amount; i++) {\n\t\t\tvar segment = segs[i];\n\t\t\tif (segment._path)\n\t\t\t\tsegment = segs[i] = segment.clone();\n\t\t\tsegment._path = this;\n\t\t\tsegment._index = index + i;\n\t\t\tif (segment._selection)\n\t\t\t\tthis._updateSelection(segment, 0, segment._selection);\n\t\t}\n\t\tif (append) {\n\t\t\tsegments.push.apply(segments, segs);\n\t\t} else {\n\t\t\tsegments.splice.apply(segments, [index, 0].concat(segs));\n\t\t\tfor (var i = index + amount, l = segments.length; i < l; i++)\n\t\t\t\tsegments[i]._index = i;\n\t\t}\n\t\tif (curves) {\n\t\t\tvar total = this._countCurves(),\n\t\t\t\tstart = index > 0 && index + amount - 1 === total ? index - 1\n\t\t\t\t\t: index,\n\t\t\t\tinsert = start,\n\t\t\t\tend = Math.min(start + amount, total);\n\t\t\tif (segs._curves) {\n\t\t\t\tcurves.splice.apply(curves, [start, 0].concat(segs._curves));\n\t\t\t\tinsert += segs._curves.length;\n\t\t\t}\n\t\t\tfor (var i = insert; i < end; i++)\n\t\t\t\tcurves.splice(i, 0, new Curve(this, null, null));\n\t\t\tthis._adjustCurves(start, end);\n\t\t}\n\t\tthis._changed(25);\n\t\treturn segs;\n\t},\n\n\t_adjustCurves: function(start, end) {\n\t\tvar segments = this._segments,\n\t\t\tcurves = this._curves,\n\t\t\tcurve;\n\t\tfor (var i = start; i < end; i++) {\n\t\t\tcurve = curves[i];\n\t\t\tcurve._path = this;\n\t\t\tcurve._segment1 = segments[i];\n\t\t\tcurve._segment2 = segments[i + 1] || segments[0];\n\t\t\tcurve._changed();\n\t\t}\n\t\tif (curve = curves[this._closed && !start ? segments.length - 1\n\t\t\t\t: start - 1]) {\n\t\t\tcurve._segment2 = segments[start] || segments[0];\n\t\t\tcurve._changed();\n\t\t}\n\t\tif (curve = curves[end]) {\n\t\t\tcurve._segment1 = segments[end];\n\t\t\tcurve._changed();\n\t\t}\n\t},\n\n\t_countCurves: function() {\n\t\tvar length = this._segments.length;\n\t\treturn !this._closed && length > 0 ? length - 1 : length;\n\t},\n\n\tadd: function(segment1 ) {\n\t\treturn arguments.length > 1 && typeof segment1 !== 'number'\n\t\t\t? this._add(Segment.readList(arguments))\n\t\t\t: this._add([ Segment.read(arguments) ])[0];\n\t},\n\n\tinsert: function(index, segment1 ) {\n\t\treturn arguments.length > 2 && typeof segment1 !== 'number'\n\t\t\t? this._add(Segment.readList(arguments, 1), index)\n\t\t\t: this._add([ Segment.read(arguments, 1) ], index)[0];\n\t},\n\n\taddSegment: function() {\n\t\treturn this._add([ Segment.read(arguments) ])[0];\n\t},\n\n\tinsertSegment: function(index ) {\n\t\treturn this._add([ Segment.read(arguments, 1) ], index)[0];\n\t},\n\n\taddSegments: function(segments) {\n\t\treturn this._add(Segment.readList(segments));\n\t},\n\n\tinsertSegments: function(index, segments) {\n\t\treturn this._add(Segment.readList(segments), index);\n\t},\n\n\tremoveSegment: function(index) {\n\t\treturn this.removeSegments(index, index + 1)[0] || null;\n\t},\n\n\tremoveSegments: function(start, end, _includeCurves) {\n\t\tstart = start || 0;\n\t\tend = Base.pick(end, this._segments.length);\n\t\tvar segments = this._segments,\n\t\t\tcurves = this._curves,\n\t\t\tcount = segments.length,\n\t\t\tremoved = segments.splice(start, end - start),\n\t\t\tamount = removed.length;\n\t\tif (!amount)\n\t\t\treturn removed;\n\t\tfor (var i = 0; i < amount; i++) {\n\t\t\tvar segment = removed[i];\n\t\t\tif (segment._selection)\n\t\t\t\tthis._updateSelection(segment, segment._selection, 0);\n\t\t\tsegment._index = segment._path = null;\n\t\t}\n\t\tfor (var i = start, l = segments.length; i < l; i++)\n\t\t\tsegments[i]._index = i;\n\t\tif (curves) {\n\t\t\tvar index = start > 0 && end === count + (this._closed ? 1 : 0)\n\t\t\t\t\t? start - 1\n\t\t\t\t\t: start,\n\t\t\t\tcurves = curves.splice(index, amount);\n\t\t\tfor (var i = curves.length - 1; i >= 0; i--)\n\t\t\t\tcurves[i]._path = null;\n\t\t\tif (_includeCurves)\n\t\t\t\tremoved._curves = curves.slice(1);\n\t\t\tthis._adjustCurves(index, index);\n\t\t}\n\t\tthis._changed(25);\n\t\treturn removed;\n\t},\n\n\tclear: '#removeSegments',\n\n\thasHandles: function() {\n\t\tvar segments = this._segments;\n\t\tfor (var i = 0, l = segments.length; i < l; i++) {\n\t\t\tif (segments[i].hasHandles())\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t},\n\n\tclearHandles: function() {\n\t\tvar segments = this._segments;\n\t\tfor (var i = 0, l = segments.length; i < l; i++)\n\t\t\tsegments[i].clearHandles();\n\t},\n\n\tgetLength: function() {\n\t\tif (this._length == null) {\n\t\t\tvar curves = this.getCurves(),\n\t\t\t\tlength = 0;\n\t\t\tfor (var i = 0, l = curves.length; i < l; i++)\n\t\t\t\tlength += curves[i].getLength();\n\t\t\tthis._length = length;\n\t\t}\n\t\treturn this._length;\n\t},\n\n\tgetArea: function() {\n\t\tvar area = this._area;\n\t\tif (area == null) {\n\t\t\tvar segments = this._segments,\n\t\t\t\tclosed = this._closed;\n\t\t\tarea = 0;\n\t\t\tfor (var i = 0, l = segments.length; i < l; i++) {\n\t\t\t\tvar last = i + 1 === l;\n\t\t\t\tarea += Curve.getArea(Curve.getValues(\n\t\t\t\t\t\tsegments[i], segments[last ? 0 : i + 1],\n\t\t\t\t\t\tnull, last && !closed));\n\t\t\t}\n\t\t\tthis._area = area;\n\t\t}\n\t\treturn area;\n\t},\n\n\tisFullySelected: function() {\n\t\tvar length = this._segments.length;\n\t\treturn this.isSelected() && length > 0 && this._segmentSelection\n\t\t\t\t=== length * 7;\n\t},\n\n\tsetFullySelected: function(selected) {\n\t\tif (selected)\n\t\t\tthis._selectSegments(true);\n\t\tthis.setSelected(selected);\n\t},\n\n\tsetSelection: function setSelection(selection) {\n\t\tif (!(selection & 1))\n\t\t\tthis._selectSegments(false);\n\t\tsetSelection.base.call(this, selection);\n\t},\n\n\t_selectSegments: function(selected) {\n\t\tvar segments = this._segments,\n\t\t\tlength = segments.length,\n\t\t\tselection = selected ? 7 : 0;\n\t\tthis._segmentSelection = selection * length;\n\t\tfor (var i = 0; i < length; i++)\n\t\t\tsegments[i]._selection = selection;\n\t},\n\n\t_updateSelection: function(segment, oldSelection, newSelection) {\n\t\tsegment._selection = newSelection;\n\t\tvar selection = this._segmentSelection += newSelection - oldSelection;\n\t\tif (selection > 0)\n\t\t\tthis.setSelected(true);\n\t},\n\n\tdivideAt: function(location) {\n\t\tvar loc = this.getLocationAt(location),\n\t\t\tcurve;\n\t\treturn loc && (curve = loc.getCurve().divideAt(loc.getCurveOffset()))\n\t\t\t\t? curve._segment1\n\t\t\t\t: null;\n\t},\n\n\tsplitAt: function(location) {\n\t\tvar loc = this.getLocationAt(location),\n\t\t\tindex = loc && loc.index,\n\t\t\ttime = loc && loc.time,\n\t\t\ttMin = 1e-8,\n\t\t\ttMax = 1 - tMin;\n\t\tif (time > tMax) {\n\t\t\tindex++;\n\t\t\ttime = 0;\n\t\t}\n\t\tvar curves = this.getCurves();\n\t\tif (index >= 0 && index < curves.length) {\n\t\t\tif (time >= tMin) {\n\t\t\t\tcurves[index++].divideAtTime(time);\n\t\t\t}\n\t\t\tvar segs = this.removeSegments(index, this._segments.length, true),\n\t\t\t\tpath;\n\t\t\tif (this._closed) {\n\t\t\t\tthis.setClosed(false);\n\t\t\t\tpath = this;\n\t\t\t} else {\n\t\t\t\tpath = new Path(Item.NO_INSERT);\n\t\t\t\tpath.insertAbove(this);\n\t\t\t\tpath.copyAttributes(this);\n\t\t\t}\n\t\t\tpath._add(segs, 0);\n\t\t\tthis.addSegment(segs[0]);\n\t\t\treturn path;\n\t\t}\n\t\treturn null;\n\t},\n\n\tsplit: function(index, time) {\n\t\tvar curve,\n\t\t\tlocation = time === undefined ? index\n\t\t\t\t: (curve = this.getCurves()[index])\n\t\t\t\t\t&& curve.getLocationAtTime(time);\n\t\treturn location != null ? this.splitAt(location) : null;\n\t},\n\n\tjoin: function(path, tolerance) {\n\t\tvar epsilon = tolerance || 0;\n\t\tif (path && path !== this) {\n\t\t\tvar segments = path._segments,\n\t\t\t\tlast1 = this.getLastSegment(),\n\t\t\t\tlast2 = path.getLastSegment();\n\t\t\tif (!last2)\n\t\t\t\treturn this;\n\t\t\tif (last1 && last1._point.isClose(last2._point, epsilon))\n\t\t\t\tpath.reverse();\n\t\t\tvar first2 = path.getFirstSegment();\n\t\t\tif (last1 && last1._point.isClose(first2._point, epsilon)) {\n\t\t\t\tlast1.setHandleOut(first2._handleOut);\n\t\t\t\tthis._add(segments.slice(1));\n\t\t\t} else {\n\t\t\t\tvar first1 = this.getFirstSegment();\n\t\t\t\tif (first1 && first1._point.isClose(first2._point, epsilon))\n\t\t\t\t\tpath.reverse();\n\t\t\t\tlast2 = path.getLastSegment();\n\t\t\t\tif (first1 && first1._point.isClose(last2._point, epsilon)) {\n\t\t\t\t\tfirst1.setHandleIn(last2._handleIn);\n\t\t\t\t\tthis._add(segments.slice(0, segments.length - 1), 0);\n\t\t\t\t} else {\n\t\t\t\t\tthis._add(segments.slice());\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (path._closed)\n\t\t\t\tthis._add([segments[0]]);\n\t\t\tpath.remove();\n\t\t}\n\t\tvar first = this.getFirstSegment(),\n\t\t\tlast = this.getLastSegment();\n\t\tif (first !== last && first._point.isClose(last._point, epsilon)) {\n\t\t\tfirst.setHandleIn(last._handleIn);\n\t\t\tlast.remove();\n\t\t\tthis.setClosed(true);\n\t\t}\n\t\treturn this;\n\t},\n\n\treduce: function(options) {\n\t\tvar curves = this.getCurves(),\n\t\t\tsimplify = options && options.simplify,\n\t\t\ttolerance = simplify ? 1e-7 : 0;\n\t\tfor (var i = curves.length - 1; i >= 0; i--) {\n\t\t\tvar curve = curves[i];\n\t\t\tif (!curve.hasHandles() && (!curve.hasLength(tolerance)\n\t\t\t\t\t|| simplify && curve.isCollinear(curve.getNext())))\n\t\t\t\tcurve.remove();\n\t\t}\n\t\treturn this;\n\t},\n\n\treverse: function() {\n\t\tthis._segments.reverse();\n\t\tfor (var i = 0, l = this._segments.length; i < l; i++) {\n\t\t\tvar segment = this._segments[i];\n\t\t\tvar handleIn = segment._handleIn;\n\t\t\tsegment._handleIn = segment._handleOut;\n\t\t\tsegment._handleOut = handleIn;\n\t\t\tsegment._index = i;\n\t\t}\n\t\tthis._curves = null;\n\t\tthis._changed(9);\n\t},\n\n\tflatten: function(flatness) {\n\t\tvar flattener = new PathFlattener(this, flatness || 0.25, 256, true),\n\t\t\tparts = flattener.parts,\n\t\t\tlength = parts.length,\n\t\t\tsegments = [];\n\t\tfor (var i = 0; i < length; i++) {\n\t\t\tsegments.push(new Segment(parts[i].curve.slice(0, 2)));\n\t\t}\n\t\tif (!this._closed && length > 0) {\n\t\t\tsegments.push(new Segment(parts[length - 1].curve.slice(6)));\n\t\t}\n\t\tthis.setSegments(segments);\n\t},\n\n\tsimplify: function(tolerance) {\n\t\tvar segments = new PathFitter(this).fit(tolerance || 2.5);\n\t\tif (segments)\n\t\t\tthis.setSegments(segments);\n\t\treturn !!segments;\n\t},\n\n\tsmooth: function(options) {\n\t\tvar that = this,\n\t\t\topts = options || {},\n\t\t\ttype = opts.type || 'asymmetric',\n\t\t\tsegments = this._segments,\n\t\t\tlength = segments.length,\n\t\t\tclosed = this._closed;\n\n\t\tfunction getIndex(value, _default) {\n\t\t\tvar index = value && value.index;\n\t\t\tif (index != null) {\n\t\t\t\tvar path = value.path;\n\t\t\t\tif (path && path !== that)\n\t\t\t\t\tthrow new Error(value._class + ' ' + index + ' of ' + path\n\t\t\t\t\t\t\t+ ' is not part of ' + that);\n\t\t\t\tif (_default && value instanceof Curve)\n\t\t\t\t\tindex++;\n\t\t\t} else {\n\t\t\t\tindex = typeof value === 'number' ? value : _default;\n\t\t\t}\n\t\t\treturn Math.min(index < 0 && closed\n\t\t\t\t\t? index % length\n\t\t\t\t\t: index < 0 ? index + length : index, length - 1);\n\t\t}\n\n\t\tvar loop = closed && opts.from === undefined && opts.to === undefined,\n\t\t\tfrom = getIndex(opts.from, 0),\n\t\t\tto = getIndex(opts.to, length - 1);\n\n\t\tif (from > to) {\n\t\t\tif (closed) {\n\t\t\t\tfrom -= length;\n\t\t\t} else {\n\t\t\t\tvar tmp = from;\n\t\t\t\tfrom = to;\n\t\t\t\tto = tmp;\n\t\t\t}\n\t\t}\n\t\tif (/^(?:asymmetric|continuous)$/.test(type)) {\n\t\t\tvar asymmetric = type === 'asymmetric',\n\t\t\t\tmin = Math.min,\n\t\t\t\tamount = to - from + 1,\n\t\t\t\tn = amount - 1,\n\t\t\t\tpadding = loop ? min(amount, 4) : 1,\n\t\t\t\tpaddingLeft = padding,\n\t\t\t\tpaddingRight = padding,\n\t\t\t\tknots = [];\n\t\t\tif (!closed) {\n\t\t\t\tpaddingLeft = min(1, from);\n\t\t\t\tpaddingRight = min(1, length - to - 1);\n\t\t\t}\n\t\t\tn += paddingLeft + paddingRight;\n\t\t\tif (n <= 1)\n\t\t\t\treturn;\n\t\t\tfor (var i = 0, j = from - paddingLeft; i <= n; i++, j++) {\n\t\t\t\tknots[i] = segments[(j < 0 ? j + length : j) % length]._point;\n\t\t\t}\n\n\t\t\tvar x = knots[0]._x + 2 * knots[1]._x,\n\t\t\t\ty = knots[0]._y + 2 * knots[1]._y,\n\t\t\t\tf = 2,\n\t\t\t\tn_1 = n - 1,\n\t\t\t\trx = [x],\n\t\t\t\try = [y],\n\t\t\t\trf = [f],\n\t\t\t\tpx = [],\n\t\t\t\tpy = [];\n\t\t\tfor (var i = 1; i < n; i++) {\n\t\t\t\tvar internal = i < n_1,\n\t\t\t\t\ta = internal ? 1 : asymmetric ? 1 : 2,\n\t\t\t\t\tb = internal ? 4 : asymmetric ? 2 : 7,\n\t\t\t\t\tu = internal ? 4 : asymmetric ? 3 : 8,\n\t\t\t\t\tv = internal ? 2 : asymmetric ? 0 : 1,\n\t\t\t\t\tm = a / f;\n\t\t\t\tf = rf[i] = b - m;\n\t\t\t\tx = rx[i] = u * knots[i]._x + v * knots[i + 1]._x - m * x;\n\t\t\t\ty = ry[i] = u * knots[i]._y + v * knots[i + 1]._y - m * y;\n\t\t\t}\n\n\t\t\tpx[n_1] = rx[n_1] / rf[n_1];\n\t\t\tpy[n_1] = ry[n_1] / rf[n_1];\n\t\t\tfor (var i = n - 2; i >= 0; i--) {\n\t\t\t\tpx[i] = (rx[i] - px[i + 1]) / rf[i];\n\t\t\t\tpy[i] = (ry[i] - py[i + 1]) / rf[i];\n\t\t\t}\n\t\t\tpx[n] = (3 * knots[n]._x - px[n_1]) / 2;\n\t\t\tpy[n] = (3 * knots[n]._y - py[n_1]) / 2;\n\n\t\t\tfor (var i = paddingLeft, max = n - paddingRight, j = from;\n\t\t\t\t\ti <= max; i++, j++) {\n\t\t\t\tvar segment = segments[j < 0 ? j + length : j],\n\t\t\t\t\tpt = segment._point,\n\t\t\t\t\thx = px[i] - pt._x,\n\t\t\t\t\thy = py[i] - pt._y;\n\t\t\t\tif (loop || i < max)\n\t\t\t\t\tsegment.setHandleOut(hx, hy);\n\t\t\t\tif (loop || i > paddingLeft)\n\t\t\t\t\tsegment.setHandleIn(-hx, -hy);\n\t\t\t}\n\t\t} else {\n\t\t\tfor (var i = from; i <= to; i++) {\n\t\t\t\tsegments[i < 0 ? i + length : i].smooth(opts,\n\t\t\t\t\t\t!loop && i === from, !loop && i === to);\n\t\t\t}\n\t\t}\n\t},\n\n\ttoShape: function(insert) {\n\t\tif (!this._closed)\n\t\t\treturn null;\n\n\t\tvar segments = this._segments,\n\t\t\ttype,\n\t\t\tsize,\n\t\t\tradius,\n\t\t\ttopCenter;\n\n\t\tfunction isCollinear(i, j) {\n\t\t\tvar seg1 = segments[i],\n\t\t\t\tseg2 = seg1.getNext(),\n\t\t\t\tseg3 = segments[j],\n\t\t\t\tseg4 = seg3.getNext();\n\t\t\treturn seg1._handleOut.isZero() && seg2._handleIn.isZero()\n\t\t\t\t\t&& seg3._handleOut.isZero() && seg4._handleIn.isZero()\n\t\t\t\t\t&& seg2._point.subtract(seg1._point).isCollinear(\n\t\t\t\t\t\tseg4._point.subtract(seg3._point));\n\t\t}\n\n\t\tfunction isOrthogonal(i) {\n\t\t\tvar seg2 = segments[i],\n\t\t\t\tseg1 = seg2.getPrevious(),\n\t\t\t\tseg3 = seg2.getNext();\n\t\t\treturn seg1._handleOut.isZero() && seg2._handleIn.isZero()\n\t\t\t\t\t&& seg2._handleOut.isZero() && seg3._handleIn.isZero()\n\t\t\t\t\t&& seg2._point.subtract(seg1._point).isOrthogonal(\n\t\t\t\t\t\tseg3._point.subtract(seg2._point));\n\t\t}\n\n\t\tfunction isArc(i) {\n\t\t\tvar seg1 = segments[i],\n\t\t\t\tseg2 = seg1.getNext(),\n\t\t\t\thandle1 = seg1._handleOut,\n\t\t\t\thandle2 = seg2._handleIn,\n\t\t\t\tkappa = 0.5522847498307936;\n\t\t\tif (handle1.isOrthogonal(handle2)) {\n\t\t\t\tvar pt1 = seg1._point,\n\t\t\t\t\tpt2 = seg2._point,\n\t\t\t\t\tcorner = new Line(pt1, handle1, true).intersect(\n\t\t\t\t\t\t\tnew Line(pt2, handle2, true), true);\n\t\t\t\treturn corner && Numerical.isZero(handle1.getLength() /\n\t\t\t\t\t\tcorner.subtract(pt1).getLength() - kappa)\n\t\t\t\t\t&& Numerical.isZero(handle2.getLength() /\n\t\t\t\t\t\tcorner.subtract(pt2).getLength() - kappa);\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\tfunction getDistance(i, j) {\n\t\t\treturn segments[i]._point.getDistance(segments[j]._point);\n\t\t}\n\n\t\tif (!this.hasHandles() && segments.length === 4\n\t\t\t\t&& isCollinear(0, 2) && isCollinear(1, 3) && isOrthogonal(1)) {\n\t\t\ttype = Shape.Rectangle;\n\t\t\tsize = new Size(getDistance(0, 3), getDistance(0, 1));\n\t\t\ttopCenter = segments[1]._point.add(segments[2]._point).divide(2);\n\t\t} else if (segments.length === 8 && isArc(0) && isArc(2) && isArc(4)\n\t\t\t\t&& isArc(6) && isCollinear(1, 5) && isCollinear(3, 7)) {\n\t\t\ttype = Shape.Rectangle;\n\t\t\tsize = new Size(getDistance(1, 6), getDistance(0, 3));\n\t\t\tradius = size.subtract(new Size(getDistance(0, 7),\n\t\t\t\t\tgetDistance(1, 2))).divide(2);\n\t\t\ttopCenter = segments[3]._point.add(segments[4]._point).divide(2);\n\t\t} else if (segments.length === 4\n\t\t\t\t&& isArc(0) && isArc(1) && isArc(2) && isArc(3)) {\n\t\t\tif (Numerical.isZero(getDistance(0, 2) - getDistance(1, 3))) {\n\t\t\t\ttype = Shape.Circle;\n\t\t\t\tradius = getDistance(0, 2) / 2;\n\t\t\t} else {\n\t\t\t\ttype = Shape.Ellipse;\n\t\t\t\tradius = new Size(getDistance(2, 0) / 2, getDistance(3, 1) / 2);\n\t\t\t}\n\t\t\ttopCenter = segments[1]._point;\n\t\t}\n\n\t\tif (type) {\n\t\t\tvar center = this.getPosition(true),\n\t\t\t\tshape = new type({\n\t\t\t\t\tcenter: center,\n\t\t\t\t\tsize: size,\n\t\t\t\t\tradius: radius,\n\t\t\t\t\tinsert: false\n\t\t\t\t});\n\t\t\tshape.copyAttributes(this, true);\n\t\t\tshape._matrix.prepend(this._matrix);\n\t\t\tshape.rotate(topCenter.subtract(center).getAngle() + 90);\n\t\t\tif (insert === undefined || insert)\n\t\t\t\tshape.insertAbove(this);\n\t\t\treturn shape;\n\t\t}\n\t\treturn null;\n\t},\n\n\ttoPath: '#clone',\n\n\tcompare: function compare(path) {\n\t\tif (!path || path instanceof CompoundPath)\n\t\t\treturn compare.base.call(this, path);\n\t\tvar curves1 = this.getCurves(),\n\t\t\tcurves2 = path.getCurves(),\n\t\t\tlength1 = curves1.length,\n\t\t\tlength2 = curves2.length;\n\t\tif (!length1 || !length2) {\n\t\t\treturn length1 == length2;\n\t\t}\n\t\tvar v1 = curves1[0].getValues(),\n\t\t\tvalues2 = [],\n\t\t\tpos1 = 0, pos2,\n\t\t\tend1 = 0, end2;\n\t\tfor (var i = 0; i < length2; i++) {\n\t\t\tvar v2 = curves2[i].getValues();\n\t\t\tvalues2.push(v2);\n\t\t\tvar overlaps = Curve.getOverlaps(v1, v2);\n\t\t\tif (overlaps) {\n\t\t\t\tpos2 = !i && overlaps[0][0] > 0 ? length2 - 1 : i;\n\t\t\t\tend2 = overlaps[0][1];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tvar abs = Math.abs,\n\t\t\tepsilon = 1e-8,\n\t\t\tv2 = values2[pos2],\n\t\t\tstart2;\n\t\twhile (v1 && v2) {\n\t\t\tvar overlaps = Curve.getOverlaps(v1, v2);\n\t\t\tif (overlaps) {\n\t\t\t\tvar t1 = overlaps[0][0];\n\t\t\t\tif (abs(t1 - end1) < epsilon) {\n\t\t\t\t\tend1 = overlaps[1][0];\n\t\t\t\t\tif (end1 === 1) {\n\t\t\t\t\t\tv1 = ++pos1 < length1 ? curves1[pos1].getValues() : null;\n\t\t\t\t\t\tend1 = 0;\n\t\t\t\t\t}\n\t\t\t\t\tvar t2 = overlaps[0][1];\n\t\t\t\t\tif (abs(t2 - end2) < epsilon) {\n\t\t\t\t\t\tif (!start2)\n\t\t\t\t\t\t\tstart2 = [pos2, t2];\n\t\t\t\t\t\tend2 = overlaps[1][1];\n\t\t\t\t\t\tif (end2 === 1) {\n\t\t\t\t\t\t\tif (++pos2 >= length2)\n\t\t\t\t\t\t\t\tpos2 = 0;\n\t\t\t\t\t\t\tv2 = values2[pos2] || curves2[pos2].getValues();\n\t\t\t\t\t\t\tend2 = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!v1) {\n\t\t\t\t\t\t\treturn start2[0] === pos2 && start2[1] === end2;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\treturn false;\n\t},\n\n\t_hitTestSelf: function(point, options, viewMatrix, strokeMatrix) {\n\t\tvar that = this,\n\t\t\tstyle = this.getStyle(),\n\t\t\tsegments = this._segments,\n\t\t\tnumSegments = segments.length,\n\t\t\tclosed = this._closed,\n\t\t\ttolerancePadding = options._tolerancePadding,\n\t\t\tstrokePadding = tolerancePadding,\n\t\t\tjoin, cap, miterLimit,\n\t\t\tarea, loc, res,\n\t\t\thitStroke = options.stroke && style.hasStroke(),\n\t\t\thitFill = options.fill && style.hasFill(),\n\t\t\thitCurves = options.curves,\n\t\t\tstrokeRadius = hitStroke\n\t\t\t\t\t? style.getStrokeWidth() / 2\n\t\t\t\t\t: hitFill && options.tolerance > 0 || hitCurves\n\t\t\t\t\t\t? 0 : null;\n\t\tif (strokeRadius !== null) {\n\t\t\tif (strokeRadius > 0) {\n\t\t\t\tjoin = style.getStrokeJoin();\n\t\t\t\tcap = style.getStrokeCap();\n\t\t\t\tmiterLimit = style.getMiterLimit();\n\t\t\t\tstrokePadding = strokePadding.add(\n\t\t\t\t\tPath._getStrokePadding(strokeRadius, strokeMatrix));\n\t\t\t} else {\n\t\t\t\tjoin = cap = 'round';\n\t\t\t}\n\t\t}\n\n\t\tfunction isCloseEnough(pt, padding) {\n\t\t\treturn point.subtract(pt).divide(padding).length <= 1;\n\t\t}\n\n\t\tfunction checkSegmentPoint(seg, pt, name) {\n\t\t\tif (!options.selected || pt.isSelected()) {\n\t\t\t\tvar anchor = seg._point;\n\t\t\t\tif (pt !== anchor)\n\t\t\t\t\tpt = pt.add(anchor);\n\t\t\t\tif (isCloseEnough(pt, strokePadding)) {\n\t\t\t\t\treturn new HitResult(name, that, {\n\t\t\t\t\t\tsegment: seg,\n\t\t\t\t\t\tpoint: pt\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfunction checkSegmentPoints(seg, ends) {\n\t\t\treturn (ends || options.segments)\n\t\t\t\t&& checkSegmentPoint(seg, seg._point, 'segment')\n\t\t\t\t|| (!ends && options.handles) && (\n\t\t\t\t\tcheckSegmentPoint(seg, seg._handleIn, 'handle-in') ||\n\t\t\t\t\tcheckSegmentPoint(seg, seg._handleOut, 'handle-out'));\n\t\t}\n\n\t\tfunction addToArea(point) {\n\t\t\tarea.add(point);\n\t\t}\n\n\t\tfunction checkSegmentStroke(segment) {\n\t\t\tvar isJoin = closed || segment._index > 0\n\t\t\t\t\t&& segment._index < numSegments - 1;\n\t\t\tif ((isJoin ? join : cap) === 'round') {\n\t\t\t\treturn isCloseEnough(segment._point, strokePadding);\n\t\t\t} else {\n\t\t\t\tarea = new Path({ internal: true, closed: true });\n\t\t\t\tif (isJoin) {\n\t\t\t\t\tif (!segment.isSmooth()) {\n\t\t\t\t\t\tPath._addBevelJoin(segment, join, strokeRadius,\n\t\t\t\t\t\t\t   miterLimit, null, strokeMatrix, addToArea, true);\n\t\t\t\t\t}\n\t\t\t\t} else if (cap === 'square') {\n\t\t\t\t\tPath._addSquareCap(segment, cap, strokeRadius, null,\n\t\t\t\t\t\t\tstrokeMatrix, addToArea, true);\n\t\t\t\t}\n\t\t\t\tif (!area.isEmpty()) {\n\t\t\t\t\tvar loc;\n\t\t\t\t\treturn area.contains(point)\n\t\t\t\t\t\t|| (loc = area.getNearestLocation(point))\n\t\t\t\t\t\t\t&& isCloseEnough(loc.getPoint(), tolerancePadding);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (options.ends && !options.segments && !closed) {\n\t\t\tif (res = checkSegmentPoints(segments[0], true)\n\t\t\t\t\t|| checkSegmentPoints(segments[numSegments - 1], true))\n\t\t\t\treturn res;\n\t\t} else if (options.segments || options.handles) {\n\t\t\tfor (var i = 0; i < numSegments; i++)\n\t\t\t\tif (res = checkSegmentPoints(segments[i]))\n\t\t\t\t\treturn res;\n\t\t}\n\t\tif (strokeRadius !== null) {\n\t\t\tloc = this.getNearestLocation(point);\n\t\t\tif (loc) {\n\t\t\t\tvar time = loc.getTime();\n\t\t\t\tif (time === 0 || time === 1 && numSegments > 1) {\n\t\t\t\t\tif (!checkSegmentStroke(loc.getSegment()))\n\t\t\t\t\t\tloc = null;\n\t\t\t\t} else if (!isCloseEnough(loc.getPoint(), strokePadding)) {\n\t\t\t\t\tloc = null;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!loc && join === 'miter' && numSegments > 1) {\n\t\t\t\tfor (var i = 0; i < numSegments; i++) {\n\t\t\t\t\tvar segment = segments[i];\n\t\t\t\t\tif (point.getDistance(segment._point)\n\t\t\t\t\t\t\t<= miterLimit * strokeRadius\n\t\t\t\t\t\t\t&& checkSegmentStroke(segment)) {\n\t\t\t\t\t\tloc = segment.getLocation();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn !loc && hitFill && this._contains(point)\n\t\t\t\t|| loc && !hitStroke && !hitCurves\n\t\t\t\t\t? new HitResult('fill', this)\n\t\t\t\t\t: loc\n\t\t\t\t\t\t? new HitResult(hitStroke ? 'stroke' : 'curve', this, {\n\t\t\t\t\t\t\tlocation: loc,\n\t\t\t\t\t\t\tpoint: loc.getPoint()\n\t\t\t\t\t\t})\n\t\t\t\t\t\t: null;\n\t}\n\n}, Base.each(Curve._evaluateMethods,\n\tfunction(name) {\n\t\tthis[name + 'At'] = function(offset) {\n\t\t\tvar loc = this.getLocationAt(offset);\n\t\t\treturn loc && loc[name]();\n\t\t};\n\t},\n{\n\tbeans: false,\n\n\tgetLocationOf: function() {\n\t\tvar point = Point.read(arguments),\n\t\t\tcurves = this.getCurves();\n\t\tfor (var i = 0, l = curves.length; i < l; i++) {\n\t\t\tvar loc = curves[i].getLocationOf(point);\n\t\t\tif (loc)\n\t\t\t\treturn loc;\n\t\t}\n\t\treturn null;\n\t},\n\n\tgetOffsetOf: function() {\n\t\tvar loc = this.getLocationOf.apply(this, arguments);\n\t\treturn loc ? loc.getOffset() : null;\n\t},\n\n\tgetLocationAt: function(offset) {\n\t\tif (typeof offset === 'number') {\n\t\t\tvar curves = this.getCurves(),\n\t\t\t\tlength = 0;\n\t\t\tfor (var i = 0, l = curves.length; i < l; i++) {\n\t\t\t\tvar start = length,\n\t\t\t\t\tcurve = curves[i];\n\t\t\t\tlength += curve.getLength();\n\t\t\t\tif (length > offset) {\n\t\t\t\t\treturn curve.getLocationAt(offset - start);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (curves.length > 0 && offset <= this.getLength()) {\n\t\t\t\treturn new CurveLocation(curves[curves.length - 1], 1);\n\t\t\t}\n\t\t} else if (offset && offset.getPath && offset.getPath() === this) {\n\t\t\treturn offset;\n\t\t}\n\t\treturn null;\n\t}\n\n}),\nnew function() {\n\n\tfunction drawHandles(ctx, segments, matrix, size) {\n\t\tvar half = size / 2,\n\t\t\tcoords = new Array(6),\n\t\t\tpX, pY;\n\n\t\tfunction drawHandle(index) {\n\t\t\tvar hX = coords[index],\n\t\t\t\thY = coords[index + 1];\n\t\t\tif (pX != hX || pY != hY) {\n\t\t\t\tctx.strokeStyle = '#009dec';\n\t\t\t\tctx.beginPath();\n\t\t\t\tctx.moveTo(pX, pY);\n\t\t\t\tctx.lineTo(hX, hY);\n\t\t\t\tctx.stroke();\n\t\t\t\t\n\t\t\t\t/*ctx.beginPath();\n\t\t\t\tctx.arc(hX, hY, half/1.2, 0, Math.PI * 2, true);\n\t\t\t\tctx.fillStyle = 'rgba(255,255,255,0.65)'\n\t\t\t\tctx.strokeStyle = '#ff0000';\n\t\t\t\tctx.fill();\n\t\t\t\tctx.stroke();*/\n\n\t\t\t\tctx.strokeStyle = '#009dec';\n\t\t\t\tctx.fillStyle = '#009dec';\n\t\t\t\tvar hs = 0.75;\n\t\t\t\tctx.rect(hX-half*hs,hY-half*hs,size*hs,size*hs);\n\t\t\t\tctx.fill();\n\t\t\t\tctx.stroke();\n\n\t\t\t\tctx.fillStyle = 'rgba(255,255,255,0.65)'\n\t\t\t\tctx.strokeStyle = '#ff0000';\n\t\t\t}\n\t\t}\n\n\t\tfor (var i = 0, l = segments.length; i < l; i++) {\n\t\t\tvar segment = segments[i],\n\t\t\t\tselection = segment._selection;\n\t\t\tsegment._transformCoordinates(matrix, coords);\n\t\t\tpX = coords[0];\n\t\t\tpY = coords[1];\n\n\t\t\tif (selection & 2)\n\t\t\t\tdrawHandle(2);\n\t\t\tif (selection & 4)\n\t\t\t\tdrawHandle(4);\n\n\t\t\t//ctx.fillRect(pX - half, pY - half, size, size);\n\t\t\tctx.beginPath();\n\t\t\tctx.arc(pX, pY, half, 0, Math.PI * 2, true);\n\t\t\t//ctx.fillStyle = '#b6b6ff';\n\t\t\t//ctx.fillStyle = 'rgba(182, 182, 255, 0.65)'\n\t\t\tctx.fillStyle = 'rgba(255,255,255,0.65)'\n\t\t\tctx.strokeStyle = '#009dec';\n\t\t\tctx.fill();\n\t\t\tctx.stroke();\n\n\t\t\t/*if (!(selection & 1)) {\n\t\t\t\tvar fillStyle = ctx.fillStyle;\n\t\t\t\tctx.fillStyle = '#ffffff';*/\n\n\t\t\t\t//ctx.fillRect(pX - half + 1, pY - half + 1, size - 2, size - 2);\n\t\t\t\t/*ctx.beginPath();\n\t\t\t\tctx.arc(pX, pY, half, 0, Math.PI * 2, true);\n\t\t\t\tctx.fill();*/\n\n\t\t\t\t/*ctx.fillStyle = fillStyle;\n\t\t\t}*/\n\t\t}\n\t}\n\n\tfunction drawSegments(ctx, path, matrix) {\n\t\tvar segments = path._segments,\n\t\t\tlength = segments.length,\n\t\t\tcoords = new Array(6),\n\t\t\tfirst = true,\n\t\t\tcurX, curY,\n\t\t\tprevX, prevY,\n\t\t\tinX, inY,\n\t\t\toutX, outY;\n\n\t\tfunction drawSegment(segment) {\n\t\t\tif (matrix) {\n\t\t\t\tsegment._transformCoordinates(matrix, coords);\n\t\t\t\tcurX = coords[0];\n\t\t\t\tcurY = coords[1];\n\t\t\t} else {\n\t\t\t\tvar point = segment._point;\n\t\t\t\tcurX = point._x;\n\t\t\t\tcurY = point._y;\n\t\t\t}\n\t\t\tif (first) {\n\t\t\t\tctx.moveTo(curX, curY);\n\t\t\t\tfirst = false;\n\t\t\t} else {\n\t\t\t\tif (matrix) {\n\t\t\t\t\tinX = coords[2];\n\t\t\t\t\tinY = coords[3];\n\t\t\t\t} else {\n\t\t\t\t\tvar handle = segment._handleIn;\n\t\t\t\t\tinX = curX + handle._x;\n\t\t\t\t\tinY = curY + handle._y;\n\t\t\t\t}\n\t\t\t\tif (inX === curX && inY === curY\n\t\t\t\t\t\t&& outX === prevX && outY === prevY) {\n\t\t\t\t\tctx.lineTo(curX, curY);\n\t\t\t\t} else {\n\t\t\t\t\tctx.bezierCurveTo(outX, outY, inX, inY, curX, curY);\n\t\t\t\t}\n\t\t\t}\n\t\t\tprevX = curX;\n\t\t\tprevY = curY;\n\t\t\tif (matrix) {\n\t\t\t\toutX = coords[4];\n\t\t\t\toutY = coords[5];\n\t\t\t} else {\n\t\t\t\tvar handle = segment._handleOut;\n\t\t\t\toutX = prevX + handle._x;\n\t\t\t\toutY = prevY + handle._y;\n\t\t\t}\n\t\t}\n\n\t\tfor (var i = 0; i < length; i++)\n\t\t\tdrawSegment(segments[i]);\n\t\tif (path._closed && length > 0)\n\t\t\tdrawSegment(segments[0]);\n\t}\n\n\treturn {\n\t\t_draw: function(ctx, param, viewMatrix, strokeMatrix) {\n\t\t\tvar dontStart = param.dontStart,\n\t\t\t\tdontPaint = param.dontFinish || param.clip,\n\t\t\t\tstyle = this.getStyle(),\n\t\t\t\thasFill = style.hasFill(),\n\t\t\t\thasStroke = style.hasStroke(),\n\t\t\t\tdashArray = style.getDashArray(),\n\t\t\t\tdashLength = !paper.support.nativeDash && hasStroke\n\t\t\t\t\t\t&& dashArray && dashArray.length;\n\n\t\t\tif (!dontStart)\n\t\t\t\tctx.beginPath();\n\n\t\t\tif (hasFill || hasStroke && !dashLength || dontPaint) {\n\t\t\t\tdrawSegments(ctx, this, strokeMatrix);\n\t\t\t\tif (this._closed)\n\t\t\t\t\tctx.closePath();\n\t\t\t}\n\n\t\t\tfunction getOffset(i) {\n\t\t\t\treturn dashArray[((i % dashLength) + dashLength) % dashLength];\n\t\t\t}\n\n\t\t\tif (!dontPaint && (hasFill || hasStroke)) {\n\t\t\t\tthis._setStyles(ctx, param, viewMatrix);\n\t\t\t\tif (hasFill) {\n\t\t\t\t\tctx.fill(style.getFillRule());\n\t\t\t\t\tctx.shadowColor = 'rgba(0,0,0,0)';\n\t\t\t\t}\n\t\t\t\tif (hasStroke) {\n\t\t\t\t\tif (dashLength) {\n\t\t\t\t\t\tif (!dontStart)\n\t\t\t\t\t\t\tctx.beginPath();\n\t\t\t\t\t\tvar flattener = new PathFlattener(this, 0.25, 32, false,\n\t\t\t\t\t\t\t\tstrokeMatrix),\n\t\t\t\t\t\t\tlength = flattener.length,\n\t\t\t\t\t\t\tfrom = -style.getDashOffset(), to,\n\t\t\t\t\t\t\ti = 0;\n\t\t\t\t\t\tfrom = from % length;\n\t\t\t\t\t\twhile (from > 0) {\n\t\t\t\t\t\t\tfrom -= getOffset(i--) + getOffset(i--);\n\t\t\t\t\t\t}\n\t\t\t\t\t\twhile (from < length) {\n\t\t\t\t\t\t\tto = from + getOffset(i++);\n\t\t\t\t\t\t\tif (from > 0 || to > 0)\n\t\t\t\t\t\t\t\tflattener.drawPart(ctx,\n\t\t\t\t\t\t\t\t\t\tMath.max(from, 0), Math.max(to, 0));\n\t\t\t\t\t\t\tfrom = to + getOffset(i++);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tctx.stroke();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_drawSelected: function(ctx, matrix) {\n\t\t\tctx.beginPath();\n\t\t\tdrawSegments(ctx, this, matrix);\n\t\t\tctx.stroke();\n\t\t\tdrawHandles(ctx, this._segments, matrix, paper.settings.handleSize);\n\t\t}\n\t};\n},\nnew function() {\n\tfunction getCurrentSegment(that) {\n\t\tvar segments = that._segments;\n\t\tif (!segments.length)\n\t\t\tthrow new Error('Use a moveTo() command first');\n\t\treturn segments[segments.length - 1];\n\t}\n\n\treturn {\n\t\tmoveTo: function() {\n\t\t\tvar segments = this._segments;\n\t\t\tif (segments.length === 1)\n\t\t\t\tthis.removeSegment(0);\n\t\t\tif (!segments.length)\n\t\t\t\tthis._add([ new Segment(Point.read(arguments)) ]);\n\t\t},\n\n\t\tmoveBy: function() {\n\t\t\tthrow new Error('moveBy() is unsupported on Path items.');\n\t\t},\n\n\t\tlineTo: function() {\n\t\t\tthis._add([ new Segment(Point.read(arguments)) ]);\n\t\t},\n\n\t\tcubicCurveTo: function() {\n\t\t\tvar handle1 = Point.read(arguments),\n\t\t\t\thandle2 = Point.read(arguments),\n\t\t\t\tto = Point.read(arguments),\n\t\t\t\tcurrent = getCurrentSegment(this);\n\t\t\tcurrent.setHandleOut(handle1.subtract(current._point));\n\t\t\tthis._add([ new Segment(to, handle2.subtract(to)) ]);\n\t\t},\n\n\t\tquadraticCurveTo: function() {\n\t\t\tvar handle = Point.read(arguments),\n\t\t\t\tto = Point.read(arguments),\n\t\t\t\tcurrent = getCurrentSegment(this)._point;\n\t\t\tthis.cubicCurveTo(\n\t\t\t\thandle.add(current.subtract(handle).multiply(1 / 3)),\n\t\t\t\thandle.add(to.subtract(handle).multiply(1 / 3)),\n\t\t\t\tto\n\t\t\t);\n\t\t},\n\n\t\tcurveTo: function() {\n\t\t\tvar through = Point.read(arguments),\n\t\t\t\tto = Point.read(arguments),\n\t\t\t\tt = Base.pick(Base.read(arguments), 0.5),\n\t\t\t\tt1 = 1 - t,\n\t\t\t\tcurrent = getCurrentSegment(this)._point,\n\t\t\t\thandle = through.subtract(current.multiply(t1 * t1))\n\t\t\t\t\t.subtract(to.multiply(t * t)).divide(2 * t * t1);\n\t\t\tif (handle.isNaN())\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'Cannot put a curve through points with parameter = ' + t);\n\t\t\tthis.quadraticCurveTo(handle, to);\n\t\t},\n\n\t\tarcTo: function() {\n\t\t\tvar abs = Math.abs,\n\t\t\t\tsqrt = Math.sqrt,\n\t\t\t\tcurrent = getCurrentSegment(this),\n\t\t\t\tfrom = current._point,\n\t\t\t\tto = Point.read(arguments),\n\t\t\t\tthrough,\n\t\t\t\tpeek = Base.peek(arguments),\n\t\t\t\tclockwise = Base.pick(peek, true),\n\t\t\t\tcenter, extent, vector, matrix;\n\t\t\tif (typeof clockwise === 'boolean') {\n\t\t\t\tvar middle = from.add(to).divide(2),\n\t\t\t\tthrough = middle.add(middle.subtract(from).rotate(\n\t\t\t\t\t\tclockwise ? -90 : 90));\n\t\t\t} else if (Base.remain(arguments) <= 2) {\n\t\t\t\tthrough = to;\n\t\t\t\tto = Point.read(arguments);\n\t\t\t} else {\n\t\t\t\tvar radius = Size.read(arguments),\n\t\t\t\t\tisZero = Numerical.isZero;\n\t\t\t\tif (isZero(radius.width) || isZero(radius.height))\n\t\t\t\t\treturn this.lineTo(to);\n\t\t\t\tvar rotation = Base.read(arguments),\n\t\t\t\t\tclockwise = !!Base.read(arguments),\n\t\t\t\t\tlarge = !!Base.read(arguments),\n\t\t\t\t\tmiddle = from.add(to).divide(2),\n\t\t\t\t\tpt = from.subtract(middle).rotate(-rotation),\n\t\t\t\t\tx = pt.x,\n\t\t\t\t\ty = pt.y,\n\t\t\t\t\trx = abs(radius.width),\n\t\t\t\t\try = abs(radius.height),\n\t\t\t\t\trxSq = rx * rx,\n\t\t\t\t\trySq = ry * ry,\n\t\t\t\t\txSq = x * x,\n\t\t\t\t\tySq = y * y;\n\t\t\t\tvar factor = sqrt(xSq / rxSq + ySq / rySq);\n\t\t\t\tif (factor > 1) {\n\t\t\t\t\trx *= factor;\n\t\t\t\t\try *= factor;\n\t\t\t\t\trxSq = rx * rx;\n\t\t\t\t\trySq = ry * ry;\n\t\t\t\t}\n\t\t\t\tfactor = (rxSq * rySq - rxSq * ySq - rySq * xSq) /\n\t\t\t\t\t\t(rxSq * ySq + rySq * xSq);\n\t\t\t\tif (abs(factor) < 1e-12)\n\t\t\t\t\tfactor = 0;\n\t\t\t\tif (factor < 0)\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t'Cannot create an arc with the given arguments');\n\t\t\t\tcenter = new Point(rx * y / ry, -ry * x / rx)\n\t\t\t\t\t\t.multiply((large === clockwise ? -1 : 1) * sqrt(factor))\n\t\t\t\t\t\t.rotate(rotation).add(middle);\n\t\t\t\tmatrix = new Matrix().translate(center).rotate(rotation)\n\t\t\t\t\t\t.scale(rx, ry);\n\t\t\t\tvector = matrix._inverseTransform(from);\n\t\t\t\textent = vector.getDirectedAngle(matrix._inverseTransform(to));\n\t\t\t\tif (!clockwise && extent > 0)\n\t\t\t\t\textent -= 360;\n\t\t\t\telse if (clockwise && extent < 0)\n\t\t\t\t\textent += 360;\n\t\t\t}\n\t\t\tif (through) {\n\t\t\t\tvar l1 = new Line(from.add(through).divide(2),\n\t\t\t\t\t\t\tthrough.subtract(from).rotate(90), true),\n\t\t\t\t\tl2 = new Line(through.add(to).divide(2),\n\t\t\t\t\t\t\tto.subtract(through).rotate(90), true),\n\t\t\t\t\tline = new Line(from, to),\n\t\t\t\t\tthroughSide = line.getSide(through);\n\t\t\t\tcenter = l1.intersect(l2, true);\n\t\t\t\tif (!center) {\n\t\t\t\t\tif (!throughSide)\n\t\t\t\t\t\treturn this.lineTo(to);\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t'Cannot create an arc with the given arguments');\n\t\t\t\t}\n\t\t\t\tvector = from.subtract(center);\n\t\t\t\textent = vector.getDirectedAngle(to.subtract(center));\n\t\t\t\tvar centerSide = line.getSide(center);\n\t\t\t\tif (centerSide === 0) {\n\t\t\t\t\textent = throughSide * abs(extent);\n\t\t\t\t} else if (throughSide === centerSide) {\n\t\t\t\t\textent += extent < 0 ? 360 : -360;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar epsilon = 1e-7,\n\t\t\t\text = abs(extent),\n\t\t\t\tcount = ext >= 360 ? 4 : Math.ceil((ext - epsilon) / 90),\n\t\t\t\tinc = extent / count,\n\t\t\t\thalf = inc * Math.PI / 360,\n\t\t\t\tz = 4 / 3 * Math.sin(half) / (1 + Math.cos(half)),\n\t\t\t\tsegments = [];\n\t\t\tfor (var i = 0; i <= count; i++) {\n\t\t\t\tvar pt = to,\n\t\t\t\t\tout = null;\n\t\t\t\tif (i < count) {\n\t\t\t\t\tout = vector.rotate(90).multiply(z);\n\t\t\t\t\tif (matrix) {\n\t\t\t\t\t\tpt = matrix._transformPoint(vector);\n\t\t\t\t\t\tout = matrix._transformPoint(vector.add(out))\n\t\t\t\t\t\t\t\t.subtract(pt);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpt = center.add(vector);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!i) {\n\t\t\t\t\tcurrent.setHandleOut(out);\n\t\t\t\t} else {\n\t\t\t\t\tvar _in = vector.rotate(-90).multiply(z);\n\t\t\t\t\tif (matrix) {\n\t\t\t\t\t\t_in = matrix._transformPoint(vector.add(_in))\n\t\t\t\t\t\t\t\t.subtract(pt);\n\t\t\t\t\t}\n\t\t\t\t\tsegments.push(new Segment(pt, _in, out));\n\t\t\t\t}\n\t\t\t\tvector = vector.rotate(inc);\n\t\t\t}\n\t\t\tthis._add(segments);\n\t\t},\n\n\t\tlineBy: function() {\n\t\t\tvar to = Point.read(arguments),\n\t\t\t\tcurrent = getCurrentSegment(this)._point;\n\t\t\tthis.lineTo(current.add(to));\n\t\t},\n\n\t\tcurveBy: function() {\n\t\t\tvar through = Point.read(arguments),\n\t\t\t\tto = Point.read(arguments),\n\t\t\t\tparameter = Base.read(arguments),\n\t\t\t\tcurrent = getCurrentSegment(this)._point;\n\t\t\tthis.curveTo(current.add(through), current.add(to), parameter);\n\t\t},\n\n\t\tcubicCurveBy: function() {\n\t\t\tvar handle1 = Point.read(arguments),\n\t\t\t\thandle2 = Point.read(arguments),\n\t\t\t\tto = Point.read(arguments),\n\t\t\t\tcurrent = getCurrentSegment(this)._point;\n\t\t\tthis.cubicCurveTo(current.add(handle1), current.add(handle2),\n\t\t\t\t\tcurrent.add(to));\n\t\t},\n\n\t\tquadraticCurveBy: function() {\n\t\t\tvar handle = Point.read(arguments),\n\t\t\t\tto = Point.read(arguments),\n\t\t\t\tcurrent = getCurrentSegment(this)._point;\n\t\t\tthis.quadraticCurveTo(current.add(handle), current.add(to));\n\t\t},\n\n\t\tarcBy: function() {\n\t\t\tvar current = getCurrentSegment(this)._point,\n\t\t\t\tpoint = current.add(Point.read(arguments)),\n\t\t\t\tclockwise = Base.pick(Base.peek(arguments), true);\n\t\t\tif (typeof clockwise === 'boolean') {\n\t\t\t\tthis.arcTo(point, clockwise);\n\t\t\t} else {\n\t\t\t\tthis.arcTo(point, current.add(Point.read(arguments)));\n\t\t\t}\n\t\t},\n\n\t\tclosePath: function(tolerance) {\n\t\t\tthis.setClosed(true);\n\t\t\tthis.join(this, tolerance);\n\t\t}\n\t};\n}, {\n\n\t_getBounds: function(matrix, options) {\n\t\tvar method = options.handle\n\t\t\t\t? 'getHandleBounds'\n\t\t\t\t: options.stroke\n\t\t\t\t? 'getStrokeBounds'\n\t\t\t\t: 'getBounds';\n\t\treturn Path[method](this._segments, this._closed, this, matrix, options);\n\t},\n\nstatics: {\n\tgetBounds: function(segments, closed, path, matrix, options, strokePadding) {\n\t\tvar first = segments[0];\n\t\tif (!first)\n\t\t\treturn new Rectangle();\n\t\tvar coords = new Array(6),\n\t\t\tprevCoords = first._transformCoordinates(matrix, new Array(6)),\n\t\t\tmin = prevCoords.slice(0, 2),\n\t\t\tmax = min.slice(),\n\t\t\troots = new Array(2);\n\n\t\tfunction processSegment(segment) {\n\t\t\tsegment._transformCoordinates(matrix, coords);\n\t\t\tfor (var i = 0; i < 2; i++) {\n\t\t\t\tCurve._addBounds(\n\t\t\t\t\tprevCoords[i],\n\t\t\t\t\tprevCoords[i + 4],\n\t\t\t\t\tcoords[i + 2],\n\t\t\t\t\tcoords[i],\n\t\t\t\t\ti, strokePadding ? strokePadding[i] : 0, min, max, roots);\n\t\t\t}\n\t\t\tvar tmp = prevCoords;\n\t\t\tprevCoords = coords;\n\t\t\tcoords = tmp;\n\t\t}\n\n\t\tfor (var i = 1, l = segments.length; i < l; i++)\n\t\t\tprocessSegment(segments[i]);\n\t\tif (closed)\n\t\t\tprocessSegment(first);\n\t\treturn new Rectangle(min[0], min[1], max[0] - min[0], max[1] - min[1]);\n\t},\n\n\tgetStrokeBounds: function(segments, closed, path, matrix, options) {\n\t\tvar style = path.getStyle(),\n\t\t\tstroke = style.hasStroke(),\n\t\t\tstrokeWidth = style.getStrokeWidth(),\n\t\t\tstrokeMatrix = stroke && path._getStrokeMatrix(matrix, options),\n\t\t\tstrokePadding = stroke && Path._getStrokePadding(strokeWidth,\n\t\t\t\tstrokeMatrix),\n\t\t\tbounds = Path.getBounds(segments, closed, path, matrix, options,\n\t\t\t\tstrokePadding);\n\t\tif (!stroke)\n\t\t\treturn bounds;\n\t\tvar strokeRadius = strokeWidth / 2,\n\t\t\tjoin = style.getStrokeJoin(),\n\t\t\tcap = style.getStrokeCap(),\n\t\t\tmiterLimit = style.getMiterLimit(),\n\t\t\tjoinBounds = new Rectangle(new Size(strokePadding));\n\n\t\tfunction addPoint(point) {\n\t\t\tbounds = bounds.include(point);\n\t\t}\n\n\t\tfunction addRound(segment) {\n\t\t\tbounds = bounds.unite(\n\t\t\t\t\tjoinBounds.setCenter(segment._point.transform(matrix)));\n\t\t}\n\n\t\tfunction addJoin(segment, join) {\n\t\t\tif (join === 'round' || segment.isSmooth()) {\n\t\t\t\taddRound(segment);\n\t\t\t} else {\n\t\t\t\tPath._addBevelJoin(segment, join, strokeRadius, miterLimit,\n\t\t\t\t\t\tmatrix, strokeMatrix, addPoint);\n\t\t\t}\n\t\t}\n\n\t\tfunction addCap(segment, cap) {\n\t\t\tif (cap === 'round') {\n\t\t\t\taddRound(segment);\n\t\t\t} else {\n\t\t\t\tPath._addSquareCap(segment, cap, strokeRadius, matrix,\n\t\t\t\t\t\tstrokeMatrix, addPoint);\n\t\t\t}\n\t\t}\n\n\t\tvar length = segments.length - (closed ? 0 : 1);\n\t\tfor (var i = 1; i < length; i++)\n\t\t\taddJoin(segments[i], join);\n\t\tif (closed) {\n\t\t\taddJoin(segments[0], join);\n\t\t} else if (length > 0) {\n\t\t\taddCap(segments[0], cap);\n\t\t\taddCap(segments[segments.length - 1], cap);\n\t\t}\n\t\treturn bounds;\n\t},\n\n\t_getStrokePadding: function(radius, matrix) {\n\t\tif (!matrix)\n\t\t\treturn [radius, radius];\n\t\tvar hor = new Point(radius, 0).transform(matrix),\n\t\t\tver = new Point(0, radius).transform(matrix),\n\t\t\tphi = hor.getAngleInRadians(),\n\t\t\ta = hor.getLength(),\n\t\t\tb = ver.getLength();\n\t\tvar sin = Math.sin(phi),\n\t\t\tcos = Math.cos(phi),\n\t\t\ttan = Math.tan(phi),\n\t\t\ttx = Math.atan2(b * tan, a),\n\t\t\tty = Math.atan2(b, tan * a);\n\t\treturn [Math.abs(a * Math.cos(tx) * cos + b * Math.sin(tx) * sin),\n\t\t\t\tMath.abs(b * Math.sin(ty) * cos + a * Math.cos(ty) * sin)];\n\t},\n\n\t_addBevelJoin: function(segment, join, radius, miterLimit, matrix,\n\t\t\tstrokeMatrix, addPoint, isArea) {\n\t\tvar curve2 = segment.getCurve(),\n\t\t\tcurve1 = curve2.getPrevious(),\n\t\t\tpoint = curve2.getPoint1().transform(matrix),\n\t\t\tnormal1 = curve1.getNormalAtTime(1).multiply(radius)\n\t\t\t\t.transform(strokeMatrix),\n\t\t\tnormal2 = curve2.getNormalAtTime(0).multiply(radius)\n\t\t\t\t.transform(strokeMatrix);\n\t\tif (normal1.getDirectedAngle(normal2) < 0) {\n\t\t\tnormal1 = normal1.negate();\n\t\t\tnormal2 = normal2.negate();\n\t\t}\n\t\tif (isArea)\n\t\t\taddPoint(point);\n\t\taddPoint(point.add(normal1));\n\t\tif (join === 'miter') {\n\t\t\tvar corner = new Line(point.add(normal1),\n\t\t\t\t\tnew Point(-normal1.y, normal1.x), true\n\t\t\t\t).intersect(new Line(point.add(normal2),\n\t\t\t\t\tnew Point(-normal2.y, normal2.x), true\n\t\t\t\t), true);\n\t\t\tif (corner && point.getDistance(corner) <= miterLimit * radius) {\n\t\t\t\taddPoint(corner);\n\t\t\t}\n\t\t}\n\t\taddPoint(point.add(normal2));\n\t},\n\n\t_addSquareCap: function(segment, cap, radius, matrix, strokeMatrix,\n\t\t\taddPoint, isArea) {\n\t\tvar point = segment._point.transform(matrix),\n\t\t\tloc = segment.getLocation(),\n\t\t\tnormal = loc.getNormal()\n\t\t\t\t\t.multiply(loc.getTime() === 0 ? radius : -radius)\n\t\t\t\t\t.transform(strokeMatrix);\n\t\tif (cap === 'square') {\n\t\t\tif (isArea) {\n\t\t\t\taddPoint(point.subtract(normal));\n\t\t\t\taddPoint(point.add(normal));\n\t\t\t}\n\t\t\tpoint = point.add(normal.rotate(-90));\n\t\t}\n\t\taddPoint(point.add(normal));\n\t\taddPoint(point.subtract(normal));\n\t},\n\n\tgetHandleBounds: function(segments, closed, path, matrix, options) {\n\t\tvar style = path.getStyle(),\n\t\t\tstroke = options.stroke && style.hasStroke(),\n\t\t\tstrokePadding,\n\t\t\tjoinPadding;\n\t\tif (stroke) {\n\t\t\tvar strokeMatrix = path._getStrokeMatrix(matrix, options),\n\t\t\t\tstrokeRadius = style.getStrokeWidth() / 2,\n\t\t\t\tjoinRadius = strokeRadius;\n\t\t\tif (style.getStrokeJoin() === 'miter')\n\t\t\t\tjoinRadius = strokeRadius * style.getMiterLimit();\n\t\t\tif (style.getStrokeCap() === 'square')\n\t\t\t\tjoinRadius = Math.max(joinRadius, strokeRadius * Math.SQRT2);\n\t\t\tstrokePadding = Path._getStrokePadding(strokeRadius, strokeMatrix);\n\t\t\tjoinPadding = Path._getStrokePadding(joinRadius, strokeMatrix);\n\t\t}\n\t\tvar coords = new Array(6),\n\t\t\tx1 = Infinity,\n\t\t\tx2 = -x1,\n\t\t\ty1 = x1,\n\t\t\ty2 = x2;\n\t\tfor (var i = 0, l = segments.length; i < l; i++) {\n\t\t\tvar segment = segments[i];\n\t\t\tsegment._transformCoordinates(matrix, coords);\n\t\t\tfor (var j = 0; j < 6; j += 2) {\n\t\t\t\tvar padding = !j ? joinPadding : strokePadding,\n\t\t\t\t\tpaddingX = padding ? padding[0] : 0,\n\t\t\t\t\tpaddingY = padding ? padding[1] : 0,\n\t\t\t\t\tx = coords[j],\n\t\t\t\t\ty = coords[j + 1],\n\t\t\t\t\txn = x - paddingX,\n\t\t\t\t\txx = x + paddingX,\n\t\t\t\t\tyn = y - paddingY,\n\t\t\t\t\tyx = y + paddingY;\n\t\t\t\tif (xn < x1) x1 = xn;\n\t\t\t\tif (xx > x2) x2 = xx;\n\t\t\t\tif (yn < y1) y1 = yn;\n\t\t\t\tif (yx > y2) y2 = yx;\n\t\t\t}\n\t\t}\n\t\treturn new Rectangle(x1, y1, x2 - x1, y2 - y1);\n\t}\n}});\n\nPath.inject({ statics: new function() {\n\n\tvar kappa = 0.5522847498307936,\n\t\tellipseSegments = [\n\t\t\tnew Segment([-1, 0], [0, kappa ], [0, -kappa]),\n\t\t\tnew Segment([0, -1], [-kappa, 0], [kappa, 0 ]),\n\t\t\tnew Segment([1, 0], [0, -kappa], [0, kappa ]),\n\t\t\tnew Segment([0, 1], [kappa, 0 ], [-kappa, 0])\n\t\t];\n\n\tfunction createPath(segments, closed, args) {\n\t\tvar props = Base.getNamed(args),\n\t\t\tpath = new Path(props && props.insert == false && Item.NO_INSERT);\n\t\tpath._add(segments);\n\t\tpath._closed = closed;\n\t\treturn path.set(props, { insert: true });\n\t}\n\n\tfunction createEllipse(center, radius, args) {\n\t\tvar segments = new Array(4);\n\t\tfor (var i = 0; i < 4; i++) {\n\t\t\tvar segment = ellipseSegments[i];\n\t\t\tsegments[i] = new Segment(\n\t\t\t\tsegment._point.multiply(radius).add(center),\n\t\t\t\tsegment._handleIn.multiply(radius),\n\t\t\t\tsegment._handleOut.multiply(radius)\n\t\t\t);\n\t\t}\n\t\treturn createPath(segments, true, args);\n\t}\n\n\treturn {\n\t\tLine: function() {\n\t\t\treturn createPath([\n\t\t\t\tnew Segment(Point.readNamed(arguments, 'from')),\n\t\t\t\tnew Segment(Point.readNamed(arguments, 'to'))\n\t\t\t], false, arguments);\n\t\t},\n\n\t\tCircle: function() {\n\t\t\tvar center = Point.readNamed(arguments, 'center'),\n\t\t\t\tradius = Base.readNamed(arguments, 'radius');\n\t\t\treturn createEllipse(center, new Size(radius), arguments);\n\t\t},\n\n\t\tRectangle: function() {\n\t\t\tvar rect = Rectangle.readNamed(arguments, 'rectangle'),\n\t\t\t\tradius = Size.readNamed(arguments, 'radius', 0,\n\t\t\t\t\t\t{ readNull: true }),\n\t\t\t\tbl = rect.getBottomLeft(true),\n\t\t\t\ttl = rect.getTopLeft(true),\n\t\t\t\ttr = rect.getTopRight(true),\n\t\t\t\tbr = rect.getBottomRight(true),\n\t\t\t\tsegments;\n\t\t\tif (!radius || radius.isZero()) {\n\t\t\t\tsegments = [\n\t\t\t\t\tnew Segment(bl),\n\t\t\t\t\tnew Segment(tl),\n\t\t\t\t\tnew Segment(tr),\n\t\t\t\t\tnew Segment(br)\n\t\t\t\t];\n\t\t\t} else {\n\t\t\t\tradius = Size.min(radius, rect.getSize(true).divide(2));\n\t\t\t\tvar rx = radius.width,\n\t\t\t\t\try = radius.height,\n\t\t\t\t\thx = rx * kappa,\n\t\t\t\t\thy = ry * kappa;\n\t\t\t\tsegments = [\n\t\t\t\t\tnew Segment(bl.add(rx, 0), null, [-hx, 0]),\n\t\t\t\t\tnew Segment(bl.subtract(0, ry), [0, hy]),\n\t\t\t\t\tnew Segment(tl.add(0, ry), null, [0, -hy]),\n\t\t\t\t\tnew Segment(tl.add(rx, 0), [-hx, 0], null),\n\t\t\t\t\tnew Segment(tr.subtract(rx, 0), null, [hx, 0]),\n\t\t\t\t\tnew Segment(tr.add(0, ry), [0, -hy], null),\n\t\t\t\t\tnew Segment(br.subtract(0, ry), null, [0, hy]),\n\t\t\t\t\tnew Segment(br.subtract(rx, 0), [hx, 0])\n\t\t\t\t];\n\t\t\t}\n\t\t\treturn createPath(segments, true, arguments);\n\t\t},\n\n\t\tRoundRectangle: '#Rectangle',\n\n\t\tEllipse: function() {\n\t\t\tvar ellipse = Shape._readEllipse(arguments);\n\t\t\treturn createEllipse(ellipse.center, ellipse.radius, arguments);\n\t\t},\n\n\t\tOval: '#Ellipse',\n\n\t\tArc: function() {\n\t\t\tvar from = Point.readNamed(arguments, 'from'),\n\t\t\t\tthrough = Point.readNamed(arguments, 'through'),\n\t\t\t\tto = Point.readNamed(arguments, 'to'),\n\t\t\t\tprops = Base.getNamed(arguments),\n\t\t\t\tpath = new Path(props && props.insert == false\n\t\t\t\t\t\t&& Item.NO_INSERT);\n\t\t\tpath.moveTo(from);\n\t\t\tpath.arcTo(through, to);\n\t\t\treturn path.set(props);\n\t\t},\n\n\t\tRegularPolygon: function() {\n\t\t\tvar center = Point.readNamed(arguments, 'center'),\n\t\t\t\tsides = Base.readNamed(arguments, 'sides'),\n\t\t\t\tradius = Base.readNamed(arguments, 'radius'),\n\t\t\t\tstep = 360 / sides,\n\t\t\t\tthree = sides % 3 === 0,\n\t\t\t\tvector = new Point(0, three ? -radius : radius),\n\t\t\t\toffset = three ? -1 : 0.5,\n\t\t\t\tsegments = new Array(sides);\n\t\t\tfor (var i = 0; i < sides; i++)\n\t\t\t\tsegments[i] = new Segment(center.add(\n\t\t\t\t\tvector.rotate((i + offset) * step)));\n\t\t\treturn createPath(segments, true, arguments);\n\t\t},\n\n\t\tStar: function() {\n\t\t\tvar center = Point.readNamed(arguments, 'center'),\n\t\t\t\tpoints = Base.readNamed(arguments, 'points') * 2,\n\t\t\t\tradius1 = Base.readNamed(arguments, 'radius1'),\n\t\t\t\tradius2 = Base.readNamed(arguments, 'radius2'),\n\t\t\t\tstep = 360 / points,\n\t\t\t\tvector = new Point(0, -1),\n\t\t\t\tsegments = new Array(points);\n\t\t\tfor (var i = 0; i < points; i++)\n\t\t\t\tsegments[i] = new Segment(center.add(vector.rotate(step * i)\n\t\t\t\t\t\t.multiply(i % 2 ? radius2 : radius1)));\n\t\t\treturn createPath(segments, true, arguments);\n\t\t}\n\t};\n}});\n\nvar CompoundPath = PathItem.extend({\n\t_class: 'CompoundPath',\n\t_serializeFields: {\n\t\tchildren: []\n\t},\n\tbeans: true,\n\n\tinitialize: function CompoundPath(arg) {\n\t\tthis._children = [];\n\t\tthis._namedChildren = {};\n\t\tif (!this._initialize(arg)) {\n\t\t\tif (typeof arg === 'string') {\n\t\t\t\tthis.setPathData(arg);\n\t\t\t} else {\n\t\t\t\tthis.addChildren(Array.isArray(arg) ? arg : arguments);\n\t\t\t}\n\t\t}\n\t},\n\n\tinsertChildren: function insertChildren(index, items) {\n\t\tvar list = items,\n\t\t\tfirst = list[0];\n\t\tif (first && typeof first[0] === 'number')\n\t\t\tlist = [list];\n\t\tfor (var i = items.length - 1; i >= 0; i--) {\n\t\t\tvar item = list[i];\n\t\t\tif (list === items && !(item instanceof Path))\n\t\t\t\tlist = Base.slice(list);\n\t\t\tif (Array.isArray(item)) {\n\t\t\t\tlist[i] = new Path({ segments: item, insert: false });\n\t\t\t} else if (item instanceof CompoundPath) {\n\t\t\t\tlist.splice.apply(list, [i, 1].concat(item.removeChildren()));\n\t\t\t\titem.remove();\n\t\t\t}\n\t\t}\n\t\treturn insertChildren.base.call(this, index, list);\n\t},\n\n\treduce: function reduce(options) {\n\t\tvar children = this._children;\n\t\tfor (var i = children.length - 1; i >= 0; i--) {\n\t\t\tvar path = children[i].reduce(options);\n\t\t\tif (path.isEmpty())\n\t\t\t\tpath.remove();\n\t\t}\n\t\tif (!children.length) {\n\t\t\tvar path = new Path(Item.NO_INSERT);\n\t\t\tpath.copyAttributes(this);\n\t\t\tpath.insertAbove(this);\n\t\t\tthis.remove();\n\t\t\treturn path;\n\t\t}\n\t\treturn reduce.base.call(this);\n\t},\n\n\tisClosed: function() {\n\t\tvar children = this._children;\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tif (!children[i]._closed)\n\t\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\tsetClosed: function(closed) {\n\t\tvar children = this._children;\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tchildren[i].setClosed(closed);\n\t\t}\n\t},\n\n\tgetFirstSegment: function() {\n\t\tvar first = this.getFirstChild();\n\t\treturn first && first.getFirstSegment();\n\t},\n\n\tgetLastSegment: function() {\n\t\tvar last = this.getLastChild();\n\t\treturn last && last.getLastSegment();\n\t},\n\n\tgetCurves: function() {\n\t\tvar children = this._children,\n\t\t\tcurves = [];\n\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\tcurves.push.apply(curves, children[i].getCurves());\n\t\treturn curves;\n\t},\n\n\tgetFirstCurve: function() {\n\t\tvar first = this.getFirstChild();\n\t\treturn first && first.getFirstCurve();\n\t},\n\n\tgetLastCurve: function() {\n\t\tvar last = this.getLastChild();\n\t\treturn last && last.getLastCurve();\n\t},\n\n\tgetArea: function() {\n\t\tvar children = this._children,\n\t\t\tarea = 0;\n\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\tarea += children[i].getArea();\n\t\treturn area;\n\t},\n\n\tgetLength: function() {\n\t\tvar children = this._children,\n\t\t\tlength = 0;\n\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\tlength += children[i].getLength();\n\t\treturn length;\n\t},\n\n\tgetPathData: function(_matrix, _precision) {\n\t\tvar children = this._children,\n\t\t\tpaths = [];\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tvar child = children[i],\n\t\t\t\tmx = child._matrix;\n\t\t\tpaths.push(child.getPathData(_matrix && !mx.isIdentity()\n\t\t\t\t\t? _matrix.appended(mx) : _matrix, _precision));\n\t\t}\n\t\treturn paths.join('');\n\t},\n\n\t_hitTestChildren: function _hitTestChildren(point, options, viewMatrix) {\n\t\treturn _hitTestChildren.base.call(this, point,\n\t\t\t\toptions.class === Path || options.type === 'path' ? options\n\t\t\t\t\t: Base.set({}, options, { fill: false }),\n\t\t\t\tviewMatrix);\n\t},\n\n\t_draw: function(ctx, param, viewMatrix, strokeMatrix) {\n\t\tvar children = this._children;\n\t\tif (!children.length)\n\t\t\treturn;\n\n\t\tparam = param.extend({ dontStart: true, dontFinish: true });\n\t\tctx.beginPath();\n\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\tchildren[i].draw(ctx, param, strokeMatrix);\n\n\t\tif (!param.clip) {\n\t\t\tthis._setStyles(ctx, param, viewMatrix);\n\t\t\tvar style = this._style;\n\t\t\tif (style.hasFill()) {\n\t\t\t\tctx.fill(style.getFillRule());\n\t\t\t\tctx.shadowColor = 'rgba(0,0,0,0)';\n\t\t\t}\n\t\t\tif (style.hasStroke())\n\t\t\t\tctx.stroke();\n\t\t}\n\t},\n\n\t_drawSelected: function(ctx, matrix, selectionItems) {\n\t\tvar children = this._children;\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tvar child = children[i],\n\t\t\t\tmx = child._matrix;\n\t\t\tif (!selectionItems[child._id]) {\n\t\t\t\tchild._drawSelected(ctx, mx.isIdentity() ? matrix\n\t\t\t\t\t\t: matrix.appended(mx));\n\t\t\t}\n\t\t}\n\t}\n},\nnew function() {\n\tfunction getCurrentPath(that, check) {\n\t\tvar children = that._children;\n\t\tif (check && !children.length)\n\t\t\tthrow new Error('Use a moveTo() command first');\n\t\treturn children[children.length - 1];\n\t}\n\n\treturn Base.each(['lineTo', 'cubicCurveTo', 'quadraticCurveTo', 'curveTo',\n\t\t\t'arcTo', 'lineBy', 'cubicCurveBy', 'quadraticCurveBy', 'curveBy',\n\t\t\t'arcBy'],\n\t\tfunction(key) {\n\t\t\tthis[key] = function() {\n\t\t\t\tvar path = getCurrentPath(this, true);\n\t\t\t\tpath[key].apply(path, arguments);\n\t\t\t};\n\t\t}, {\n\t\t\tmoveTo: function() {\n\t\t\t\tvar current = getCurrentPath(this),\n\t\t\t\t\tpath = current && current.isEmpty() ? current\n\t\t\t\t\t\t\t: new Path(Item.NO_INSERT);\n\t\t\t\tif (path !== current)\n\t\t\t\t\tthis.addChild(path);\n\t\t\t\tpath.moveTo.apply(path, arguments);\n\t\t\t},\n\n\t\t\tmoveBy: function() {\n\t\t\t\tvar current = getCurrentPath(this, true),\n\t\t\t\t\tlast = current && current.getLastSegment(),\n\t\t\t\t\tpoint = Point.read(arguments);\n\t\t\t\tthis.moveTo(last ? point.add(last._point) : point);\n\t\t\t},\n\n\t\t\tclosePath: function(tolerance) {\n\t\t\t\tgetCurrentPath(this, true).closePath(tolerance);\n\t\t\t}\n\t\t}\n\t);\n}, Base.each(['reverse', 'flatten', 'simplify', 'smooth'], function(key) {\n\tthis[key] = function(param) {\n\t\tvar children = this._children,\n\t\t\tres;\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tres = children[i][key](param) || res;\n\t\t}\n\t\treturn res;\n\t};\n}, {}));\n\nPathItem.inject(new function() {\n\tvar min = Math.min,\n\t\tmax = Math.max,\n\t\tabs = Math.abs,\n\t\toperators = {\n\t\t\tunite:     { '1': true, '2': true },\n\t\t\tintersect: { '2': true },\n\t\t\tsubtract:  { '1': true },\n\t\t\texclude:   { '1': true, '-1': true }\n\t\t};\n\n\tfunction preparePath(path, resolve) {\n\t\tvar res = path.clone(false).reduce({ simplify: true })\n\t\t\t\t.transform(null, true, true);\n\t\treturn resolve\n\t\t\t\t? res.resolveCrossings().reorient(\n\t\t\t\t\tres.getFillRule() === 'nonzero', true)\n\t\t\t\t: res;\n\t}\n\n\tfunction createResult(paths, simplify, path1, path2, options) {\n\t\tvar result = new CompoundPath(Item.NO_INSERT);\n\t\tresult.addChildren(paths, true);\n\t\tresult = result.reduce({ simplify: simplify });\n\t\tif (!(options && options.insert == false)) {\n\t\t\tresult.insertAbove(path2 && path1.isSibling(path2)\n\t\t\t\t\t&& path1.getIndex() < path2.getIndex() ? path2 : path1);\n\t\t}\n\t\tresult.copyAttributes(path1, true);\n\t\treturn result;\n\t}\n\n\tfunction traceBoolean(path1, path2, operation, options) {\n\t\tif (options && (options.trace == false || options.stroke) &&\n\t\t\t\t/^(subtract|intersect)$/.test(operation))\n\t\t\treturn splitBoolean(path1, path2, operation);\n\t\tvar _path1 = preparePath(path1, true),\n\t\t\t_path2 = path2 && path1 !== path2 && preparePath(path2, true),\n\t\t\toperator = operators[operation];\n\t\toperator[operation] = true;\n\t\tif (_path2 && (operator.subtract || operator.exclude)\n\t\t\t\t^ (_path2.isClockwise() ^ _path1.isClockwise()))\n\t\t\t_path2.reverse();\n\t\tvar crossings = divideLocations(\n\t\t\t\tCurveLocation.expand(_path1.getCrossings(_path2))),\n\t\t\tpaths1 = _path1._children || [_path1],\n\t\t\tpaths2 = _path2 && (_path2._children || [_path2]),\n\t\t\tsegments = [],\n\t\t\tcurves = [],\n\t\t\tpaths;\n\n\t\tfunction collect(paths) {\n\t\t\tfor (var i = 0, l = paths.length; i < l; i++) {\n\t\t\t\tvar path = paths[i];\n\t\t\t\tsegments.push.apply(segments, path._segments);\n\t\t\t\tcurves.push.apply(curves, path.getCurves());\n\t\t\t\tpath._overlapsOnly = true;\n\t\t\t}\n\t\t}\n\n\t\tif (crossings.length) {\n\t\t\tcollect(paths1);\n\t\t\tif (paths2)\n\t\t\t\tcollect(paths2);\n\t\t\tfor (var i = 0, l = crossings.length; i < l; i++) {\n\t\t\t\tpropagateWinding(crossings[i]._segment, _path1, _path2, curves,\n\t\t\t\t\t\toperator);\n\t\t\t}\n\t\t\tfor (var i = 0, l = segments.length; i < l; i++) {\n\t\t\t\tvar segment = segments[i],\n\t\t\t\t\tinter = segment._intersection;\n\t\t\t\tif (!segment._winding) {\n\t\t\t\t\tpropagateWinding(segment, _path1, _path2, curves, operator);\n\t\t\t\t}\n\t\t\t\tif (!(inter && inter._overlap))\n\t\t\t\t\tsegment._path._overlapsOnly = false;\n\t\t\t}\n\t\t\tpaths = tracePaths(segments, operator);\n\t\t} else {\n\t\t\tpaths = reorientPaths(\n\t\t\t\t\tpaths2 ? paths1.concat(paths2) : paths1.slice(),\n\t\t\t\t\tfunction(w) {\n\t\t\t\t\t\treturn !!operator[w];\n\t\t\t\t\t});\n\t\t}\n\n\t\treturn createResult(paths, true, path1, path2, options);\n\t}\n\n\tfunction splitBoolean(path1, path2, operation) {\n\t\tvar _path1 = preparePath(path1),\n\t\t\t_path2 = preparePath(path2),\n\t\t\tcrossings = _path1.getCrossings(_path2),\n\t\t\tsubtract = operation === 'subtract',\n\t\t\tdivide = operation === 'divide',\n\t\t\tadded = {},\n\t\t\tpaths = [];\n\n\t\tfunction addPath(path) {\n\t\t\tif (!added[path._id] && (divide ||\n\t\t\t\t\t_path2.contains(path.getPointAt(path.getLength() / 2))\n\t\t\t\t\t\t^ subtract)) {\n\t\t\t\tpaths.unshift(path);\n\t\t\t\treturn added[path._id] = true;\n\t\t\t}\n\t\t}\n\n\t\tfor (var i = crossings.length - 1; i >= 0; i--) {\n\t\t\tvar path = crossings[i].split();\n\t\t\tif (path) {\n\t\t\t\tif (addPath(path))\n\t\t\t\t\tpath.getFirstSegment().setHandleIn(0, 0);\n\t\t\t\t_path1.getLastSegment().setHandleOut(0, 0);\n\t\t\t}\n\t\t}\n\t\taddPath(_path1);\n\t\treturn createResult(paths, false, path1, path2);\n\t}\n\n\tfunction linkIntersections(from, to) {\n\t\tvar prev = from;\n\t\twhile (prev) {\n\t\t\tif (prev === to)\n\t\t\t\treturn;\n\t\t\tprev = prev._previous;\n\t\t}\n\t\twhile (from._next && from._next !== to)\n\t\t\tfrom = from._next;\n\t\tif (!from._next) {\n\t\t\twhile (to._previous)\n\t\t\t\tto = to._previous;\n\t\t\tfrom._next = to;\n\t\t\tto._previous = from;\n\t\t}\n\t}\n\n\tfunction clearCurveHandles(curves) {\n\t\tfor (var i = curves.length - 1; i >= 0; i--)\n\t\t\tcurves[i].clearHandles();\n\t}\n\n\tfunction reorientPaths(paths, isInside, clockwise) {\n\t\tvar length = paths && paths.length;\n\t\tif (length) {\n\t\t\tvar lookup = Base.each(paths, function (path, i) {\n\t\t\t\t\tthis[path._id] = {\n\t\t\t\t\t\tcontainer: null,\n\t\t\t\t\t\twinding: path.isClockwise() ? 1 : -1,\n\t\t\t\t\t\tindex: i\n\t\t\t\t\t};\n\t\t\t\t}, {}),\n\t\t\t\tsorted = paths.slice().sort(function (a, b) {\n\t\t\t\t\treturn abs(b.getArea()) - abs(a.getArea());\n\t\t\t\t}),\n\t\t\t\tfirst = sorted[0];\n\t\t\tif (clockwise == null)\n\t\t\t\tclockwise = first.isClockwise();\n\t\t\tfor (var i = 0; i < length; i++) {\n\t\t\t\tvar path1 = sorted[i],\n\t\t\t\t\tentry1 = lookup[path1._id],\n\t\t\t\t\tpoint = path1.getInteriorPoint(),\n\t\t\t\t\tcontainerWinding = 0;\n\t\t\t\tfor (var j = i - 1; j >= 0; j--) {\n\t\t\t\t\tvar path2 = sorted[j];\n\t\t\t\t\tif (path2.contains(point)) {\n\t\t\t\t\t\tvar entry2 = lookup[path2._id];\n\t\t\t\t\t\tcontainerWinding = entry2.winding;\n\t\t\t\t\t\tentry1.winding += containerWinding;\n\t\t\t\t\t\tentry1.container = entry2.exclude ? entry2.container\n\t\t\t\t\t\t\t\t: path2;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (isInside(entry1.winding) === isInside(containerWinding)) {\n\t\t\t\t\tentry1.exclude = true;\n\t\t\t\t\tpaths[entry1.index] = null;\n\t\t\t\t} else {\n\t\t\t\t\tvar container = entry1.container;\n\t\t\t\t\tpath1.setClockwise(container ? !container.isClockwise()\n\t\t\t\t\t\t\t: clockwise);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn paths;\n\t}\n\n\tfunction divideLocations(locations, include, clearLater) {\n\t\tvar results = include && [],\n\t\t\ttMin = 1e-8,\n\t\t\ttMax = 1 - tMin,\n\t\t\tclearHandles = false,\n\t\t\tclearCurves = clearLater || [],\n\t\t\tclearLookup = clearLater && {},\n\t\t\trenormalizeLocs,\n\t\t\tprevCurve,\n\t\t\tprevTime;\n\n\t\tfunction getId(curve) {\n\t\t\treturn curve._path._id + '.' + curve._segment1._index;\n\t\t}\n\n\t\tfor (var i = (clearLater && clearLater.length) - 1; i >= 0; i--) {\n\t\t\tvar curve = clearLater[i];\n\t\t\tif (curve._path)\n\t\t\t\tclearLookup[getId(curve)] = true;\n\t\t}\n\n\t\tfor (var i = locations.length - 1; i >= 0; i--) {\n\t\t\tvar loc = locations[i],\n\t\t\t\ttime = loc._time,\n\t\t\t\torigTime = time,\n\t\t\t\texclude = include && !include(loc),\n\t\t\t\tcurve = loc._curve,\n\t\t\t\tsegment;\n\t\t\tif (curve) {\n\t\t\t\tif (curve !== prevCurve) {\n\t\t\t\t\tclearHandles = !curve.hasHandles()\n\t\t\t\t\t\t\t|| clearLookup && clearLookup[getId(curve)];\n\t\t\t\t\trenormalizeLocs = [];\n\t\t\t\t\tprevTime = null;\n\t\t\t\t\tprevCurve = curve;\n\t\t\t\t} else if (prevTime >= tMin) {\n\t\t\t\t\ttime /= prevTime;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (exclude) {\n\t\t\t\tif (renormalizeLocs)\n\t\t\t\t\trenormalizeLocs.push(loc);\n\t\t\t\tcontinue;\n\t\t\t} else if (include) {\n\t\t\t\tresults.unshift(loc);\n\t\t\t}\n\t\t\tprevTime = origTime;\n\t\t\tif (time < tMin) {\n\t\t\t\tsegment = curve._segment1;\n\t\t\t} else if (time > tMax) {\n\t\t\t\tsegment = curve._segment2;\n\t\t\t} else {\n\t\t\t\tvar newCurve = curve.divideAtTime(time, true);\n\t\t\t\tif (clearHandles)\n\t\t\t\t\tclearCurves.push(curve, newCurve);\n\t\t\t\tsegment = newCurve._segment1;\n\t\t\t\tfor (var j = renormalizeLocs.length - 1; j >= 0; j--) {\n\t\t\t\t\tvar l = renormalizeLocs[j];\n\t\t\t\t\tl._time = (l._time - time) / (1 - time);\n\t\t\t\t}\n\t\t\t}\n\t\t\tloc._setSegment(segment);\n\t\t\tvar inter = segment._intersection,\n\t\t\t\tdest = loc._intersection;\n\t\t\tif (inter) {\n\t\t\t\tlinkIntersections(inter, dest);\n\t\t\t\tvar other = inter;\n\t\t\t\twhile (other) {\n\t\t\t\t\tlinkIntersections(other._intersection, inter);\n\t\t\t\t\tother = other._next;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsegment._intersection = dest;\n\t\t\t}\n\t\t}\n\t\tif (!clearLater)\n\t\t\tclearCurveHandles(clearCurves);\n\t\treturn results || locations;\n\t}\n\n\tfunction getWinding(point, curves, dir, closed, dontFlip) {\n\t\tvar ia = dir ? 1 : 0,\n\t\t\tio = ia ^ 1,\n\t\t\tpv = [point.x, point.y],\n\t\t\tpa = pv[ia],\n\t\t\tpo = pv[io],\n\t\t\twindingEpsilon = 1e-9,\n\t\t\tqualityEpsilon = 1e-6,\n\t\t\tpaL = pa - windingEpsilon,\n\t\t\tpaR = pa + windingEpsilon,\n\t\t\twindingL = 0,\n\t\t\twindingR = 0,\n\t\t\tpathWindingL = 0,\n\t\t\tpathWindingR = 0,\n\t\t\tonPath = false,\n\t\t\tonAnyPath = false,\n\t\t\tquality = 1,\n\t\t\troots = [],\n\t\t\tvPrev,\n\t\t\tvClose;\n\n\t\tfunction addWinding(v) {\n\t\t\tvar o0 = v[io + 0],\n\t\t\t\to3 = v[io + 6];\n\t\t\tif (po < min(o0, o3) || po > max(o0, o3)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar a0 = v[ia + 0],\n\t\t\t\ta1 = v[ia + 2],\n\t\t\t\ta2 = v[ia + 4],\n\t\t\t\ta3 = v[ia + 6];\n\t\t\tif (o0 === o3) {\n\t\t\t\tif (a0 < paR && a3 > paL || a3 < paR && a0 > paL) {\n\t\t\t\t\tonPath = true;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar t =   po === o0 ? 0\n\t\t\t\t\t: po === o3 ? 1\n\t\t\t\t\t: paL > max(a0, a1, a2, a3) || paR < min(a0, a1, a2, a3)\n\t\t\t\t\t? 1\n\t\t\t\t\t: Curve.solveCubic(v, io, po, roots, 0, 1) > 0\n\t\t\t\t\t\t? roots[0]\n\t\t\t\t\t\t: 1,\n\t\t\t\ta =   t === 0 ? a0\n\t\t\t\t\t: t === 1 ? a3\n\t\t\t\t\t: Curve.getPoint(v, t)[dir ? 'y' : 'x'],\n\t\t\t\twinding = o0 > o3 ? 1 : -1,\n\t\t\t\twindingPrev = vPrev[io] > vPrev[io + 6] ? 1 : -1,\n\t\t\t\ta3Prev = vPrev[ia + 6];\n\t\t\tif (po !== o0) {\n\t\t\t\tif (a < paL) {\n\t\t\t\t\tpathWindingL += winding;\n\t\t\t\t} else if (a > paR) {\n\t\t\t\t\tpathWindingR += winding;\n\t\t\t\t} else {\n\t\t\t\t\tonPath = true;\n\t\t\t\t}\n\t\t\t\tif (a > pa - qualityEpsilon && a < pa + qualityEpsilon)\n\t\t\t\t\tquality /= 2;\n\t\t\t} else {\n\t\t\t\tif (winding !== windingPrev) {\n\t\t\t\t\tif (a0 < paL) {\n\t\t\t\t\t\tpathWindingL += winding;\n\t\t\t\t\t} else if (a0 > paR) {\n\t\t\t\t\t\tpathWindingR += winding;\n\t\t\t\t\t}\n\t\t\t\t} else if (a0 != a3Prev) {\n\t\t\t\t\tif (a3Prev < paR && a > paR) {\n\t\t\t\t\t\tpathWindingR += winding;\n\t\t\t\t\t\tonPath = true;\n\t\t\t\t\t} else if (a3Prev > paL && a < paL) {\n\t\t\t\t\t\tpathWindingL += winding;\n\t\t\t\t\t\tonPath = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tquality = 0;\n\t\t\t}\n\t\t\tvPrev = v;\n\t\t\treturn !dontFlip && a > paL && a < paR\n\t\t\t\t\t&& Curve.getTangent(v, t)[dir ? 'x' : 'y'] === 0\n\t\t\t\t\t&& getWinding(point, curves, !dir, closed, true);\n\t\t}\n\n\t\tfunction handleCurve(v) {\n\t\t\tvar o0 = v[io + 0],\n\t\t\t\to1 = v[io + 2],\n\t\t\t\to2 = v[io + 4],\n\t\t\t\to3 = v[io + 6];\n\t\t\tif (po <= max(o0, o1, o2, o3) && po >= min(o0, o1, o2, o3)) {\n\t\t\t\tvar a0 = v[ia + 0],\n\t\t\t\t\ta1 = v[ia + 2],\n\t\t\t\t\ta2 = v[ia + 4],\n\t\t\t\t\ta3 = v[ia + 6],\n\t\t\t\t\tmonoCurves = paL > max(a0, a1, a2, a3) ||\n\t\t\t\t\t\t\t\t paR < min(a0, a1, a2, a3)\n\t\t\t\t\t\t\t? [v] : Curve.getMonoCurves(v, dir),\n\t\t\t\t\tres;\n\t\t\t\tfor (var i = 0, l = monoCurves.length; i < l; i++) {\n\t\t\t\t\tif (res = addWinding(monoCurves[i]))\n\t\t\t\t\t\treturn res;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (var i = 0, l = curves.length; i < l; i++) {\n\t\t\tvar curve = curves[i],\n\t\t\t\tpath = curve._path,\n\t\t\t\tv = curve.getValues(),\n\t\t\t\tres;\n\t\t\tif (!i || curves[i - 1]._path !== path) {\n\t\t\t\tvPrev = null;\n\t\t\t\tif (!path._closed) {\n\t\t\t\t\tvClose = Curve.getValues(\n\t\t\t\t\t\t\tpath.getLastCurve().getSegment2(),\n\t\t\t\t\t\t\tcurve.getSegment1(),\n\t\t\t\t\t\t\tnull, !closed);\n\t\t\t\t\tif (vClose[io] !== vClose[io + 6]) {\n\t\t\t\t\t\tvPrev = vClose;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!vPrev) {\n\t\t\t\t\tvPrev = v;\n\t\t\t\t\tvar prev = path.getLastCurve();\n\t\t\t\t\twhile (prev && prev !== curve) {\n\t\t\t\t\t\tvar v2 = prev.getValues();\n\t\t\t\t\t\tif (v2[io] !== v2[io + 6]) {\n\t\t\t\t\t\t\tvPrev = v2;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tprev = prev.getPrevious();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (res = handleCurve(v))\n\t\t\t\treturn res;\n\n\t\t\tif (i + 1 === l || curves[i + 1]._path !== path) {\n\t\t\t\tif (vClose && (res = handleCurve(vClose)))\n\t\t\t\t\treturn res;\n\t\t\t\tif (onPath && !pathWindingL && !pathWindingR) {\n\t\t\t\t\tpathWindingL = pathWindingR = path.isClockwise(closed) ^ dir\n\t\t\t\t\t\t\t? 1 : -1;\n\t\t\t\t}\n\t\t\t\twindingL += pathWindingL;\n\t\t\t\twindingR += pathWindingR;\n\t\t\t\tpathWindingL = pathWindingR = 0;\n\t\t\t\tif (onPath) {\n\t\t\t\t\tonAnyPath = true;\n\t\t\t\t\tonPath = false;\n\t\t\t\t}\n\t\t\t\tvClose = null;\n\t\t\t}\n\t\t}\n\t\twindingL = abs(windingL);\n\t\twindingR = abs(windingR);\n\t\treturn {\n\t\t\twinding: max(windingL, windingR),\n\t\t\twindingL: windingL,\n\t\t\twindingR: windingR,\n\t\t\tquality: quality,\n\t\t\tonPath: onAnyPath\n\t\t};\n\t}\n\n\tfunction propagateWinding(segment, path1, path2, curves, operator) {\n\t\tvar chain = [],\n\t\t\tstart = segment,\n\t\t\ttotalLength = 0,\n\t\t\twinding;\n\t\tdo {\n\t\t\tvar curve = segment.getCurve(),\n\t\t\t\tlength = curve.getLength();\n\t\t\tchain.push({ segment: segment, curve: curve, length: length });\n\t\t\ttotalLength += length;\n\t\t\tsegment = segment.getNext();\n\t\t} while (segment && !segment._intersection && segment !== start);\n\t\tvar offsets = [0.5, 0.25, 0.75],\n\t\t\twinding = { winding: 0, quality: -1 },\n\t\t\ttMin = 1e-8,\n\t\t\ttMax = 1 - tMin;\n\t\tfor (var i = 0; i < offsets.length && winding.quality < 0.5; i++) {\n\t\t\tvar length = totalLength * offsets[i];\n\t\t\tfor (var j = 0, l = chain.length; j < l; j++) {\n\t\t\t\tvar entry = chain[j],\n\t\t\t\t\tcurveLength = entry.length;\n\t\t\t\tif (length <= curveLength) {\n\t\t\t\t\tvar curve = entry.curve,\n\t\t\t\t\t\tpath = curve._path,\n\t\t\t\t\t\tparent = path._parent,\n\t\t\t\t\t\toperand = parent instanceof CompoundPath ? parent : path,\n\t\t\t\t\t\tt = Numerical.clamp(curve.getTimeAt(length), tMin, tMax),\n\t\t\t\t\t\tpt = curve.getPointAtTime(t),\n\t\t\t\t\t\tdir = abs(curve.getTangentAtTime(t).y) < Math.SQRT1_2;\n\t\t\t\t\tvar wind = !(operator.subtract && path2 && (\n\t\t\t\t\t\t\toperand === path1 &&\n\t\t\t\t\t\t\t\tpath2._getWinding(pt, dir, true).winding ||\n\t\t\t\t\t\t\toperand === path2 &&\n\t\t\t\t\t\t\t\t!path1._getWinding(pt, dir, true).winding))\n\t\t\t\t\t\t\t? getWinding(pt, curves, dir, true)\n\t\t\t\t\t\t\t: { winding: 0, quality: 1 };\n\t\t\t\t\tif (wind.quality > winding.quality)\n\t\t\t\t\t\twinding = wind;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tlength -= curveLength;\n\t\t\t}\n\t\t}\n\t\tfor (var j = chain.length - 1; j >= 0; j--) {\n\t\t\tchain[j].segment._winding = winding;\n\t\t}\n\t}\n\n\tfunction tracePaths(segments, operator) {\n\t\tvar paths = [],\n\t\t\tstarts;\n\n\t\tfunction isValid(seg) {\n\t\t\tvar winding;\n\t\t\treturn !!(seg && !seg._visited && (!operator\n\t\t\t\t\t|| operator[(winding = seg._winding || {}).winding]\n\t\t\t\t\t\t&& !(operator.unite && winding.winding === 2\n\t\t\t\t\t\t\t&& winding.windingL && winding.windingR)));\n\t\t}\n\n\t\tfunction isStart(seg) {\n\t\t\tif (seg) {\n\t\t\t\tfor (var i = 0, l = starts.length; i < l; i++) {\n\t\t\t\t\tif (seg === starts[i])\n\t\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\tfunction visitPath(path) {\n\t\t\tvar segments = path._segments;\n\t\t\tfor (var i = 0, l = segments.length; i < l; i++) {\n\t\t\t\tsegments[i]._visited = true;\n\t\t\t}\n\t\t}\n\n\t\tfunction getCrossingSegments(segment, collectStarts) {\n\t\t\tvar inter = segment._intersection,\n\t\t\t\tstart = inter,\n\t\t\t\tcrossings = [];\n\t\t\tif (collectStarts)\n\t\t\t\tstarts = [segment];\n\n\t\t\tfunction collect(inter, end) {\n\t\t\t\twhile (inter && inter !== end) {\n\t\t\t\t\tvar other = inter._segment,\n\t\t\t\t\t\tpath = other._path,\n\t\t\t\t\t\tnext = other.getNext() || path && path.getFirstSegment(),\n\t\t\t\t\t\tnextInter = next && next._intersection;\n\t\t\t\t\tif (other !== segment && (isStart(other) || isStart(next)\n\t\t\t\t\t\t|| next && (isValid(other) && (isValid(next)\n\t\t\t\t\t\t\t|| nextInter && isValid(nextInter._segment))))) {\n\t\t\t\t\t\tcrossings.push(other);\n\t\t\t\t\t}\n\t\t\t\t\tif (collectStarts)\n\t\t\t\t\t\tstarts.push(other);\n\t\t\t\t\tinter = inter._next;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (inter) {\n\t\t\t\tcollect(inter);\n\t\t\t\twhile (inter && inter._prev)\n\t\t\t\t\tinter = inter._prev;\n\t\t\t\tcollect(inter, start);\n\t\t\t}\n\t\t\treturn crossings;\n\t\t}\n\n\t\tsegments.sort(function(seg1, seg2) {\n\t\t\tvar inter1 = seg1._intersection,\n\t\t\t\tinter2 = seg2._intersection,\n\t\t\t\tover1 = !!(inter1 && inter1._overlap),\n\t\t\t\tover2 = !!(inter2 && inter2._overlap),\n\t\t\t\tpath1 = seg1._path,\n\t\t\t\tpath2 = seg2._path;\n\t\t\treturn over1 ^ over2\n\t\t\t\t\t? over1 ? 1 : -1\n\t\t\t\t\t: !inter1 ^ !inter2\n\t\t\t\t\t\t? inter1 ? 1 : -1\n\t\t\t\t\t\t: path1 !== path2\n\t\t\t\t\t\t\t? path1._id - path2._id\n\t\t\t\t\t\t\t: seg1._index - seg2._index;\n\t\t});\n\n\t\tfor (var i = 0, l = segments.length; i < l; i++) {\n\t\t\tvar seg = segments[i],\n\t\t\t\tvalid = isValid(seg),\n\t\t\t\tpath = null,\n\t\t\t\tfinished = false,\n\t\t\t\tclosed = true,\n\t\t\t\tbranches = [],\n\t\t\t\tbranch,\n\t\t\t\tvisited,\n\t\t\t\thandleIn;\n\t\t\tif (valid && seg._path._overlapsOnly) {\n\t\t\t\tvar path1 = seg._path,\n\t\t\t\t\tpath2 = seg._intersection._segment._path;\n\t\t\t\tif (path1.compare(path2)) {\n\t\t\t\t\tif (path1.getArea())\n\t\t\t\t\t\tpaths.push(path1.clone(false));\n\t\t\t\t\tvisitPath(path1);\n\t\t\t\t\tvisitPath(path2);\n\t\t\t\t\tvalid = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\twhile (valid) {\n\t\t\t\tvar first = !path,\n\t\t\t\t\tcrossings = getCrossingSegments(seg, first),\n\t\t\t\t\tother = crossings.shift(),\n\t\t\t\t\tfinished = !first && (isStart(seg) || isStart(other)),\n\t\t\t\t\tcross = !finished && other;\n\t\t\t\tif (first) {\n\t\t\t\t\tpath = new Path(Item.NO_INSERT);\n\t\t\t\t\tbranch = null;\n\t\t\t\t}\n\t\t\t\tif (finished) {\n\t\t\t\t\tif (seg.isFirst() || seg.isLast())\n\t\t\t\t\t\tclosed = seg._path._closed;\n\t\t\t\t\tseg._visited = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (cross && branch) {\n\t\t\t\t\tbranches.push(branch);\n\t\t\t\t\tbranch = null;\n\t\t\t\t}\n\t\t\t\tif (!branch) {\n\t\t\t\t\tif (cross)\n\t\t\t\t\t\tcrossings.push(seg);\n\t\t\t\t\tbranch = {\n\t\t\t\t\t\tstart: path._segments.length,\n\t\t\t\t\t\tcrossings: crossings,\n\t\t\t\t\t\tvisited: visited = [],\n\t\t\t\t\t\thandleIn: handleIn\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tif (cross)\n\t\t\t\t\tseg = other;\n\t\t\t\tif (!isValid(seg)) {\n\t\t\t\t\tpath.removeSegments(branch.start);\n\t\t\t\t\tfor (var j = 0, k = visited.length; j < k; j++) {\n\t\t\t\t\t\tvisited[j]._visited = false;\n\t\t\t\t\t}\n\t\t\t\t\tvisited.length = 0;\n\t\t\t\t\tdo {\n\t\t\t\t\t\tseg = branch && branch.crossings.shift();\n\t\t\t\t\t\tif (!seg) {\n\t\t\t\t\t\t\tbranch = branches.pop();\n\t\t\t\t\t\t\tif (branch) {\n\t\t\t\t\t\t\t\tvisited = branch.visited;\n\t\t\t\t\t\t\t\thandleIn = branch.handleIn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} while (branch && !isValid(seg));\n\t\t\t\t\tif (!seg)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tvar next = seg.getNext();\n\t\t\t\tpath.add(new Segment(seg._point, handleIn,\n\t\t\t\t\t\tnext && seg._handleOut));\n\t\t\t\tseg._visited = true;\n\t\t\t\tvisited.push(seg);\n\t\t\t\tseg = next || seg._path.getFirstSegment();\n\t\t\t\thandleIn = next && next._handleIn;\n\t\t\t}\n\t\t\tif (finished) {\n\t\t\t\tif (closed) {\n\t\t\t\t\tpath.firstSegment.setHandleIn(handleIn);\n\t\t\t\t\tpath.setClosed(closed);\n\t\t\t\t}\n\t\t\t\tif (path.getArea() !== 0) {\n\t\t\t\t\tpaths.push(path);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn paths;\n\t}\n\n\treturn {\n\t\t_getWinding: function(point, dir, closed) {\n\t\t\treturn getWinding(point, this.getCurves(), dir, closed);\n\t\t},\n\n\t\tunite: function(path, options) {\n\t\t\treturn traceBoolean(this, path, 'unite', options);\n\t\t},\n\n\t\tintersect: function(path, options) {\n\t\t\treturn traceBoolean(this, path, 'intersect', options);\n\t\t},\n\n\t\tsubtract: function(path, options) {\n\t\t\treturn traceBoolean(this, path, 'subtract', options);\n\t\t},\n\n\t\texclude: function(path, options) {\n\t\t\treturn traceBoolean(this, path, 'exclude', options);\n\t\t},\n\n\t\tdivide: function(path, options) {\n\t\t\treturn options && (options.trace == false || options.stroke)\n\t\t\t\t\t? splitBoolean(this, path, 'divide')\n\t\t\t\t\t: createResult([\n\t\t\t\t\t\tthis.subtract(path, options),\n\t\t\t\t\t\tthis.intersect(path, options)\n\t\t\t\t\t], true, this, path, options);\n\t\t},\n\n\t\tresolveCrossings: function() {\n\t\t\tvar children = this._children,\n\t\t\t\tpaths = children || [this];\n\n\t\t\tfunction hasOverlap(seg) {\n\t\t\t\tvar inter = seg && seg._intersection;\n\t\t\t\treturn inter && inter._overlap;\n\t\t\t}\n\n\t\t\tvar hasOverlaps = false,\n\t\t\t\thasCrossings = false,\n\t\t\t\tintersections = this.getIntersections(null, function(inter) {\n\t\t\t\t\treturn inter.hasOverlap() && (hasOverlaps = true) ||\n\t\t\t\t\t\t\tinter.isCrossing() && (hasCrossings = true);\n\t\t\t\t}),\n\t\t\t\tclearCurves = hasOverlaps && hasCrossings && [];\n\t\t\tintersections = CurveLocation.expand(intersections);\n\t\t\tif (hasOverlaps) {\n\t\t\t\tvar overlaps = divideLocations(intersections, function(inter) {\n\t\t\t\t\treturn inter.hasOverlap();\n\t\t\t\t}, clearCurves);\n\t\t\t\tfor (var i = overlaps.length - 1; i >= 0; i--) {\n\t\t\t\t\tvar seg = overlaps[i]._segment,\n\t\t\t\t\t\tprev = seg.getPrevious(),\n\t\t\t\t\t\tnext = seg.getNext();\n\t\t\t\t\tif (hasOverlap(prev) && hasOverlap(next)) {\n\t\t\t\t\t\tseg.remove();\n\t\t\t\t\t\tprev._handleOut._set(0, 0);\n\t\t\t\t\t\tnext._handleIn._set(0, 0);\n\t\t\t\t\t\tif (prev !== seg && !prev.getCurve().hasLength()) {\n\t\t\t\t\t\t\tnext._handleIn.set(prev._handleIn);\n\t\t\t\t\t\t\tprev.remove();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (hasCrossings) {\n\t\t\t\tdivideLocations(intersections, hasOverlaps && function(inter) {\n\t\t\t\t\tvar curve1 = inter.getCurve(),\n\t\t\t\t\t\tseg1 = inter.getSegment(),\n\t\t\t\t\t\tother = inter._intersection,\n\t\t\t\t\t\tcurve2 = other._curve,\n\t\t\t\t\t\tseg2 = other._segment;\n\t\t\t\t\tif (curve1 && curve2 && curve1._path && curve2._path)\n\t\t\t\t\t\treturn true;\n\t\t\t\t\tif (seg1)\n\t\t\t\t\t\tseg1._intersection = null;\n\t\t\t\t\tif (seg2)\n\t\t\t\t\t\tseg2._intersection = null;\n\t\t\t\t}, clearCurves);\n\t\t\t\tif (clearCurves)\n\t\t\t\t\tclearCurveHandles(clearCurves);\n\t\t\t\tpaths = tracePaths(Base.each(paths, function(path) {\n\t\t\t\t\tthis.push.apply(this, path._segments);\n\t\t\t\t}, []));\n\t\t\t}\n\t\t\tvar length = paths.length,\n\t\t\t\titem;\n\t\t\tif (length > 1 && children) {\n\t\t\t\tif (paths !== children)\n\t\t\t\t\tthis.setChildren(paths);\n\t\t\t\titem = this;\n\t\t\t} else if (length === 1 && !children) {\n\t\t\t\tif (paths[0] !== this)\n\t\t\t\t\tthis.setSegments(paths[0].removeSegments());\n\t\t\t\titem = this;\n\t\t\t}\n\t\t\tif (!item) {\n\t\t\t\titem = new CompoundPath(Item.NO_INSERT);\n\t\t\t\titem.addChildren(paths);\n\t\t\t\titem = item.reduce();\n\t\t\t\titem.copyAttributes(this);\n\t\t\t\tthis.replaceWith(item);\n\t\t\t}\n\t\t\treturn item;\n\t\t},\n\n\t\treorient: function(nonZero, clockwise) {\n\t\t\tvar children = this._children;\n\t\t\tif (children && children.length) {\n\t\t\t\tthis.setChildren(reorientPaths(this.removeChildren(),\n\t\t\t\t\t\tfunction(w) {\n\t\t\t\t\t\t\treturn !!(nonZero ? w : w & 1);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tclockwise));\n\t\t\t} else if (clockwise !== undefined) {\n\t\t\t\tthis.setClockwise(clockwise);\n\t\t\t}\n\t\t\treturn this;\n\t\t},\n\n\t\tgetInteriorPoint: function() {\n\t\t\tvar bounds = this.getBounds(),\n\t\t\t\tpoint = bounds.getCenter(true);\n\t\t\tif (!this.contains(point)) {\n\t\t\t\tvar curves = this.getCurves(),\n\t\t\t\t\ty = point.y,\n\t\t\t\t\tintercepts = [],\n\t\t\t\t\troots = [];\n\t\t\t\tfor (var i = 0, l = curves.length; i < l; i++) {\n\t\t\t\t\tvar v = curves[i].getValues(),\n\t\t\t\t\t\to0 = v[1],\n\t\t\t\t\t\to1 = v[3],\n\t\t\t\t\t\to2 = v[5],\n\t\t\t\t\t\to3 = v[7];\n\t\t\t\t\tif (y >= min(o0, o1, o2, o3) && y <= max(o0, o1, o2, o3)) {\n\t\t\t\t\t\tvar monoCurves = Curve.getMonoCurves(v);\n\t\t\t\t\t\tfor (var j = 0, m = monoCurves.length; j < m; j++) {\n\t\t\t\t\t\t\tvar mv = monoCurves[j],\n\t\t\t\t\t\t\t\tmo0 = mv[1],\n\t\t\t\t\t\t\t\tmo3 = mv[7];\n\t\t\t\t\t\t\tif ((mo0 !== mo3) &&\n\t\t\t\t\t\t\t\t(y >= mo0 && y <= mo3 || y >= mo3 && y <= mo0)){\n\t\t\t\t\t\t\t\tvar x = y === mo0 ? mv[0]\n\t\t\t\t\t\t\t\t\t: y === mo3 ? mv[6]\n\t\t\t\t\t\t\t\t\t: Curve.solveCubic(mv, 1, y, roots, 0, 1)\n\t\t\t\t\t\t\t\t\t\t=== 1\n\t\t\t\t\t\t\t\t\t\t? Curve.getPoint(mv, roots[0]).x\n\t\t\t\t\t\t\t\t\t\t: (mv[0] + mv[6]) / 2;\n\t\t\t\t\t\t\t\tintercepts.push(x);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (intercepts.length > 1) {\n\t\t\t\t\tintercepts.sort(function(a, b) { return a - b; });\n\t\t\t\t\tpoint.x = (intercepts[0] + intercepts[1]) / 2;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn point;\n\t\t}\n\t};\n});\n\nvar PathFlattener = Base.extend({\n\t_class: 'PathFlattener',\n\n\tinitialize: function(path, flatness, maxRecursion, ignoreStraight, matrix) {\n\t\tvar curves = [],\n\t\t\tparts = [],\n\t\t\tlength = 0,\n\t\t\tminSpan = 1 / (maxRecursion || 32),\n\t\t\tsegments = path._segments,\n\t\t\tsegment1 = segments[0],\n\t\t\tsegment2;\n\n\t\tfunction addCurve(segment1, segment2) {\n\t\t\tvar curve = Curve.getValues(segment1, segment2, matrix);\n\t\t\tcurves.push(curve);\n\t\t\tcomputeParts(curve, segment1._index, 0, 1);\n\t\t}\n\n\t\tfunction computeParts(curve, index, t1, t2) {\n\t\t\tif ((t2 - t1) > minSpan\n\t\t\t\t\t&& !(ignoreStraight && Curve.isStraight(curve))\n\t\t\t\t\t&& !Curve.isFlatEnough(curve, flatness || 0.25)) {\n\t\t\t\tvar halves = Curve.subdivide(curve, 0.5),\n\t\t\t\t\ttMid = (t1 + t2) / 2;\n\t\t\t\tcomputeParts(halves[0], index, t1, tMid);\n\t\t\t\tcomputeParts(halves[1], index, tMid, t2);\n\t\t\t} else {\n\t\t\t\tvar dx = curve[6] - curve[0],\n\t\t\t\t\tdy = curve[7] - curve[1],\n\t\t\t\t\tdist = Math.sqrt(dx * dx + dy * dy);\n\t\t\t\tif (dist > 0) {\n\t\t\t\t\tlength += dist;\n\t\t\t\t\tparts.push({\n\t\t\t\t\t\toffset: length,\n\t\t\t\t\t\tcurve: curve,\n\t\t\t\t\t\tindex: index,\n\t\t\t\t\t\ttime: t2,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (var i = 1, l = segments.length; i < l; i++) {\n\t\t\tsegment2 = segments[i];\n\t\t\taddCurve(segment1, segment2);\n\t\t\tsegment1 = segment2;\n\t\t}\n\t\tif (path._closed)\n\t\t\taddCurve(segment2, segments[0]);\n\t\tthis.curves = curves;\n\t\tthis.parts = parts;\n\t\tthis.length = length;\n\t\tthis.index = 0;\n\t},\n\n\t_get: function(offset) {\n\t\tvar parts = this.parts,\n\t\t\tlength = parts.length,\n\t\t\tstart,\n\t\t\ti, j = this.index;\n\t\tfor (;;) {\n\t\t\ti = j;\n\t\t\tif (!j || parts[--j].offset < offset)\n\t\t\t\tbreak;\n\t\t}\n\t\tfor (; i < length; i++) {\n\t\t\tvar part = parts[i];\n\t\t\tif (part.offset >= offset) {\n\t\t\t\tthis.index = i;\n\t\t\t\tvar prev = parts[i - 1],\n\t\t\t\t\tprevTime = prev && prev.index === part.index ? prev.time : 0,\n\t\t\t\t\tprevOffset = prev ? prev.offset : 0;\n\t\t\t\treturn {\n\t\t\t\t\tindex: part.index,\n\t\t\t\t\ttime: prevTime + (part.time - prevTime)\n\t\t\t\t\t\t* (offset - prevOffset) / (part.offset - prevOffset)\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tindex: parts[length - 1].index,\n\t\t\ttime: 1\n\t\t};\n\t},\n\n\tdrawPart: function(ctx, from, to) {\n\t\tvar start = this._get(from),\n\t\t\tend = this._get(to);\n\t\tfor (var i = start.index, l = end.index; i <= l; i++) {\n\t\t\tvar curve = Curve.getPart(this.curves[i],\n\t\t\t\t\ti === start.index ? start.time : 0,\n\t\t\t\t\ti === end.index ? end.time : 1);\n\t\t\tif (i === start.index)\n\t\t\t\tctx.moveTo(curve[0], curve[1]);\n\t\t\tctx.bezierCurveTo.apply(ctx, curve.slice(2));\n\t\t}\n\t}\n}, Base.each(Curve._evaluateMethods,\n\tfunction(name) {\n\t\tthis[name + 'At'] = function(offset) {\n\t\t\tvar param = this._get(offset);\n\t\t\treturn Curve[name](this.curves[param.index], param.time);\n\t\t};\n\t}, {})\n);\n\nvar PathFitter = Base.extend({\n\tinitialize: function(path) {\n\t\tvar points = this.points = [],\n\t\t\tsegments = path._segments,\n\t\t\tclosed = path._closed;\n\t\tfor (var i = 0, prev, l = segments.length; i < l; i++) {\n\t\t\tvar point = segments[i].point;\n\t\t\tif (!prev || !prev.equals(point)) {\n\t\t\t\tpoints.push(prev = point.clone());\n\t\t\t}\n\t\t}\n\t\tif (closed) {\n\t\t\tpoints.unshift(points[points.length - 1]);\n\t\t\tpoints.push(points[1]);\n\t\t}\n\t\tthis.closed = closed;\n\t},\n\n\tfit: function(error) {\n\t\tvar points = this.points,\n\t\t\tlength = points.length,\n\t\t\tsegments = null;\n\t\tif (length > 0) {\n\t\t\tsegments = [new Segment(points[0])];\n\t\t\tif (length > 1) {\n\t\t\t\tthis.fitCubic(segments, error, 0, length - 1,\n\t\t\t\t\t\tpoints[1].subtract(points[0]),\n\t\t\t\t\t\tpoints[length - 2].subtract(points[length - 1]));\n\t\t\t\tif (this.closed) {\n\t\t\t\t\tsegments.shift();\n\t\t\t\t\tsegments.pop();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn segments;\n\t},\n\n\tfitCubic: function(segments, error, first, last, tan1, tan2) {\n\t\tvar points = this.points;\n\t\tif (last - first === 1) {\n\t\t\tvar pt1 = points[first],\n\t\t\t\tpt2 = points[last],\n\t\t\t\tdist = pt1.getDistance(pt2) / 3;\n\t\t\tthis.addCurve(segments, [pt1, pt1.add(tan1.normalize(dist)),\n\t\t\t\t\tpt2.add(tan2.normalize(dist)), pt2]);\n\t\t\treturn;\n\t\t}\n\t\tvar uPrime = this.chordLengthParameterize(first, last),\n\t\t\tmaxError = Math.max(error, error * error),\n\t\t\tsplit,\n\t\t\tparametersInOrder = true;\n\t\tfor (var i = 0; i <= 4; i++) {\n\t\t\tvar curve = this.generateBezier(first, last, uPrime, tan1, tan2);\n\t\t\tvar max = this.findMaxError(first, last, curve, uPrime);\n\t\t\tif (max.error < error && parametersInOrder) {\n\t\t\t\tthis.addCurve(segments, curve);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsplit = max.index;\n\t\t\tif (max.error >= maxError)\n\t\t\t\tbreak;\n\t\t\tparametersInOrder = this.reparameterize(first, last, uPrime, curve);\n\t\t\tmaxError = max.error;\n\t\t}\n\t\tvar tanCenter = points[split - 1].subtract(points[split + 1]);\n\t\tthis.fitCubic(segments, error, first, split, tan1, tanCenter);\n\t\tthis.fitCubic(segments, error, split, last, tanCenter.negate(), tan2);\n\t},\n\n\taddCurve: function(segments, curve) {\n\t\tvar prev = segments[segments.length - 1];\n\t\tprev.setHandleOut(curve[1].subtract(curve[0]));\n\t\tsegments.push(new Segment(curve[3], curve[2].subtract(curve[3])));\n\t},\n\n\tgenerateBezier: function(first, last, uPrime, tan1, tan2) {\n\t\tvar epsilon = 1e-12,\n\t\t\tabs = Math.abs,\n\t\t\tpoints = this.points,\n\t\t\tpt1 = points[first],\n\t\t\tpt2 = points[last],\n\t\t\tC = [[0, 0], [0, 0]],\n\t\t\tX = [0, 0];\n\n\t\tfor (var i = 0, l = last - first + 1; i < l; i++) {\n\t\t\tvar u = uPrime[i],\n\t\t\t\tt = 1 - u,\n\t\t\t\tb = 3 * u * t,\n\t\t\t\tb0 = t * t * t,\n\t\t\t\tb1 = b * t,\n\t\t\t\tb2 = b * u,\n\t\t\t\tb3 = u * u * u,\n\t\t\t\ta1 = tan1.normalize(b1),\n\t\t\t\ta2 = tan2.normalize(b2),\n\t\t\t\ttmp = points[first + i]\n\t\t\t\t\t.subtract(pt1.multiply(b0 + b1))\n\t\t\t\t\t.subtract(pt2.multiply(b2 + b3));\n\t\t\tC[0][0] += a1.dot(a1);\n\t\t\tC[0][1] += a1.dot(a2);\n\t\t\tC[1][0] = C[0][1];\n\t\t\tC[1][1] += a2.dot(a2);\n\t\t\tX[0] += a1.dot(tmp);\n\t\t\tX[1] += a2.dot(tmp);\n\t\t}\n\n\t\tvar detC0C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1],\n\t\t\talpha1,\n\t\t\talpha2;\n\t\tif (abs(detC0C1) > epsilon) {\n\t\t\tvar detC0X = C[0][0] * X[1]    - C[1][0] * X[0],\n\t\t\t\tdetXC1 = X[0]    * C[1][1] - X[1]    * C[0][1];\n\t\t\talpha1 = detXC1 / detC0C1;\n\t\t\talpha2 = detC0X / detC0C1;\n\t\t} else {\n\t\t\tvar c0 = C[0][0] + C[0][1],\n\t\t\t\tc1 = C[1][0] + C[1][1];\n\t\t\talpha1 = alpha2 = abs(c0) > epsilon ? X[0] / c0\n\t\t\t\t\t\t\t: abs(c1) > epsilon ? X[1] / c1\n\t\t\t\t\t\t\t: 0;\n\t\t}\n\n\t\tvar segLength = pt2.getDistance(pt1),\n\t\t\teps = epsilon * segLength,\n\t\t\thandle1,\n\t\t\thandle2;\n\t\tif (alpha1 < eps || alpha2 < eps) {\n\t\t\talpha1 = alpha2 = segLength / 3;\n\t\t} else {\n\t\t\tvar line = pt2.subtract(pt1);\n\t\t\thandle1 = tan1.normalize(alpha1);\n\t\t\thandle2 = tan2.normalize(alpha2);\n\t\t\tif (handle1.dot(line) - handle2.dot(line) > segLength * segLength) {\n\t\t\t\talpha1 = alpha2 = segLength / 3;\n\t\t\t\thandle1 = handle2 = null;\n\t\t\t}\n\t\t}\n\n\t\treturn [pt1,\n\t\t\t\tpt1.add(handle1 || tan1.normalize(alpha1)),\n\t\t\t\tpt2.add(handle2 || tan2.normalize(alpha2)),\n\t\t\t\tpt2];\n\t},\n\n\treparameterize: function(first, last, u, curve) {\n\t\tfor (var i = first; i <= last; i++) {\n\t\t\tu[i - first] = this.findRoot(curve, this.points[i], u[i - first]);\n\t\t}\n\t\tfor (var i = 1, l = u.length; i < l; i++) {\n\t\t\tif (u[i] <= u[i - 1])\n\t\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\tfindRoot: function(curve, point, u) {\n\t\tvar curve1 = [],\n\t\t\tcurve2 = [];\n\t\tfor (var i = 0; i <= 2; i++) {\n\t\t\tcurve1[i] = curve[i + 1].subtract(curve[i]).multiply(3);\n\t\t}\n\t\tfor (var i = 0; i <= 1; i++) {\n\t\t\tcurve2[i] = curve1[i + 1].subtract(curve1[i]).multiply(2);\n\t\t}\n\t\tvar pt = this.evaluate(3, curve, u),\n\t\t\tpt1 = this.evaluate(2, curve1, u),\n\t\t\tpt2 = this.evaluate(1, curve2, u),\n\t\t\tdiff = pt.subtract(point),\n\t\t\tdf = pt1.dot(pt1) + diff.dot(pt2);\n\t\treturn Numerical.isZero(df) ? u : u - diff.dot(pt1) / df;\n\t},\n\n\tevaluate: function(degree, curve, t) {\n\t\tvar tmp = curve.slice();\n\t\tfor (var i = 1; i <= degree; i++) {\n\t\t\tfor (var j = 0; j <= degree - i; j++) {\n\t\t\t\ttmp[j] = tmp[j].multiply(1 - t).add(tmp[j + 1].multiply(t));\n\t\t\t}\n\t\t}\n\t\treturn tmp[0];\n\t},\n\n\tchordLengthParameterize: function(first, last) {\n\t\tvar u = [0];\n\t\tfor (var i = first + 1; i <= last; i++) {\n\t\t\tu[i - first] = u[i - first - 1]\n\t\t\t\t\t+ this.points[i].getDistance(this.points[i - 1]);\n\t\t}\n\t\tfor (var i = 1, m = last - first; i <= m; i++) {\n\t\t\tu[i] /= u[m];\n\t\t}\n\t\treturn u;\n\t},\n\n\tfindMaxError: function(first, last, curve, u) {\n\t\tvar index = Math.floor((last - first + 1) / 2),\n\t\t\tmaxDist = 0;\n\t\tfor (var i = first + 1; i < last; i++) {\n\t\t\tvar P = this.evaluate(3, curve, u[i - first]);\n\t\t\tvar v = P.subtract(this.points[i]);\n\t\t\tvar dist = v.x * v.x + v.y * v.y;\n\t\t\tif (dist >= maxDist) {\n\t\t\t\tmaxDist = dist;\n\t\t\t\tindex = i;\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\terror: maxDist,\n\t\t\tindex: index\n\t\t};\n\t}\n});\n\nvar TextItem = Item.extend({\n\t_class: 'TextItem',\n\t_applyMatrix: false,\n\t_canApplyMatrix: false,\n\t_serializeFields: {\n\t\tcontent: null\n\t},\n\t_boundsOptions: { stroke: false, handle: false },\n\n\tinitialize: function TextItem(arg) {\n\t\tthis._content = '';\n\t\tthis._lines = [];\n\t\tvar hasProps = arg && Base.isPlainObject(arg)\n\t\t\t\t&& arg.x === undefined && arg.y === undefined;\n\t\tthis._initialize(hasProps && arg, !hasProps && Point.read(arguments));\n\t},\n\n\t_equals: function(item) {\n\t\treturn this._content === item._content;\n\t},\n\n\tcopyContent: function(source) {\n\t\tthis.setContent(source._content);\n\t},\n\n\tgetContent: function() {\n\t\treturn this._content;\n\t},\n\n\tsetContent: function(content) {\n\t\tthis._content = '' + content;\n\t\tthis._lines = this._content.split(/\\r\\n|\\n|\\r/mg);\n\t\tthis._changed(265);\n\t},\n\n\tisEmpty: function() {\n\t\treturn !this._content;\n\t},\n\n\tgetCharacterStyle: '#getStyle',\n\tsetCharacterStyle: '#setStyle',\n\n\tgetParagraphStyle: '#getStyle',\n\tsetParagraphStyle: '#setStyle'\n});\n\nvar PointText = TextItem.extend({\n\t_class: 'PointText',\n\n\tinitialize: function PointText() {\n\t\tTextItem.apply(this, arguments);\n\t},\n\n\tgetPoint: function() {\n\t\tvar point = this._matrix.getTranslation();\n\t\treturn new LinkedPoint(point.x, point.y, this, 'setPoint');\n\t},\n\n\tsetPoint: function() {\n\t\tvar point = Point.read(arguments);\n\t\tthis.translate(point.subtract(this._matrix.getTranslation()));\n\t},\n\n\t_draw: function(ctx, param, viewMatrix) {\n\t\tif (!this._content)\n\t\t\treturn;\n\t\tthis._setStyles(ctx, param, viewMatrix);\n\t\tvar lines = this._lines,\n\t\t\tstyle = this._style,\n\t\t\thasFill = style.hasFill(),\n\t\t\thasStroke = style.hasStroke(),\n\t\t\tleading = style.getLeading(),\n\t\t\tshadowColor = ctx.shadowColor;\n\t\tctx.font = style.getFontStyle();\n\t\tctx.textAlign = style.getJustification();\n\t\tfor (var i = 0, l = lines.length; i < l; i++) {\n\t\t\tctx.shadowColor = shadowColor;\n\t\t\tvar line = lines[i];\n\t\t\tif (hasFill) {\n\t\t\t\tctx.fillText(line, 0, 0);\n\t\t\t\tctx.shadowColor = 'rgba(0,0,0,0)';\n\t\t\t}\n\t\t\tif (hasStroke)\n\t\t\t\tctx.strokeText(line, 0, 0);\n\t\t\tctx.translate(0, leading);\n\t\t}\n\t},\n\n\t_getBounds: function(matrix, options) {\n\t\tvar style = this._style,\n\t\t\tlines = this._lines,\n\t\t\tnumLines = lines.length,\n\t\t\tjustification = style.getJustification(),\n\t\t\tleading = style.getLeading(),\n\t\t\twidth = this.getView().getTextWidth(style.getFontStyle(), lines),\n\t\t\tx = 0;\n\t\tif (justification !== 'left')\n\t\t\tx -= width / (justification === 'center' ? 2: 1);\n\t\tvar rect = new Rectangle(x,\n\t\t\t\t\tnumLines ? - 0.75 * leading : 0,\n\t\t\t\t\twidth, numLines * leading);\n\t\treturn matrix ? matrix._transformBounds(rect, rect) : rect;\n\t}\n});\n\nvar Color = Base.extend(new function() {\n\tvar types = {\n\t\tgray: ['gray'],\n\t\trgb: ['red', 'green', 'blue'],\n\t\thsb: ['hue', 'saturation', 'brightness'],\n\t\thsl: ['hue', 'saturation', 'lightness'],\n\t\tgradient: ['gradient', 'origin', 'destination', 'highlight']\n\t};\n\n\tvar componentParsers = {},\n\t\tcolorCache = {},\n\t\tcolorCtx;\n\n\tfunction fromCSS(string) {\n\t\tvar match = string.match(/^#(\\w{1,2})(\\w{1,2})(\\w{1,2})$/),\n\t\t\tcomponents;\n\t\tif (match) {\n\t\t\tcomponents = [0, 0, 0];\n\t\t\tfor (var i = 0; i < 3; i++) {\n\t\t\t\tvar value = match[i + 1];\n\t\t\t\tcomponents[i] = parseInt(value.length == 1\n\t\t\t\t\t\t? value + value : value, 16) / 255;\n\t\t\t}\n\t\t} else if (match = string.match(/^rgba?\\((.*)\\)$/)) {\n\t\t\tcomponents = match[1].split(',');\n\t\t\tfor (var i = 0, l = components.length; i < l; i++) {\n\t\t\t\tvar value = +components[i];\n\t\t\t\tcomponents[i] = i < 3 ? value / 255 : value;\n\t\t\t}\n\t\t} else if (window) {\n\t\t\tvar cached = colorCache[string];\n\t\t\tif (!cached) {\n\t\t\t\tif (!colorCtx) {\n\t\t\t\t\tcolorCtx = CanvasProvider.getContext(1, 1);\n\t\t\t\t\tcolorCtx.globalCompositeOperation = 'copy';\n\t\t\t\t}\n\t\t\t\tcolorCtx.fillStyle = 'rgba(0,0,0,0)';\n\t\t\t\tcolorCtx.fillStyle = string;\n\t\t\t\tcolorCtx.fillRect(0, 0, 1, 1);\n\t\t\t\tvar data = colorCtx.getImageData(0, 0, 1, 1).data;\n\t\t\t\tcached = colorCache[string] = [\n\t\t\t\t\tdata[0] / 255,\n\t\t\t\t\tdata[1] / 255,\n\t\t\t\t\tdata[2] / 255\n\t\t\t\t];\n\t\t\t}\n\t\t\tcomponents = cached.slice();\n\t\t} else {\n\t\t\tcomponents = [0, 0, 0];\n\t\t}\n\t\treturn components;\n\t}\n\n\tvar hsbIndices = [\n\t\t[0, 3, 1],\n\t\t[2, 0, 1],\n\t\t[1, 0, 3],\n\t\t[1, 2, 0],\n\t\t[3, 1, 0],\n\t\t[0, 1, 2]\n\t];\n\n\tvar converters = {\n\t\t'rgb-hsb': function(r, g, b) {\n\t\t\tvar max = Math.max(r, g, b),\n\t\t\t\tmin = Math.min(r, g, b),\n\t\t\t\tdelta = max - min,\n\t\t\t\th = delta === 0 ? 0\n\t\t\t\t\t:   ( max == r ? (g - b) / delta + (g < b ? 6 : 0)\n\t\t\t\t\t\t: max == g ? (b - r) / delta + 2\n\t\t\t\t\t\t:            (r - g) / delta + 4) * 60;\n\t\t\treturn [h, max === 0 ? 0 : delta / max, max];\n\t\t},\n\n\t\t'hsb-rgb': function(h, s, b) {\n\t\t\th = (((h / 60) % 6) + 6) % 6;\n\t\t\tvar i = Math.floor(h),\n\t\t\t\tf = h - i,\n\t\t\t\ti = hsbIndices[i],\n\t\t\t\tv = [\n\t\t\t\t\tb,\n\t\t\t\t\tb * (1 - s),\n\t\t\t\t\tb * (1 - s * f),\n\t\t\t\t\tb * (1 - s * (1 - f))\n\t\t\t\t];\n\t\t\treturn [v[i[0]], v[i[1]], v[i[2]]];\n\t\t},\n\n\t\t'rgb-hsl': function(r, g, b) {\n\t\t\tvar max = Math.max(r, g, b),\n\t\t\t\tmin = Math.min(r, g, b),\n\t\t\t\tdelta = max - min,\n\t\t\t\tachromatic = delta === 0,\n\t\t\t\th = achromatic ? 0\n\t\t\t\t\t:   ( max == r ? (g - b) / delta + (g < b ? 6 : 0)\n\t\t\t\t\t\t: max == g ? (b - r) / delta + 2\n\t\t\t\t\t\t:            (r - g) / delta + 4) * 60,\n\t\t\t\tl = (max + min) / 2,\n\t\t\t\ts = achromatic ? 0 : l < 0.5\n\t\t\t\t\t\t? delta / (max + min)\n\t\t\t\t\t\t: delta / (2 - max - min);\n\t\t\treturn [h, s, l];\n\t\t},\n\n\t\t'hsl-rgb': function(h, s, l) {\n\t\t\th = (((h / 360) % 1) + 1) % 1;\n\t\t\tif (s === 0)\n\t\t\t\treturn [l, l, l];\n\t\t\tvar t3s = [ h + 1 / 3, h, h - 1 / 3 ],\n\t\t\t\tt2 = l < 0.5 ? l * (1 + s) : l + s - l * s,\n\t\t\t\tt1 = 2 * l - t2,\n\t\t\t\tc = [];\n\t\t\tfor (var i = 0; i < 3; i++) {\n\t\t\t\tvar t3 = t3s[i];\n\t\t\t\tif (t3 < 0) t3 += 1;\n\t\t\t\tif (t3 > 1) t3 -= 1;\n\t\t\t\tc[i] = 6 * t3 < 1\n\t\t\t\t\t? t1 + (t2 - t1) * 6 * t3\n\t\t\t\t\t: 2 * t3 < 1\n\t\t\t\t\t\t? t2\n\t\t\t\t\t\t: 3 * t3 < 2\n\t\t\t\t\t\t\t? t1 + (t2 - t1) * ((2 / 3) - t3) * 6\n\t\t\t\t\t\t\t: t1;\n\t\t\t}\n\t\t\treturn c;\n\t\t},\n\n\t\t'rgb-gray': function(r, g, b) {\n\t\t\treturn [r * 0.2989 + g * 0.587 + b * 0.114];\n\t\t},\n\n\t\t'gray-rgb': function(g) {\n\t\t\treturn [g, g, g];\n\t\t},\n\n\t\t'gray-hsb': function(g) {\n\t\t\treturn [0, 0, g];\n\t\t},\n\n\t\t'gray-hsl': function(g) {\n\t\t\treturn [0, 0, g];\n\t\t},\n\n\t\t'gradient-rgb': function() {\n\t\t\treturn [];\n\t\t},\n\n\t\t'rgb-gradient': function() {\n\t\t\treturn [];\n\t\t}\n\n\t};\n\n\treturn Base.each(types, function(properties, type) {\n\t\tcomponentParsers[type] = [];\n\t\tBase.each(properties, function(name, index) {\n\t\t\tvar part = Base.capitalize(name),\n\t\t\t\thasOverlap = /^(hue|saturation)$/.test(name),\n\t\t\t\tparser = componentParsers[type][index] = name === 'gradient'\n\t\t\t\t\t? function(value) {\n\t\t\t\t\t\tvar current = this._components[0];\n\t\t\t\t\t\tvalue = Gradient.read(Array.isArray(value) ? value\n\t\t\t\t\t\t\t\t: arguments, 0, { readNull: true });\n\t\t\t\t\t\tif (current !== value) {\n\t\t\t\t\t\t\tif (current)\n\t\t\t\t\t\t\t\tcurrent._removeOwner(this);\n\t\t\t\t\t\t\tif (value)\n\t\t\t\t\t\t\t\tvalue._addOwner(this);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn value;\n\t\t\t\t\t}\n\t\t\t\t\t: type === 'gradient'\n\t\t\t\t\t\t? function() {\n\t\t\t\t\t\t\treturn Point.read(arguments, 0, {\n\t\t\t\t\t\t\t\t\treadNull: name === 'highlight',\n\t\t\t\t\t\t\t\t\tclone: true\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\t: function(value) {\n\t\t\t\t\t\t\treturn value == null || isNaN(value) ? 0 : value;\n\t\t\t\t\t\t};\n\n\t\t\tthis['get' + part] = function() {\n\t\t\t\treturn this._type === type\n\t\t\t\t\t|| hasOverlap && /^hs[bl]$/.test(this._type)\n\t\t\t\t\t\t? this._components[index]\n\t\t\t\t\t\t: this._convert(type)[index];\n\t\t\t};\n\n\t\t\tthis['set' + part] = function(value) {\n\t\t\t\tif (this._type !== type\n\t\t\t\t\t\t&& !(hasOverlap && /^hs[bl]$/.test(this._type))) {\n\t\t\t\t\tthis._components = this._convert(type);\n\t\t\t\t\tthis._properties = types[type];\n\t\t\t\t\tthis._type = type;\n\t\t\t\t}\n\t\t\t\tthis._components[index] = parser.call(this, value);\n\t\t\t\tthis._changed();\n\t\t\t};\n\t\t}, this);\n\t}, {\n\t\t_class: 'Color',\n\t\t_readIndex: true,\n\n\t\tinitialize: function Color(arg) {\n\t\t\tvar args = arguments,\n\t\t\t\treading = this.__read,\n\t\t\t\tread = 0,\n\t\t\t\ttype,\n\t\t\t\tcomponents,\n\t\t\t\talpha,\n\t\t\t\tvalues;\n\t\t\tif (Array.isArray(arg)) {\n\t\t\t\targs = arg;\n\t\t\t\targ = args[0];\n\t\t\t}\n\t\t\tvar argType = arg != null && typeof arg;\n\t\t\tif (argType === 'string' && arg in types) {\n\t\t\t\ttype = arg;\n\t\t\t\targ = args[1];\n\t\t\t\tif (Array.isArray(arg)) {\n\t\t\t\t\tcomponents = arg;\n\t\t\t\t\talpha = args[2];\n\t\t\t\t} else {\n\t\t\t\t\tif (reading)\n\t\t\t\t\t\tread = 1;\n\t\t\t\t\targs = Base.slice(args, 1);\n\t\t\t\t\targType = typeof arg;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!components) {\n\t\t\t\tvalues = argType === 'number'\n\t\t\t\t\t\t? args\n\t\t\t\t\t\t: argType === 'object' && arg.length != null\n\t\t\t\t\t\t\t? arg\n\t\t\t\t\t\t\t: null;\n\t\t\t\tif (values) {\n\t\t\t\t\tif (!type)\n\t\t\t\t\t\ttype = values.length >= 3\n\t\t\t\t\t\t\t\t? 'rgb'\n\t\t\t\t\t\t\t\t: 'gray';\n\t\t\t\t\tvar length = types[type].length;\n\t\t\t\t\talpha = values[length];\n\t\t\t\t\tif (reading) {\n\t\t\t\t\t\tread += values === arguments\n\t\t\t\t\t\t\t? length + (alpha != null ? 1 : 0)\n\t\t\t\t\t\t\t: 1;\n\t\t\t\t\t}\n\t\t\t\t\tif (values.length > length)\n\t\t\t\t\t\tvalues = Base.slice(values, 0, length);\n\t\t\t\t} else if (argType === 'string') {\n\t\t\t\t\ttype = 'rgb';\n\t\t\t\t\tcomponents = fromCSS(arg);\n\t\t\t\t\tif (components.length === 4) {\n\t\t\t\t\t\talpha = components[3];\n\t\t\t\t\t\tcomponents.length--;\n\t\t\t\t\t}\n\t\t\t\t} else if (argType === 'object') {\n\t\t\t\t\tif (arg.constructor === Color) {\n\t\t\t\t\t\ttype = arg._type;\n\t\t\t\t\t\tcomponents = arg._components.slice();\n\t\t\t\t\t\talpha = arg._alpha;\n\t\t\t\t\t\tif (type === 'gradient') {\n\t\t\t\t\t\t\tfor (var i = 1, l = components.length; i < l; i++) {\n\t\t\t\t\t\t\t\tvar point = components[i];\n\t\t\t\t\t\t\t\tif (point)\n\t\t\t\t\t\t\t\t\tcomponents[i] = point.clone();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (arg.constructor === Gradient) {\n\t\t\t\t\t\ttype = 'gradient';\n\t\t\t\t\t\tvalues = args;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttype = 'hue' in arg\n\t\t\t\t\t\t\t? 'lightness' in arg\n\t\t\t\t\t\t\t\t? 'hsl'\n\t\t\t\t\t\t\t\t: 'hsb'\n\t\t\t\t\t\t\t: 'gradient' in arg || 'stops' in arg\n\t\t\t\t\t\t\t\t\t|| 'radial' in arg\n\t\t\t\t\t\t\t\t? 'gradient'\n\t\t\t\t\t\t\t\t: 'gray' in arg\n\t\t\t\t\t\t\t\t\t? 'gray'\n\t\t\t\t\t\t\t\t\t: 'rgb';\n\t\t\t\t\t\tvar properties = types[type],\n\t\t\t\t\t\t\tparsers = componentParsers[type];\n\t\t\t\t\t\tthis._components = components = [];\n\t\t\t\t\t\tfor (var i = 0, l = properties.length; i < l; i++) {\n\t\t\t\t\t\t\tvar value = arg[properties[i]];\n\t\t\t\t\t\t\tif (value == null && !i && type === 'gradient'\n\t\t\t\t\t\t\t\t\t&& 'stops' in arg) {\n\t\t\t\t\t\t\t\tvalue = {\n\t\t\t\t\t\t\t\t\tstops: arg.stops,\n\t\t\t\t\t\t\t\t\tradial: arg.radial\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tvalue = parsers[i].call(this, value);\n\t\t\t\t\t\t\tif (value != null)\n\t\t\t\t\t\t\t\tcomponents[i] = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t\talpha = arg.alpha;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (reading && type)\n\t\t\t\t\tread = 1;\n\t\t\t}\n\t\t\tthis._type = type || 'rgb';\n\t\t\tif (!components) {\n\t\t\t\tthis._components = components = [];\n\t\t\t\tvar parsers = componentParsers[this._type];\n\t\t\t\tfor (var i = 0, l = parsers.length; i < l; i++) {\n\t\t\t\t\tvar value = parsers[i].call(this, values && values[i]);\n\t\t\t\t\tif (value != null)\n\t\t\t\t\t\tcomponents[i] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._components = components;\n\t\t\tthis._properties = types[this._type];\n\t\t\tthis._alpha = alpha;\n\t\t\tif (reading)\n\t\t\t\tthis.__read = read;\n\t\t\treturn this;\n\t\t},\n\n\t\tset: '#initialize',\n\n\t\t_serialize: function(options, dictionary) {\n\t\t\tvar components = this.getComponents();\n\t\t\treturn Base.serialize(\n\t\t\t\t\t/^(gray|rgb)$/.test(this._type)\n\t\t\t\t\t\t? components\n\t\t\t\t\t\t: [this._type].concat(components),\n\t\t\t\t\toptions, true, dictionary);\n\t\t},\n\n\t\t_changed: function() {\n\t\t\tthis._canvasStyle = null;\n\t\t\tif (this._owner)\n\t\t\t\tthis._owner._changed(65);\n\t\t},\n\n\t\t_convert: function(type) {\n\t\t\tvar converter;\n\t\t\treturn this._type === type\n\t\t\t\t\t? this._components.slice()\n\t\t\t\t\t: (converter = converters[this._type + '-' + type])\n\t\t\t\t\t\t? converter.apply(this, this._components)\n\t\t\t\t\t\t: converters['rgb-' + type].apply(this,\n\t\t\t\t\t\t\tconverters[this._type + '-rgb'].apply(this,\n\t\t\t\t\t\t\t\tthis._components));\n\t\t},\n\n\t\tconvert: function(type) {\n\t\t\treturn new Color(type, this._convert(type), this._alpha);\n\t\t},\n\n\t\tgetType: function() {\n\t\t\treturn this._type;\n\t\t},\n\n\t\tsetType: function(type) {\n\t\t\tthis._components = this._convert(type);\n\t\t\tthis._properties = types[type];\n\t\t\tthis._type = type;\n\t\t},\n\n\t\tgetComponents: function() {\n\t\t\tvar components = this._components.slice();\n\t\t\tif (this._alpha != null)\n\t\t\t\tcomponents.push(this._alpha);\n\t\t\treturn components;\n\t\t},\n\n\t\tgetAlpha: function() {\n\t\t\treturn this._alpha != null ? this._alpha : 1;\n\t\t},\n\n\t\tsetAlpha: function(alpha) {\n\t\t\tthis._alpha = alpha == null ? null : Math.min(Math.max(alpha, 0), 1);\n\t\t\tthis._changed();\n\t\t},\n\n\t\thasAlpha: function() {\n\t\t\treturn this._alpha != null;\n\t\t},\n\n\t\tequals: function(color) {\n\t\t\tvar col = Base.isPlainValue(color, true)\n\t\t\t\t\t? Color.read(arguments)\n\t\t\t\t\t: color;\n\t\t\treturn col === this || col && this._class === col._class\n\t\t\t\t\t&& this._type === col._type\n\t\t\t\t\t&& this.getAlpha() === col.getAlpha()\n\t\t\t\t\t&& Base.equals(this._components, col._components)\n\t\t\t\t\t|| false;\n\t\t},\n\n\t\ttoString: function() {\n\t\t\tvar properties = this._properties,\n\t\t\t\tparts = [],\n\t\t\t\tisGradient = this._type === 'gradient',\n\t\t\t\tf = Formatter.instance;\n\t\t\tfor (var i = 0, l = properties.length; i < l; i++) {\n\t\t\t\tvar value = this._components[i];\n\t\t\t\tif (value != null)\n\t\t\t\t\tparts.push(properties[i] + ': '\n\t\t\t\t\t\t\t+ (isGradient ? value : f.number(value)));\n\t\t\t}\n\t\t\tif (this._alpha != null)\n\t\t\t\tparts.push('alpha: ' + f.number(this._alpha));\n\t\t\treturn '{ ' + parts.join(', ') + ' }';\n\t\t},\n\n\t\ttoCSS: function(hex) {\n\t\t\tvar components = this._convert('rgb'),\n\t\t\t\talpha = hex || this._alpha == null ? 1 : this._alpha;\n\t\t\tfunction convert(val) {\n\t\t\t\treturn Math.round((val < 0 ? 0 : val > 1 ? 1 : val) * 255);\n\t\t\t}\n\t\t\tcomponents = [\n\t\t\t\tconvert(components[0]),\n\t\t\t\tconvert(components[1]),\n\t\t\t\tconvert(components[2])\n\t\t\t];\n\t\t\tif (alpha < 1)\n\t\t\t\tcomponents.push(alpha < 0 ? 0 : alpha);\n\t\t\treturn hex\n\t\t\t\t\t? '#' + ((1 << 24) + (components[0] << 16)\n\t\t\t\t\t\t+ (components[1] << 8)\n\t\t\t\t\t\t+ components[2]).toString(16).slice(1)\n\t\t\t\t\t: (components.length == 4 ? 'rgba(' : 'rgb(')\n\t\t\t\t\t\t+ components.join(',') + ')';\n\t\t},\n\n\t\ttoCanvasStyle: function(ctx, matrix) {\n\t\t\tif (this._canvasStyle)\n\t\t\t\treturn this._canvasStyle;\n\t\t\tif (this._type !== 'gradient')\n\t\t\t\treturn this._canvasStyle = this.toCSS();\n\t\t\tvar components = this._components,\n\t\t\t\tgradient = components[0],\n\t\t\t\tstops = gradient._stops,\n\t\t\t\torigin = components[1],\n\t\t\t\tdestination = components[2],\n\t\t\t\thighlight = components[3],\n\t\t\t\tinverse = matrix && matrix.inverted(),\n\t\t\t\tcanvasGradient;\n\t\t\tif (inverse) {\n\t\t\t\torigin = inverse._transformPoint(origin);\n\t\t\t\tdestination = inverse._transformPoint(destination);\n\t\t\t\tif (highlight)\n\t\t\t\t\thighlight = inverse._transformPoint(highlight);\n\t\t\t}\n\t\t\tif (gradient._radial) {\n\t\t\t\tvar radius = destination.getDistance(origin);\n\t\t\t\tif (highlight) {\n\t\t\t\t\tvar vector = highlight.subtract(origin);\n\t\t\t\t\tif (vector.getLength() > radius)\n\t\t\t\t\t\thighlight = origin.add(vector.normalize(radius - 0.1));\n\t\t\t\t}\n\t\t\t\tvar start = highlight || origin;\n\t\t\t\tcanvasGradient = ctx.createRadialGradient(start.x, start.y,\n\t\t\t\t\t\t0, origin.x, origin.y, radius);\n\t\t\t} else {\n\t\t\t\tcanvasGradient = ctx.createLinearGradient(origin.x, origin.y,\n\t\t\t\t\t\tdestination.x, destination.y);\n\t\t\t}\n\t\t\tfor (var i = 0, l = stops.length; i < l; i++) {\n\t\t\t\tvar stop = stops[i],\n\t\t\t\t\toffset = stop._offset;\n\t\t\t\tcanvasGradient.addColorStop(\n\t\t\t\t\t\toffset == null ? i / (l - 1) : offset,\n\t\t\t\t\t\tstop._color.toCanvasStyle());\n\t\t\t}\n\t\t\treturn this._canvasStyle = canvasGradient;\n\t\t},\n\n\t\ttransform: function(matrix) {\n\t\t\tif (this._type === 'gradient') {\n\t\t\t\tvar components = this._components;\n\t\t\t\tfor (var i = 1, l = components.length; i < l; i++) {\n\t\t\t\t\tvar point = components[i];\n\t\t\t\t\tmatrix._transformPoint(point, point, true);\n\t\t\t\t}\n\t\t\t\tthis._changed();\n\t\t\t}\n\t\t},\n\n\t\tstatics: {\n\t\t\t_types: types,\n\n\t\t\trandom: function() {\n\t\t\t\tvar random = Math.random;\n\t\t\t\treturn new Color(random(), random(), random());\n\t\t\t}\n\t\t}\n\t});\n},\nnew function() {\n\tvar operators = {\n\t\tadd: function(a, b) {\n\t\t\treturn a + b;\n\t\t},\n\n\t\tsubtract: function(a, b) {\n\t\t\treturn a - b;\n\t\t},\n\n\t\tmultiply: function(a, b) {\n\t\t\treturn a * b;\n\t\t},\n\n\t\tdivide: function(a, b) {\n\t\t\treturn a / b;\n\t\t}\n\t};\n\n\treturn Base.each(operators, function(operator, name) {\n\t\tthis[name] = function(color) {\n\t\t\tcolor = Color.read(arguments);\n\t\t\tvar type = this._type,\n\t\t\t\tcomponents1 = this._components,\n\t\t\t\tcomponents2 = color._convert(type);\n\t\t\tfor (var i = 0, l = components1.length; i < l; i++)\n\t\t\t\tcomponents2[i] = operator(components1[i], components2[i]);\n\t\t\treturn new Color(type, components2,\n\t\t\t\t\tthis._alpha != null\n\t\t\t\t\t\t\t? operator(this._alpha, color.getAlpha())\n\t\t\t\t\t\t\t: null);\n\t\t};\n\t}, {\n\t});\n});\n\nvar Gradient = Base.extend({\n\t_class: 'Gradient',\n\n\tinitialize: function Gradient(stops, radial) {\n\t\tthis._id = UID.get();\n\t\tif (stops && Base.isPlainObject(stops)) {\n\t\t\tthis.set(stops);\n\t\t\tstops = radial = null;\n\t\t}\n\t\tif (this._stops == null) {\n\t\t\tthis.setStops(stops || ['white', 'black']);\n\t\t}\n\t\tif (this._radial == null) {\n\t\t\tthis.setRadial(typeof radial === 'string' && radial === 'radial'\n\t\t\t\t\t|| radial || false);\n\t\t}\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\treturn dictionary.add(this, function() {\n\t\t\treturn Base.serialize([this._stops, this._radial],\n\t\t\t\t\toptions, true, dictionary);\n\t\t});\n\t},\n\n\t_changed: function() {\n\t\tfor (var i = 0, l = this._owners && this._owners.length; i < l; i++) {\n\t\t\tthis._owners[i]._changed();\n\t\t}\n\t},\n\n\t_addOwner: function(color) {\n\t\tif (!this._owners)\n\t\t\tthis._owners = [];\n\t\tthis._owners.push(color);\n\t},\n\n\t_removeOwner: function(color) {\n\t\tvar index = this._owners ? this._owners.indexOf(color) : -1;\n\t\tif (index != -1) {\n\t\t\tthis._owners.splice(index, 1);\n\t\t\tif (!this._owners.length)\n\t\t\t\tthis._owners = undefined;\n\t\t}\n\t},\n\n\tclone: function() {\n\t\tvar stops = [];\n\t\tfor (var i = 0, l = this._stops.length; i < l; i++) {\n\t\t\tstops[i] = this._stops[i].clone();\n\t\t}\n\t\treturn new Gradient(stops, this._radial);\n\t},\n\n\tgetStops: function() {\n\t\treturn this._stops;\n\t},\n\n\tsetStops: function(stops) {\n\t\tif (stops.length < 2) {\n\t\t\tthrow new Error(\n\t\t\t\t\t'Gradient stop list needs to contain at least two stops.');\n\t\t}\n\t\tvar _stops = this._stops;\n\t\tif (_stops) {\n\t\t\tfor (var i = 0, l = _stops.length; i < l; i++)\n\t\t\t\t_stops[i]._owner = undefined;\n\t\t}\n\t\t_stops = this._stops = GradientStop.readList(stops, 0, { clone: true });\n\t\tfor (var i = 0, l = _stops.length; i < l; i++)\n\t\t\t_stops[i]._owner = this;\n\t\tthis._changed();\n\t},\n\n\tgetRadial: function() {\n\t\treturn this._radial;\n\t},\n\n\tsetRadial: function(radial) {\n\t\tthis._radial = radial;\n\t\tthis._changed();\n\t},\n\n\tequals: function(gradient) {\n\t\tif (gradient === this)\n\t\t\treturn true;\n\t\tif (gradient && this._class === gradient._class) {\n\t\t\tvar stops1 = this._stops,\n\t\t\t\tstops2 = gradient._stops,\n\t\t\t\tlength = stops1.length;\n\t\t\tif (length === stops2.length) {\n\t\t\t\tfor (var i = 0; i < length; i++) {\n\t\t\t\t\tif (!stops1[i].equals(stops2[i]))\n\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n});\n\nvar GradientStop = Base.extend({\n\t_class: 'GradientStop',\n\n\tinitialize: function GradientStop(arg0, arg1) {\n\t\tvar color = arg0,\n\t\t\toffset = arg1;\n\t\tif (typeof arg0 === 'object' && arg1 === undefined) {\n\t\t\tif (Array.isArray(arg0) && typeof arg0[0] !== 'number') {\n\t\t\t\tcolor = arg0[0];\n\t\t\t\toffset = arg0[1];\n\t\t\t} else if ('color' in arg0 || 'offset' in arg0\n\t\t\t\t\t|| 'rampPoint' in arg0) {\n\t\t\t\tcolor = arg0.color;\n\t\t\t\toffset = arg0.offset || arg0.rampPoint || 0;\n\t\t\t}\n\t\t}\n\t\tthis.setColor(color);\n\t\tthis.setOffset(offset);\n\t},\n\n\tclone: function() {\n\t\treturn new GradientStop(this._color.clone(), this._offset);\n\t},\n\n\t_serialize: function(options, dictionary) {\n\t\tvar color = this._color,\n\t\t\toffset = this._offset;\n\t\treturn Base.serialize(offset == null ? [color] : [color, offset],\n\t\t\t\toptions, true, dictionary);\n\t},\n\n\t_changed: function() {\n\t\tif (this._owner)\n\t\t\tthis._owner._changed(65);\n\t},\n\n\tgetOffset: function() {\n\t\treturn this._offset;\n\t},\n\n\tsetOffset: function(offset) {\n\t\tthis._offset = offset;\n\t\tthis._changed();\n\t},\n\n\tgetRampPoint: '#getOffset',\n\tsetRampPoint: '#setOffset',\n\n\tgetColor: function() {\n\t\treturn this._color;\n\t},\n\n\tsetColor: function() {\n\t\tvar color = Color.read(arguments, 0, { clone: true });\n\t\tif (color)\n\t\t\tcolor._owner = this;\n\t\tthis._color = color;\n\t\tthis._changed();\n\t},\n\n\tequals: function(stop) {\n\t\treturn stop === this || stop && this._class === stop._class\n\t\t\t\t&& this._color.equals(stop._color)\n\t\t\t\t&& this._offset == stop._offset\n\t\t\t\t|| false;\n\t}\n});\n\nvar Style = Base.extend(new function() {\n\tvar itemDefaults = {\n\t\tfillColor: null,\n\t\tfillRule: 'nonzero',\n\t\tstrokeColor: null,\n\t\tstrokeWidth: 1,\n\t\tstrokeCap: 'butt',\n\t\tstrokeJoin: 'miter',\n\t\tstrokeScaling: true,\n\t\tmiterLimit: 10,\n\t\tdashOffset: 0,\n\t\tdashArray: [],\n\t\tshadowColor: null,\n\t\tshadowBlur: 0,\n\t\tshadowOffset: new Point(),\n\t\tselectedColor: null\n\t},\n\tgroupDefaults = Base.set({}, itemDefaults, {\n\t\tfontFamily: 'sans-serif',\n\t\tfontWeight: 'normal',\n\t\tfontSize: 12,\n\t\tleading: null,\n\t\tjustification: 'left'\n\t}),\n\ttextDefaults = Base.set({}, groupDefaults, {\n\t\tfillColor: new Color()\n\t}),\n\tflags = {\n\t\tstrokeWidth: 97,\n\t\tstrokeCap: 97,\n\t\tstrokeJoin: 97,\n\t\tstrokeScaling: 105,\n\t\tmiterLimit: 97,\n\t\tfontFamily: 9,\n\t\tfontWeight: 9,\n\t\tfontSize: 9,\n\t\tfont: 9,\n\t\tleading: 9,\n\t\tjustification: 9\n\t},\n\titem = {\n\t\tbeans: true\n\t},\n\tfields = {\n\t\t_class: 'Style',\n\t\tbeans: true,\n\n\t\tinitialize: function Style(style, _owner, _project) {\n\t\t\tthis._values = {};\n\t\t\tthis._owner = _owner;\n\t\t\tthis._project = _owner && _owner._project || _project\n\t\t\t\t\t|| paper.project;\n\t\t\tthis._defaults = !_owner || _owner instanceof Group ? groupDefaults\n\t\t\t\t\t: _owner instanceof TextItem ? textDefaults\n\t\t\t\t\t: itemDefaults;\n\t\t\tif (style)\n\t\t\t\tthis.set(style);\n\t\t}\n\t};\n\n\tBase.each(groupDefaults, function(value, key) {\n\t\tvar isColor = /Color$/.test(key),\n\t\t\tisPoint = key === 'shadowOffset',\n\t\t\tpart = Base.capitalize(key),\n\t\t\tflag = flags[key],\n\t\t\tset = 'set' + part,\n\t\t\tget = 'get' + part;\n\n\t\tfields[set] = function(value) {\n\t\t\tvar owner = this._owner,\n\t\t\t\tchildren = owner && owner._children;\n\t\t\tif (children && children.length > 0\n\t\t\t\t\t&& !(owner instanceof CompoundPath)) {\n\t\t\t\tfor (var i = 0, l = children.length; i < l; i++)\n\t\t\t\t\tchildren[i]._style[set](value);\n\t\t\t} else if (key in this._defaults) {\n\t\t\t\tvar old = this._values[key];\n\t\t\t\tif (old !== value) {\n\t\t\t\t\tif (isColor) {\n\t\t\t\t\t\tif (old && old._owner !== undefined)\n\t\t\t\t\t\t\told._owner = undefined;\n\t\t\t\t\t\tif (value && value.constructor === Color) {\n\t\t\t\t\t\t\tif (value._owner)\n\t\t\t\t\t\t\t\tvalue = value.clone();\n\t\t\t\t\t\t\tvalue._owner = owner;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis._values[key] = value;\n\t\t\t\t\tif (owner)\n\t\t\t\t\t\towner._changed(flag || 65);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tfields[get] = function(_dontMerge) {\n\t\t\tvar owner = this._owner,\n\t\t\t\tchildren = owner && owner._children,\n\t\t\t\tvalue;\n\t\t\tif (key in this._defaults && (!children || !children.length\n\t\t\t\t\t|| _dontMerge || owner instanceof CompoundPath)) {\n\t\t\t\tvar value = this._values[key];\n\t\t\t\tif (value === undefined) {\n\t\t\t\t\tvalue = this._defaults[key];\n\t\t\t\t\tif (value && value.clone)\n\t\t\t\t\t\tvalue = value.clone();\n\t\t\t\t} else {\n\t\t\t\t\tvar ctor = isColor ? Color : isPoint ? Point : null;\n\t\t\t\t\tif (ctor && !(value && value.constructor === ctor)) {\n\t\t\t\t\t\tthis._values[key] = value = ctor.read([value], 0,\n\t\t\t\t\t\t\t\t{ readNull: true, clone: true });\n\t\t\t\t\t\tif (value && isColor)\n\t\t\t\t\t\t\tvalue._owner = owner;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (children) {\n\t\t\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\t\t\tvar childValue = children[i]._style[get]();\n\t\t\t\t\tif (!i) {\n\t\t\t\t\t\tvalue = childValue;\n\t\t\t\t\t} else if (!Base.equals(value, childValue)) {\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn value;\n\t\t};\n\n\t\titem[get] = function(_dontMerge) {\n\t\t\treturn this._style[get](_dontMerge);\n\t\t};\n\n\t\titem[set] = function(value) {\n\t\t\tthis._style[set](value);\n\t\t};\n\t});\n\n\tBase.each({\n\t\tFont: 'FontFamily',\n\t\tWindingRule: 'FillRule'\n\t}, function(value, key) {\n\t\tvar get = 'get' + key,\n\t\t\tset = 'set' + key;\n\t\tfields[get] = item[get] = '#get' + value;\n\t\tfields[set] = item[set] = '#set' + value;\n\t});\n\n\tItem.inject(item);\n\treturn fields;\n}, {\n\tset: function(style) {\n\t\tvar isStyle = style instanceof Style,\n\t\t\tvalues = isStyle ? style._values : style;\n\t\tif (values) {\n\t\t\tfor (var key in values) {\n\t\t\t\tif (key in this._defaults) {\n\t\t\t\t\tvar value = values[key];\n\t\t\t\t\tthis[key] = value && isStyle && value.clone\n\t\t\t\t\t\t\t? value.clone() : value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tequals: function(style) {\n\t\tfunction compare(style1, style2, secondary) {\n\t\t\tvar values1 = style1._values,\n\t\t\t\tvalues2 = style2._values,\n\t\t\t\tdefaults2 = style2._defaults;\n\t\t\tfor (var key in values1) {\n\t\t\t\tvar value1 = values1[key],\n\t\t\t\t\tvalue2 = values2[key];\n\t\t\t\tif (!(secondary && key in values2) && !Base.equals(value1,\n\t\t\t\t\t\tvalue2 === undefined ? defaults2[key] : value2))\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\treturn style === this || style && this._class === style._class\n\t\t\t\t&& compare(this, style)\n\t\t\t\t&& compare(style, this, true)\n\t\t\t\t|| false;\n\t},\n\n\thasFill: function() {\n\t\tvar color = this.getFillColor();\n\t\treturn !!color && color.alpha > 0;\n\t},\n\n\thasStroke: function() {\n\t\tvar color = this.getStrokeColor();\n\t\treturn !!color && color.alpha > 0 && this.getStrokeWidth() > 0;\n\t},\n\n\thasShadow: function() {\n\t\tvar color = this.getShadowColor();\n\t\treturn !!color && color.alpha > 0 && (this.getShadowBlur() > 0\n\t\t\t\t|| !this.getShadowOffset().isZero());\n\t},\n\n\tgetView: function() {\n\t\treturn this._project._view;\n\t},\n\n\tgetFontStyle: function() {\n\t\tvar fontSize = this.getFontSize();\n\t\treturn this.getFontWeight()\n\t\t\t\t+ ' ' + fontSize + (/[a-z]/i.test(fontSize + '') ? ' ' : 'px ')\n\t\t\t\t+ this.getFontFamily();\n\t},\n\n\tgetFont: '#getFontFamily',\n\tsetFont: '#setFontFamily',\n\n\tgetLeading: function getLeading() {\n\t\tvar leading = getLeading.base.call(this),\n\t\t\tfontSize = this.getFontSize();\n\t\tif (/pt|em|%|px/.test(fontSize))\n\t\t\tfontSize = this.getView().getPixelSize(fontSize);\n\t\treturn leading != null ? leading : fontSize * 1.2;\n\t}\n\n});\n\nvar DomElement = new function() {\n\tfunction handlePrefix(el, name, set, value) {\n\t\tvar prefixes = ['', 'webkit', 'moz', 'Moz', 'ms', 'o'],\n\t\t\tsuffix = name[0].toUpperCase() + name.substring(1);\n\t\tfor (var i = 0; i < 6; i++) {\n\t\t\tvar prefix = prefixes[i],\n\t\t\t\tkey = prefix ? prefix + suffix : name;\n\t\t\tif (key in el) {\n\t\t\t\tif (set) {\n\t\t\t\t\tel[key] = value;\n\t\t\t\t} else {\n\t\t\t\t\treturn el[key];\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tgetStyles: function(el) {\n\t\t\tvar doc = el && el.nodeType !== 9 ? el.ownerDocument : el,\n\t\t\t\tview = doc && doc.defaultView;\n\t\t\treturn view && view.getComputedStyle(el, '');\n\t\t},\n\n\t\tgetBounds: function(el, viewport) {\n\t\t\tvar doc = el.ownerDocument,\n\t\t\t\tbody = doc.body,\n\t\t\t\thtml = doc.documentElement,\n\t\t\t\trect;\n\t\t\ttry {\n\t\t\t\trect = el.getBoundingClientRect();\n\t\t\t} catch (e) {\n\t\t\t\trect = { left: 0, top: 0, width: 0, height: 0 };\n\t\t\t}\n\t\t\tvar x = rect.left - (html.clientLeft || body.clientLeft || 0),\n\t\t\t\ty = rect.top - (html.clientTop || body.clientTop || 0);\n\t\t\tif (!viewport) {\n\t\t\t\tvar view = doc.defaultView;\n\t\t\t\tx += view.pageXOffset || html.scrollLeft || body.scrollLeft;\n\t\t\t\ty += view.pageYOffset || html.scrollTop || body.scrollTop;\n\t\t\t}\n\t\t\treturn new Rectangle(x, y, rect.width, rect.height);\n\t\t},\n\n\t\tgetViewportBounds: function(el) {\n\t\t\tvar doc = el.ownerDocument,\n\t\t\t\tview = doc.defaultView,\n\t\t\t\thtml = doc.documentElement;\n\t\t\treturn new Rectangle(0, 0,\n\t\t\t\tview.innerWidth || html.clientWidth,\n\t\t\t\tview.innerHeight || html.clientHeight\n\t\t\t);\n\t\t},\n\n\t\tgetOffset: function(el, viewport) {\n\t\t\treturn DomElement.getBounds(el, viewport).getPoint();\n\t\t},\n\n\t\tgetSize: function(el) {\n\t\t\treturn DomElement.getBounds(el, true).getSize();\n\t\t},\n\n\t\tisInvisible: function(el) {\n\t\t\treturn DomElement.getSize(el).equals(new Size(0, 0));\n\t\t},\n\n\t\tisInView: function(el) {\n\t\t\treturn !DomElement.isInvisible(el)\n\t\t\t\t\t&& DomElement.getViewportBounds(el).intersects(\n\t\t\t\t\t\tDomElement.getBounds(el, true));\n\t\t},\n\n\t\tisInserted: function(el) {\n\t\t\treturn document.body.contains(el);\n\t\t},\n\n\t\tgetPrefixed: function(el, name) {\n\t\t\treturn el && handlePrefix(el, name);\n\t\t},\n\n\t\tsetPrefixed: function(el, name, value) {\n\t\t\tif (typeof name === 'object') {\n\t\t\t\tfor (var key in name)\n\t\t\t\t\thandlePrefix(el, key, true, name[key]);\n\t\t\t} else {\n\t\t\t\thandlePrefix(el, name, true, value);\n\t\t\t}\n\t\t}\n\t};\n};\n\nvar DomEvent = {\n\tadd: function(el, events) {\n\t\tif (el) {\n\t\t\tfor (var type in events) {\n\t\t\t\tvar func = events[type],\n\t\t\t\t\tparts = type.split(/[\\s,]+/g);\n\t\t\t\tfor (var i = 0, l = parts.length; i < l; i++)\n\t\t\t\t\tel.addEventListener(parts[i], func, false);\n\t\t\t}\n\t\t}\n\t},\n\n\tremove: function(el, events) {\n\t\tif (el) {\n\t\t\tfor (var type in events) {\n\t\t\t\tvar func = events[type],\n\t\t\t\t\tparts = type.split(/[\\s,]+/g);\n\t\t\t\tfor (var i = 0, l = parts.length; i < l; i++)\n\t\t\t\t\tel.removeEventListener(parts[i], func, false);\n\t\t\t}\n\t\t}\n\t},\n\n\tgetPoint: function(event) {\n\t\tvar pos = event.targetTouches\n\t\t\t\t? event.targetTouches.length\n\t\t\t\t\t? event.targetTouches[0]\n\t\t\t\t\t: event.changedTouches[0]\n\t\t\t\t: event;\n\t\treturn new Point(\n\t\t\tpos.pageX || pos.clientX + document.documentElement.scrollLeft,\n\t\t\tpos.pageY || pos.clientY + document.documentElement.scrollTop\n\t\t);\n\t},\n\n\tgetTarget: function(event) {\n\t\treturn event.target || event.srcElement;\n\t},\n\n\tgetRelatedTarget: function(event) {\n\t\treturn event.relatedTarget || event.toElement;\n\t},\n\n\tgetOffset: function(event, target) {\n\t\treturn DomEvent.getPoint(event).subtract(DomElement.getOffset(\n\t\t\t\ttarget || DomEvent.getTarget(event)));\n\t}\n};\n\nDomEvent.requestAnimationFrame = new function() {\n\tvar nativeRequest = DomElement.getPrefixed(window, 'requestAnimationFrame'),\n\t\trequested = false,\n\t\tcallbacks = [],\n\t\ttimer;\n\n\tfunction handleCallbacks() {\n\t\tvar functions = callbacks;\n\t\tcallbacks = [];\n\t\tfor (var i = 0, l = functions.length; i < l; i++)\n\t\t\tfunctions[i]();\n\t\trequested = nativeRequest && callbacks.length;\n\t\tif (requested)\n\t\t\tnativeRequest(handleCallbacks);\n\t}\n\n\treturn function(callback) {\n\t\tcallbacks.push(callback);\n\t\tif (nativeRequest) {\n\t\t\tif (!requested) {\n\t\t\t\tnativeRequest(handleCallbacks);\n\t\t\t\trequested = true;\n\t\t\t}\n\t\t} else if (!timer) {\n\t\t\ttimer = setInterval(handleCallbacks, 1000 / 60);\n\t\t}\n\t};\n};\n\nvar View = Base.extend(Emitter, {\n\t_class: 'View',\n\n\tinitialize: function View(project, element) {\n\n\t\tfunction getSize(name) {\n\t\t\treturn element[name] || parseInt(element.getAttribute(name), 10);\n\t\t}\n\n\t\tfunction getCanvasSize() {\n\t\t\tvar size = DomElement.getSize(element);\n\t\t\treturn size.isNaN() || size.isZero()\n\t\t\t\t\t? new Size(getSize('width'), getSize('height'))\n\t\t\t\t\t: size;\n\t\t}\n\n\t\tvar size;\n\t\tif (window && element) {\n\t\t\tthis._id = element.getAttribute('id');\n\t\t\tif (this._id == null)\n\t\t\t\telement.setAttribute('id', this._id = 'view-' + View._id++);\n\t\t\tDomEvent.add(element, this._viewEvents);\n\t\t\tvar none = 'none';\n\t\t\tDomElement.setPrefixed(element.style, {\n\t\t\t\tuserDrag: none,\n\t\t\t\tuserSelect: none,\n\t\t\t\ttouchCallout: none,\n\t\t\t\tcontentZooming: none,\n\t\t\t\ttapHighlightColor: 'rgba(0,0,0,0)'\n\t\t\t});\n\n\t\t\tif (PaperScope.hasAttribute(element, 'resize')) {\n\t\t\t\tvar that = this;\n\t\t\t\tDomEvent.add(window, this._windowEvents = {\n\t\t\t\t\tresize: function() {\n\t\t\t\t\t\tthat.setViewSize(getCanvasSize());\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tsize = getCanvasSize();\n\n\t\t\tif (PaperScope.hasAttribute(element, 'stats')\n\t\t\t\t\t&& typeof Stats !== 'undefined') {\n\t\t\t\tthis._stats = new Stats();\n\t\t\t\tvar stats = this._stats.domElement,\n\t\t\t\t\tstyle = stats.style,\n\t\t\t\t\toffset = DomElement.getOffset(element);\n\t\t\t\tstyle.position = 'absolute';\n\t\t\t\tstyle.left = offset.x + 'px';\n\t\t\t\tstyle.top = offset.y + 'px';\n\t\t\t\tdocument.body.appendChild(stats);\n\t\t\t}\n\t\t} else {\n\t\t\tsize = new Size(element);\n\t\t\telement = null;\n\t\t}\n\t\tthis._project = project;\n\t\tthis._scope = project._scope;\n\t\tthis._element = element;\n\t\tif (!this._pixelRatio)\n\t\t\tthis._pixelRatio = window && window.devicePixelRatio || 1;\n\t\tthis._setElementSize(size.width, size.height);\n\t\tthis._viewSize = size;\n\t\tView._views.push(this);\n\t\tView._viewsById[this._id] = this;\n\t\t(this._matrix = new Matrix())._owner = this;\n\t\tif (!View._focused)\n\t\t\tView._focused = this;\n\t\tthis._frameItems = {};\n\t\tthis._frameItemCount = 0;\n\t\tthis._itemEvents = { native: {}, virtual: {} };\n\t\tthis._autoUpdate = !paper.agent.node;\n\t\tthis._needsUpdate = false;\n\t},\n\n\tremove: function() {\n\t\tif (!this._project)\n\t\t\treturn false;\n\t\tif (View._focused === this)\n\t\t\tView._focused = null;\n\t\tView._views.splice(View._views.indexOf(this), 1);\n\t\tdelete View._viewsById[this._id];\n\t\tvar project = this._project;\n\t\tif (project._view === this)\n\t\t\tproject._view = null;\n\t\tDomEvent.remove(this._element, this._viewEvents);\n\t\tDomEvent.remove(window, this._windowEvents);\n\t\tthis._element = this._project = null;\n\t\tthis.off('frame');\n\t\tthis._animate = false;\n\t\tthis._frameItems = {};\n\t\treturn true;\n\t},\n\n\t_events: Base.each(\n\t\tItem._itemHandlers.concat(['onResize', 'onKeyDown', 'onKeyUp']),\n\t\tfunction(name) {\n\t\t\tthis[name] = {};\n\t\t}, {\n\t\t\tonFrame: {\n\t\t\t\tinstall: function() {\n\t\t\t\t\tthis.play();\n\t\t\t\t},\n\n\t\t\t\tuninstall: function() {\n\t\t\t\t\tthis.pause();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t),\n\n\t_animate: false,\n\t_time: 0,\n\t_count: 0,\n\n\tgetAutoUpdate: function() {\n\t\treturn this._autoUpdate;\n\t},\n\n\tsetAutoUpdate: function(autoUpdate) {\n\t\tthis._autoUpdate = autoUpdate;\n\t\tif (autoUpdate)\n\t\t\tthis.requestUpdate();\n\t},\n\n\tupdate: function() {\n\t},\n\n\tdraw: function() {\n\t\tthis.update();\n\t},\n\n\trequestUpdate: function() {\n\t\tif (!this._requested) {\n\t\t\tvar that = this;\n\t\t\tDomEvent.requestAnimationFrame(function() {\n\t\t\t\tthat._requested = false;\n\t\t\t\tif (that._animate) {\n\t\t\t\t\tthat.requestUpdate();\n\t\t\t\t\tvar element = that._element;\n\t\t\t\t\tif ((!DomElement.getPrefixed(document, 'hidden')\n\t\t\t\t\t\t\t|| PaperScope.getAttribute(element, 'keepalive')\n\t\t\t\t\t\t\t\t=== 'true') && DomElement.isInView(element)) {\n\t\t\t\t\t\tthat._handleFrame();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (that._autoUpdate)\n\t\t\t\t\tthat.update();\n\t\t\t});\n\t\t\tthis._requested = true;\n\t\t}\n\t},\n\n\tplay: function() {\n\t\tthis._animate = true;\n\t\tthis.requestUpdate();\n\t},\n\n\tpause: function() {\n\t\tthis._animate = false;\n\t},\n\n\t_handleFrame: function() {\n\t\tpaper = this._scope;\n\t\tvar now = Date.now() / 1000,\n\t\t\tdelta = this._last ? now - this._last : 0;\n\t\tthis._last = now;\n\t\tthis.emit('frame', new Base({\n\t\t\tdelta: delta,\n\t\t\ttime: this._time += delta,\n\t\t\tcount: this._count++\n\t\t}));\n\t\tif (this._stats)\n\t\t\tthis._stats.update();\n\t},\n\n\t_animateItem: function(item, animate) {\n\t\tvar items = this._frameItems;\n\t\tif (animate) {\n\t\t\titems[item._id] = {\n\t\t\t\titem: item,\n\t\t\t\ttime: 0,\n\t\t\t\tcount: 0\n\t\t\t};\n\t\t\tif (++this._frameItemCount === 1)\n\t\t\t\tthis.on('frame', this._handleFrameItems);\n\t\t} else {\n\t\t\tdelete items[item._id];\n\t\t\tif (--this._frameItemCount === 0) {\n\t\t\t\tthis.off('frame', this._handleFrameItems);\n\t\t\t}\n\t\t}\n\t},\n\n\t_handleFrameItems: function(event) {\n\t\tfor (var i in this._frameItems) {\n\t\t\tvar entry = this._frameItems[i];\n\t\t\tentry.item.emit('frame', new Base(event, {\n\t\t\t\ttime: entry.time += event.delta,\n\t\t\t\tcount: entry.count++\n\t\t\t}));\n\t\t}\n\t},\n\n\t_changed: function() {\n\t\tthis._project._changed(2049);\n\t\tthis._bounds = this._decomposed = undefined;\n\t},\n\n\tgetElement: function() {\n\t\treturn this._element;\n\t},\n\n\tgetPixelRatio: function() {\n\t\treturn this._pixelRatio;\n\t},\n\n\tgetResolution: function() {\n\t\treturn this._pixelRatio * 72;\n\t},\n\n\tgetViewSize: function() {\n\t\tvar size = this._viewSize;\n\t\treturn new LinkedSize(size.width, size.height, this, 'setViewSize');\n\t},\n\n\tsetViewSize: function() {\n\t\tvar size = Size.read(arguments),\n\t\t\tdelta = size.subtract(this._viewSize);\n\t\tif (delta.isZero())\n\t\t\treturn;\n\t\tthis._setElementSize(size.width, size.height);\n\t\tthis._viewSize.set(size);\n\t\tthis._changed();\n\t\tthis.emit('resize', { size: size, delta: delta });\n\t\tif (this._autoUpdate) {\n\t\t\tthis.update();\n\t\t}\n\t},\n\n\t_setElementSize: function(width, height) {\n\t\tvar element = this._element;\n\t\tif (element) {\n\t\t\tif (element.width !== width)\n\t\t\t\telement.width = width;\n\t\t\tif (element.height !== height)\n\t\t\t\telement.height = height;\n\t\t}\n\t},\n\n\tgetBounds: function() {\n\t\tif (!this._bounds)\n\t\t\tthis._bounds = this._matrix.inverted()._transformBounds(\n\t\t\t\t\tnew Rectangle(new Point(), this._viewSize));\n\t\treturn this._bounds;\n\t},\n\n\tgetSize: function() {\n\t\treturn this.getBounds().getSize();\n\t},\n\n\tisVisible: function() {\n\t\treturn DomElement.isInView(this._element);\n\t},\n\n\tisInserted: function() {\n\t\treturn DomElement.isInserted(this._element);\n\t},\n\n\tgetPixelSize: function(size) {\n\t\tvar element = this._element,\n\t\t\tpixels;\n\t\tif (element) {\n\t\t\tvar parent = element.parentNode,\n\t\t\t\ttemp = document.createElement('div');\n\t\t\ttemp.style.fontSize = size;\n\t\t\tparent.appendChild(temp);\n\t\t\tpixels = parseFloat(DomElement.getStyles(temp).fontSize);\n\t\t\tparent.removeChild(temp);\n\t\t} else {\n\t\t\tpixels = parseFloat(pixels);\n\t\t}\n\t\treturn pixels;\n\t},\n\n\tgetTextWidth: function(font, lines) {\n\t\treturn 0;\n\t}\n}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) {\n\tvar rotate = key === 'rotate';\n\tthis[key] = function() {\n\t\tvar value = (rotate ? Base : Point).read(arguments),\n\t\t\tcenter = Point.read(arguments, 0, { readNull: true });\n\t\treturn this.transform(new Matrix()[key](value,\n\t\t\t\tcenter || this.getCenter(true)));\n\t};\n}, {\n\t_decompose: function() {\n\t\treturn this._decomposed || (this._decomposed = this._matrix.decompose());\n\t},\n\n\ttranslate: function() {\n\t\tvar mx = new Matrix();\n\t\treturn this.transform(mx.translate.apply(mx, arguments));\n\t},\n\n\tgetCenter: function() {\n\t\treturn this.getBounds().getCenter();\n\t},\n\n\tsetCenter: function() {\n\t\tvar center = Point.read(arguments);\n\t\tthis.translate(this.getCenter().subtract(center));\n\t},\n\n\tgetZoom: function() {\n\t\tvar decomposed = this._decompose(),\n\t\t\tscaling = decomposed && decomposed.scaling;\n\t\treturn scaling ? (scaling.x + scaling.y) / 2 : 0;\n\t},\n\n\tsetZoom: function(zoom) {\n\t\tthis.transform(new Matrix().scale(zoom / this.getZoom(),\n\t\t\tthis.getCenter()));\n\t},\n\n\tgetRotation: function() {\n\t\tvar decomposed = this._decompose();\n\t\treturn decomposed && decomposed.rotation;\n\t},\n\n\tsetRotation: function(rotation) {\n\t\tvar current = this.getRotation();\n\t\tif (current != null && rotation != null) {\n\t\t\tthis.rotate(rotation - current);\n\t\t}\n\t},\n\n\tgetScaling: function() {\n\t\tvar decomposed = this._decompose(),\n\t\t\tscaling = decomposed && decomposed.scaling;\n\t\treturn scaling\n\t\t\t\t? new LinkedPoint(scaling.x, scaling.y, this, 'setScaling')\n\t\t\t\t: undefined;\n\t},\n\n\tsetScaling: function() {\n\t\tvar current = this.getScaling(),\n\t\t\tscaling = Point.read(arguments, 0, { clone: true, readNull: true });\n\t\tif (current && scaling) {\n\t\t\tthis.scale(scaling.x / current.x, scaling.y / current.y);\n\t\t}\n\t},\n\n\tgetMatrix: function() {\n\t\treturn this._matrix;\n\t},\n\n\tsetMatrix: function() {\n\t\tvar matrix = this._matrix;\n\t\tmatrix.initialize.apply(matrix, arguments);\n\t},\n\n\ttransform: function(matrix) {\n\t\tthis._matrix.append(matrix);\n\t},\n\n\tscrollBy: function() {\n\t\tthis.translate(Point.read(arguments).negate());\n\t}\n}), {\n\n\tprojectToView: function() {\n\t\treturn this._matrix._transformPoint(Point.read(arguments));\n\t},\n\n\tviewToProject: function() {\n\t\treturn this._matrix._inverseTransform(Point.read(arguments));\n\t},\n\n\tgetEventPoint: function(event) {\n\t\treturn this.viewToProject(DomEvent.getOffset(event, this._element));\n\t},\n\n}, {\n\tstatics: {\n\t\t_views: [],\n\t\t_viewsById: {},\n\t\t_id: 0,\n\n\t\tcreate: function(project, element) {\n\t\t\tif (document && typeof element === 'string')\n\t\t\t\telement = document.getElementById(element);\n\t\t\tvar ctor = window ? CanvasView : View;\n\t\t\treturn new ctor(project, element);\n\t\t}\n\t}\n},\nnew function() {\n\tif (!window)\n\t\treturn;\n\tvar prevFocus,\n\t\ttempFocus,\n\t\tdragging = false,\n\t\tmouseDown = false;\n\n\tfunction getView(event) {\n\t\tvar target = DomEvent.getTarget(event);\n\t\treturn target.getAttribute && View._viewsById[\n\t\t\t\ttarget.getAttribute('id')];\n\t}\n\n\tfunction updateFocus() {\n\t\tvar view = View._focused;\n\t\tif (!view || !view.isVisible()) {\n\t\t\tfor (var i = 0, l = View._views.length; i < l; i++) {\n\t\t\t\tif ((view = View._views[i]).isVisible()) {\n\t\t\t\t\tView._focused = tempFocus = view;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction handleMouseMove(view, event, point) {\n\t\tview._handleMouseEvent('mousemove', event, point);\n\t}\n\n\tvar navigator = window.navigator,\n\t\tmousedown, mousemove, mouseup;\n\tif (navigator.pointerEnabled || navigator.msPointerEnabled) {\n\t\tmousedown = 'pointerdown MSPointerDown';\n\t\tmousemove = 'pointermove MSPointerMove';\n\t\tmouseup = 'pointerup pointercancel MSPointerUp MSPointerCancel';\n\t} else {\n\t\tmousedown = 'touchstart';\n\t\tmousemove = 'touchmove';\n\t\tmouseup = 'touchend touchcancel';\n\t\tif (!('ontouchstart' in window && navigator.userAgent.match(\n\t\t\t\t/mobile|tablet|ip(ad|hone|od)|android|silk/i))) {\n\t\t\tmousedown += ' mousedown';\n\t\t\tmousemove += ' mousemove';\n\t\t\tmouseup += ' mouseup';\n\t\t}\n\t}\n\n\tvar viewEvents = {},\n\t\tdocEvents = {\n\t\t\tmouseout: function(event) {\n\t\t\t\tvar view = View._focused,\n\t\t\t\t\ttarget = DomEvent.getRelatedTarget(event);\n\t\t\t\tif (view && (!target || target.nodeName === 'HTML')) {\n\t\t\t\t\tvar offset = DomEvent.getOffset(event, view._element),\n\t\t\t\t\t\tx = offset.x,\n\t\t\t\t\t\tabs = Math.abs,\n\t\t\t\t\t\tax = abs(x),\n\t\t\t\t\t\tmax = 1 << 25,\n\t\t\t\t\t\tdiff = ax - max;\n\t\t\t\t\toffset.x = abs(diff) < ax ? diff * (x < 0 ? -1 : 1) : x;\n\t\t\t\t\thandleMouseMove(view, event, view.viewToProject(offset));\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tscroll: updateFocus\n\t\t};\n\n\tviewEvents[mousedown] = function(event) {\n\t\tvar view = View._focused = getView(event);\n\t\tif (!dragging) {\n\t\t\tdragging = true;\n\t\t\tview._handleMouseEvent('mousedown', event);\n\t\t}\n\t};\n\n\tdocEvents[mousemove] = function(event) {\n\t\tvar view = View._focused;\n\t\tif (!mouseDown) {\n\t\t\tvar target = getView(event);\n\t\t\tif (target) {\n\t\t\t\tif (view !== target) {\n\t\t\t\t\tif (view)\n\t\t\t\t\t\thandleMouseMove(view, event);\n\t\t\t\t\tif (!prevFocus)\n\t\t\t\t\t\tprevFocus = view;\n\t\t\t\t\tview = View._focused = tempFocus = target;\n\t\t\t\t}\n\t\t\t} else if (tempFocus && tempFocus === view) {\n\t\t\t\tif (prevFocus && !prevFocus.isInserted())\n\t\t\t\t\tprevFocus = null;\n\t\t\t\tview = View._focused = prevFocus;\n\t\t\t\tprevFocus = null;\n\t\t\t\tupdateFocus();\n\t\t\t}\n\t\t}\n\t\tif (view)\n\t\t\thandleMouseMove(view, event);\n\t};\n\n\tdocEvents[mousedown] = function() {\n\t\tmouseDown = true;\n\t};\n\n\tdocEvents[mouseup] = function(event) {\n\t\tvar view = View._focused;\n\t\tif (view && dragging)\n\t\t\tview._handleMouseEvent('mouseup', event);\n\t\tmouseDown = dragging = false;\n\t};\n\n\tDomEvent.add(document, docEvents);\n\n\tDomEvent.add(window, {\n\t\tload: updateFocus\n\t});\n\n\tvar called = false,\n\t\tprevented = false,\n\t\tfallbacks = {\n\t\t\tdoubleclick: 'click',\n\t\t\tmousedrag: 'mousemove'\n\t\t},\n\t\twasInView = false,\n\t\toverView,\n\t\tdownPoint,\n\t\tlastPoint,\n\t\tdownItem,\n\t\toverItem,\n\t\tdragItem,\n\t\tclickItem,\n\t\tclickTime,\n\t\tdblClick;\n\n\tfunction emitMouseEvent(obj, target, type, event, point, prevPoint,\n\t\t\tstopItem) {\n\t\tvar stopped = false,\n\t\t\tmouseEvent;\n\n\t\tfunction emit(obj, type) {\n\t\t\tif (obj.responds(type)) {\n\t\t\t\tif (!mouseEvent) {\n\t\t\t\t\tmouseEvent = new MouseEvent(type, event, point,\n\t\t\t\t\t\t\ttarget || obj,\n\t\t\t\t\t\t\tprevPoint ? point.subtract(prevPoint) : null);\n\t\t\t\t}\n\t\t\t\tif (obj.emit(type, mouseEvent)) {\n\t\t\t\t\tcalled = true;\n\t\t\t\t\tif (mouseEvent.prevented)\n\t\t\t\t\t\tprevented = true;\n\t\t\t\t\tif (mouseEvent.stopped)\n\t\t\t\t\t\treturn stopped = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tvar fallback = fallbacks[type];\n\t\t\t\tif (fallback)\n\t\t\t\t\treturn emit(obj, fallback);\n\t\t\t}\n\t\t}\n\n\t\twhile (obj && obj !== stopItem) {\n\t\t\tif (emit(obj, type))\n\t\t\t\tbreak;\n\t\t\tobj = obj._parent;\n\t\t}\n\t\treturn stopped;\n\t}\n\n\tfunction emitMouseEvents(view, hitItem, type, event, point, prevPoint) {\n\t\tview._project.removeOn(type);\n\t\tprevented = called = false;\n\t\treturn (dragItem && emitMouseEvent(dragItem, null, type, event,\n\t\t\t\t\tpoint, prevPoint)\n\t\t\t|| hitItem && hitItem !== dragItem\n\t\t\t\t&& !hitItem.isDescendant(dragItem)\n\t\t\t\t&& emitMouseEvent(hitItem, null, type, event, point, prevPoint,\n\t\t\t\t\tdragItem)\n\t\t\t|| emitMouseEvent(view, dragItem || hitItem || view, type, event,\n\t\t\t\t\tpoint, prevPoint));\n\t}\n\n\tvar itemEventsMap = {\n\t\tmousedown: {\n\t\t\tmousedown: 1,\n\t\t\tmousedrag: 1,\n\t\t\tclick: 1,\n\t\t\tdoubleclick: 1\n\t\t},\n\t\tmouseup: {\n\t\t\tmouseup: 1,\n\t\t\tmousedrag: 1,\n\t\t\tclick: 1,\n\t\t\tdoubleclick: 1\n\t\t},\n\t\tmousemove: {\n\t\t\tmousedrag: 1,\n\t\t\tmousemove: 1,\n\t\t\tmouseenter: 1,\n\t\t\tmouseleave: 1\n\t\t}\n\t};\n\n\treturn {\n\t\t_viewEvents: viewEvents,\n\n\t\t_handleMouseEvent: function(type, event, point) {\n\t\t\tvar itemEvents = this._itemEvents,\n\t\t\t\thitItems = itemEvents.native[type],\n\t\t\t\tnativeMove = type === 'mousemove',\n\t\t\t\ttool = this._scope.tool,\n\t\t\t\tview = this;\n\n\t\t\tfunction responds(type) {\n\t\t\t\treturn itemEvents.virtual[type] || view.responds(type)\n\t\t\t\t\t\t|| tool && tool.responds(type);\n\t\t\t}\n\n\t\t\tif (nativeMove && dragging && responds('mousedrag'))\n\t\t\t\ttype = 'mousedrag';\n\t\t\tif (!point)\n\t\t\t\tpoint = this.getEventPoint(event);\n\n\t\t\tvar inView = this.getBounds().contains(point),\n\t\t\t\thit = hitItems && inView && view._project.hitTest(point, {\n\t\t\t\t\ttolerance: 0,\n\t\t\t\t\tfill: true,\n\t\t\t\t\tstroke: true\n\t\t\t\t}),\n\t\t\t\thitItem = hit && hit.item || null,\n\t\t\t\thandle = false,\n\t\t\t\tmouse = {};\n\t\t\tmouse[type.substr(5)] = true;\n\n\t\t\tif (hitItems && hitItem !== overItem) {\n\t\t\t\tif (overItem) {\n\t\t\t\t\temitMouseEvent(overItem, null, 'mouseleave', event, point);\n\t\t\t\t}\n\t\t\t\tif (hitItem) {\n\t\t\t\t\temitMouseEvent(hitItem, null, 'mouseenter', event, point);\n\t\t\t\t}\n\t\t\t\toverItem = hitItem;\n\t\t\t}\n\t\t\tif (wasInView ^ inView) {\n\t\t\t\temitMouseEvent(this, null, inView ? 'mouseenter' : 'mouseleave',\n\t\t\t\t\t\tevent, point);\n\t\t\t\toverView = inView ? this : null;\n\t\t\t\thandle = true;\n\t\t\t}\n\t\t\tif ((inView || mouse.drag) && !point.equals(lastPoint)) {\n\t\t\t\temitMouseEvents(this, hitItem, nativeMove ? type : 'mousemove',\n\t\t\t\t\t\tevent, point, lastPoint);\n\t\t\t\thandle = true;\n\t\t\t}\n\t\t\twasInView = inView;\n\t\t\tif (mouse.down && inView || mouse.up && downPoint) {\n\t\t\t\temitMouseEvents(this, hitItem, type, event, point, downPoint);\n\t\t\t\tif (mouse.down) {\n\t\t\t\t\tdblClick = hitItem === clickItem\n\t\t\t\t\t\t&& (Date.now() - clickTime < 300);\n\t\t\t\t\tdownItem = clickItem = hitItem;\n\t\t\t\t\tif (!prevented && hitItem) {\n\t\t\t\t\t\tvar item = hitItem;\n\t\t\t\t\t\twhile (item && !item.responds('mousedrag'))\n\t\t\t\t\t\t\titem = item._parent;\n\t\t\t\t\t\tif (item)\n\t\t\t\t\t\t\tdragItem = hitItem;\n\t\t\t\t\t}\n\t\t\t\t\tdownPoint = point;\n\t\t\t\t} else if (mouse.up) {\n\t\t\t\t\tif (!prevented && hitItem === downItem) {\n\t\t\t\t\t\tclickTime = Date.now();\n\t\t\t\t\t\temitMouseEvents(this, hitItem, dblClick ? 'doubleclick'\n\t\t\t\t\t\t\t\t: 'click', event, point, downPoint);\n\t\t\t\t\t\tdblClick = false;\n\t\t\t\t\t}\n\t\t\t\t\tdownItem = dragItem = null;\n\t\t\t\t}\n\t\t\t\twasInView = false;\n\t\t\t\thandle = true;\n\t\t\t}\n\t\t\tlastPoint = point;\n\t\t\tif (handle && tool) {\n\t\t\t\tcalled = tool._handleMouseEvent(type, event, point, mouse)\n\t\t\t\t\t|| called;\n\t\t\t}\n\n\t\t\tif (called && !mouse.move || mouse.down && responds('mouseup'))\n\t\t\t\tevent.preventDefault();\n\t\t},\n\n\t\t_handleKeyEvent: function(type, event, key, character) {\n\t\t\tvar scope = this._scope,\n\t\t\t\ttool = scope.tool,\n\t\t\t\tkeyEvent;\n\n\t\t\tfunction emit(obj) {\n\t\t\t\tif (obj.responds(type)) {\n\t\t\t\t\tpaper = scope;\n\t\t\t\t\tobj.emit(type, keyEvent = keyEvent\n\t\t\t\t\t\t\t|| new KeyEvent(type, event, key, character));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.isVisible()) {\n\t\t\t\temit(this);\n\t\t\t\tif (tool && tool.responds(type))\n\t\t\t\t\temit(tool);\n\t\t\t}\n\t\t},\n\n\t\t_countItemEvent: function(type, sign) {\n\t\t\tvar itemEvents = this._itemEvents,\n\t\t\t\tnative = itemEvents.native,\n\t\t\t\tvirtual = itemEvents.virtual;\n\t\t\tfor (var key in itemEventsMap) {\n\t\t\t\tnative[key] = (native[key] || 0)\n\t\t\t\t\t\t+ (itemEventsMap[key][type] || 0) * sign;\n\t\t\t}\n\t\t\tvirtual[type] = (virtual[type] || 0) + sign;\n\t\t},\n\n\t\tstatics: {\n\t\t\tupdateFocus: updateFocus\n\t\t}\n\t};\n});\n\nvar CanvasView = View.extend({\n\t_class: 'CanvasView',\n\n\tinitialize: function CanvasView(project, canvas) {\n\t\tif (!(canvas instanceof window.HTMLCanvasElement)) {\n\t\t\tvar size = Size.read(arguments, 1);\n\t\t\tif (size.isZero())\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\t'Cannot create CanvasView with the provided argument: '\n\t\t\t\t\t\t+ Base.slice(arguments, 1));\n\t\t\tcanvas = CanvasProvider.getCanvas(size);\n\t\t}\n\t\tvar ctx = this._context = canvas.getContext('2d');\n\t\tctx.save();\n\t\tthis._pixelRatio = 1;\n\t\tif (!/^off|false$/.test(PaperScope.getAttribute(canvas, 'hidpi'))) {\n\t\t\tvar deviceRatio = window.devicePixelRatio || 1,\n\t\t\t\tbackingStoreRatio = DomElement.getPrefixed(ctx,\n\t\t\t\t\t\t'backingStorePixelRatio') || 1;\n\t\t\tthis._pixelRatio = deviceRatio / backingStoreRatio;\n\t\t}\n\t\tView.call(this, project, canvas);\n\t\tthis._needsUpdate = true;\n\t},\n\n\tremove: function remove() {\n\t\tthis._context.restore();\n\t\treturn remove.base.call(this);\n\t},\n\n\t_setElementSize: function _setElementSize(width, height) {\n\t\tvar pixelRatio = this._pixelRatio;\n\t\t_setElementSize.base.call(this, width * pixelRatio, height * pixelRatio);\n\t\tif (pixelRatio !== 1) {\n\t\t\tvar element = this._element,\n\t\t\t\tctx = this._context;\n\t\t\tif (!PaperScope.hasAttribute(element, 'resize')) {\n\t\t\t\tvar style = element.style;\n\t\t\t\tstyle.width = width + 'px';\n\t\t\t\tstyle.height = height + 'px';\n\t\t\t}\n\t\t\tctx.restore();\n\t\t\tctx.save();\n\t\t\tctx.scale(pixelRatio, pixelRatio);\n\t\t}\n\t},\n\n\tgetPixelSize: function getPixelSize(size) {\n\t\tvar agent = paper.agent,\n\t\t\tpixels;\n\t\tif (agent && agent.firefox) {\n\t\t\tpixels = getPixelSize.base.call(this, size);\n\t\t} else {\n\t\t\tvar ctx = this._context,\n\t\t\t\tprevFont = ctx.font;\n\t\t\tctx.font = size + ' serif';\n\t\t\tpixels = parseFloat(ctx.font);\n\t\t\tctx.font = prevFont;\n\t\t}\n\t\treturn pixels;\n\t},\n\n\tgetTextWidth: function(font, lines) {\n\t\tvar ctx = this._context,\n\t\t\tprevFont = ctx.font,\n\t\t\twidth = 0;\n\t\tctx.font = font;\n\t\tfor (var i = 0, l = lines.length; i < l; i++)\n\t\t\twidth = Math.max(width, ctx.measureText(lines[i]).width);\n\t\tctx.font = prevFont;\n\t\treturn width;\n\t},\n\n\tupdate: function() {\n\t\tif (!this._needsUpdate)\n\t\t\treturn false;\n\t\tvar project = this._project,\n\t\t\tctx = this._context,\n\t\t\tsize = this._viewSize;\n\t\tctx.clearRect(0, 0, size.width + 1, size.height + 1);\n\t\tif (project)\n\t\t\tproject.draw(ctx, this._matrix, this._pixelRatio);\n\t\tthis._needsUpdate = false;\n\t\treturn true;\n\t}\n});\n\nvar Event = Base.extend({\n\t_class: 'Event',\n\n\tinitialize: function Event(event) {\n\t\tthis.event = event;\n\t\tthis.type = event && event.type;\n\t},\n\n\tprevented: false,\n\tstopped: false,\n\n\tpreventDefault: function() {\n\t\tthis.prevented = true;\n\t\tthis.event.preventDefault();\n\t},\n\n\tstopPropagation: function() {\n\t\tthis.stopped = true;\n\t\tthis.event.stopPropagation();\n\t},\n\n\tstop: function() {\n\t\tthis.stopPropagation();\n\t\tthis.preventDefault();\n\t},\n\n\tgetTimeStamp: function() {\n\t\treturn this.event.timeStamp;\n\t},\n\n\tgetModifiers: function() {\n\t\treturn Key.modifiers;\n\t}\n});\n\nvar KeyEvent = Event.extend({\n\t_class: 'KeyEvent',\n\n\tinitialize: function KeyEvent(type, event, key, character) {\n\t\tthis.type = type;\n\t\tthis.event = event;\n\t\tthis.key = key;\n\t\tthis.character = character;\n\t},\n\n\ttoString: function() {\n\t\treturn \"{ type: '\" + this.type\n\t\t\t\t+ \"', key: '\" + this.key\n\t\t\t\t+ \"', character: '\" + this.character\n\t\t\t\t+ \"', modifiers: \" + this.getModifiers()\n\t\t\t\t+ \" }\";\n\t}\n});\n\nvar Key = new function() {\n\tvar keyLookup = {\n\t\t\t'\\t': 'tab',\n\t\t\t' ': 'space',\n\t\t\t'\\b': 'backspace',\n\t\t\t'\\x7f': 'delete',\n\t\t\t'Spacebar': 'space',\n\t\t\t'Del': 'delete',\n\t\t\t'Win': 'meta',\n\t\t\t'Esc': 'escape'\n\t\t},\n\n\t\tcharLookup = {\n\t\t\t'tab': '\\t',\n\t\t\t'space': ' ',\n\t\t\t'enter': '\\r'\n\t\t},\n\n\t\tkeyMap = {},\n\t\tcharMap = {},\n\t\tmetaFixMap,\n\t\tdownKey,\n\n\t\tmodifiers = new Base({\n\t\t\tshift: false,\n\t\t\tcontrol: false,\n\t\t\talt: false,\n\t\t\tmeta: false,\n\t\t\tcapsLock: false,\n\t\t\tspace: false\n\t\t}).inject({\n\t\t\toption: {\n\t\t\t\tget: function() {\n\t\t\t\t\treturn this.alt;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tcommand: {\n\t\t\t\tget: function() {\n\t\t\t\t\tvar agent = paper && paper.agent;\n\t\t\t\t\treturn agent && agent.mac ? this.meta : this.control;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\tfunction getKey(event) {\n\t\tvar key = event.key || event.keyIdentifier;\n\t\tkey = /^U\\+/.test(key)\n\t\t\t\t? String.fromCharCode(parseInt(key.substr(2), 16))\n\t\t\t\t: /^Arrow[A-Z]/.test(key) ? key.substr(5)\n\t\t\t\t: key === 'Unidentified' ? String.fromCharCode(event.keyCode)\n\t\t\t\t: key;\n\t\treturn keyLookup[key] ||\n\t\t\t\t(key.length > 1 ? Base.hyphenate(key) : key.toLowerCase());\n\t}\n\n\tfunction handleKey(down, key, character, event) {\n\t\tvar type = down ? 'keydown' : 'keyup',\n\t\t\tview = View._focused,\n\t\t\tname;\n\t\tkeyMap[key] = down;\n\t\tif (down) {\n\t\t\tcharMap[key] = character;\n\t\t} else {\n\t\t\tdelete charMap[key];\n\t\t}\n\t\tif (key.length > 1 && (name = Base.camelize(key)) in modifiers) {\n\t\t\tmodifiers[name] = down;\n\t\t\tvar agent = paper && paper.agent;\n\t\t\tif (name === 'meta' && agent && agent.mac) {\n\t\t\t\tif (down) {\n\t\t\t\t\tmetaFixMap = {};\n\t\t\t\t} else {\n\t\t\t\t\tfor (var k in metaFixMap) {\n\t\t\t\t\t\tif (k in charMap)\n\t\t\t\t\t\t\thandleKey(false, k, metaFixMap[k], event);\n\t\t\t\t\t}\n\t\t\t\t\tmetaFixMap = null;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (down && metaFixMap) {\n\t\t\tmetaFixMap[key] = character;\n\t\t}\n\t\tif (view) {\n\t\t\tview._handleKeyEvent(down ? 'keydown' : 'keyup', event, key,\n\t\t\t\t\tcharacter);\n\t\t}\n\t}\n\n\tDomEvent.add(document, {\n\t\tkeydown: function(event) {\n\t\t\tvar key = getKey(event),\n\t\t\t\tagent = paper && paper.agent;\n\t\t\tif (key.length > 1 || agent && (agent.chrome && (event.altKey\n\t\t\t\t\t\t|| agent.mac && event.metaKey\n\t\t\t\t\t\t|| !agent.mac && event.ctrlKey))) {\n\t\t\t\thandleKey(true, key,\n\t\t\t\t\t\tcharLookup[key] || (key.length > 1 ? '' : key), event);\n\t\t\t} else {\n\t\t\t\tdownKey = key;\n\t\t\t}\n\t\t},\n\n\t\tkeypress: function(event) {\n\t\t\tif (downKey) {\n\t\t\t\tvar key = getKey(event),\n\t\t\t\t\tcode = event.charCode,\n\t\t\t\t\tcharacter = code >= 32 ? String.fromCharCode(code)\n\t\t\t\t\t\t: key.length > 1 ? '' : key;\n\t\t\t\tif (key !== downKey) {\n\t\t\t\t\tkey = character.toLowerCase();\n\t\t\t\t}\n\t\t\t\thandleKey(true, key, character, event);\n\t\t\t\tdownKey = null;\n\t\t\t}\n\t\t},\n\n\t\tkeyup: function(event) {\n\t\t\tvar key = getKey(event);\n\t\t\tif (key in charMap)\n\t\t\t\thandleKey(false, key, charMap[key], event);\n\t\t}\n\t});\n\n\tDomEvent.add(window, {\n\t\tblur: function(event) {\n\t\t\tfor (var key in charMap)\n\t\t\t\thandleKey(false, key, charMap[key], event);\n\t\t}\n\t});\n\n\treturn {\n\t\tmodifiers: modifiers,\n\n\t\tisDown: function(key) {\n\t\t\treturn !!keyMap[key];\n\t\t}\n\t};\n};\n\nvar MouseEvent = Event.extend({\n\t_class: 'MouseEvent',\n\n\tinitialize: function MouseEvent(type, event, point, target, delta) {\n\t\tthis.type = type;\n\t\tthis.event = event;\n\t\tthis.point = point;\n\t\tthis.target = target;\n\t\tthis.delta = delta;\n\t},\n\n\ttoString: function() {\n\t\treturn \"{ type: '\" + this.type\n\t\t\t\t+ \"', point: \" + this.point\n\t\t\t\t+ ', target: ' + this.target\n\t\t\t\t+ (this.delta ? ', delta: ' + this.delta : '')\n\t\t\t\t+ ', modifiers: ' + this.getModifiers()\n\t\t\t\t+ ' }';\n\t}\n});\n\nvar ToolEvent = Event.extend({\n\t_class: 'ToolEvent',\n\t_item: null,\n\n\tinitialize: function ToolEvent(tool, type, event) {\n\t\tthis.tool = tool;\n\t\tthis.type = type;\n\t\tthis.event = event;\n\t},\n\n\t_choosePoint: function(point, toolPoint) {\n\t\treturn point ? point : toolPoint ? toolPoint.clone() : null;\n\t},\n\n\tgetPoint: function() {\n\t\treturn this._choosePoint(this._point, this.tool._point);\n\t},\n\n\tsetPoint: function(point) {\n\t\tthis._point = point;\n\t},\n\n\tgetLastPoint: function() {\n\t\treturn this._choosePoint(this._lastPoint, this.tool._lastPoint);\n\t},\n\n\tsetLastPoint: function(lastPoint) {\n\t\tthis._lastPoint = lastPoint;\n\t},\n\n\tgetDownPoint: function() {\n\t\treturn this._choosePoint(this._downPoint, this.tool._downPoint);\n\t},\n\n\tsetDownPoint: function(downPoint) {\n\t\tthis._downPoint = downPoint;\n\t},\n\n\tgetMiddlePoint: function() {\n\t\tif (!this._middlePoint && this.tool._lastPoint) {\n\t\t\treturn this.tool._point.add(this.tool._lastPoint).divide(2);\n\t\t}\n\t\treturn this._middlePoint;\n\t},\n\n\tsetMiddlePoint: function(middlePoint) {\n\t\tthis._middlePoint = middlePoint;\n\t},\n\n\tgetDelta: function() {\n\t\treturn !this._delta && this.tool._lastPoint\n\t\t\t\t? this.tool._point.subtract(this.tool._lastPoint)\n\t\t\t\t: this._delta;\n\t},\n\n\tsetDelta: function(delta) {\n\t\tthis._delta = delta;\n\t},\n\n\tgetCount: function() {\n\t\treturn this.tool[/^mouse(down|up)$/.test(this.type)\n\t\t\t\t? '_downCount' : '_moveCount'];\n\t},\n\n\tsetCount: function(count) {\n\t\tthis.tool[/^mouse(down|up)$/.test(this.type) ? 'downCount' : 'count']\n\t\t\t= count;\n\t},\n\n\tgetItem: function() {\n\t\tif (!this._item) {\n\t\t\tvar result = this.tool._scope.project.hitTest(this.getPoint());\n\t\t\tif (result) {\n\t\t\t\tvar item = result.item,\n\t\t\t\t\tparent = item._parent;\n\t\t\t\twhile (/^(Group|CompoundPath)$/.test(parent._class)) {\n\t\t\t\t\titem = parent;\n\t\t\t\t\tparent = parent._parent;\n\t\t\t\t}\n\t\t\t\tthis._item = item;\n\t\t\t}\n\t\t}\n\t\treturn this._item;\n\t},\n\n\tsetItem: function(item) {\n\t\tthis._item = item;\n\t},\n\n\ttoString: function() {\n\t\treturn '{ type: ' + this.type\n\t\t\t\t+ ', point: ' + this.getPoint()\n\t\t\t\t+ ', count: ' + this.getCount()\n\t\t\t\t+ ', modifiers: ' + this.getModifiers()\n\t\t\t\t+ ' }';\n\t}\n});\n\nvar Tool = PaperScopeItem.extend({\n\t_class: 'Tool',\n\t_list: 'tools',\n\t_reference: 'tool',\n\t_events: ['onMouseDown', 'onMouseUp', 'onMouseDrag', 'onMouseMove',\n\t\t\t'onActivate', 'onDeactivate', 'onEditOptions', 'onKeyDown',\n\t\t\t'onKeyUp'],\n\n\tinitialize: function Tool(props) {\n\t\tPaperScopeItem.call(this);\n\t\tthis._moveCount = -1;\n\t\tthis._downCount = -1;\n\t\tthis.set(props);\n\t},\n\n\tgetMinDistance: function() {\n\t\treturn this._minDistance;\n\t},\n\n\tsetMinDistance: function(minDistance) {\n\t\tthis._minDistance = minDistance;\n\t\tif (minDistance != null && this._maxDistance != null\n\t\t\t\t&& minDistance > this._maxDistance) {\n\t\t\tthis._maxDistance = minDistance;\n\t\t}\n\t},\n\n\tgetMaxDistance: function() {\n\t\treturn this._maxDistance;\n\t},\n\n\tsetMaxDistance: function(maxDistance) {\n\t\tthis._maxDistance = maxDistance;\n\t\tif (this._minDistance != null && maxDistance != null\n\t\t\t\t&& maxDistance < this._minDistance) {\n\t\t\tthis._minDistance = maxDistance;\n\t\t}\n\t},\n\n\tgetFixedDistance: function() {\n\t\treturn this._minDistance == this._maxDistance\n\t\t\t? this._minDistance : null;\n\t},\n\n\tsetFixedDistance: function(distance) {\n\t\tthis._minDistance = this._maxDistance = distance;\n\t},\n\n\t_handleMouseEvent: function(type, event, point, mouse) {\n\t\tpaper = this._scope;\n\t\tif (mouse.drag && !this.responds(type))\n\t\t\ttype = 'mousemove';\n\t\tvar move = mouse.move || mouse.drag,\n\t\t\tresponds = this.responds(type),\n\t\t\tminDistance = this.minDistance,\n\t\t\tmaxDistance = this.maxDistance,\n\t\t\tcalled = false,\n\t\t\ttool = this;\n\t\tfunction update(minDistance, maxDistance) {\n\t\t\tvar pt = point,\n\t\t\t\ttoolPoint = move ? tool._point : (tool._downPoint || pt);\n\t\t\tif (move) {\n\t\t\t\tif (tool._moveCount && pt.equals(toolPoint)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif (toolPoint && (minDistance != null || maxDistance != null)) {\n\t\t\t\t\tvar vector = pt.subtract(toolPoint),\n\t\t\t\t\t\tdistance = vector.getLength();\n\t\t\t\t\tif (distance < (minDistance || 0))\n\t\t\t\t\t\treturn false;\n\t\t\t\t\tif (maxDistance) {\n\t\t\t\t\t\tpt = toolPoint.add(vector.normalize(\n\t\t\t\t\t\t\t\tMath.min(distance, maxDistance)));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ttool._moveCount++;\n\t\t\t}\n\t\t\ttool._point = pt;\n\t\t\ttool._lastPoint = toolPoint || pt;\n\t\t\tif (mouse.down) {\n\t\t\t\ttool._moveCount = -1;\n\t\t\t\ttool._downPoint = pt;\n\t\t\t\ttool._downCount++;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tfunction emit() {\n\t\t\tif (responds) {\n\t\t\t\tcalled = tool.emit(type, new ToolEvent(tool, type, event))\n\t\t\t\t\t\t|| called;\n\t\t\t}\n\t\t}\n\n\t\tif (mouse.down) {\n\t\t\tupdate();\n\t\t\temit();\n\t\t} else if (mouse.up) {\n\t\t\tupdate(null, maxDistance);\n\t\t\temit();\n\t\t} else if (responds) {\n\t\t\twhile (update(minDistance, maxDistance))\n\t\t\t\temit();\n\t\t}\n\t\treturn called;\n\t}\n\n});\n\nvar Http = {\n\trequest: function(options) {\n\t\tvar xhr = new self.XMLHttpRequest();\n\t\txhr.open((options.method || 'get').toUpperCase(), options.url,\n\t\t\t\tBase.pick(options.async, true));\n\t\tif (options.mimeType)\n\t\t\txhr.overrideMimeType(options.mimeType);\n\t\txhr.onload = function() {\n\t\t\tvar status = xhr.status;\n\t\t\tif (status === 0 || status === 200) {\n\t\t\t\tif (options.onLoad) {\n\t\t\t\t\toptions.onLoad.call(xhr, xhr.responseText);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\txhr.onerror();\n\t\t\t}\n\t\t};\n\t\txhr.onerror = function() {\n\t\t\tvar status = xhr.status,\n\t\t\t\tmessage = 'Could not load \"' + options.url + '\" (Status: '\n\t\t\t\t\t\t+ status + ')';\n\t\t\tif (options.onError) {\n\t\t\t\toptions.onError(message, status);\n\t\t\t} else {\n\t\t\t\tthrow new Error(message);\n\t\t\t}\n\t\t};\n\t\treturn xhr.send(null);\n\t}\n};\n\nvar CanvasProvider = {\n\tcanvases: [],\n\n\tgetCanvas: function(width, height) {\n\t\tif (!window)\n\t\t\treturn null;\n\t\tvar canvas,\n\t\t\tclear = true;\n\t\tif (typeof width === 'object') {\n\t\t\theight = width.height;\n\t\t\twidth = width.width;\n\t\t}\n\t\tif (this.canvases.length) {\n\t\t\tcanvas = this.canvases.pop();\n\t\t} else {\n\t\t\tcanvas = document.createElement('canvas');\n\t\t\tclear = false;\n\t\t}\n\t\tvar ctx = canvas.getContext('2d');\n\t\tif (!ctx) {\n\t\t\tthrow new Error('Canvas ' + canvas +\n\t\t\t\t\t' is unable to provide a 2D context.');\n\t\t}\n\t\tif (canvas.width === width && canvas.height === height) {\n\t\t\tif (clear)\n\t\t\t\tctx.clearRect(0, 0, width + 1, height + 1);\n\t\t} else {\n\t\t\tcanvas.width = width;\n\t\t\tcanvas.height = height;\n\t\t}\n\t\tctx.save();\n\t\treturn canvas;\n\t},\n\n\tgetContext: function(width, height) {\n\t\tvar canvas = this.getCanvas(width, height);\n\t\treturn canvas ? canvas.getContext('2d') : null;\n\t},\n\n\trelease: function(obj) {\n\t\tvar canvas = obj && obj.canvas ? obj.canvas : obj;\n\t\tif (canvas && canvas.getContext) {\n\t\t\tcanvas.getContext('2d').restore();\n\t\t\tthis.canvases.push(canvas);\n\t\t}\n\t}\n};\n\nvar BlendMode = new function() {\n\tvar min = Math.min,\n\t\tmax = Math.max,\n\t\tabs = Math.abs,\n\t\tsr, sg, sb, sa,\n\t\tbr, bg, bb, ba,\n\t\tdr, dg, db;\n\n\tfunction getLum(r, g, b) {\n\t\treturn 0.2989 * r + 0.587 * g + 0.114 * b;\n\t}\n\n\tfunction setLum(r, g, b, l) {\n\t\tvar d = l - getLum(r, g, b);\n\t\tdr = r + d;\n\t\tdg = g + d;\n\t\tdb = b + d;\n\t\tvar l = getLum(dr, dg, db),\n\t\t\tmn = min(dr, dg, db),\n\t\t\tmx = max(dr, dg, db);\n\t\tif (mn < 0) {\n\t\t\tvar lmn = l - mn;\n\t\t\tdr = l + (dr - l) * l / lmn;\n\t\t\tdg = l + (dg - l) * l / lmn;\n\t\t\tdb = l + (db - l) * l / lmn;\n\t\t}\n\t\tif (mx > 255) {\n\t\t\tvar ln = 255 - l,\n\t\t\t\tmxl = mx - l;\n\t\t\tdr = l + (dr - l) * ln / mxl;\n\t\t\tdg = l + (dg - l) * ln / mxl;\n\t\t\tdb = l + (db - l) * ln / mxl;\n\t\t}\n\t}\n\n\tfunction getSat(r, g, b) {\n\t\treturn max(r, g, b) - min(r, g, b);\n\t}\n\n\tfunction setSat(r, g, b, s) {\n\t\tvar col = [r, g, b],\n\t\t\tmx = max(r, g, b),\n\t\t\tmn = min(r, g, b),\n\t\t\tmd;\n\t\tmn = mn === r ? 0 : mn === g ? 1 : 2;\n\t\tmx = mx === r ? 0 : mx === g ? 1 : 2;\n\t\tmd = min(mn, mx) === 0 ? max(mn, mx) === 1 ? 2 : 1 : 0;\n\t\tif (col[mx] > col[mn]) {\n\t\t\tcol[md] = (col[md] - col[mn]) * s / (col[mx] - col[mn]);\n\t\t\tcol[mx] = s;\n\t\t} else {\n\t\t\tcol[md] = col[mx] = 0;\n\t\t}\n\t\tcol[mn] = 0;\n\t\tdr = col[0];\n\t\tdg = col[1];\n\t\tdb = col[2];\n\t}\n\n\tvar modes = {\n\t\tmultiply: function() {\n\t\t\tdr = br * sr / 255;\n\t\t\tdg = bg * sg / 255;\n\t\t\tdb = bb * sb / 255;\n\t\t},\n\n\t\tscreen: function() {\n\t\t\tdr = br + sr - (br * sr / 255);\n\t\t\tdg = bg + sg - (bg * sg / 255);\n\t\t\tdb = bb + sb - (bb * sb / 255);\n\t\t},\n\n\t\toverlay: function() {\n\t\t\tdr = br < 128 ? 2 * br * sr / 255 : 255 - 2 * (255 - br) * (255 - sr) / 255;\n\t\t\tdg = bg < 128 ? 2 * bg * sg / 255 : 255 - 2 * (255 - bg) * (255 - sg) / 255;\n\t\t\tdb = bb < 128 ? 2 * bb * sb / 255 : 255 - 2 * (255 - bb) * (255 - sb) / 255;\n\t\t},\n\n\t\t'soft-light': function() {\n\t\t\tvar t = sr * br / 255;\n\t\t\tdr = t + br * (255 - (255 - br) * (255 - sr) / 255 - t) / 255;\n\t\t\tt = sg * bg / 255;\n\t\t\tdg = t + bg * (255 - (255 - bg) * (255 - sg) / 255 - t) / 255;\n\t\t\tt = sb * bb / 255;\n\t\t\tdb = t + bb * (255 - (255 - bb) * (255 - sb) / 255 - t) / 255;\n\t\t},\n\n\t\t'hard-light': function() {\n\t\t\tdr = sr < 128 ? 2 * sr * br / 255 : 255 - 2 * (255 - sr) * (255 - br) / 255;\n\t\t\tdg = sg < 128 ? 2 * sg * bg / 255 : 255 - 2 * (255 - sg) * (255 - bg) / 255;\n\t\t\tdb = sb < 128 ? 2 * sb * bb / 255 : 255 - 2 * (255 - sb) * (255 - bb) / 255;\n\t\t},\n\n\t\t'color-dodge': function() {\n\t\t\tdr = br === 0 ? 0 : sr === 255 ? 255 : min(255, 255 * br / (255 - sr));\n\t\t\tdg = bg === 0 ? 0 : sg === 255 ? 255 : min(255, 255 * bg / (255 - sg));\n\t\t\tdb = bb === 0 ? 0 : sb === 255 ? 255 : min(255, 255 * bb / (255 - sb));\n\t\t},\n\n\t\t'color-burn': function() {\n\t\t\tdr = br === 255 ? 255 : sr === 0 ? 0 : max(0, 255 - (255 - br) * 255 / sr);\n\t\t\tdg = bg === 255 ? 255 : sg === 0 ? 0 : max(0, 255 - (255 - bg) * 255 / sg);\n\t\t\tdb = bb === 255 ? 255 : sb === 0 ? 0 : max(0, 255 - (255 - bb) * 255 / sb);\n\t\t},\n\n\t\tdarken: function() {\n\t\t\tdr = br < sr ? br : sr;\n\t\t\tdg = bg < sg ? bg : sg;\n\t\t\tdb = bb < sb ? bb : sb;\n\t\t},\n\n\t\tlighten: function() {\n\t\t\tdr = br > sr ? br : sr;\n\t\t\tdg = bg > sg ? bg : sg;\n\t\t\tdb = bb > sb ? bb : sb;\n\t\t},\n\n\t\tdifference: function() {\n\t\t\tdr = br - sr;\n\t\t\tif (dr < 0)\n\t\t\t\tdr = -dr;\n\t\t\tdg = bg - sg;\n\t\t\tif (dg < 0)\n\t\t\t\tdg = -dg;\n\t\t\tdb = bb - sb;\n\t\t\tif (db < 0)\n\t\t\t\tdb = -db;\n\t\t},\n\n\t\texclusion: function() {\n\t\t\tdr = br + sr * (255 - br - br) / 255;\n\t\t\tdg = bg + sg * (255 - bg - bg) / 255;\n\t\t\tdb = bb + sb * (255 - bb - bb) / 255;\n\t\t},\n\n\t\thue: function() {\n\t\t\tsetSat(sr, sg, sb, getSat(br, bg, bb));\n\t\t\tsetLum(dr, dg, db, getLum(br, bg, bb));\n\t\t},\n\n\t\tsaturation: function() {\n\t\t\tsetSat(br, bg, bb, getSat(sr, sg, sb));\n\t\t\tsetLum(dr, dg, db, getLum(br, bg, bb));\n\t\t},\n\n\t\tluminosity: function() {\n\t\t\tsetLum(br, bg, bb, getLum(sr, sg, sb));\n\t\t},\n\n\t\tcolor: function() {\n\t\t\tsetLum(sr, sg, sb, getLum(br, bg, bb));\n\t\t},\n\n\t\tadd: function() {\n\t\t\tdr = min(br + sr, 255);\n\t\t\tdg = min(bg + sg, 255);\n\t\t\tdb = min(bb + sb, 255);\n\t\t},\n\n\t\tsubtract: function() {\n\t\t\tdr = max(br - sr, 0);\n\t\t\tdg = max(bg - sg, 0);\n\t\t\tdb = max(bb - sb, 0);\n\t\t},\n\n\t\taverage: function() {\n\t\t\tdr = (br + sr) / 2;\n\t\t\tdg = (bg + sg) / 2;\n\t\t\tdb = (bb + sb) / 2;\n\t\t},\n\n\t\tnegation: function() {\n\t\t\tdr = 255 - abs(255 - sr - br);\n\t\t\tdg = 255 - abs(255 - sg - bg);\n\t\t\tdb = 255 - abs(255 - sb - bb);\n\t\t}\n\t};\n\n\tvar nativeModes = this.nativeModes = Base.each([\n\t\t'source-over', 'source-in', 'source-out', 'source-atop',\n\t\t'destination-over', 'destination-in', 'destination-out',\n\t\t'destination-atop', 'lighter', 'darker', 'copy', 'xor'\n\t], function(mode) {\n\t\tthis[mode] = true;\n\t}, {});\n\n\tvar ctx = CanvasProvider.getContext(1, 1);\n\tif (ctx) {\n\t\tBase.each(modes, function(func, mode) {\n\t\t\tvar darken = mode === 'darken',\n\t\t\t\tok = false;\n\t\t\tctx.save();\n\t\t\ttry {\n\t\t\t\tctx.fillStyle = darken ? '#300' : '#a00';\n\t\t\t\tctx.fillRect(0, 0, 1, 1);\n\t\t\t\tctx.globalCompositeOperation = mode;\n\t\t\t\tif (ctx.globalCompositeOperation === mode) {\n\t\t\t\t\tctx.fillStyle = darken ? '#a00' : '#300';\n\t\t\t\t\tctx.fillRect(0, 0, 1, 1);\n\t\t\t\t\tok = ctx.getImageData(0, 0, 1, 1).data[0] !== darken\n\t\t\t\t\t\t\t? 170 : 51;\n\t\t\t\t}\n\t\t\t} catch (e) {}\n\t\t\tctx.restore();\n\t\t\tnativeModes[mode] = ok;\n\t\t});\n\t\tCanvasProvider.release(ctx);\n\t}\n\n\tthis.process = function(mode, srcContext, dstContext, alpha, offset) {\n\t\tvar srcCanvas = srcContext.canvas,\n\t\t\tnormal = mode === 'normal';\n\t\tif (normal || nativeModes[mode]) {\n\t\t\tdstContext.save();\n\t\t\tdstContext.setTransform(1, 0, 0, 1, 0, 0);\n\t\t\tdstContext.globalAlpha = alpha;\n\t\t\tif (!normal)\n\t\t\t\tdstContext.globalCompositeOperation = mode;\n\t\t\tdstContext.drawImage(srcCanvas, offset.x, offset.y);\n\t\t\tdstContext.restore();\n\t\t} else {\n\t\t\tvar process = modes[mode];\n\t\t\tif (!process)\n\t\t\t\treturn;\n\t\t\tvar dstData = dstContext.getImageData(offset.x, offset.y,\n\t\t\t\t\tsrcCanvas.width, srcCanvas.height),\n\t\t\t\tdst = dstData.data,\n\t\t\t\tsrc = srcContext.getImageData(0, 0,\n\t\t\t\t\tsrcCanvas.width, srcCanvas.height).data;\n\t\t\tfor (var i = 0, l = dst.length; i < l; i += 4) {\n\t\t\t\tsr = src[i];\n\t\t\t\tbr = dst[i];\n\t\t\t\tsg = src[i + 1];\n\t\t\t\tbg = dst[i + 1];\n\t\t\t\tsb = src[i + 2];\n\t\t\t\tbb = dst[i + 2];\n\t\t\t\tsa = src[i + 3];\n\t\t\t\tba = dst[i + 3];\n\t\t\t\tprocess();\n\t\t\t\tvar a1 = sa * alpha / 255,\n\t\t\t\t\ta2 = 1 - a1;\n\t\t\t\tdst[i] = a1 * dr + a2 * br;\n\t\t\t\tdst[i + 1] = a1 * dg + a2 * bg;\n\t\t\t\tdst[i + 2] = a1 * db + a2 * bb;\n\t\t\t\tdst[i + 3] = sa * alpha + a2 * ba;\n\t\t\t}\n\t\t\tdstContext.putImageData(dstData, offset.x, offset.y);\n\t\t}\n\t};\n};\n\nvar SvgElement = new function() {\n\tvar svg = 'http://www.w3.org/2000/svg',\n\t\txmlns = 'http://www.w3.org/2000/xmlns',\n\t\txlink = 'http://www.w3.org/1999/xlink',\n\t\tattributeNamespace = {\n\t\t\thref: xlink,\n\t\t\txlink: xmlns,\n\t\t\txmlns: xmlns + '/',\n\t\t\t'xmlns:xlink': xmlns + '/'\n\t\t};\n\n\tfunction create(tag, attributes, formatter) {\n\t\treturn set(document.createElementNS(svg, tag), attributes, formatter);\n\t}\n\n\tfunction get(node, name) {\n\t\tvar namespace = attributeNamespace[name],\n\t\t\tvalue = namespace\n\t\t\t\t? node.getAttributeNS(namespace, name)\n\t\t\t\t: node.getAttribute(name);\n\t\treturn value === 'null' ? null : value;\n\t}\n\n\tfunction set(node, attributes, formatter) {\n\t\tfor (var name in attributes) {\n\t\t\tvar value = attributes[name],\n\t\t\t\tnamespace = attributeNamespace[name];\n\t\t\tif (typeof value === 'number' && formatter)\n\t\t\t\tvalue = formatter.number(value);\n\t\t\tif (namespace) {\n\t\t\t\tnode.setAttributeNS(namespace, name, value);\n\t\t\t} else {\n\t\t\t\tnode.setAttribute(name, value);\n\t\t\t}\n\t\t}\n\t\treturn node;\n\t}\n\n\treturn {\n\t\tsvg: svg,\n\t\txmlns: xmlns,\n\t\txlink: xlink,\n\n\t\tcreate: create,\n\t\tget: get,\n\t\tset: set\n\t};\n};\n\nvar SvgStyles = Base.each({\n\tfillColor: ['fill', 'color'],\n\tfillRule: ['fill-rule', 'string'],\n\tstrokeColor: ['stroke', 'color'],\n\tstrokeWidth: ['stroke-width', 'number'],\n\tstrokeCap: ['stroke-linecap', 'string'],\n\tstrokeJoin: ['stroke-linejoin', 'string'],\n\tstrokeScaling: ['vector-effect', 'lookup', {\n\t\ttrue: 'none',\n\t\tfalse: 'non-scaling-stroke'\n\t}, function(item, value) {\n\t\treturn !value\n\t\t\t\t&& (item instanceof PathItem\n\t\t\t\t\t|| item instanceof Shape\n\t\t\t\t\t|| item instanceof TextItem);\n\t}],\n\tmiterLimit: ['stroke-miterlimit', 'number'],\n\tdashArray: ['stroke-dasharray', 'array'],\n\tdashOffset: ['stroke-dashoffset', 'number'],\n\tfontFamily: ['font-family', 'string'],\n\tfontWeight: ['font-weight', 'string'],\n\tfontSize: ['font-size', 'number'],\n\tjustification: ['text-anchor', 'lookup', {\n\t\tleft: 'start',\n\t\tcenter: 'middle',\n\t\tright: 'end'\n\t}],\n\topacity: ['opacity', 'number'],\n\tblendMode: ['mix-blend-mode', 'style']\n}, function(entry, key) {\n\tvar part = Base.capitalize(key),\n\t\tlookup = entry[2];\n\tthis[key] = {\n\t\ttype: entry[1],\n\t\tproperty: key,\n\t\tattribute: entry[0],\n\t\ttoSVG: lookup,\n\t\tfromSVG: lookup && Base.each(lookup, function(value, name) {\n\t\t\tthis[value] = name;\n\t\t}, {}),\n\t\texportFilter: entry[3],\n\t\tget: 'get' + part,\n\t\tset: 'set' + part\n\t};\n}, {});\n\nnew function() {\n\tvar formatter;\n\n\tfunction getTransform(matrix, coordinates, center) {\n\t\tvar attrs = new Base(),\n\t\t\ttrans = matrix.getTranslation();\n\t\tif (coordinates) {\n\t\t\tmatrix = matrix._shiftless();\n\t\t\tvar point = matrix._inverseTransform(trans);\n\t\t\tattrs[center ? 'cx' : 'x'] = point.x;\n\t\t\tattrs[center ? 'cy' : 'y'] = point.y;\n\t\t\ttrans = null;\n\t\t}\n\t\tif (!matrix.isIdentity()) {\n\t\t\tvar decomposed = matrix.decompose();\n\t\t\tif (decomposed) {\n\t\t\t\tvar parts = [],\n\t\t\t\t\tangle = decomposed.rotation,\n\t\t\t\t\tscale = decomposed.scaling,\n\t\t\t\t\tskew = decomposed.skewing;\n\t\t\t\tif (trans && !trans.isZero())\n\t\t\t\t\tparts.push('translate(' + formatter.point(trans) + ')');\n\t\t\t\tif (angle)\n\t\t\t\t\tparts.push('rotate(' + formatter.number(angle) + ')');\n\t\t\t\tif (!Numerical.isZero(scale.x - 1)\n\t\t\t\t\t\t|| !Numerical.isZero(scale.y - 1))\n\t\t\t\t\tparts.push('scale(' + formatter.point(scale) +')');\n\t\t\t\tif (skew.x)\n\t\t\t\t\tparts.push('skewX(' + formatter.number(skew.x) + ')');\n\t\t\t\tif (skew.y)\n\t\t\t\t\tparts.push('skewY(' + formatter.number(skew.y) + ')');\n\t\t\t\tattrs.transform = parts.join(' ');\n\t\t\t} else {\n\t\t\t\tattrs.transform = 'matrix(' + matrix.getValues().join(',') + ')';\n\t\t\t}\n\t\t}\n\t\treturn attrs;\n\t}\n\n\tfunction exportGroup(item, options) {\n\t\tvar attrs = getTransform(item._matrix),\n\t\t\tchildren = item._children;\n\t\tvar node = SvgElement.create('g', attrs, formatter);\n\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\tvar child = children[i];\n\t\t\tvar childNode = exportSVG(child, options);\n\t\t\tif (childNode) {\n\t\t\t\tif (child.isClipMask()) {\n\t\t\t\t\tvar clip = SvgElement.create('clipPath');\n\t\t\t\t\tclip.appendChild(childNode);\n\t\t\t\t\tsetDefinition(child, clip, 'clip');\n\t\t\t\t\tSvgElement.set(node, {\n\t\t\t\t\t\t'clip-path': 'url(#' + clip.id + ')'\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tnode.appendChild(childNode);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn node;\n\t}\n\n\tfunction exportRaster(item, options) {\n\t\tvar attrs = getTransform(item._matrix, true),\n\t\t\tsize = item.getSize(),\n\t\t\timage = item.getImage();\n\t\tattrs.x -= size.width / 2;\n\t\tattrs.y -= size.height / 2;\n\t\tattrs.width = size.width;\n\t\tattrs.height = size.height;\n\t\tattrs.href = options.embedImages == false && image && image.src\n\t\t\t\t|| item.toDataURL();\n\t\treturn SvgElement.create('image', attrs, formatter);\n\t}\n\n\tfunction exportPath(item, options) {\n\t\tvar matchShapes = options.matchShapes;\n\t\tif (matchShapes) {\n\t\t\tvar shape = item.toShape(false);\n\t\t\tif (shape)\n\t\t\t\treturn exportShape(shape, options);\n\t\t}\n\t\tvar segments = item._segments,\n\t\t\tlength = segments.length,\n\t\t\ttype,\n\t\t\tattrs = getTransform(item._matrix);\n\t\tif (matchShapes && length >= 2 && !item.hasHandles()) {\n\t\t\tif (length > 2) {\n\t\t\t\ttype = item._closed ? 'polygon' : 'polyline';\n\t\t\t\tvar parts = [];\n\t\t\t\tfor (var i = 0; i < length; i++) {\n\t\t\t\t\tparts.push(formatter.point(segments[i]._point));\n\t\t\t\t}\n\t\t\t\tattrs.points = parts.join(' ');\n\t\t\t} else {\n\t\t\t\ttype = 'line';\n\t\t\t\tvar start = segments[0]._point,\n\t\t\t\t\tend = segments[1]._point;\n\t\t\t\tattrs.set({\n\t\t\t\t\tx1: start.x,\n\t\t\t\t\ty1: start.y,\n\t\t\t\t\tx2: end.x,\n\t\t\t\t\ty2: end.y\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\ttype = 'path';\n\t\t\tattrs.d = item.getPathData(null, options.precision);\n\t\t}\n\t\treturn SvgElement.create(type, attrs, formatter);\n\t}\n\n\tfunction exportShape(item) {\n\t\tvar type = item._type,\n\t\t\tradius = item._radius,\n\t\t\tattrs = getTransform(item._matrix, true, type !== 'rectangle');\n\t\tif (type === 'rectangle') {\n\t\t\ttype = 'rect';\n\t\t\tvar size = item._size,\n\t\t\t\twidth = size.width,\n\t\t\t\theight = size.height;\n\t\t\tattrs.x -= width / 2;\n\t\t\tattrs.y -= height / 2;\n\t\t\tattrs.width = width;\n\t\t\tattrs.height = height;\n\t\t\tif (radius.isZero())\n\t\t\t\tradius = null;\n\t\t}\n\t\tif (radius) {\n\t\t\tif (type === 'circle') {\n\t\t\t\tattrs.r = radius;\n\t\t\t} else {\n\t\t\t\tattrs.rx = radius.width;\n\t\t\t\tattrs.ry = radius.height;\n\t\t\t}\n\t\t}\n\t\treturn SvgElement.create(type, attrs, formatter);\n\t}\n\n\tfunction exportCompoundPath(item, options) {\n\t\tvar attrs = getTransform(item._matrix);\n\t\tvar data = item.getPathData(null, options.precision);\n\t\tif (data)\n\t\t\tattrs.d = data;\n\t\treturn SvgElement.create('path', attrs, formatter);\n\t}\n\n\tfunction exportSymbolItem(item, options) {\n\t\tvar attrs = getTransform(item._matrix, true),\n\t\t\tdefinition = item._definition,\n\t\t\tnode = getDefinition(definition, 'symbol'),\n\t\t\tdefinitionItem = definition._item,\n\t\t\tbounds = definitionItem.getBounds();\n\t\tif (!node) {\n\t\t\tnode = SvgElement.create('symbol', {\n\t\t\t\tviewBox: formatter.rectangle(bounds)\n\t\t\t});\n\t\t\tnode.appendChild(exportSVG(definitionItem, options));\n\t\t\tsetDefinition(definition, node, 'symbol');\n\t\t}\n\t\tattrs.href = '#' + node.id;\n\t\tattrs.x += bounds.x;\n\t\tattrs.y += bounds.y;\n\t\tattrs.width = bounds.width;\n\t\tattrs.height = bounds.height;\n\t\tattrs.overflow = 'visible';\n\t\treturn SvgElement.create('use', attrs, formatter);\n\t}\n\n\tfunction exportGradient(color) {\n\t\tvar gradientNode = getDefinition(color, 'color');\n\t\tif (!gradientNode) {\n\t\t\tvar gradient = color.getGradient(),\n\t\t\t\tradial = gradient._radial,\n\t\t\t\torigin = color.getOrigin(),\n\t\t\t\tdestination = color.getDestination(),\n\t\t\t\tattrs;\n\t\t\tif (radial) {\n\t\t\t\tattrs = {\n\t\t\t\t\tcx: origin.x,\n\t\t\t\t\tcy: origin.y,\n\t\t\t\t\tr: origin.getDistance(destination)\n\t\t\t\t};\n\t\t\t\tvar highlight = color.getHighlight();\n\t\t\t\tif (highlight) {\n\t\t\t\t\tattrs.fx = highlight.x;\n\t\t\t\t\tattrs.fy = highlight.y;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tattrs = {\n\t\t\t\t\tx1: origin.x,\n\t\t\t\t\ty1: origin.y,\n\t\t\t\t\tx2: destination.x,\n\t\t\t\t\ty2: destination.y\n\t\t\t\t};\n\t\t\t}\n\t\t\tattrs.gradientUnits = 'userSpaceOnUse';\n\t\t\tgradientNode = SvgElement.create((radial ? 'radial' : 'linear')\n\t\t\t\t\t+ 'Gradient', attrs, formatter);\n\t\t\tvar stops = gradient._stops;\n\t\t\tfor (var i = 0, l = stops.length; i < l; i++) {\n\t\t\t\tvar stop = stops[i],\n\t\t\t\t\tstopColor = stop._color,\n\t\t\t\t\talpha = stopColor.getAlpha(),\n\t\t\t\t\toffset = stop._offset;\n\t\t\t\tattrs = {\n\t\t\t\t\toffset: offset == null ? i / (l - 1) : offset\n\t\t\t\t};\n\t\t\t\tif (stopColor)\n\t\t\t\t\tattrs['stop-color'] = stopColor.toCSS(true);\n\t\t\t\tif (alpha < 1)\n\t\t\t\t\tattrs['stop-opacity'] = alpha;\n\t\t\t\tgradientNode.appendChild(\n\t\t\t\t\t\tSvgElement.create('stop', attrs, formatter));\n\t\t\t}\n\t\t\tsetDefinition(color, gradientNode, 'color');\n\t\t}\n\t\treturn 'url(#' + gradientNode.id + ')';\n\t}\n\n\tfunction exportText(item) {\n\t\tvar node = SvgElement.create('text', getTransform(item._matrix, true),\n\t\t\t\tformatter);\n\t\tnode.textContent = item._content;\n\t\treturn node;\n\t}\n\n\tvar exporters = {\n\t\tGroup: exportGroup,\n\t\tLayer: exportGroup,\n\t\tRaster: exportRaster,\n\t\tPath: exportPath,\n\t\tShape: exportShape,\n\t\tCompoundPath: exportCompoundPath,\n\t\tSymbolItem: exportSymbolItem,\n\t\tPointText: exportText\n\t};\n\n\tfunction applyStyle(item, node, isRoot) {\n\t\tvar attrs = {},\n\t\t\tparent = !isRoot && item.getParent(),\n\t\t\tstyle = [];\n\n\t\tif (item._name != null)\n\t\t\tattrs.id = item._name;\n\n\t\tBase.each(SvgStyles, function(entry) {\n\t\t\tvar get = entry.get,\n\t\t\t\ttype = entry.type,\n\t\t\t\tvalue = item[get]();\n\t\t\tif (entry.exportFilter\n\t\t\t\t\t? entry.exportFilter(item, value)\n\t\t\t\t\t: !parent || !Base.equals(parent[get](), value)) {\n\t\t\t\tif (type === 'color' && value != null) {\n\t\t\t\t\tvar alpha = value.getAlpha();\n\t\t\t\t\tif (alpha < 1)\n\t\t\t\t\t\tattrs[entry.attribute + '-opacity'] = alpha;\n\t\t\t\t}\n\t\t\t\tif (type === 'style') {\n\t\t\t\t\tstyle.push(entry.attribute + ': ' + value);\n\t\t\t\t} else {\n\t\t\t\t\tattrs[entry.attribute] = value == null ? 'none'\n\t\t\t\t\t\t\t: type === 'color' ? value.gradient\n\t\t\t\t\t\t\t\t? exportGradient(value, item)\n\t\t\t\t\t\t\t\t: value.toCSS(true)\n\t\t\t\t\t\t\t: type === 'array' ? value.join(',')\n\t\t\t\t\t\t\t: type === 'lookup' ? entry.toSVG[value]\n\t\t\t\t\t\t\t: value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tif (style.length)\n\t\t\tattrs.style = style.join(';');\n\n\t\tif (attrs.opacity === 1)\n\t\t\tdelete attrs.opacity;\n\n\t\tif (!item._visible)\n\t\t\tattrs.visibility = 'hidden';\n\n\t\treturn SvgElement.set(node, attrs, formatter);\n\t}\n\n\tvar definitions;\n\tfunction getDefinition(item, type) {\n\t\tif (!definitions)\n\t\t\tdefinitions = { ids: {}, svgs: {} };\n\t\treturn item && definitions.svgs[type + '-'\n\t\t\t\t+ (item._id || item.__id || (item.__id = UID.get('svg')))];\n\t}\n\n\tfunction setDefinition(item, node, type) {\n\t\tif (!definitions)\n\t\t\tgetDefinition();\n\t\tvar typeId = definitions.ids[type] = (definitions.ids[type] || 0) + 1;\n\t\tnode.id = type + '-' + typeId;\n\t\tdefinitions.svgs[type + '-' + (item._id || item.__id)] = node;\n\t}\n\n\tfunction exportDefinitions(node, options) {\n\t\tvar svg = node,\n\t\t\tdefs = null;\n\t\tif (definitions) {\n\t\t\tsvg = node.nodeName.toLowerCase() === 'svg' && node;\n\t\t\tfor (var i in definitions.svgs) {\n\t\t\t\tif (!defs) {\n\t\t\t\t\tif (!svg) {\n\t\t\t\t\t\tsvg = SvgElement.create('svg');\n\t\t\t\t\t\tsvg.appendChild(node);\n\t\t\t\t\t}\n\t\t\t\t\tdefs = svg.insertBefore(SvgElement.create('defs'),\n\t\t\t\t\t\t\tsvg.firstChild);\n\t\t\t\t}\n\t\t\t\tdefs.appendChild(definitions.svgs[i]);\n\t\t\t}\n\t\t\tdefinitions = null;\n\t\t}\n\t\treturn options.asString\n\t\t\t\t? new self.XMLSerializer().serializeToString(svg)\n\t\t\t\t: svg;\n\t}\n\n\tfunction exportSVG(item, options, isRoot) {\n\t\tvar exporter = exporters[item._class],\n\t\t\tnode = exporter && exporter(item, options);\n\t\tif (node) {\n\t\t\tvar onExport = options.onExport;\n\t\t\tif (onExport)\n\t\t\t\tnode = onExport(item, node, options) || node;\n\t\t\tvar data = JSON.stringify(item._data);\n\t\t\tif (data && data !== '{}' && data !== 'null')\n\t\t\t\tnode.setAttribute('data-paper-data', data);\n\t\t}\n\t\treturn node && applyStyle(item, node, isRoot);\n\t}\n\n\tfunction setOptions(options) {\n\t\tif (!options)\n\t\t\toptions = {};\n\t\tformatter = new Formatter(options.precision);\n\t\treturn options;\n\t}\n\n\tItem.inject({\n\t\texportSVG: function(options) {\n\t\t\toptions = setOptions(options);\n\t\t\treturn exportDefinitions(exportSVG(this, options, true), options);\n\t\t}\n\t});\n\n\tProject.inject({\n\t\texportSVG: function(options) {\n\t\t\toptions = setOptions(options);\n\t\t\tvar children = this._children,\n\t\t\t\tview = this.getView(),\n\t\t\t\tbounds = Base.pick(options.bounds, 'view'),\n\t\t\t\tmx = options.matrix || bounds === 'view' && view._matrix,\n\t\t\t\tmatrix = mx && Matrix.read([mx]),\n\t\t\t\trect = bounds === 'view'\n\t\t\t\t\t? new Rectangle([0, 0], view.getViewSize())\n\t\t\t\t\t: bounds === 'content'\n\t\t\t\t\t\t? Item._getBounds(children, matrix, { stroke: true })\n\t\t\t\t\t\t\t.rect\n\t\t\t\t\t\t: Rectangle.read([bounds], 0, { readNull: true }),\n\t\t\t\tattrs = {\n\t\t\t\t\tversion: '1.1',\n\t\t\t\t\txmlns: SvgElement.svg,\n\t\t\t\t\t'xmlns:xlink': SvgElement.xlink,\n\t\t\t\t};\n\t\t\tif (rect) {\n\t\t\t\tattrs.width = rect.width;\n\t\t\t\tattrs.height = rect.height;\n\t\t\t\tif (rect.x || rect.y)\n\t\t\t\t\tattrs.viewBox = formatter.rectangle(rect);\n\t\t\t}\n\t\t\tvar node = SvgElement.create('svg', attrs, formatter),\n\t\t\t\tparent = node;\n\t\t\tif (matrix && !matrix.isIdentity()) {\n\t\t\t\tparent = node.appendChild(SvgElement.create('g',\n\t\t\t\t\t\tgetTransform(matrix), formatter));\n\t\t\t}\n\t\t\tfor (var i = 0, l = children.length; i < l; i++) {\n\t\t\t\tparent.appendChild(exportSVG(children[i], options, true));\n\t\t\t}\n\t\t\treturn exportDefinitions(node, options);\n\t\t}\n\t});\n};\n\nnew function() {\n\n\tvar definitions = {},\n\t\trootSize;\n\n\tfunction getValue(node, name, isString, allowNull, allowPercent) {\n\t\tvar value = SvgElement.get(node, name),\n\t\t\tres = value == null\n\t\t\t\t? allowNull\n\t\t\t\t\t? null\n\t\t\t\t\t: isString ? '' : 0\n\t\t\t\t: isString\n\t\t\t\t\t? value\n\t\t\t\t\t: parseFloat(value);\n\t\treturn /%\\s*$/.test(value)\n\t\t\t? (res / 100) * (allowPercent ? 1\n\t\t\t\t: rootSize[/x|^width/.test(name) ? 'width' : 'height'])\n\t\t\t: res;\n\t}\n\n\tfunction getPoint(node, x, y, allowNull, allowPercent) {\n\t\tx = getValue(node, x || 'x', false, allowNull, allowPercent);\n\t\ty = getValue(node, y || 'y', false, allowNull, allowPercent);\n\t\treturn allowNull && (x == null || y == null) ? null\n\t\t\t\t: new Point(x, y);\n\t}\n\n\tfunction getSize(node, w, h, allowNull, allowPercent) {\n\t\tw = getValue(node, w || 'width', false, allowNull, allowPercent);\n\t\th = getValue(node, h || 'height', false, allowNull, allowPercent);\n\t\treturn allowNull && (w == null || h == null) ? null\n\t\t\t\t: new Size(w, h);\n\t}\n\n\tfunction convertValue(value, type, lookup) {\n\t\treturn value === 'none' ? null\n\t\t\t\t: type === 'number' ? parseFloat(value)\n\t\t\t\t: type === 'array' ?\n\t\t\t\t\tvalue ? value.split(/[\\s,]+/g).map(parseFloat) : []\n\t\t\t\t: type === 'color' ? getDefinition(value) || value\n\t\t\t\t: type === 'lookup' ? lookup[value]\n\t\t\t\t: value;\n\t}\n\n\tfunction importGroup(node, type, options, isRoot) {\n\t\tvar nodes = node.childNodes,\n\t\t\tisClip = type === 'clippath',\n\t\t\tisDefs = type === 'defs',\n\t\t\titem = new Group(),\n\t\t\tproject = item._project,\n\t\t\tcurrentStyle = project._currentStyle,\n\t\t\tchildren = [];\n\t\tif (!isClip && !isDefs) {\n\t\t\titem = applyAttributes(item, node, isRoot);\n\t\t\tproject._currentStyle = item._style.clone();\n\t\t}\n\t\tif (isRoot) {\n\t\t\tvar defs = node.querySelectorAll('defs');\n\t\t\tfor (var i = 0, l = defs.length; i < l; i++) {\n\t\t\t\timportNode(defs[i], options, false);\n\t\t\t}\n\t\t}\n\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\tvar childNode = nodes[i],\n\t\t\t\tchild;\n\t\t\tif (childNode.nodeType === 1\n\t\t\t\t\t&& !/^defs$/i.test(childNode.nodeName)\n\t\t\t\t\t&& (child = importNode(childNode, options, false))\n\t\t\t\t\t&& !(child instanceof SymbolDefinition))\n\t\t\t\tchildren.push(child);\n\t\t}\n\t\titem.addChildren(children);\n\t\tif (isClip)\n\t\t\titem = applyAttributes(item.reduce(), node, isRoot);\n\t\tproject._currentStyle = currentStyle;\n\t\tif (isClip || isDefs) {\n\t\t\titem.remove();\n\t\t\titem = null;\n\t\t}\n\t\treturn item;\n\t}\n\n\tfunction importPoly(node, type) {\n\t\tvar coords = node.getAttribute('points').match(\n\t\t\t\t\t/[+-]?(?:\\d*\\.\\d+|\\d+\\.?)(?:[eE][+-]?\\d+)?/g),\n\t\t\tpoints = [];\n\t\tfor (var i = 0, l = coords.length; i < l; i += 2)\n\t\t\tpoints.push(new Point(\n\t\t\t\t\tparseFloat(coords[i]),\n\t\t\t\t\tparseFloat(coords[i + 1])));\n\t\tvar path = new Path(points);\n\t\tif (type === 'polygon')\n\t\t\tpath.closePath();\n\t\treturn path;\n\t}\n\n\tfunction importPath(node) {\n\t\treturn PathItem.create(node.getAttribute('d'));\n\t}\n\n\tfunction importGradient(node, type) {\n\t\tvar id = (getValue(node, 'href', true) || '').substring(1),\n\t\t\tradial = type === 'radialgradient',\n\t\t\tgradient;\n\t\tif (id) {\n\t\t\tgradient = definitions[id].getGradient();\n\t\t\tif (gradient._radial ^ radial) {\n\t\t\t\tgradient = gradient.clone();\n\t\t\t\tgradient._radial = radial;\n\t\t\t}\n\t\t} else {\n\t\t\tvar nodes = node.childNodes,\n\t\t\t\tstops = [];\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tvar child = nodes[i];\n\t\t\t\tif (child.nodeType === 1)\n\t\t\t\t\tstops.push(applyAttributes(new GradientStop(), child));\n\t\t\t}\n\t\t\tgradient = new Gradient(stops, radial);\n\t\t}\n\t\tvar origin, destination, highlight,\n\t\t\tscaleToBounds = getValue(node, 'gradientUnits', true) !==\n\t\t\t\t'userSpaceOnUse';\n\t\tif (radial) {\n\t\t\torigin = getPoint(node, 'cx', 'cy', false, scaleToBounds);\n\t\t\tdestination = origin.add(\n\t\t\t\t\tgetValue(node, 'r', false, false, scaleToBounds), 0);\n\t\t\thighlight = getPoint(node, 'fx', 'fy', true, scaleToBounds);\n\t\t} else {\n\t\t\torigin = getPoint(node, 'x1', 'y1', false, scaleToBounds);\n\t\t\tdestination = getPoint(node, 'x2', 'y2', false, scaleToBounds);\n\t\t}\n\t\tvar color = applyAttributes(\n\t\t\t\tnew Color(gradient, origin, destination, highlight), node);\n\t\tcolor._scaleToBounds = scaleToBounds;\n\t\treturn null;\n\t}\n\n\tvar importers = {\n\t\t'#document': function (node, type, options, isRoot) {\n\t\t\tvar nodes = node.childNodes;\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tvar child = nodes[i];\n\t\t\t\tif (child.nodeType === 1)\n\t\t\t\t\treturn importNode(child, options, isRoot);\n\t\t\t}\n\t\t},\n\t\tg: importGroup,\n\t\tsvg: importGroup,\n\t\tclippath: importGroup,\n\t\tpolygon: importPoly,\n\t\tpolyline: importPoly,\n\t\tpath: importPath,\n\t\tlineargradient: importGradient,\n\t\tradialgradient: importGradient,\n\n\t\timage: function (node) {\n\t\t\tvar raster = new Raster(getValue(node, 'href', true));\n\t\t\traster.on('load', function() {\n\t\t\t\tvar size = getSize(node);\n\t\t\t\tthis.setSize(size);\n\t\t\t\tvar center = this._matrix._transformPoint(\n\t\t\t\t\t\tgetPoint(node).add(size.divide(2)));\n\t\t\t\tthis.translate(center);\n\t\t\t});\n\t\t\treturn raster;\n\t\t},\n\n\t\tsymbol: function(node, type, options, isRoot) {\n\t\t\treturn new SymbolDefinition(\n\t\t\t\t\timportGroup(node, type, options, isRoot), true);\n\t\t},\n\n\t\tdefs: importGroup,\n\n\t\tuse: function(node) {\n\t\t\tvar id = (getValue(node, 'href', true) || '').substring(1),\n\t\t\t\tdefinition = definitions[id],\n\t\t\t\tpoint = getPoint(node);\n\t\t\treturn definition\n\t\t\t\t\t? definition instanceof SymbolDefinition\n\t\t\t\t\t\t? definition.place(point)\n\t\t\t\t\t\t: definition.clone().translate(point)\n\t\t\t\t\t: null;\n\t\t},\n\n\t\tcircle: function(node) {\n\t\t\treturn new Shape.Circle(\n\t\t\t\t\tgetPoint(node, 'cx', 'cy'),\n\t\t\t\t\tgetValue(node, 'r'));\n\t\t},\n\n\t\tellipse: function(node) {\n\t\t\treturn new Shape.Ellipse({\n\t\t\t\tcenter: getPoint(node, 'cx', 'cy'),\n\t\t\t\tradius: getSize(node, 'rx', 'ry')\n\t\t\t});\n\t\t},\n\n\t\trect: function(node) {\n\t\t\treturn new Shape.Rectangle(new Rectangle(\n\t\t\t\t\t\tgetPoint(node),\n\t\t\t\t\t\tgetSize(node)\n\t\t\t\t\t), getSize(node, 'rx', 'ry'));\n\t\t\t},\n\n\t\tline: function(node) {\n\t\t\treturn new Path.Line(\n\t\t\t\t\tgetPoint(node, 'x1', 'y1'),\n\t\t\t\t\tgetPoint(node, 'x2', 'y2'));\n\t\t},\n\n\t\ttext: function(node) {\n\t\t\tvar text = new PointText(getPoint(node).add(\n\t\t\t\t\tgetPoint(node, 'dx', 'dy')));\n\t\t\ttext.setContent(node.textContent.trim() || '');\n\t\t\treturn text;\n\t\t}\n\t};\n\n\tfunction applyTransform(item, value, name, node) {\n\t\tif (item.transform) {\n\t\t\tvar transforms = (node.getAttribute(name) || '').split(/\\)\\s*/g),\n\t\t\t\tmatrix = new Matrix();\n\t\t\tfor (var i = 0, l = transforms.length; i < l; i++) {\n\t\t\t\tvar transform = transforms[i];\n\t\t\t\tif (!transform)\n\t\t\t\t\tbreak;\n\t\t\t\tvar parts = transform.split(/\\(\\s*/),\n\t\t\t\t\tcommand = parts[0],\n\t\t\t\t\tv = parts[1].split(/[\\s,]+/g);\n\t\t\t\tfor (var j = 0, m = v.length; j < m; j++)\n\t\t\t\t\tv[j] = parseFloat(v[j]);\n\t\t\t\tswitch (command) {\n\t\t\t\tcase 'matrix':\n\t\t\t\t\tmatrix.append(\n\t\t\t\t\t\t\tnew Matrix(v[0], v[1], v[2], v[3], v[4], v[5]));\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'rotate':\n\t\t\t\t\tmatrix.rotate(v[0], v[1], v[2]);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'translate':\n\t\t\t\t\tmatrix.translate(v[0], v[1]);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'scale':\n\t\t\t\t\tmatrix.scale(v);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'skewX':\n\t\t\t\t\tmatrix.skew(v[0], 0);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'skewY':\n\t\t\t\t\tmatrix.skew(0, v[0]);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\titem.transform(matrix);\n\t\t}\n\t}\n\n\tfunction applyOpacity(item, value, name) {\n\t\tvar key = name === 'fill-opacity' ? 'getFillColor' : 'getStrokeColor',\n\t\t\tcolor = item[key] && item[key]();\n\t\tif (color)\n\t\t\tcolor.setAlpha(parseFloat(value));\n\t}\n\n\tvar attributes = Base.set(Base.each(SvgStyles, function(entry) {\n\t\tthis[entry.attribute] = function(item, value) {\n\t\t\tif (item[entry.set]) {\n\t\t\t\titem[entry.set](convertValue(value, entry.type, entry.fromSVG));\n\t\t\t\tif (entry.type === 'color') {\n\t\t\t\t\tvar color = item[entry.get]();\n\t\t\t\t\tif (color) {\n\t\t\t\t\t\tif (color._scaleToBounds) {\n\t\t\t\t\t\t\tvar bounds = item.getBounds();\n\t\t\t\t\t\t\tcolor.transform(new Matrix()\n\t\t\t\t\t\t\t\t.translate(bounds.getPoint())\n\t\t\t\t\t\t\t\t.scale(bounds.getSize()));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}, {}), {\n\t\tid: function(item, value) {\n\t\t\tdefinitions[value] = item;\n\t\t\tif (item.setName)\n\t\t\t\titem.setName(value);\n\t\t},\n\n\t\t'clip-path': function(item, value) {\n\t\t\tvar clip = getDefinition(value);\n\t\t\tif (clip) {\n\t\t\t\tclip = clip.clone();\n\t\t\t\tclip.setClipMask(true);\n\t\t\t\tif (item instanceof Group) {\n\t\t\t\t\titem.insertChild(0, clip);\n\t\t\t\t} else {\n\t\t\t\t\treturn new Group(clip, item);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tgradientTransform: applyTransform,\n\t\ttransform: applyTransform,\n\n\t\t'fill-opacity': applyOpacity,\n\t\t'stroke-opacity': applyOpacity,\n\n\t\tvisibility: function(item, value) {\n\t\t\tif (item.setVisible)\n\t\t\t\titem.setVisible(value === 'visible');\n\t\t},\n\n\t\tdisplay: function(item, value) {\n\t\t\tif (item.setVisible)\n\t\t\t\titem.setVisible(value !== null);\n\t\t},\n\n\t\t'stop-color': function(item, value) {\n\t\t\tif (item.setColor)\n\t\t\t\titem.setColor(value);\n\t\t},\n\n\t\t'stop-opacity': function(item, value) {\n\t\t\tif (item._color)\n\t\t\t\titem._color.setAlpha(parseFloat(value));\n\t\t},\n\n\t\toffset: function(item, value) {\n\t\t\tif (item.setOffset) {\n\t\t\t\tvar percent = value.match(/(.*)%$/);\n\t\t\t\titem.setOffset(percent ? percent[1] / 100 : parseFloat(value));\n\t\t\t}\n\t\t},\n\n\t\tviewBox: function(item, value, name, node, styles) {\n\t\t\tvar rect = new Rectangle(convertValue(value, 'array')),\n\t\t\t\tsize = getSize(node, null, null, true),\n\t\t\t\tgroup,\n\t\t\t\tmatrix;\n\t\t\tif (item instanceof Group) {\n\t\t\t\tvar scale = size ? size.divide(rect.getSize()) : 1,\n\t\t\t\tmatrix = new Matrix().scale(scale)\n\t\t\t\t\t\t.translate(rect.getPoint().negate());\n\t\t\t\tgroup = item;\n\t\t\t} else if (item instanceof SymbolDefinition) {\n\t\t\t\tif (size)\n\t\t\t\t\trect.setSize(size);\n\t\t\t\tgroup = item._item;\n\t\t\t}\n\t\t\tif (group)  {\n\t\t\t\tif (getAttribute(node, 'overflow', styles) !== 'visible') {\n\t\t\t\t\tvar clip = new Shape.Rectangle(rect);\n\t\t\t\t\tclip.setClipMask(true);\n\t\t\t\t\tgroup.addChild(clip);\n\t\t\t\t}\n\t\t\t\tif (matrix)\n\t\t\t\t\tgroup.transform(matrix);\n\t\t\t}\n\t\t}\n\t});\n\n\tfunction getAttribute(node, name, styles) {\n\t\tvar attr = node.attributes[name],\n\t\t\tvalue = attr && attr.value;\n\t\tif (!value) {\n\t\t\tvar style = Base.camelize(name);\n\t\t\tvalue = node.style[style];\n\t\t\tif (!value && styles.node[style] !== styles.parent[style])\n\t\t\t\tvalue = styles.node[style];\n\t\t}\n\t\treturn !value ? undefined\n\t\t\t\t: value === 'none' ? null\n\t\t\t\t: value;\n\t}\n\n\tfunction applyAttributes(item, node, isRoot) {\n\t\tif (node.style) {\n\t\t\tvar parent = node.parentNode,\n\t\t\t\tstyles = {\n\t\t\t\t\tnode: DomElement.getStyles(node) || {},\n\t\t\t\t\tparent: !isRoot && !/^defs$/i.test(parent.tagName)\n\t\t\t\t\t\t\t&& DomElement.getStyles(parent) || {}\n\t\t\t\t};\n\t\t\tBase.each(attributes, function(apply, name) {\n\t\t\t\tvar value = getAttribute(node, name, styles);\n\t\t\t\titem = value !== undefined\n\t\t\t\t\t\t&& apply(item, value, name, node, styles) || item;\n\t\t\t});\n\t\t}\n\t\treturn item;\n\t}\n\n\tfunction getDefinition(value) {\n\t\tvar match = value && value.match(/\\((?:[\"'#]*)([^\"')]+)/),\n\t\t\tname = match && match[1],\n\t\t\tres = name && definitions[window\n\t\t\t\t\t? name.replace(window.location.href.split('#')[0] + '#', '')\n\t\t\t\t\t: name];\n\t\tif (res && res._scaleToBounds) {\n\t\t\tres = res.clone();\n\t\t\tres._scaleToBounds = true;\n\t\t}\n\t\treturn res;\n\t}\n\n\tfunction importNode(node, options, isRoot) {\n\t\tvar type = node.nodeName.toLowerCase(),\n\t\t\tisElement = type !== '#document',\n\t\t\tbody = document.body,\n\t\t\tcontainer,\n\t\t\tparent,\n\t\t\tnext;\n\t\tif (isRoot && isElement) {\n\t\t\trootSize = paper.getView().getSize();\n\t\t\trootSize = getSize(node, null, null, true) || rootSize;\n\t\t\tcontainer = SvgElement.create('svg', {\n\t\t\t\tstyle: 'stroke-width: 1px; stroke-miterlimit: 10'\n\t\t\t});\n\t\t\tparent = node.parentNode;\n\t\t\tnext = node.nextSibling;\n\t\t\tcontainer.appendChild(node);\n\t\t\tbody.appendChild(container);\n\t\t}\n\t\tvar settings = paper.settings,\n\t\t\tapplyMatrix = settings.applyMatrix,\n\t\t\tinsertItems = settings.insertItems;\n\t\tsettings.applyMatrix = false;\n\t\tsettings.insertItems = false;\n\t\tvar importer = importers[type],\n\t\t\titem = importer && importer(node, type, options, isRoot) || null;\n\t\tsettings.insertItems = insertItems;\n\t\tsettings.applyMatrix = applyMatrix;\n\t\tif (item) {\n\t\t\tif (isElement && !(item instanceof Group))\n\t\t\t\titem = applyAttributes(item, node, isRoot);\n\t\t\tvar onImport = options.onImport,\n\t\t\t\tdata = isElement && node.getAttribute('data-paper-data');\n\t\t\tif (onImport)\n\t\t\t\titem = onImport(node, item, options) || item;\n\t\t\tif (options.expandShapes && item instanceof Shape) {\n\t\t\t\titem.remove();\n\t\t\t\titem = item.toPath();\n\t\t\t}\n\t\t\tif (data)\n\t\t\t\titem._data = JSON.parse(data);\n\t\t}\n\t\tif (container) {\n\t\t\tbody.removeChild(container);\n\t\t\tif (parent) {\n\t\t\t\tif (next) {\n\t\t\t\t\tparent.insertBefore(node, next);\n\t\t\t\t} else {\n\t\t\t\t\tparent.appendChild(node);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (isRoot) {\n\t\t\tdefinitions = {};\n\t\t\tif (item && Base.pick(options.applyMatrix, applyMatrix))\n\t\t\t\titem.matrix.apply(true, true);\n\t\t}\n\t\treturn item;\n\t}\n\n\tfunction importSVG(source, options, owner) {\n\t\tif (!source)\n\t\t\treturn null;\n\t\toptions = typeof options === 'function' ? { onLoad: options }\n\t\t\t\t: options || {};\n\t\tvar scope = paper,\n\t\t\titem = null;\n\n\t\tfunction onLoad(svg) {\n\t\t\ttry {\n\t\t\t\tvar node = typeof svg === 'object' ? svg : new self.DOMParser()\n\t\t\t\t\t\t.parseFromString(svg, 'image/svg+xml');\n\t\t\t\tif (!node.nodeName) {\n\t\t\t\t\tnode = null;\n\t\t\t\t\tthrow new Error('Unsupported SVG source: ' + source);\n\t\t\t\t}\n\t\t\t\tpaper = scope;\n\t\t\t\titem = importNode(node, options, true);\n\t\t\t\tif (!options || options.insert !== false) {\n\t\t\t\t\towner._insertItem(undefined, item);\n\t\t\t\t}\n\t\t\t\tvar onLoad = options.onLoad;\n\t\t\t\tif (onLoad)\n\t\t\t\t\tonLoad(item, svg);\n\t\t\t} catch (e) {\n\t\t\t\tonError(e);\n\t\t\t}\n\t\t}\n\n\t\tfunction onError(message, status) {\n\t\t\tvar onError = options.onError;\n\t\t\tif (onError) {\n\t\t\t\tonError(message, status);\n\t\t\t} else {\n\t\t\t\tthrow new Error(message);\n\t\t\t}\n\t\t}\n\n\t\tif (typeof source === 'string' && !/^.*</.test(source)) {\n\t\t\tvar node = document.getElementById(source);\n\t\t\tif (node) {\n\t\t\t\tonLoad(node);\n\t\t\t} else {\n\t\t\t\tHttp.request({\n\t\t\t\t\turl: source,\n\t\t\t\t\tasync: true,\n\t\t\t\t\tonLoad: onLoad,\n\t\t\t\t\tonError: onError\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (typeof File !== 'undefined' && source instanceof File) {\n\t\t\tvar reader = new FileReader();\n\t\t\treader.onload = function() {\n\t\t\t\tonLoad(reader.result);\n\t\t\t};\n\t\t\treader.onerror = function() {\n\t\t\t\tonError(reader.error);\n\t\t\t};\n\t\t\treturn reader.readAsText(source);\n\t\t} else {\n\t\t\tonLoad(source);\n\t\t}\n\n\t\treturn item;\n\t}\n\n\tItem.inject({\n\t\timportSVG: function(node, options) {\n\t\t\treturn importSVG(node, options, this);\n\t\t}\n\t});\n\n\tProject.inject({\n\t\timportSVG: function(node, options) {\n\t\t\tthis.activate();\n\t\t\treturn importSVG(node, options, this);\n\t\t}\n\t});\n};\n\nBase.exports.PaperScript = function() {\n\tvar global = this,\n\t\tacorn = global.acorn;\n\tif (!acorn && typeof require !== 'undefined') {\n\t\ttry { acorn = require('acorn'); } catch(e) {}\n\t}\n\tif (!acorn) {\n\t\tvar exports, module;\n\t\tacorn = exports = module = {};\n\n(function(root, mod) {\n  if (typeof exports == \"object\" && typeof module == \"object\") return mod(exports);\n  if (typeof define == \"function\" && define.amd) return define([\"exports\"], mod);\n  mod(root.acorn || (root.acorn = {}));\n})(this, function(exports) {\n  \"use strict\";\n\n  exports.version = \"0.5.0\";\n\n  var options, input, inputLen, sourceFile;\n\n  exports.parse = function(inpt, opts) {\n\tinput = String(inpt); inputLen = input.length;\n\tsetOptions(opts);\n\tinitTokenState();\n\treturn parseTopLevel(options.program);\n  };\n\n  var defaultOptions = exports.defaultOptions = {\n\tecmaVersion: 5,\n\tstrictSemicolons: false,\n\tallowTrailingCommas: true,\n\tforbidReserved: false,\n\tallowReturnOutsideFunction: false,\n\tlocations: false,\n\tonComment: null,\n\tranges: false,\n\tprogram: null,\n\tsourceFile: null,\n\tdirectSourceFile: null\n  };\n\n  function setOptions(opts) {\n\toptions = opts || {};\n\tfor (var opt in defaultOptions) if (!Object.prototype.hasOwnProperty.call(options, opt))\n\t  options[opt] = defaultOptions[opt];\n\tsourceFile = options.sourceFile || null;\n  }\n\n  var getLineInfo = exports.getLineInfo = function(input, offset) {\n\tfor (var line = 1, cur = 0;;) {\n\t  lineBreak.lastIndex = cur;\n\t  var match = lineBreak.exec(input);\n\t  if (match && match.index < offset) {\n\t\t++line;\n\t\tcur = match.index + match[0].length;\n\t  } else break;\n\t}\n\treturn {line: line, column: offset - cur};\n  };\n\n  exports.tokenize = function(inpt, opts) {\n\tinput = String(inpt); inputLen = input.length;\n\tsetOptions(opts);\n\tinitTokenState();\n\n\tvar t = {};\n\tfunction getToken(forceRegexp) {\n\t  lastEnd = tokEnd;\n\t  readToken(forceRegexp);\n\t  t.start = tokStart; t.end = tokEnd;\n\t  t.startLoc = tokStartLoc; t.endLoc = tokEndLoc;\n\t  t.type = tokType; t.value = tokVal;\n\t  return t;\n\t}\n\tgetToken.jumpTo = function(pos, reAllowed) {\n\t  tokPos = pos;\n\t  if (options.locations) {\n\t\ttokCurLine = 1;\n\t\ttokLineStart = lineBreak.lastIndex = 0;\n\t\tvar match;\n\t\twhile ((match = lineBreak.exec(input)) && match.index < pos) {\n\t\t  ++tokCurLine;\n\t\t  tokLineStart = match.index + match[0].length;\n\t\t}\n\t  }\n\t  tokRegexpAllowed = reAllowed;\n\t  skipSpace();\n\t};\n\treturn getToken;\n  };\n\n  var tokPos;\n\n  var tokStart, tokEnd;\n\n  var tokStartLoc, tokEndLoc;\n\n  var tokType, tokVal;\n\n  var tokRegexpAllowed;\n\n  var tokCurLine, tokLineStart;\n\n  var lastStart, lastEnd, lastEndLoc;\n\n  var inFunction, labels, strict;\n\n  function raise(pos, message) {\n\tvar loc = getLineInfo(input, pos);\n\tmessage += \" (\" + loc.line + \":\" + loc.column + \")\";\n\tvar err = new SyntaxError(message);\n\terr.pos = pos; err.loc = loc; err.raisedAt = tokPos;\n\tthrow err;\n  }\n\n  var empty = [];\n\n  var _num = {type: \"num\"}, _regexp = {type: \"regexp\"}, _string = {type: \"string\"};\n  var _name = {type: \"name\"}, _eof = {type: \"eof\"};\n\n  var _break = {keyword: \"break\"}, _case = {keyword: \"case\", beforeExpr: true}, _catch = {keyword: \"catch\"};\n  var _continue = {keyword: \"continue\"}, _debugger = {keyword: \"debugger\"}, _default = {keyword: \"default\"};\n  var _do = {keyword: \"do\", isLoop: true}, _else = {keyword: \"else\", beforeExpr: true};\n  var _finally = {keyword: \"finally\"}, _for = {keyword: \"for\", isLoop: true}, _function = {keyword: \"function\"};\n  var _if = {keyword: \"if\"}, _return = {keyword: \"return\", beforeExpr: true}, _switch = {keyword: \"switch\"};\n  var _throw = {keyword: \"throw\", beforeExpr: true}, _try = {keyword: \"try\"}, _var = {keyword: \"var\"};\n  var _while = {keyword: \"while\", isLoop: true}, _with = {keyword: \"with\"}, _new = {keyword: \"new\", beforeExpr: true};\n  var _this = {keyword: \"this\"};\n\n  var _null = {keyword: \"null\", atomValue: null}, _true = {keyword: \"true\", atomValue: true};\n  var _false = {keyword: \"false\", atomValue: false};\n\n  var _in = {keyword: \"in\", binop: 7, beforeExpr: true};\n\n  var keywordTypes = {\"break\": _break, \"case\": _case, \"catch\": _catch,\n\t\t\t\t\t  \"continue\": _continue, \"debugger\": _debugger, \"default\": _default,\n\t\t\t\t\t  \"do\": _do, \"else\": _else, \"finally\": _finally, \"for\": _for,\n\t\t\t\t\t  \"function\": _function, \"if\": _if, \"return\": _return, \"switch\": _switch,\n\t\t\t\t\t  \"throw\": _throw, \"try\": _try, \"var\": _var, \"while\": _while, \"with\": _with,\n\t\t\t\t\t  \"null\": _null, \"true\": _true, \"false\": _false, \"new\": _new, \"in\": _in,\n\t\t\t\t\t  \"instanceof\": {keyword: \"instanceof\", binop: 7, beforeExpr: true}, \"this\": _this,\n\t\t\t\t\t  \"typeof\": {keyword: \"typeof\", prefix: true, beforeExpr: true},\n\t\t\t\t\t  \"void\": {keyword: \"void\", prefix: true, beforeExpr: true},\n\t\t\t\t\t  \"delete\": {keyword: \"delete\", prefix: true, beforeExpr: true}};\n\n  var _bracketL = {type: \"[\", beforeExpr: true}, _bracketR = {type: \"]\"}, _braceL = {type: \"{\", beforeExpr: true};\n  var _braceR = {type: \"}\"}, _parenL = {type: \"(\", beforeExpr: true}, _parenR = {type: \")\"};\n  var _comma = {type: \",\", beforeExpr: true}, _semi = {type: \";\", beforeExpr: true};\n  var _colon = {type: \":\", beforeExpr: true}, _dot = {type: \".\"}, _question = {type: \"?\", beforeExpr: true};\n\n  var _slash = {binop: 10, beforeExpr: true}, _eq = {isAssign: true, beforeExpr: true};\n  var _assign = {isAssign: true, beforeExpr: true};\n  var _incDec = {postfix: true, prefix: true, isUpdate: true}, _prefix = {prefix: true, beforeExpr: true};\n  var _logicalOR = {binop: 1, beforeExpr: true};\n  var _logicalAND = {binop: 2, beforeExpr: true};\n  var _bitwiseOR = {binop: 3, beforeExpr: true};\n  var _bitwiseXOR = {binop: 4, beforeExpr: true};\n  var _bitwiseAND = {binop: 5, beforeExpr: true};\n  var _equality = {binop: 6, beforeExpr: true};\n  var _relational = {binop: 7, beforeExpr: true};\n  var _bitShift = {binop: 8, beforeExpr: true};\n  var _plusMin = {binop: 9, prefix: true, beforeExpr: true};\n  var _multiplyModulo = {binop: 10, beforeExpr: true};\n\n  exports.tokTypes = {bracketL: _bracketL, bracketR: _bracketR, braceL: _braceL, braceR: _braceR,\n\t\t\t\t\t  parenL: _parenL, parenR: _parenR, comma: _comma, semi: _semi, colon: _colon,\n\t\t\t\t\t  dot: _dot, question: _question, slash: _slash, eq: _eq, name: _name, eof: _eof,\n\t\t\t\t\t  num: _num, regexp: _regexp, string: _string};\n  for (var kw in keywordTypes) exports.tokTypes[\"_\" + kw] = keywordTypes[kw];\n\n  function makePredicate(words) {\n\twords = words.split(\" \");\n\tvar f = \"\", cats = [];\n\tout: for (var i = 0; i < words.length; ++i) {\n\t  for (var j = 0; j < cats.length; ++j)\n\t\tif (cats[j][0].length == words[i].length) {\n\t\t  cats[j].push(words[i]);\n\t\t  continue out;\n\t\t}\n\t  cats.push([words[i]]);\n\t}\n\tfunction compareTo(arr) {\n\t  if (arr.length == 1) return f += \"return str === \" + JSON.stringify(arr[0]) + \";\";\n\t  f += \"switch(str){\";\n\t  for (var i = 0; i < arr.length; ++i) f += \"case \" + JSON.stringify(arr[i]) + \":\";\n\t  f += \"return true}return false;\";\n\t}\n\n\tif (cats.length > 3) {\n\t  cats.sort(function(a, b) {return b.length - a.length;});\n\t  f += \"switch(str.length){\";\n\t  for (var i = 0; i < cats.length; ++i) {\n\t\tvar cat = cats[i];\n\t\tf += \"case \" + cat[0].length + \":\";\n\t\tcompareTo(cat);\n\t  }\n\t  f += \"}\";\n\n\t} else {\n\t  compareTo(words);\n\t}\n\treturn new Function(\"str\", f);\n  }\n\n  var isReservedWord3 = makePredicate(\"abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile\");\n\n  var isReservedWord5 = makePredicate(\"class enum extends super const export import\");\n\n  var isStrictReservedWord = makePredicate(\"implements interface let package private protected public static yield\");\n\n  var isStrictBadIdWord = makePredicate(\"eval arguments\");\n\n  var isKeyword = makePredicate(\"break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this\");\n\n  var nonASCIIwhitespace = /[\\u1680\\u180e\\u2000-\\u200a\\u202f\\u205f\\u3000\\ufeff]/;\n  var nonASCIIidentifierStartChars = \"\\xaa\\xb5\\xba\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\u02c1\\u02c6-\\u02d1\\u02e0-\\u02e4\\u02ec\\u02ee\\u0370-\\u0374\\u0376\\u0377\\u037a-\\u037d\\u0386\\u0388-\\u038a\\u038c\\u038e-\\u03a1\\u03a3-\\u03f5\\u03f7-\\u0481\\u048a-\\u0527\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05d0-\\u05ea\\u05f0-\\u05f2\\u0620-\\u064a\\u066e\\u066f\\u0671-\\u06d3\\u06d5\\u06e5\\u06e6\\u06ee\\u06ef\\u06fa-\\u06fc\\u06ff\\u0710\\u0712-\\u072f\\u074d-\\u07a5\\u07b1\\u07ca-\\u07ea\\u07f4\\u07f5\\u07fa\\u0800-\\u0815\\u081a\\u0824\\u0828\\u0840-\\u0858\\u08a0\\u08a2-\\u08ac\\u0904-\\u0939\\u093d\\u0950\\u0958-\\u0961\\u0971-\\u0977\\u0979-\\u097f\\u0985-\\u098c\\u098f\\u0990\\u0993-\\u09a8\\u09aa-\\u09b0\\u09b2\\u09b6-\\u09b9\\u09bd\\u09ce\\u09dc\\u09dd\\u09df-\\u09e1\\u09f0\\u09f1\\u0a05-\\u0a0a\\u0a0f\\u0a10\\u0a13-\\u0a28\\u0a2a-\\u0a30\\u0a32\\u0a33\\u0a35\\u0a36\\u0a38\\u0a39\\u0a59-\\u0a5c\\u0a5e\\u0a72-\\u0a74\\u0a85-\\u0a8d\\u0a8f-\\u0a91\\u0a93-\\u0aa8\\u0aaa-\\u0ab0\\u0ab2\\u0ab3\\u0ab5-\\u0ab9\\u0abd\\u0ad0\\u0ae0\\u0ae1\\u0b05-\\u0b0c\\u0b0f\\u0b10\\u0b13-\\u0b28\\u0b2a-\\u0b30\\u0b32\\u0b33\\u0b35-\\u0b39\\u0b3d\\u0b5c\\u0b5d\\u0b5f-\\u0b61\\u0b71\\u0b83\\u0b85-\\u0b8a\\u0b8e-\\u0b90\\u0b92-\\u0b95\\u0b99\\u0b9a\\u0b9c\\u0b9e\\u0b9f\\u0ba3\\u0ba4\\u0ba8-\\u0baa\\u0bae-\\u0bb9\\u0bd0\\u0c05-\\u0c0c\\u0c0e-\\u0c10\\u0c12-\\u0c28\\u0c2a-\\u0c33\\u0c35-\\u0c39\\u0c3d\\u0c58\\u0c59\\u0c60\\u0c61\\u0c85-\\u0c8c\\u0c8e-\\u0c90\\u0c92-\\u0ca8\\u0caa-\\u0cb3\\u0cb5-\\u0cb9\\u0cbd\\u0cde\\u0ce0\\u0ce1\\u0cf1\\u0cf2\\u0d05-\\u0d0c\\u0d0e-\\u0d10\\u0d12-\\u0d3a\\u0d3d\\u0d4e\\u0d60\\u0d61\\u0d7a-\\u0d7f\\u0d85-\\u0d96\\u0d9a-\\u0db1\\u0db3-\\u0dbb\\u0dbd\\u0dc0-\\u0dc6\\u0e01-\\u0e30\\u0e32\\u0e33\\u0e40-\\u0e46\\u0e81\\u0e82\\u0e84\\u0e87\\u0e88\\u0e8a\\u0e8d\\u0e94-\\u0e97\\u0e99-\\u0e9f\\u0ea1-\\u0ea3\\u0ea5\\u0ea7\\u0eaa\\u0eab\\u0ead-\\u0eb0\\u0eb2\\u0eb3\\u0ebd\\u0ec0-\\u0ec4\\u0ec6\\u0edc-\\u0edf\\u0f00\\u0f40-\\u0f47\\u0f49-\\u0f6c\\u0f88-\\u0f8c\\u1000-\\u102a\\u103f\\u1050-\\u1055\\u105a-\\u105d\\u1061\\u1065\\u1066\\u106e-\\u1070\\u1075-\\u1081\\u108e\\u10a0-\\u10c5\\u10c7\\u10cd\\u10d0-\\u10fa\\u10fc-\\u1248\\u124a-\\u124d\\u1250-\\u1256\\u1258\\u125a-\\u125d\\u1260-\\u1288\\u128a-\\u128d\\u1290-\\u12b0\\u12b2-\\u12b5\\u12b8-\\u12be\\u12c0\\u12c2-\\u12c5\\u12c8-\\u12d6\\u12d8-\\u1310\\u1312-\\u1315\\u1318-\\u135a\\u1380-\\u138f\\u13a0-\\u13f4\\u1401-\\u166c\\u166f-\\u167f\\u1681-\\u169a\\u16a0-\\u16ea\\u16ee-\\u16f0\\u1700-\\u170c\\u170e-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176c\\u176e-\\u1770\\u1780-\\u17b3\\u17d7\\u17dc\\u1820-\\u1877\\u1880-\\u18a8\\u18aa\\u18b0-\\u18f5\\u1900-\\u191c\\u1950-\\u196d\\u1970-\\u1974\\u1980-\\u19ab\\u19c1-\\u19c7\\u1a00-\\u1a16\\u1a20-\\u1a54\\u1aa7\\u1b05-\\u1b33\\u1b45-\\u1b4b\\u1b83-\\u1ba0\\u1bae\\u1baf\\u1bba-\\u1be5\\u1c00-\\u1c23\\u1c4d-\\u1c4f\\u1c5a-\\u1c7d\\u1ce9-\\u1cec\\u1cee-\\u1cf1\\u1cf5\\u1cf6\\u1d00-\\u1dbf\\u1e00-\\u1f15\\u1f18-\\u1f1d\\u1f20-\\u1f45\\u1f48-\\u1f4d\\u1f50-\\u1f57\\u1f59\\u1f5b\\u1f5d\\u1f5f-\\u1f7d\\u1f80-\\u1fb4\\u1fb6-\\u1fbc\\u1fbe\\u1fc2-\\u1fc4\\u1fc6-\\u1fcc\\u1fd0-\\u1fd3\\u1fd6-\\u1fdb\\u1fe0-\\u1fec\\u1ff2-\\u1ff4\\u1ff6-\\u1ffc\\u2071\\u207f\\u2090-\\u209c\\u2102\\u2107\\u210a-\\u2113\\u2115\\u2119-\\u211d\\u2124\\u2126\\u2128\\u212a-\\u212d\\u212f-\\u2139\\u213c-\\u213f\\u2145-\\u2149\\u214e\\u2160-\\u2188\\u2c00-\\u2c2e\\u2c30-\\u2c5e\\u2c60-\\u2ce4\\u2ceb-\\u2cee\\u2cf2\\u2cf3\\u2d00-\\u2d25\\u2d27\\u2d2d\\u2d30-\\u2d67\\u2d6f\\u2d80-\\u2d96\\u2da0-\\u2da6\\u2da8-\\u2dae\\u2db0-\\u2db6\\u2db8-\\u2dbe\\u2dc0-\\u2dc6\\u2dc8-\\u2dce\\u2dd0-\\u2dd6\\u2dd8-\\u2dde\\u2e2f\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303c\\u3041-\\u3096\\u309d-\\u309f\\u30a1-\\u30fa\\u30fc-\\u30ff\\u3105-\\u312d\\u3131-\\u318e\\u31a0-\\u31ba\\u31f0-\\u31ff\\u3400-\\u4db5\\u4e00-\\u9fcc\\ua000-\\ua48c\\ua4d0-\\ua4fd\\ua500-\\ua60c\\ua610-\\ua61f\\ua62a\\ua62b\\ua640-\\ua66e\\ua67f-\\ua697\\ua6a0-\\ua6ef\\ua717-\\ua71f\\ua722-\\ua788\\ua78b-\\ua78e\\ua790-\\ua793\\ua7a0-\\ua7aa\\ua7f8-\\ua801\\ua803-\\ua805\\ua807-\\ua80a\\ua80c-\\ua822\\ua840-\\ua873\\ua882-\\ua8b3\\ua8f2-\\ua8f7\\ua8fb\\ua90a-\\ua925\\ua930-\\ua946\\ua960-\\ua97c\\ua984-\\ua9b2\\ua9cf\\uaa00-\\uaa28\\uaa40-\\uaa42\\uaa44-\\uaa4b\\uaa60-\\uaa76\\uaa7a\\uaa80-\\uaaaf\\uaab1\\uaab5\\uaab6\\uaab9-\\uaabd\\uaac0\\uaac2\\uaadb-\\uaadd\\uaae0-\\uaaea\\uaaf2-\\uaaf4\\uab01-\\uab06\\uab09-\\uab0e\\uab11-\\uab16\\uab20-\\uab26\\uab28-\\uab2e\\uabc0-\\uabe2\\uac00-\\ud7a3\\ud7b0-\\ud7c6\\ud7cb-\\ud7fb\\uf900-\\ufa6d\\ufa70-\\ufad9\\ufb00-\\ufb06\\ufb13-\\ufb17\\ufb1d\\ufb1f-\\ufb28\\ufb2a-\\ufb36\\ufb38-\\ufb3c\\ufb3e\\ufb40\\ufb41\\ufb43\\ufb44\\ufb46-\\ufbb1\\ufbd3-\\ufd3d\\ufd50-\\ufd8f\\ufd92-\\ufdc7\\ufdf0-\\ufdfb\\ufe70-\\ufe74\\ufe76-\\ufefc\\uff21-\\uff3a\\uff41-\\uff5a\\uff66-\\uffbe\\uffc2-\\uffc7\\uffca-\\uffcf\\uffd2-\\uffd7\\uffda-\\uffdc\";\n  var nonASCIIidentifierChars = \"\\u0300-\\u036f\\u0483-\\u0487\\u0591-\\u05bd\\u05bf\\u05c1\\u05c2\\u05c4\\u05c5\\u05c7\\u0610-\\u061a\\u0620-\\u0649\\u0672-\\u06d3\\u06e7-\\u06e8\\u06fb-\\u06fc\\u0730-\\u074a\\u0800-\\u0814\\u081b-\\u0823\\u0825-\\u0827\\u0829-\\u082d\\u0840-\\u0857\\u08e4-\\u08fe\\u0900-\\u0903\\u093a-\\u093c\\u093e-\\u094f\\u0951-\\u0957\\u0962-\\u0963\\u0966-\\u096f\\u0981-\\u0983\\u09bc\\u09be-\\u09c4\\u09c7\\u09c8\\u09d7\\u09df-\\u09e0\\u0a01-\\u0a03\\u0a3c\\u0a3e-\\u0a42\\u0a47\\u0a48\\u0a4b-\\u0a4d\\u0a51\\u0a66-\\u0a71\\u0a75\\u0a81-\\u0a83\\u0abc\\u0abe-\\u0ac5\\u0ac7-\\u0ac9\\u0acb-\\u0acd\\u0ae2-\\u0ae3\\u0ae6-\\u0aef\\u0b01-\\u0b03\\u0b3c\\u0b3e-\\u0b44\\u0b47\\u0b48\\u0b4b-\\u0b4d\\u0b56\\u0b57\\u0b5f-\\u0b60\\u0b66-\\u0b6f\\u0b82\\u0bbe-\\u0bc2\\u0bc6-\\u0bc8\\u0bca-\\u0bcd\\u0bd7\\u0be6-\\u0bef\\u0c01-\\u0c03\\u0c46-\\u0c48\\u0c4a-\\u0c4d\\u0c55\\u0c56\\u0c62-\\u0c63\\u0c66-\\u0c6f\\u0c82\\u0c83\\u0cbc\\u0cbe-\\u0cc4\\u0cc6-\\u0cc8\\u0cca-\\u0ccd\\u0cd5\\u0cd6\\u0ce2-\\u0ce3\\u0ce6-\\u0cef\\u0d02\\u0d03\\u0d46-\\u0d48\\u0d57\\u0d62-\\u0d63\\u0d66-\\u0d6f\\u0d82\\u0d83\\u0dca\\u0dcf-\\u0dd4\\u0dd6\\u0dd8-\\u0ddf\\u0df2\\u0df3\\u0e34-\\u0e3a\\u0e40-\\u0e45\\u0e50-\\u0e59\\u0eb4-\\u0eb9\\u0ec8-\\u0ecd\\u0ed0-\\u0ed9\\u0f18\\u0f19\\u0f20-\\u0f29\\u0f35\\u0f37\\u0f39\\u0f41-\\u0f47\\u0f71-\\u0f84\\u0f86-\\u0f87\\u0f8d-\\u0f97\\u0f99-\\u0fbc\\u0fc6\\u1000-\\u1029\\u1040-\\u1049\\u1067-\\u106d\\u1071-\\u1074\\u1082-\\u108d\\u108f-\\u109d\\u135d-\\u135f\\u170e-\\u1710\\u1720-\\u1730\\u1740-\\u1750\\u1772\\u1773\\u1780-\\u17b2\\u17dd\\u17e0-\\u17e9\\u180b-\\u180d\\u1810-\\u1819\\u1920-\\u192b\\u1930-\\u193b\\u1951-\\u196d\\u19b0-\\u19c0\\u19c8-\\u19c9\\u19d0-\\u19d9\\u1a00-\\u1a15\\u1a20-\\u1a53\\u1a60-\\u1a7c\\u1a7f-\\u1a89\\u1a90-\\u1a99\\u1b46-\\u1b4b\\u1b50-\\u1b59\\u1b6b-\\u1b73\\u1bb0-\\u1bb9\\u1be6-\\u1bf3\\u1c00-\\u1c22\\u1c40-\\u1c49\\u1c5b-\\u1c7d\\u1cd0-\\u1cd2\\u1d00-\\u1dbe\\u1e01-\\u1f15\\u200c\\u200d\\u203f\\u2040\\u2054\\u20d0-\\u20dc\\u20e1\\u20e5-\\u20f0\\u2d81-\\u2d96\\u2de0-\\u2dff\\u3021-\\u3028\\u3099\\u309a\\ua640-\\ua66d\\ua674-\\ua67d\\ua69f\\ua6f0-\\ua6f1\\ua7f8-\\ua800\\ua806\\ua80b\\ua823-\\ua827\\ua880-\\ua881\\ua8b4-\\ua8c4\\ua8d0-\\ua8d9\\ua8f3-\\ua8f7\\ua900-\\ua909\\ua926-\\ua92d\\ua930-\\ua945\\ua980-\\ua983\\ua9b3-\\ua9c0\\uaa00-\\uaa27\\uaa40-\\uaa41\\uaa4c-\\uaa4d\\uaa50-\\uaa59\\uaa7b\\uaae0-\\uaae9\\uaaf2-\\uaaf3\\uabc0-\\uabe1\\uabec\\uabed\\uabf0-\\uabf9\\ufb20-\\ufb28\\ufe00-\\ufe0f\\ufe20-\\ufe26\\ufe33\\ufe34\\ufe4d-\\ufe4f\\uff10-\\uff19\\uff3f\";\n  var nonASCIIidentifierStart = new RegExp(\"[\" + nonASCIIidentifierStartChars + \"]\");\n  var nonASCIIidentifier = new RegExp(\"[\" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + \"]\");\n\n  var newline = /[\\n\\r\\u2028\\u2029]/;\n\n  var lineBreak = /\\r\\n|[\\n\\r\\u2028\\u2029]/g;\n\n  var isIdentifierStart = exports.isIdentifierStart = function(code) {\n\tif (code < 65) return code === 36;\n\tif (code < 91) return true;\n\tif (code < 97) return code === 95;\n\tif (code < 123)return true;\n\treturn code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code));\n  };\n\n  var isIdentifierChar = exports.isIdentifierChar = function(code) {\n\tif (code < 48) return code === 36;\n\tif (code < 58) return true;\n\tif (code < 65) return false;\n\tif (code < 91) return true;\n\tif (code < 97) return code === 95;\n\tif (code < 123)return true;\n\treturn code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code));\n  };\n\n  function line_loc_t() {\n\tthis.line = tokCurLine;\n\tthis.column = tokPos - tokLineStart;\n  }\n\n  function initTokenState() {\n\ttokCurLine = 1;\n\ttokPos = tokLineStart = 0;\n\ttokRegexpAllowed = true;\n\tskipSpace();\n  }\n\n  function finishToken(type, val) {\n\ttokEnd = tokPos;\n\tif (options.locations) tokEndLoc = new line_loc_t;\n\ttokType = type;\n\tskipSpace();\n\ttokVal = val;\n\ttokRegexpAllowed = type.beforeExpr;\n  }\n\n  function skipBlockComment() {\n\tvar startLoc = options.onComment && options.locations && new line_loc_t;\n\tvar start = tokPos, end = input.indexOf(\"*/\", tokPos += 2);\n\tif (end === -1) raise(tokPos - 2, \"Unterminated comment\");\n\ttokPos = end + 2;\n\tif (options.locations) {\n\t  lineBreak.lastIndex = start;\n\t  var match;\n\t  while ((match = lineBreak.exec(input)) && match.index < tokPos) {\n\t\t++tokCurLine;\n\t\ttokLineStart = match.index + match[0].length;\n\t  }\n\t}\n\tif (options.onComment)\n\t  options.onComment(true, input.slice(start + 2, end), start, tokPos,\n\t\t\t\t\t\tstartLoc, options.locations && new line_loc_t);\n  }\n\n  function skipLineComment() {\n\tvar start = tokPos;\n\tvar startLoc = options.onComment && options.locations && new line_loc_t;\n\tvar ch = input.charCodeAt(tokPos+=2);\n\twhile (tokPos < inputLen && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) {\n\t  ++tokPos;\n\t  ch = input.charCodeAt(tokPos);\n\t}\n\tif (options.onComment)\n\t  options.onComment(false, input.slice(start + 2, tokPos), start, tokPos,\n\t\t\t\t\t\tstartLoc, options.locations && new line_loc_t);\n  }\n\n  function skipSpace() {\n\twhile (tokPos < inputLen) {\n\t  var ch = input.charCodeAt(tokPos);\n\t  if (ch === 32) {\n\t\t++tokPos;\n\t  } else if (ch === 13) {\n\t\t++tokPos;\n\t\tvar next = input.charCodeAt(tokPos);\n\t\tif (next === 10) {\n\t\t  ++tokPos;\n\t\t}\n\t\tif (options.locations) {\n\t\t  ++tokCurLine;\n\t\t  tokLineStart = tokPos;\n\t\t}\n\t  } else if (ch === 10 || ch === 8232 || ch === 8233) {\n\t\t++tokPos;\n\t\tif (options.locations) {\n\t\t  ++tokCurLine;\n\t\t  tokLineStart = tokPos;\n\t\t}\n\t  } else if (ch > 8 && ch < 14) {\n\t\t++tokPos;\n\t  } else if (ch === 47) {\n\t\tvar next = input.charCodeAt(tokPos + 1);\n\t\tif (next === 42) {\n\t\t  skipBlockComment();\n\t\t} else if (next === 47) {\n\t\t  skipLineComment();\n\t\t} else break;\n\t  } else if (ch === 160) {\n\t\t++tokPos;\n\t  } else if (ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {\n\t\t++tokPos;\n\t  } else {\n\t\tbreak;\n\t  }\n\t}\n  }\n\n  function readToken_dot() {\n\tvar next = input.charCodeAt(tokPos + 1);\n\tif (next >= 48 && next <= 57) return readNumber(true);\n\t++tokPos;\n\treturn finishToken(_dot);\n  }\n\n  function readToken_slash() {\n\tvar next = input.charCodeAt(tokPos + 1);\n\tif (tokRegexpAllowed) {++tokPos; return readRegexp();}\n\tif (next === 61) return finishOp(_assign, 2);\n\treturn finishOp(_slash, 1);\n  }\n\n  function readToken_mult_modulo() {\n\tvar next = input.charCodeAt(tokPos + 1);\n\tif (next === 61) return finishOp(_assign, 2);\n\treturn finishOp(_multiplyModulo, 1);\n  }\n\n  function readToken_pipe_amp(code) {\n\tvar next = input.charCodeAt(tokPos + 1);\n\tif (next === code) return finishOp(code === 124 ? _logicalOR : _logicalAND, 2);\n\tif (next === 61) return finishOp(_assign, 2);\n\treturn finishOp(code === 124 ? _bitwiseOR : _bitwiseAND, 1);\n  }\n\n  function readToken_caret() {\n\tvar next = input.charCodeAt(tokPos + 1);\n\tif (next === 61) return finishOp(_assign, 2);\n\treturn finishOp(_bitwiseXOR, 1);\n  }\n\n  function readToken_plus_min(code) {\n\tvar next = input.charCodeAt(tokPos + 1);\n\tif (next === code) {\n\t  if (next == 45 && input.charCodeAt(tokPos + 2) == 62 &&\n\t\t  newline.test(input.slice(lastEnd, tokPos))) {\n\t\ttokPos += 3;\n\t\tskipLineComment();\n\t\tskipSpace();\n\t\treturn readToken();\n\t  }\n\t  return finishOp(_incDec, 2);\n\t}\n\tif (next === 61) return finishOp(_assign, 2);\n\treturn finishOp(_plusMin, 1);\n  }\n\n  function readToken_lt_gt(code) {\n\tvar next = input.charCodeAt(tokPos + 1);\n\tvar size = 1;\n\tif (next === code) {\n\t  size = code === 62 && input.charCodeAt(tokPos + 2) === 62 ? 3 : 2;\n\t  if (input.charCodeAt(tokPos + size) === 61) return finishOp(_assign, size + 1);\n\t  return finishOp(_bitShift, size);\n\t}\n\tif (next == 33 && code == 60 && input.charCodeAt(tokPos + 2) == 45 &&\n\t\tinput.charCodeAt(tokPos + 3) == 45) {\n\t  tokPos += 4;\n\t  skipLineComment();\n\t  skipSpace();\n\t  return readToken();\n\t}\n\tif (next === 61)\n\t  size = input.charCodeAt(tokPos + 2) === 61 ? 3 : 2;\n\treturn finishOp(_relational, size);\n  }\n\n  function readToken_eq_excl(code) {\n\tvar next = input.charCodeAt(tokPos + 1);\n\tif (next === 61) return finishOp(_equality, input.charCodeAt(tokPos + 2) === 61 ? 3 : 2);\n\treturn finishOp(code === 61 ? _eq : _prefix, 1);\n  }\n\n  function getTokenFromCode(code) {\n\tswitch(code) {\n\tcase 46:\n\t  return readToken_dot();\n\n\tcase 40: ++tokPos; return finishToken(_parenL);\n\tcase 41: ++tokPos; return finishToken(_parenR);\n\tcase 59: ++tokPos; return finishToken(_semi);\n\tcase 44: ++tokPos; return finishToken(_comma);\n\tcase 91: ++tokPos; return finishToken(_bracketL);\n\tcase 93: ++tokPos; return finishToken(_bracketR);\n\tcase 123: ++tokPos; return finishToken(_braceL);\n\tcase 125: ++tokPos; return finishToken(_braceR);\n\tcase 58: ++tokPos; return finishToken(_colon);\n\tcase 63: ++tokPos; return finishToken(_question);\n\n\tcase 48:\n\t  var next = input.charCodeAt(tokPos + 1);\n\t  if (next === 120 || next === 88) return readHexNumber();\n\tcase 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57:\n\t  return readNumber(false);\n\n\tcase 34: case 39:\n\t  return readString(code);\n\n\tcase 47:\n\t  return readToken_slash(code);\n\n\tcase 37: case 42:\n\t  return readToken_mult_modulo();\n\n\tcase 124: case 38:\n\t  return readToken_pipe_amp(code);\n\n\tcase 94:\n\t  return readToken_caret();\n\n\tcase 43: case 45:\n\t  return readToken_plus_min(code);\n\n\tcase 60: case 62:\n\t  return readToken_lt_gt(code);\n\n\tcase 61: case 33:\n\t  return readToken_eq_excl(code);\n\n\tcase 126:\n\t  return finishOp(_prefix, 1);\n\t}\n\n\treturn false;\n  }\n\n  function readToken(forceRegexp) {\n\tif (!forceRegexp) tokStart = tokPos;\n\telse tokPos = tokStart + 1;\n\tif (options.locations) tokStartLoc = new line_loc_t;\n\tif (forceRegexp) return readRegexp();\n\tif (tokPos >= inputLen) return finishToken(_eof);\n\n\tvar code = input.charCodeAt(tokPos);\n\tif (isIdentifierStart(code) || code === 92 ) return readWord();\n\n\tvar tok = getTokenFromCode(code);\n\n\tif (tok === false) {\n\t  var ch = String.fromCharCode(code);\n\t  if (ch === \"\\\\\" || nonASCIIidentifierStart.test(ch)) return readWord();\n\t  raise(tokPos, \"Unexpected character '\" + ch + \"'\");\n\t}\n\treturn tok;\n  }\n\n  function finishOp(type, size) {\n\tvar str = input.slice(tokPos, tokPos + size);\n\ttokPos += size;\n\tfinishToken(type, str);\n  }\n\n  function readRegexp() {\n\tvar content = \"\", escaped, inClass, start = tokPos;\n\tfor (;;) {\n\t  if (tokPos >= inputLen) raise(start, \"Unterminated regular expression\");\n\t  var ch = input.charAt(tokPos);\n\t  if (newline.test(ch)) raise(start, \"Unterminated regular expression\");\n\t  if (!escaped) {\n\t\tif (ch === \"[\") inClass = true;\n\t\telse if (ch === \"]\" && inClass) inClass = false;\n\t\telse if (ch === \"/\" && !inClass) break;\n\t\tescaped = ch === \"\\\\\";\n\t  } else escaped = false;\n\t  ++tokPos;\n\t}\n\tvar content = input.slice(start, tokPos);\n\t++tokPos;\n\tvar mods = readWord1();\n\tif (mods && !/^[gmsiy]*$/.test(mods)) raise(start, \"Invalid regexp flag\");\n\ttry {\n\t  var value = new RegExp(content, mods);\n\t} catch (e) {\n\t  if (e instanceof SyntaxError) raise(start, e.message);\n\t  raise(e);\n\t}\n\treturn finishToken(_regexp, value);\n  }\n\n  function readInt(radix, len) {\n\tvar start = tokPos, total = 0;\n\tfor (var i = 0, e = len == null ? Infinity : len; i < e; ++i) {\n\t  var code = input.charCodeAt(tokPos), val;\n\t  if (code >= 97) val = code - 97 + 10;\n\t  else if (code >= 65) val = code - 65 + 10;\n\t  else if (code >= 48 && code <= 57) val = code - 48;\n\t  else val = Infinity;\n\t  if (val >= radix) break;\n\t  ++tokPos;\n\t  total = total * radix + val;\n\t}\n\tif (tokPos === start || len != null && tokPos - start !== len) return null;\n\n\treturn total;\n  }\n\n  function readHexNumber() {\n\ttokPos += 2;\n\tvar val = readInt(16);\n\tif (val == null) raise(tokStart + 2, \"Expected hexadecimal number\");\n\tif (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, \"Identifier directly after number\");\n\treturn finishToken(_num, val);\n  }\n\n  function readNumber(startsWithDot) {\n\tvar start = tokPos, isFloat = false, octal = input.charCodeAt(tokPos) === 48;\n\tif (!startsWithDot && readInt(10) === null) raise(start, \"Invalid number\");\n\tif (input.charCodeAt(tokPos) === 46) {\n\t  ++tokPos;\n\t  readInt(10);\n\t  isFloat = true;\n\t}\n\tvar next = input.charCodeAt(tokPos);\n\tif (next === 69 || next === 101) {\n\t  next = input.charCodeAt(++tokPos);\n\t  if (next === 43 || next === 45) ++tokPos;\n\t  if (readInt(10) === null) raise(start, \"Invalid number\");\n\t  isFloat = true;\n\t}\n\tif (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, \"Identifier directly after number\");\n\n\tvar str = input.slice(start, tokPos), val;\n\tif (isFloat) val = parseFloat(str);\n\telse if (!octal || str.length === 1) val = parseInt(str, 10);\n\telse if (/[89]/.test(str) || strict) raise(start, \"Invalid number\");\n\telse val = parseInt(str, 8);\n\treturn finishToken(_num, val);\n  }\n\n  function readString(quote) {\n\ttokPos++;\n\tvar out = \"\";\n\tfor (;;) {\n\t  if (tokPos >= inputLen) raise(tokStart, \"Unterminated string constant\");\n\t  var ch = input.charCodeAt(tokPos);\n\t  if (ch === quote) {\n\t\t++tokPos;\n\t\treturn finishToken(_string, out);\n\t  }\n\t  if (ch === 92) {\n\t\tch = input.charCodeAt(++tokPos);\n\t\tvar octal = /^[0-7]+/.exec(input.slice(tokPos, tokPos + 3));\n\t\tif (octal) octal = octal[0];\n\t\twhile (octal && parseInt(octal, 8) > 255) octal = octal.slice(0, -1);\n\t\tif (octal === \"0\") octal = null;\n\t\t++tokPos;\n\t\tif (octal) {\n\t\t  if (strict) raise(tokPos - 2, \"Octal literal in strict mode\");\n\t\t  out += String.fromCharCode(parseInt(octal, 8));\n\t\t  tokPos += octal.length - 1;\n\t\t} else {\n\t\t  switch (ch) {\n\t\t  case 110: out += \"\\n\"; break;\n\t\t  case 114: out += \"\\r\"; break;\n\t\t  case 120: out += String.fromCharCode(readHexChar(2)); break;\n\t\t  case 117: out += String.fromCharCode(readHexChar(4)); break;\n\t\t  case 85: out += String.fromCharCode(readHexChar(8)); break;\n\t\t  case 116: out += \"\\t\"; break;\n\t\t  case 98: out += \"\\b\"; break;\n\t\t  case 118: out += \"\\u000b\"; break;\n\t\t  case 102: out += \"\\f\"; break;\n\t\t  case 48: out += \"\\0\"; break;\n\t\t  case 13: if (input.charCodeAt(tokPos) === 10) ++tokPos;\n\t\t  case 10:\n\t\t\tif (options.locations) { tokLineStart = tokPos; ++tokCurLine; }\n\t\t\tbreak;\n\t\t  default: out += String.fromCharCode(ch); break;\n\t\t  }\n\t\t}\n\t  } else {\n\t\tif (ch === 13 || ch === 10 || ch === 8232 || ch === 8233) raise(tokStart, \"Unterminated string constant\");\n\t\tout += String.fromCharCode(ch);\n\t\t++tokPos;\n\t  }\n\t}\n  }\n\n  function readHexChar(len) {\n\tvar n = readInt(16, len);\n\tif (n === null) raise(tokStart, \"Bad character escape sequence\");\n\treturn n;\n  }\n\n  var containsEsc;\n\n  function readWord1() {\n\tcontainsEsc = false;\n\tvar word, first = true, start = tokPos;\n\tfor (;;) {\n\t  var ch = input.charCodeAt(tokPos);\n\t  if (isIdentifierChar(ch)) {\n\t\tif (containsEsc) word += input.charAt(tokPos);\n\t\t++tokPos;\n\t  } else if (ch === 92) {\n\t\tif (!containsEsc) word = input.slice(start, tokPos);\n\t\tcontainsEsc = true;\n\t\tif (input.charCodeAt(++tokPos) != 117)\n\t\t  raise(tokPos, \"Expecting Unicode escape sequence \\\\uXXXX\");\n\t\t++tokPos;\n\t\tvar esc = readHexChar(4);\n\t\tvar escStr = String.fromCharCode(esc);\n\t\tif (!escStr) raise(tokPos - 1, \"Invalid Unicode escape\");\n\t\tif (!(first ? isIdentifierStart(esc) : isIdentifierChar(esc)))\n\t\t  raise(tokPos - 4, \"Invalid Unicode escape\");\n\t\tword += escStr;\n\t  } else {\n\t\tbreak;\n\t  }\n\t  first = false;\n\t}\n\treturn containsEsc ? word : input.slice(start, tokPos);\n  }\n\n  function readWord() {\n\tvar word = readWord1();\n\tvar type = _name;\n\tif (!containsEsc && isKeyword(word))\n\t  type = keywordTypes[word];\n\treturn finishToken(type, word);\n  }\n\n  function next() {\n\tlastStart = tokStart;\n\tlastEnd = tokEnd;\n\tlastEndLoc = tokEndLoc;\n\treadToken();\n  }\n\n  function setStrict(strct) {\n\tstrict = strct;\n\ttokPos = tokStart;\n\tif (options.locations) {\n\t  while (tokPos < tokLineStart) {\n\t\ttokLineStart = input.lastIndexOf(\"\\n\", tokLineStart - 2) + 1;\n\t\t--tokCurLine;\n\t  }\n\t}\n\tskipSpace();\n\treadToken();\n  }\n\n  function node_t() {\n\tthis.type = null;\n\tthis.start = tokStart;\n\tthis.end = null;\n  }\n\n  function node_loc_t() {\n\tthis.start = tokStartLoc;\n\tthis.end = null;\n\tif (sourceFile !== null) this.source = sourceFile;\n  }\n\n  function startNode() {\n\tvar node = new node_t();\n\tif (options.locations)\n\t  node.loc = new node_loc_t();\n\tif (options.directSourceFile)\n\t  node.sourceFile = options.directSourceFile;\n\tif (options.ranges)\n\t  node.range = [tokStart, 0];\n\treturn node;\n  }\n\n  function startNodeFrom(other) {\n\tvar node = new node_t();\n\tnode.start = other.start;\n\tif (options.locations) {\n\t  node.loc = new node_loc_t();\n\t  node.loc.start = other.loc.start;\n\t}\n\tif (options.ranges)\n\t  node.range = [other.range[0], 0];\n\n\treturn node;\n  }\n\n  function finishNode(node, type) {\n\tnode.type = type;\n\tnode.end = lastEnd;\n\tif (options.locations)\n\t  node.loc.end = lastEndLoc;\n\tif (options.ranges)\n\t  node.range[1] = lastEnd;\n\treturn node;\n  }\n\n  function isUseStrict(stmt) {\n\treturn options.ecmaVersion >= 5 && stmt.type === \"ExpressionStatement\" &&\n\t  stmt.expression.type === \"Literal\" && stmt.expression.value === \"use strict\";\n  }\n\n  function eat(type) {\n\tif (tokType === type) {\n\t  next();\n\t  return true;\n\t}\n  }\n\n  function canInsertSemicolon() {\n\treturn !options.strictSemicolons &&\n\t  (tokType === _eof || tokType === _braceR || newline.test(input.slice(lastEnd, tokStart)));\n  }\n\n  function semicolon() {\n\tif (!eat(_semi) && !canInsertSemicolon()) unexpected();\n  }\n\n  function expect(type) {\n\tif (tokType === type) next();\n\telse unexpected();\n  }\n\n  function unexpected() {\n\traise(tokStart, \"Unexpected token\");\n  }\n\n  function checkLVal(expr) {\n\tif (expr.type !== \"Identifier\" && expr.type !== \"MemberExpression\")\n\t  raise(expr.start, \"Assigning to rvalue\");\n\tif (strict && expr.type === \"Identifier\" && isStrictBadIdWord(expr.name))\n\t  raise(expr.start, \"Assigning to \" + expr.name + \" in strict mode\");\n  }\n\n  function parseTopLevel(program) {\n\tlastStart = lastEnd = tokPos;\n\tif (options.locations) lastEndLoc = new line_loc_t;\n\tinFunction = strict = null;\n\tlabels = [];\n\treadToken();\n\n\tvar node = program || startNode(), first = true;\n\tif (!program) node.body = [];\n\twhile (tokType !== _eof) {\n\t  var stmt = parseStatement();\n\t  node.body.push(stmt);\n\t  if (first && isUseStrict(stmt)) setStrict(true);\n\t  first = false;\n\t}\n\treturn finishNode(node, \"Program\");\n  }\n\n  var loopLabel = {kind: \"loop\"}, switchLabel = {kind: \"switch\"};\n\n  function parseStatement() {\n\tif (tokType === _slash || tokType === _assign && tokVal == \"/=\")\n\t  readToken(true);\n\n\tvar starttype = tokType, node = startNode();\n\n\tswitch (starttype) {\n\tcase _break: case _continue:\n\t  next();\n\t  var isBreak = starttype === _break;\n\t  if (eat(_semi) || canInsertSemicolon()) node.label = null;\n\t  else if (tokType !== _name) unexpected();\n\t  else {\n\t\tnode.label = parseIdent();\n\t\tsemicolon();\n\t  }\n\n\t  for (var i = 0; i < labels.length; ++i) {\n\t\tvar lab = labels[i];\n\t\tif (node.label == null || lab.name === node.label.name) {\n\t\t  if (lab.kind != null && (isBreak || lab.kind === \"loop\")) break;\n\t\t  if (node.label && isBreak) break;\n\t\t}\n\t  }\n\t  if (i === labels.length) raise(node.start, \"Unsyntactic \" + starttype.keyword);\n\t  return finishNode(node, isBreak ? \"BreakStatement\" : \"ContinueStatement\");\n\n\tcase _debugger:\n\t  next();\n\t  semicolon();\n\t  return finishNode(node, \"DebuggerStatement\");\n\n\tcase _do:\n\t  next();\n\t  labels.push(loopLabel);\n\t  node.body = parseStatement();\n\t  labels.pop();\n\t  expect(_while);\n\t  node.test = parseParenExpression();\n\t  semicolon();\n\t  return finishNode(node, \"DoWhileStatement\");\n\n\tcase _for:\n\t  next();\n\t  labels.push(loopLabel);\n\t  expect(_parenL);\n\t  if (tokType === _semi) return parseFor(node, null);\n\t  if (tokType === _var) {\n\t\tvar init = startNode();\n\t\tnext();\n\t\tparseVar(init, true);\n\t\tfinishNode(init, \"VariableDeclaration\");\n\t\tif (init.declarations.length === 1 && eat(_in))\n\t\t  return parseForIn(node, init);\n\t\treturn parseFor(node, init);\n\t  }\n\t  var init = parseExpression(false, true);\n\t  if (eat(_in)) {checkLVal(init); return parseForIn(node, init);}\n\t  return parseFor(node, init);\n\n\tcase _function:\n\t  next();\n\t  return parseFunction(node, true);\n\n\tcase _if:\n\t  next();\n\t  node.test = parseParenExpression();\n\t  node.consequent = parseStatement();\n\t  node.alternate = eat(_else) ? parseStatement() : null;\n\t  return finishNode(node, \"IfStatement\");\n\n\tcase _return:\n\t  if (!inFunction && !options.allowReturnOutsideFunction)\n\t\traise(tokStart, \"'return' outside of function\");\n\t  next();\n\n\t  if (eat(_semi) || canInsertSemicolon()) node.argument = null;\n\t  else { node.argument = parseExpression(); semicolon(); }\n\t  return finishNode(node, \"ReturnStatement\");\n\n\tcase _switch:\n\t  next();\n\t  node.discriminant = parseParenExpression();\n\t  node.cases = [];\n\t  expect(_braceL);\n\t  labels.push(switchLabel);\n\n\t  for (var cur, sawDefault; tokType != _braceR;) {\n\t\tif (tokType === _case || tokType === _default) {\n\t\t  var isCase = tokType === _case;\n\t\t  if (cur) finishNode(cur, \"SwitchCase\");\n\t\t  node.cases.push(cur = startNode());\n\t\t  cur.consequent = [];\n\t\t  next();\n\t\t  if (isCase) cur.test = parseExpression();\n\t\t  else {\n\t\t\tif (sawDefault) raise(lastStart, \"Multiple default clauses\"); sawDefault = true;\n\t\t\tcur.test = null;\n\t\t  }\n\t\t  expect(_colon);\n\t\t} else {\n\t\t  if (!cur) unexpected();\n\t\t  cur.consequent.push(parseStatement());\n\t\t}\n\t  }\n\t  if (cur) finishNode(cur, \"SwitchCase\");\n\t  next();\n\t  labels.pop();\n\t  return finishNode(node, \"SwitchStatement\");\n\n\tcase _throw:\n\t  next();\n\t  if (newline.test(input.slice(lastEnd, tokStart)))\n\t\traise(lastEnd, \"Illegal newline after throw\");\n\t  node.argument = parseExpression();\n\t  semicolon();\n\t  return finishNode(node, \"ThrowStatement\");\n\n\tcase _try:\n\t  next();\n\t  node.block = parseBlock();\n\t  node.handler = null;\n\t  if (tokType === _catch) {\n\t\tvar clause = startNode();\n\t\tnext();\n\t\texpect(_parenL);\n\t\tclause.param = parseIdent();\n\t\tif (strict && isStrictBadIdWord(clause.param.name))\n\t\t  raise(clause.param.start, \"Binding \" + clause.param.name + \" in strict mode\");\n\t\texpect(_parenR);\n\t\tclause.guard = null;\n\t\tclause.body = parseBlock();\n\t\tnode.handler = finishNode(clause, \"CatchClause\");\n\t  }\n\t  node.guardedHandlers = empty;\n\t  node.finalizer = eat(_finally) ? parseBlock() : null;\n\t  if (!node.handler && !node.finalizer)\n\t\traise(node.start, \"Missing catch or finally clause\");\n\t  return finishNode(node, \"TryStatement\");\n\n\tcase _var:\n\t  next();\n\t  parseVar(node);\n\t  semicolon();\n\t  return finishNode(node, \"VariableDeclaration\");\n\n\tcase _while:\n\t  next();\n\t  node.test = parseParenExpression();\n\t  labels.push(loopLabel);\n\t  node.body = parseStatement();\n\t  labels.pop();\n\t  return finishNode(node, \"WhileStatement\");\n\n\tcase _with:\n\t  if (strict) raise(tokStart, \"'with' in strict mode\");\n\t  next();\n\t  node.object = parseParenExpression();\n\t  node.body = parseStatement();\n\t  return finishNode(node, \"WithStatement\");\n\n\tcase _braceL:\n\t  return parseBlock();\n\n\tcase _semi:\n\t  next();\n\t  return finishNode(node, \"EmptyStatement\");\n\n\tdefault:\n\t  var maybeName = tokVal, expr = parseExpression();\n\t  if (starttype === _name && expr.type === \"Identifier\" && eat(_colon)) {\n\t\tfor (var i = 0; i < labels.length; ++i)\n\t\t  if (labels[i].name === maybeName) raise(expr.start, \"Label '\" + maybeName + \"' is already declared\");\n\t\tvar kind = tokType.isLoop ? \"loop\" : tokType === _switch ? \"switch\" : null;\n\t\tlabels.push({name: maybeName, kind: kind});\n\t\tnode.body = parseStatement();\n\t\tlabels.pop();\n\t\tnode.label = expr;\n\t\treturn finishNode(node, \"LabeledStatement\");\n\t  } else {\n\t\tnode.expression = expr;\n\t\tsemicolon();\n\t\treturn finishNode(node, \"ExpressionStatement\");\n\t  }\n\t}\n  }\n\n  function parseParenExpression() {\n\texpect(_parenL);\n\tvar val = parseExpression();\n\texpect(_parenR);\n\treturn val;\n  }\n\n  function parseBlock(allowStrict) {\n\tvar node = startNode(), first = true, strict = false, oldStrict;\n\tnode.body = [];\n\texpect(_braceL);\n\twhile (!eat(_braceR)) {\n\t  var stmt = parseStatement();\n\t  node.body.push(stmt);\n\t  if (first && allowStrict && isUseStrict(stmt)) {\n\t\toldStrict = strict;\n\t\tsetStrict(strict = true);\n\t  }\n\t  first = false;\n\t}\n\tif (strict && !oldStrict) setStrict(false);\n\treturn finishNode(node, \"BlockStatement\");\n  }\n\n  function parseFor(node, init) {\n\tnode.init = init;\n\texpect(_semi);\n\tnode.test = tokType === _semi ? null : parseExpression();\n\texpect(_semi);\n\tnode.update = tokType === _parenR ? null : parseExpression();\n\texpect(_parenR);\n\tnode.body = parseStatement();\n\tlabels.pop();\n\treturn finishNode(node, \"ForStatement\");\n  }\n\n  function parseForIn(node, init) {\n\tnode.left = init;\n\tnode.right = parseExpression();\n\texpect(_parenR);\n\tnode.body = parseStatement();\n\tlabels.pop();\n\treturn finishNode(node, \"ForInStatement\");\n  }\n\n  function parseVar(node, noIn) {\n\tnode.declarations = [];\n\tnode.kind = \"var\";\n\tfor (;;) {\n\t  var decl = startNode();\n\t  decl.id = parseIdent();\n\t  if (strict && isStrictBadIdWord(decl.id.name))\n\t\traise(decl.id.start, \"Binding \" + decl.id.name + \" in strict mode\");\n\t  decl.init = eat(_eq) ? parseExpression(true, noIn) : null;\n\t  node.declarations.push(finishNode(decl, \"VariableDeclarator\"));\n\t  if (!eat(_comma)) break;\n\t}\n\treturn node;\n  }\n\n  function parseExpression(noComma, noIn) {\n\tvar expr = parseMaybeAssign(noIn);\n\tif (!noComma && tokType === _comma) {\n\t  var node = startNodeFrom(expr);\n\t  node.expressions = [expr];\n\t  while (eat(_comma)) node.expressions.push(parseMaybeAssign(noIn));\n\t  return finishNode(node, \"SequenceExpression\");\n\t}\n\treturn expr;\n  }\n\n  function parseMaybeAssign(noIn) {\n\tvar left = parseMaybeConditional(noIn);\n\tif (tokType.isAssign) {\n\t  var node = startNodeFrom(left);\n\t  node.operator = tokVal;\n\t  node.left = left;\n\t  next();\n\t  node.right = parseMaybeAssign(noIn);\n\t  checkLVal(left);\n\t  return finishNode(node, \"AssignmentExpression\");\n\t}\n\treturn left;\n  }\n\n  function parseMaybeConditional(noIn) {\n\tvar expr = parseExprOps(noIn);\n\tif (eat(_question)) {\n\t  var node = startNodeFrom(expr);\n\t  node.test = expr;\n\t  node.consequent = parseExpression(true);\n\t  expect(_colon);\n\t  node.alternate = parseExpression(true, noIn);\n\t  return finishNode(node, \"ConditionalExpression\");\n\t}\n\treturn expr;\n  }\n\n  function parseExprOps(noIn) {\n\treturn parseExprOp(parseMaybeUnary(), -1, noIn);\n  }\n\n  function parseExprOp(left, minPrec, noIn) {\n\tvar prec = tokType.binop;\n\tif (prec != null && (!noIn || tokType !== _in)) {\n\t  if (prec > minPrec) {\n\t\tvar node = startNodeFrom(left);\n\t\tnode.left = left;\n\t\tnode.operator = tokVal;\n\t\tvar op = tokType;\n\t\tnext();\n\t\tnode.right = parseExprOp(parseMaybeUnary(), prec, noIn);\n\t\tvar exprNode = finishNode(node, (op === _logicalOR || op === _logicalAND) ? \"LogicalExpression\" : \"BinaryExpression\");\n\t\treturn parseExprOp(exprNode, minPrec, noIn);\n\t  }\n\t}\n\treturn left;\n  }\n\n  function parseMaybeUnary() {\n\tif (tokType.prefix) {\n\t  var node = startNode(), update = tokType.isUpdate;\n\t  node.operator = tokVal;\n\t  node.prefix = true;\n\t  tokRegexpAllowed = true;\n\t  next();\n\t  node.argument = parseMaybeUnary();\n\t  if (update) checkLVal(node.argument);\n\t  else if (strict && node.operator === \"delete\" &&\n\t\t\t   node.argument.type === \"Identifier\")\n\t\traise(node.start, \"Deleting local variable in strict mode\");\n\t  return finishNode(node, update ? \"UpdateExpression\" : \"UnaryExpression\");\n\t}\n\tvar expr = parseExprSubscripts();\n\twhile (tokType.postfix && !canInsertSemicolon()) {\n\t  var node = startNodeFrom(expr);\n\t  node.operator = tokVal;\n\t  node.prefix = false;\n\t  node.argument = expr;\n\t  checkLVal(expr);\n\t  next();\n\t  expr = finishNode(node, \"UpdateExpression\");\n\t}\n\treturn expr;\n  }\n\n  function parseExprSubscripts() {\n\treturn parseSubscripts(parseExprAtom());\n  }\n\n  function parseSubscripts(base, noCalls) {\n\tif (eat(_dot)) {\n\t  var node = startNodeFrom(base);\n\t  node.object = base;\n\t  node.property = parseIdent(true);\n\t  node.computed = false;\n\t  return parseSubscripts(finishNode(node, \"MemberExpression\"), noCalls);\n\t} else if (eat(_bracketL)) {\n\t  var node = startNodeFrom(base);\n\t  node.object = base;\n\t  node.property = parseExpression();\n\t  node.computed = true;\n\t  expect(_bracketR);\n\t  return parseSubscripts(finishNode(node, \"MemberExpression\"), noCalls);\n\t} else if (!noCalls && eat(_parenL)) {\n\t  var node = startNodeFrom(base);\n\t  node.callee = base;\n\t  node.arguments = parseExprList(_parenR, false);\n\t  return parseSubscripts(finishNode(node, \"CallExpression\"), noCalls);\n\t} else return base;\n  }\n\n  function parseExprAtom() {\n\tswitch (tokType) {\n\tcase _this:\n\t  var node = startNode();\n\t  next();\n\t  return finishNode(node, \"ThisExpression\");\n\tcase _name:\n\t  return parseIdent();\n\tcase _num: case _string: case _regexp:\n\t  var node = startNode();\n\t  node.value = tokVal;\n\t  node.raw = input.slice(tokStart, tokEnd);\n\t  next();\n\t  return finishNode(node, \"Literal\");\n\n\tcase _null: case _true: case _false:\n\t  var node = startNode();\n\t  node.value = tokType.atomValue;\n\t  node.raw = tokType.keyword;\n\t  next();\n\t  return finishNode(node, \"Literal\");\n\n\tcase _parenL:\n\t  var tokStartLoc1 = tokStartLoc, tokStart1 = tokStart;\n\t  next();\n\t  var val = parseExpression();\n\t  val.start = tokStart1;\n\t  val.end = tokEnd;\n\t  if (options.locations) {\n\t\tval.loc.start = tokStartLoc1;\n\t\tval.loc.end = tokEndLoc;\n\t  }\n\t  if (options.ranges)\n\t\tval.range = [tokStart1, tokEnd];\n\t  expect(_parenR);\n\t  return val;\n\n\tcase _bracketL:\n\t  var node = startNode();\n\t  next();\n\t  node.elements = parseExprList(_bracketR, true, true);\n\t  return finishNode(node, \"ArrayExpression\");\n\n\tcase _braceL:\n\t  return parseObj();\n\n\tcase _function:\n\t  var node = startNode();\n\t  next();\n\t  return parseFunction(node, false);\n\n\tcase _new:\n\t  return parseNew();\n\n\tdefault:\n\t  unexpected();\n\t}\n  }\n\n  function parseNew() {\n\tvar node = startNode();\n\tnext();\n\tnode.callee = parseSubscripts(parseExprAtom(), true);\n\tif (eat(_parenL)) node.arguments = parseExprList(_parenR, false);\n\telse node.arguments = empty;\n\treturn finishNode(node, \"NewExpression\");\n  }\n\n  function parseObj() {\n\tvar node = startNode(), first = true, sawGetSet = false;\n\tnode.properties = [];\n\tnext();\n\twhile (!eat(_braceR)) {\n\t  if (!first) {\n\t\texpect(_comma);\n\t\tif (options.allowTrailingCommas && eat(_braceR)) break;\n\t  } else first = false;\n\n\t  var prop = {key: parsePropertyName()}, isGetSet = false, kind;\n\t  if (eat(_colon)) {\n\t\tprop.value = parseExpression(true);\n\t\tkind = prop.kind = \"init\";\n\t  } else if (options.ecmaVersion >= 5 && prop.key.type === \"Identifier\" &&\n\t\t\t\t (prop.key.name === \"get\" || prop.key.name === \"set\")) {\n\t\tisGetSet = sawGetSet = true;\n\t\tkind = prop.kind = prop.key.name;\n\t\tprop.key = parsePropertyName();\n\t\tif (tokType !== _parenL) unexpected();\n\t\tprop.value = parseFunction(startNode(), false);\n\t  } else unexpected();\n\n\t  if (prop.key.type === \"Identifier\" && (strict || sawGetSet)) {\n\t\tfor (var i = 0; i < node.properties.length; ++i) {\n\t\t  var other = node.properties[i];\n\t\t  if (other.key.name === prop.key.name) {\n\t\t\tvar conflict = kind == other.kind || isGetSet && other.kind === \"init\" ||\n\t\t\t  kind === \"init\" && (other.kind === \"get\" || other.kind === \"set\");\n\t\t\tif (conflict && !strict && kind === \"init\" && other.kind === \"init\") conflict = false;\n\t\t\tif (conflict) raise(prop.key.start, \"Redefinition of property\");\n\t\t  }\n\t\t}\n\t  }\n\t  node.properties.push(prop);\n\t}\n\treturn finishNode(node, \"ObjectExpression\");\n  }\n\n  function parsePropertyName() {\n\tif (tokType === _num || tokType === _string) return parseExprAtom();\n\treturn parseIdent(true);\n  }\n\n  function parseFunction(node, isStatement) {\n\tif (tokType === _name) node.id = parseIdent();\n\telse if (isStatement) unexpected();\n\telse node.id = null;\n\tnode.params = [];\n\tvar first = true;\n\texpect(_parenL);\n\twhile (!eat(_parenR)) {\n\t  if (!first) expect(_comma); else first = false;\n\t  node.params.push(parseIdent());\n\t}\n\n\tvar oldInFunc = inFunction, oldLabels = labels;\n\tinFunction = true; labels = [];\n\tnode.body = parseBlock(true);\n\tinFunction = oldInFunc; labels = oldLabels;\n\n\tif (strict || node.body.body.length && isUseStrict(node.body.body[0])) {\n\t  for (var i = node.id ? -1 : 0; i < node.params.length; ++i) {\n\t\tvar id = i < 0 ? node.id : node.params[i];\n\t\tif (isStrictReservedWord(id.name) || isStrictBadIdWord(id.name))\n\t\t  raise(id.start, \"Defining '\" + id.name + \"' in strict mode\");\n\t\tif (i >= 0) for (var j = 0; j < i; ++j) if (id.name === node.params[j].name)\n\t\t  raise(id.start, \"Argument name clash in strict mode\");\n\t  }\n\t}\n\n\treturn finishNode(node, isStatement ? \"FunctionDeclaration\" : \"FunctionExpression\");\n  }\n\n  function parseExprList(close, allowTrailingComma, allowEmpty) {\n\tvar elts = [], first = true;\n\twhile (!eat(close)) {\n\t  if (!first) {\n\t\texpect(_comma);\n\t\tif (allowTrailingComma && options.allowTrailingCommas && eat(close)) break;\n\t  } else first = false;\n\n\t  if (allowEmpty && tokType === _comma) elts.push(null);\n\t  else elts.push(parseExpression(true));\n\t}\n\treturn elts;\n  }\n\n  function parseIdent(liberal) {\n\tvar node = startNode();\n\tif (liberal && options.forbidReserved == \"everywhere\") liberal = false;\n\tif (tokType === _name) {\n\t  if (!liberal &&\n\t\t  (options.forbidReserved &&\n\t\t   (options.ecmaVersion === 3 ? isReservedWord3 : isReservedWord5)(tokVal) ||\n\t\t   strict && isStrictReservedWord(tokVal)) &&\n\t\t  input.slice(tokStart, tokEnd).indexOf(\"\\\\\") == -1)\n\t\traise(tokStart, \"The keyword '\" + tokVal + \"' is reserved\");\n\t  node.name = tokVal;\n\t} else if (liberal && tokType.keyword) {\n\t  node.name = tokType.keyword;\n\t} else {\n\t  unexpected();\n\t}\n\ttokRegexpAllowed = false;\n\tnext();\n\treturn finishNode(node, \"Identifier\");\n  }\n\n});\n\n\t\tif (!acorn.version)\n\t\t\tacorn = null;\n\t}\n\n\tfunction parse(code, options) {\n\t\treturn (global.acorn || acorn).parse(code, options);\n\t}\n\n\tvar binaryOperators = {\n\t\t'+': '__add',\n\t\t'-': '__subtract',\n\t\t'*': '__multiply',\n\t\t'/': '__divide',\n\t\t'%': '__modulo',\n\t\t'==': '__equals',\n\t\t'!=': '__equals'\n\t};\n\n\tvar unaryOperators = {\n\t\t'-': '__negate',\n\t\t'+': '__self'\n\t};\n\n\tvar fields = Base.each(\n\t\t['add', 'subtract', 'multiply', 'divide', 'modulo', 'equals', 'negate'],\n\t\tfunction(name) {\n\t\t\tthis['__' + name] = '#' + name;\n\t\t},\n\t\t{\n\t\t\t__self: function() {\n\t\t\t\treturn this;\n\t\t\t}\n\t\t}\n\t);\n\tPoint.inject(fields);\n\tSize.inject(fields);\n\tColor.inject(fields);\n\n\tfunction __$__(left, operator, right) {\n\t\tvar handler = binaryOperators[operator];\n\t\tif (left && left[handler]) {\n\t\t\tvar res = left[handler](right);\n\t\t\treturn operator === '!=' ? !res : res;\n\t\t}\n\t\tswitch (operator) {\n\t\tcase '+': return left + right;\n\t\tcase '-': return left - right;\n\t\tcase '*': return left * right;\n\t\tcase '/': return left / right;\n\t\tcase '%': return left % right;\n\t\tcase '==': return left == right;\n\t\tcase '!=': return left != right;\n\t\t}\n\t}\n\n\tfunction $__(operator, value) {\n\t\tvar handler = unaryOperators[operator];\n\t\tif (value && value[handler])\n\t\t\treturn value[handler]();\n\t\tswitch (operator) {\n\t\tcase '+': return +value;\n\t\tcase '-': return -value;\n\t\t}\n\t}\n\n\tfunction compile(code, options) {\n\t\tif (!code)\n\t\t\treturn '';\n\t\toptions = options || {};\n\n\t\tvar insertions = [];\n\n\t\tfunction getOffset(offset) {\n\t\t\tfor (var i = 0, l = insertions.length; i < l; i++) {\n\t\t\t\tvar insertion = insertions[i];\n\t\t\t\tif (insertion[0] >= offset)\n\t\t\t\t\tbreak;\n\t\t\t\toffset += insertion[1];\n\t\t\t}\n\t\t\treturn offset;\n\t\t}\n\n\t\tfunction getCode(node) {\n\t\t\treturn code.substring(getOffset(node.range[0]),\n\t\t\t\t\tgetOffset(node.range[1]));\n\t\t}\n\n\t\tfunction getBetween(left, right) {\n\t\t\treturn code.substring(getOffset(left.range[1]),\n\t\t\t\t\tgetOffset(right.range[0]));\n\t\t}\n\n\t\tfunction replaceCode(node, str) {\n\t\t\tvar start = getOffset(node.range[0]),\n\t\t\t\tend = getOffset(node.range[1]),\n\t\t\t\tinsert = 0;\n\t\t\tfor (var i = insertions.length - 1; i >= 0; i--) {\n\t\t\t\tif (start > insertions[i][0]) {\n\t\t\t\t\tinsert = i + 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tinsertions.splice(insert, 0, [start, str.length - end + start]);\n\t\t\tcode = code.substring(0, start) + str + code.substring(end);\n\t\t}\n\n\t\tfunction walkAST(node, parent) {\n\t\t\tif (!node)\n\t\t\t\treturn;\n\t\t\tfor (var key in node) {\n\t\t\t\tif (key === 'range' || key === 'loc')\n\t\t\t\t\tcontinue;\n\t\t\t\tvar value = node[key];\n\t\t\t\tif (Array.isArray(value)) {\n\t\t\t\t\tfor (var i = 0, l = value.length; i < l; i++)\n\t\t\t\t\t\twalkAST(value[i], node);\n\t\t\t\t} else if (value && typeof value === 'object') {\n\t\t\t\t\twalkAST(value, node);\n\t\t\t\t}\n\t\t\t}\n\t\t\tswitch (node.type) {\n\t\t\tcase 'UnaryExpression':\n\t\t\t\tif (node.operator in unaryOperators\n\t\t\t\t\t\t&& node.argument.type !== 'Literal') {\n\t\t\t\t\tvar arg = getCode(node.argument);\n\t\t\t\t\treplaceCode(node, '$__(\"' + node.operator + '\", '\n\t\t\t\t\t\t\t+ arg + ')');\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'BinaryExpression':\n\t\t\t\tif (node.operator in binaryOperators\n\t\t\t\t\t\t&& node.left.type !== 'Literal') {\n\t\t\t\t\tvar left = getCode(node.left),\n\t\t\t\t\t\tright = getCode(node.right),\n\t\t\t\t\t\tbetween = getBetween(node.left, node.right),\n\t\t\t\t\t\toperator = node.operator;\n\t\t\t\t\treplaceCode(node, '__$__(' + left + ','\n\t\t\t\t\t\t\t+ between.replace(new RegExp('\\\\' + operator),\n\t\t\t\t\t\t\t\t'\"' + operator + '\"')\n\t\t\t\t\t\t\t+ ', ' + right + ')');\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'UpdateExpression':\n\t\t\tcase 'AssignmentExpression':\n\t\t\t\tvar parentType = parent && parent.type;\n\t\t\t\tif (!(\n\t\t\t\t\t\tparentType === 'ForStatement'\n\t\t\t\t\t\t|| parentType === 'BinaryExpression'\n\t\t\t\t\t\t\t&& /^[=!<>]/.test(parent.operator)\n\t\t\t\t\t\t|| parentType === 'MemberExpression' && parent.computed\n\t\t\t\t)) {\n\t\t\t\t\tif (node.type === 'UpdateExpression') {\n\t\t\t\t\t\tvar arg = getCode(node.argument),\n\t\t\t\t\t\t\texp = '__$__(' + arg + ', \"' + node.operator[0]\n\t\t\t\t\t\t\t\t\t+ '\", 1)',\n\t\t\t\t\t\t\tstr = arg + ' = ' + exp;\n\t\t\t\t\t\tif (!node.prefix\n\t\t\t\t\t\t\t\t&& (parentType === 'AssignmentExpression'\n\t\t\t\t\t\t\t\t\t|| parentType === 'VariableDeclarator')) {\n\t\t\t\t\t\t\tif (getCode(parent.left || parent.id) === arg)\n\t\t\t\t\t\t\t\tstr = exp;\n\t\t\t\t\t\t\tstr = arg + '; ' + str;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treplaceCode(node, str);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (/^.=$/.test(node.operator)\n\t\t\t\t\t\t\t\t&& node.left.type !== 'Literal') {\n\t\t\t\t\t\t\tvar left = getCode(node.left),\n\t\t\t\t\t\t\t\tright = getCode(node.right),\n\t\t\t\t\t\t\t\texp = left + ' = __$__(' + left + ', \"'\n\t\t\t\t\t\t\t\t\t+ node.operator[0] + '\", ' + right + ')';\n\t\t\t\t\t\t\treplaceCode(node, /^\\(.*\\)$/.test(getCode(node))\n\t\t\t\t\t\t\t\t\t? '(' + exp + ')' : exp);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tfunction encodeVLQ(value) {\n\t\t\tvar res = '',\n\t\t\t\tbase64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\t\t\tvalue = (Math.abs(value) << 1) + (value < 0 ? 1 : 0);\n\t\t\twhile (value || !res) {\n\t\t\t\tvar next = value & (32 - 1);\n\t\t\t\tvalue >>= 5;\n\t\t\t\tif (value)\n\t\t\t\t\tnext |= 32;\n\t\t\t\tres += base64[next];\n\t\t\t}\n\t\t\treturn res;\n\t\t}\n\n\t\tvar url = options.url || '',\n\t\t\tagent = paper.agent,\n\t\t\tversion = agent.versionNumber,\n\t\t\toffsetCode = false,\n\t\t\tsourceMaps = options.sourceMaps,\n\t\t\tsource = options.source || code,\n\t\t\tlineBreaks = /\\r\\n|\\n|\\r/mg,\n\t\t\toffset = options.offset || 0,\n\t\t\tmap;\n\t\tif (sourceMaps && (agent.chrome && version >= 30\n\t\t\t\t|| agent.webkit && version >= 537.76\n\t\t\t\t|| agent.firefox && version >= 23\n\t\t\t\t|| agent.node)) {\n\t\t\tif (agent.node) {\n\t\t\t\toffset -= 2;\n\t\t\t} else if (window && url && !window.location.href.indexOf(url)) {\n\t\t\t\tvar html = document.getElementsByTagName('html')[0].innerHTML;\n\t\t\t\toffset = html.substr(0, html.indexOf(code) + 1).match(\n\t\t\t\t\t\tlineBreaks).length + 1;\n\t\t\t}\n\t\t\toffsetCode = offset > 0 && !(\n\t\t\t\t\tagent.chrome && version >= 36 ||\n\t\t\t\t\tagent.safari && version >= 600 ||\n\t\t\t\t\tagent.firefox && version >= 40 ||\n\t\t\t\t\tagent.node);\n\t\t\tvar mappings = ['AA' + encodeVLQ(offsetCode ? 0 : offset) + 'A'];\n\t\t\tmappings.length = (code.match(lineBreaks) || []).length + 1\n\t\t\t\t\t+ (offsetCode ? offset : 0);\n\t\t\tmap = {\n\t\t\t\tversion: 3,\n\t\t\t\tfile: url,\n\t\t\t\tnames:[],\n\t\t\t\tmappings: mappings.join(';AACA'),\n\t\t\t\tsourceRoot: '',\n\t\t\t\tsources: [url],\n\t\t\t\tsourcesContent: [source]\n\t\t\t};\n\t\t}\n\t\twalkAST(parse(code, { ranges: true, preserveParens: true }));\n\t\tif (map) {\n\t\t\tif (offsetCode) {\n\t\t\t\tcode = new Array(offset + 1).join('\\n') + code;\n\t\t\t}\n\t\t\tif (/^(inline|both)$/.test(sourceMaps)) {\n\t\t\t\tcode += \"\\n//# sourceMappingURL=data:application/json;base64,\"\n\t\t\t\t\t\t+ self.btoa(unescape(encodeURIComponent(\n\t\t\t\t\t\t\tJSON.stringify(map))));\n\t\t\t}\n\t\t\tcode += \"\\n//# sourceURL=\" + (url || 'paperscript');\n\t\t}\n\t\treturn {\n\t\t\turl: url,\n\t\t\tsource: source,\n\t\t\tcode: code,\n\t\t\tmap: map\n\t\t};\n\t}\n\n\tfunction execute(code, scope, options) {\n\t\tpaper = scope;\n\t\tvar view = scope.getView(),\n\t\t\ttool = /\\btool\\.\\w+|\\s+on(?:Key|Mouse)(?:Up|Down|Move|Drag)\\b/\n\t\t\t\t\t.test(code) && !/\\bnew\\s+Tool\\b/.test(code)\n\t\t\t\t\t\t? new Tool() : null,\n\t\t\ttoolHandlers = tool ? tool._events : [],\n\t\t\thandlers = ['onFrame', 'onResize'].concat(toolHandlers),\n\t\t\tparams = [],\n\t\t\targs = [],\n\t\t\tfunc,\n\t\t\tcompiled = typeof code === 'object' ? code : compile(code, options);\n\t\tcode = compiled.code;\n\t\tfunction expose(scope, hidden) {\n\t\t\tfor (var key in scope) {\n\t\t\t\tif ((hidden || !/^_/.test(key)) && new RegExp('([\\\\b\\\\s\\\\W]|^)'\n\t\t\t\t\t\t+ key.replace(/\\$/g, '\\\\$') + '\\\\b').test(code)) {\n\t\t\t\t\tparams.push(key);\n\t\t\t\t\targs.push(scope[key]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\texpose({ __$__: __$__, $__: $__, paper: scope, view: view, tool: tool },\n\t\t\t\ttrue);\n\t\texpose(scope);\n\t\thandlers = Base.each(handlers, function(key) {\n\t\t\tif (new RegExp('\\\\s+' + key + '\\\\b').test(code)) {\n\t\t\t\tparams.push(key);\n\t\t\t\tthis.push(key + ': ' + key);\n\t\t\t}\n\t\t}, []).join(', ');\n\t\tif (handlers)\n\t\t\tcode += '\\nreturn { ' + handlers + ' };';\n\t\tvar agent = paper.agent;\n\t\tif (document && (agent.chrome\n\t\t\t\t|| agent.firefox && agent.versionNumber < 40)) {\n\t\t\tvar script = document.createElement('script'),\n\t\t\t\thead = document.head || document.getElementsByTagName('head')[0];\n\t\t\tif (agent.firefox)\n\t\t\t\tcode = '\\n' + code;\n\t\t\tscript.appendChild(document.createTextNode(\n\t\t\t\t'paper._execute = function(' + params + ') {' + code + '\\n}'\n\t\t\t));\n\t\t\thead.appendChild(script);\n\t\t\tfunc = paper._execute;\n\t\t\tdelete paper._execute;\n\t\t\thead.removeChild(script);\n\t\t} else {\n\t\t\tfunc = Function(params, code);\n\t\t}\n\t\tvar res = func.apply(scope, args) || {};\n\t\tBase.each(toolHandlers, function(key) {\n\t\t\tvar value = res[key];\n\t\t\tif (value)\n\t\t\t\ttool[key] = value;\n\t\t});\n\t\tif (view) {\n\t\t\tif (res.onResize)\n\t\t\t\tview.setOnResize(res.onResize);\n\t\t\tview.emit('resize', {\n\t\t\t\tsize: view.size,\n\t\t\t\tdelta: new Point()\n\t\t\t});\n\t\t\tif (res.onFrame)\n\t\t\t\tview.setOnFrame(res.onFrame);\n\t\t\tview.requestUpdate();\n\t\t}\n\t\treturn compiled;\n\t}\n\n\tfunction loadScript(script) {\n\t\tif (/^text\\/(?:x-|)paperscript$/.test(script.type)\n\t\t\t\t&& PaperScope.getAttribute(script, 'ignore') !== 'true') {\n\t\t\tvar canvasId = PaperScope.getAttribute(script, 'canvas'),\n\t\t\t\tcanvas = document.getElementById(canvasId),\n\t\t\t\tsrc = script.src || script.getAttribute('data-src'),\n\t\t\t\tasync = PaperScope.hasAttribute(script, 'async'),\n\t\t\t\tscopeAttribute = 'data-paper-scope';\n\t\t\tif (!canvas)\n\t\t\t\tthrow new Error('Unable to find canvas with id \"'\n\t\t\t\t\t\t+ canvasId + '\"');\n\t\t\tvar scope = PaperScope.get(canvas.getAttribute(scopeAttribute))\n\t\t\t\t\t\t|| new PaperScope().setup(canvas);\n\t\t\tcanvas.setAttribute(scopeAttribute, scope._id);\n\t\t\tif (src) {\n\t\t\t\tHttp.request({\n\t\t\t\t\turl: src,\n\t\t\t\t\tasync: async,\n\t\t\t\t\tmimeType: 'text/plain',\n\t\t\t\t\tonLoad: function(code) {\n\t\t\t\t\t\texecute(code, scope, src);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\texecute(script.innerHTML, scope, script.baseURI);\n\t\t\t}\n\t\t\tscript.setAttribute('data-paper-ignore', 'true');\n\t\t\treturn scope;\n\t\t}\n\t}\n\n\tfunction loadAll() {\n\t\tBase.each(document && document.getElementsByTagName('script'),\n\t\t\t\tloadScript);\n\t}\n\n\tfunction load(script) {\n\t\treturn script ? loadScript(script) : loadAll();\n\t}\n\n\tif (window) {\n\t\tif (document.readyState === 'complete') {\n\t\t\tsetTimeout(loadAll);\n\t\t} else {\n\t\t\tDomEvent.add(window, { load: loadAll });\n\t\t}\n\t}\n\n\treturn {\n\t\tcompile: compile,\n\t\texecute: execute,\n\t\tload: load,\n\t\tparse: parse\n\t};\n\n}.call(this);\n\npaper = new (PaperScope.inject(Base.exports, {\n\tBase: Base,\n\tNumerical: Numerical,\n\tKey: Key,\n\tDomEvent: DomEvent,\n\tDomElement: DomElement,\n\tdocument: document,\n\twindow: window,\n\tSymbol: SymbolDefinition,\n\tPlacedSymbol: SymbolItem\n}))();\n\nif (paper.agent.node) {\n\trequire('./node/extend.js')(paper);\n}\n\nif (typeof define === 'function' && define.amd) {\n\tdefine('paper', paper);\n} else if (typeof module === 'object' && module) {\n\tmodule.exports = paper;\n}\n\nreturn paper;\n}.call(this, typeof self === 'object' ? self : null);\n"
  },
  {
    "path": "lib/paperholefinder.js",
    "content": "// tiny utility function for finding holes in a paper.js project\n// made by zripo for the wick drawing tools\n\nvar PaperHoleFinder = (function () {\n\n    // Return the shape of the smallest hole in 'paperProject' \n    // that would be created by clicking the mouse at 'point'.\n    function getHoleShapeAtPosition (paperProject, point) {\n        var path = getProjectAsSinglePath(paperProject);\n        var holeShapes = getHolesOfPathAsShapes(path);\n        var filledHoleShape = getSmallestShapeContainingPoint(path, holeShapes, point);\n\n        return filledHoleShape;\n    }\n\n    // Unites all paths in paperProject into one super path\n    function getProjectAsSinglePath (paperProject) {\n        var allPathsInProject = paperProject.getActiveLayer().children;\n\n        // This fixes the bug where fill bucket would fill holes created by objects on different layers\n        var projectCurrentLayer = wickEditor.project.getCurrentLayer();\n        allPathsInProject = allPathsInProject.filter(function (path) {\n            return path.wick.parentFrame.parentLayer === projectCurrentLayer;\n        })\n\n        var superPath = allPathsInProject[0].children[0].clone({insert:false});\n\n        // Unite all paths together into a superpath.\n        for(var i = 1; i < allPathsInProject.length; i++) {\n            var path = allPathsInProject[i];\n            if(superPath.closePath) superPath.closePath();\n            path.children.forEach(function (child) {\n                if(child.closePath) child.closePath();\n            });\n            superPath = superPath.unite(path);\n        }\n\n        return superPath;\n    }\n\n    // Returns shapes of all holes of a given path\n    function getHolesOfPathAsShapes (path) {\n        var holeShapes = [];\n\n        // Get an inverted version of the path by subtracting it from a giant rectangle.\n        var hugeRectangle = new paper.Path.Rectangle(new paper.Point(-1000,-1000), new paper.Size(2000,2000));\n        var negativeSpace = hugeRectangle.subtract(path);\n        hugeRectangle.remove();\n        negativeSpace.remove();\n\n        // Convert holes into paths representing the shapes of the holes.\n        negativeSpace.children.forEach(function (child) {\n            if(child.clockwise && child.area !== 4000000) {\n                var clone = child.clone({insert:false});\n                var group = new paper.Group({insert:false});\n                group.addChild(clone);\n                clone.clockwise = false;\n                clone.fillColor = 'green';\n                group.fillRule = 'evenodd';\n                //paper.project.getActiveLayer().addChild(clone);\n                holeShapes.push(clone);\n            }\n        });\n\n        return holeShapes;\n    }\n\n    // Returns smallest shape from 'shapes' that contains 'point'\n    // Needs the original path shape and the shapes of its holes.\n    // Returns null if no holes contain the point.\n    function getSmallestShapeContainingPoint (originalPathShape, holeShapes, point) {\n        var shapesContainingPoint = getShapesContainingPoint(holeShapes, point);\n        if(shapesContainingPoint.length === 0) {\n            // No shapes contained the point.\n            return null;\n        } else {\n            // >=1 shapes contain the point - process the smallest one and return it.\n            var smallestShape = shapesContainingPoint[0];\n            return removeSubholesFromHoleShape(smallestShape, originalPathShape, holeShapes);\n        }\n    }\n\n    // Returns shapes from 'shapes' that contain 'point' in order from smallest to largest\n    function getShapesContainingPoint (shapes, point) {\n        var shapesContainingPoint = [];\n\n        shapes.forEach(function (shape) {\n            if(shape.contains(point)) {\n                shapesContainingPoint.push(shape);\n            }\n        });\n\n        shapesContainingPoint.sort(function (a,b) {\n            return b.area-a.area;\n        });\n\n        return shapesContainingPoint;\n    }\n\n    function removeSubholesFromHoleShape (holeShape, originalPathShape, holeShapes) {\n        //console.log('removeSubholesFromHoleShape')\n\n        var holeShapeSubholesRemoved = holeShape;\n        holeShapes.forEach(function (holeShapeToSubtract) {\n            if(holeShapeToSubtract.area === holeShapeSubholesRemoved.area) return;\n            if(holeShapeToSubtract.area < holeShapeSubholesRemoved.area) return;\n            holeShapeSubholesRemoved = holeShapeSubholesRemoved.subtract(holeShapeToSubtract);\n        });\n\n        var holeShapeOriginalPathRemoved = holeShapeSubholesRemoved.subtract(originalPathShape);\n        \n        return holeShapeOriginalPathRemoved;\n    }\n\n    function expandHole (path) {\n        var HOLE_EXPAND_AMT = -0.4;\n\n        var children;\n        if(path instanceof paper.Path) {\n            children = [path];\n        } else if(path instanceof paper.CompoundPath) {\n            children = path.children;\n        }\n\n        children.forEach(function (hole) {\n            var normals = [];\n            hole.closePath();\n            hole.segments.forEach(function (segment) {\n                var a = segment.previous.point;\n                var b = segment.point;\n                var c = segment.next.point;\n\n                var ab = {x: b.x-a.x, y: b.y-a.y};\n                var cb = {x: b.x-c.x, y: b.y-c.y};\n\n                var d = {x: ab.x-cb.x, y: ab.y-cb.y};\n                d.h = Math.sqrt((d.x*d.x)+(d.y*d.y));\n                d.x /= d.h;\n                d.y /= d.h;\n\n                d = rotate_point(d.x, d.y, 0, 0, 90);\n\n                normals.push({x:d.x,y:d.y});\n            });\n\n            for (var i = 0; i < hole.segments.length; i++) {\n                var segment = hole.segments[i];\n                var normal = normals[i];\n                segment.point.x += normal.x*-HOLE_EXPAND_AMT;\n                segment.point.y += normal.y*-HOLE_EXPAND_AMT;\n            }\n        });\n    }\n\n    // http://www.felixeve.co.uk/how-to-rotate-a-point-around-an-origin-with-javascript/\n    function rotate_point(pointX, pointY, originX, originY, angle) {\n        angle = angle * Math.PI / 180.0;\n        return {\n            x: Math.cos(angle) * (pointX-originX) - Math.sin(angle) * (pointY-originY) + originX,\n            y: Math.sin(angle) * (pointX-originX) + Math.cos(angle) * (pointY-originY) + originY\n        };\n    }\n\n    // Export main function\n    var paperHoleFinder = {};\n    paperHoleFinder.getHoleShapeAtPosition = getHoleShapeAtPosition;\n    paperHoleFinder.expandHole = expandHole;\n    return paperHoleFinder;\n})();\n"
  },
  {
    "path": "lib/pixi-layers.js",
    "content": "var pixi_display;\n(function (pixi_display) {\n    var Container = PIXI.Container;\n    Object.assign(Container.prototype, {\n        renderWebGL: function (renderer) {\n            if (this._activeParentLayer && this._activeParentLayer != renderer._activeLayer) {\n                return;\n            }\n            if (!this.visible) {\n                this.displayOrder = 0;\n                return;\n            }\n            this.displayOrder = renderer.incDisplayOrder();\n            if (this.worldAlpha <= 0 || !this.renderable) {\n                return;\n            }\n            this.containerRenderWebGL(renderer);\n        },\n        renderCanvas: function (renderer) {\n            if (this._activeParentLayer && this._activeParentLayer != renderer._activeLayer) {\n                return;\n            }\n            if (!this.visible) {\n                this.displayOrder = 0;\n                return;\n            }\n            this.displayOrder = renderer.incDisplayOrder();\n            if (this.worldAlpha <= 0 || !this.renderable) {\n                return;\n            }\n            this.containerRenderCanvas(renderer);\n        },\n        containerRenderWebGL: PIXI.Container.prototype.renderWebGL,\n        containerRenderCanvas: PIXI.Container.prototype.renderCanvas\n    });\n})(pixi_display || (pixi_display = {}));\nObject.assign(PIXI.DisplayObject.prototype, {\n    parentLayer: null,\n    _activeParentLayer: null,\n    parentGroup: null,\n    zOrder: 0,\n    zIndex: 0,\n    updateOrder: 0,\n    displayOrder: 0,\n    layerableChildren: true\n});\nif (PIXI.particles && PIXI.particles.ParticleContainer) {\n    PIXI.particles.ParticleContainer.prototype.layerableChildren = false;\n}\nelse if (PIXI.ParticleContainer) {\n    PIXI.ParticleContainer.prototype.layerableChildren = false;\n}\nvar __extends = (this && this.__extends) || (function () {\n    var extendStatics = Object.setPrototypeOf ||\n        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n    return function (d, b) {\n        extendStatics(d, b);\n        function __() { this.constructor = d; }\n        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n    };\n})();\nvar pixi_display;\n(function (pixi_display) {\n    var utils = PIXI.utils;\n    var Group = (function (_super) {\n        __extends(Group, _super);\n        function Group(zIndex, sorting) {\n            var _this = _super.call(this) || this;\n            _this._activeLayer = null;\n            _this._activeStage = null;\n            _this._activeChildren = [];\n            _this._lastUpdateId = -1;\n            _this.canDrawWithoutLayer = false;\n            _this.canDrawInParentStage = true;\n            _this.zIndex = 0;\n            _this.enableSort = false;\n            _this._tempResult = [];\n            _this._tempZero = [];\n            _this.useZeroOptimization = false;\n            _this.zIndex = zIndex;\n            _this.enableSort = !!sorting;\n            if (typeof sorting === 'function') {\n                _this.on('sort', sorting);\n            }\n            return _this;\n        }\n        Group.prototype.doSort = function (layer, sorted) {\n            if (this.listeners('sort', true)) {\n                for (var i = 0; i < sorted.length; i++) {\n                    this.emit('sort', sorted[i]);\n                }\n            }\n            if (this.useZeroOptimization) {\n                this.doSortWithZeroOptimization(layer, sorted);\n            }\n            else {\n                sorted.sort(Group.compareZIndex);\n            }\n        };\n        Group.compareZIndex = function (a, b) {\n            if (a.zIndex !== b.zIndex) {\n                return a.zIndex - b.zIndex;\n            }\n            if (a.zOrder > b.zOrder) {\n                return -1;\n            }\n            if (a.zOrder < b.zOrder) {\n                return 1;\n            }\n            return a.updateOrder - b.updateOrder;\n        };\n        Group.prototype.doSortWithZeroOptimization = function (layer, sorted) {\n            throw new Error(\"not implemented yet\");\n        };\n        Group.prototype.clear = function () {\n            this._activeLayer = null;\n            this._activeStage = null;\n            this._activeChildren.length = 0;\n        };\n        Group.prototype.addDisplayObject = function (stage, displayObject) {\n            this.check(stage);\n            displayObject._activeParentLayer = this._activeLayer;\n            if (this._activeLayer) {\n                this._activeLayer._activeChildren.push(displayObject);\n            }\n            else {\n                this._activeChildren.push(displayObject);\n            }\n        };\n        Group.prototype.foundLayer = function (stage, layer) {\n            this.check(stage);\n            if (this._activeLayer != null) {\n                Group.conflict();\n            }\n            this._activeLayer = layer;\n            this._activeStage = stage;\n        };\n        Group.prototype.foundStage = function (stage) {\n            if (!this._activeLayer && !this.canDrawInParentStage) {\n                this.clear();\n            }\n        };\n        Group.prototype.check = function (stage) {\n            if (this._lastUpdateId < Group._layerUpdateId) {\n                this._lastUpdateId = Group._layerUpdateId;\n                this.clear();\n                this._activeStage = stage;\n            }\n            else if (this.canDrawInParentStage) {\n                var current = this._activeStage;\n                while (current && current != stage) {\n                    current = current._activeParentStage;\n                }\n                this._activeStage = current;\n                if (current == null) {\n                    this.clear();\n                    return;\n                }\n            }\n        };\n        Group.conflict = function () {\n            if (Group._lastLayerConflict + 5000 < Date.now()) {\n                Group._lastLayerConflict = Date.now();\n                console.log(\"PIXI-display plugin found two layers with the same group in one stage - that's not healthy. Please place a breakpoint here and debug it\");\n            }\n        };\n        return Group;\n    }(utils.EventEmitter));\n    Group._layerUpdateId = 0;\n    Group._lastLayerConflict = 0;\n    pixi_display.Group = Group;\n})(pixi_display || (pixi_display = {}));\nvar pixi_display;\n(function (pixi_display) {\n    var InteractionManager = PIXI.interaction.InteractionManager;\n    Object.assign(InteractionManager.prototype, {\n        _queue: [[], []],\n        _displayProcessInteractive: function (point, displayObject, hitTestOrder, interactive, outOfMask) {\n            if (!displayObject || !displayObject.visible) {\n                return 0;\n            }\n            var hit = 0, interactiveParent = interactive = displayObject.interactive || interactive;\n            if (displayObject.hitArea) {\n                interactiveParent = false;\n            }\n            if (displayObject._activeParentLayer) {\n                outOfMask = false;\n            }\n            var mask = displayObject._mask;\n            if (hitTestOrder < Infinity && mask) {\n                if (!mask.containsPoint(point)) {\n                    outOfMask = true;\n                }\n            }\n            if (hitTestOrder < Infinity && displayObject.filterArea) {\n                if (!displayObject.filterArea.contains(point.x, point.y)) {\n                    outOfMask = true;\n                }\n            }\n            var children = displayObject.children;\n            if (displayObject.interactiveChildren && children) {\n                for (var i = children.length - 1; i >= 0; i--) {\n                    var child = children[i];\n                    var hitChild = this._displayProcessInteractive(point, child, hitTestOrder, interactiveParent, outOfMask);\n                    if (hitChild) {\n                        if (!child.parent) {\n                            continue;\n                        }\n                        hit = hitChild;\n                        hitTestOrder = hitChild;\n                    }\n                }\n            }\n            if (interactive) {\n                if (!outOfMask) {\n                    if (hitTestOrder < displayObject.displayOrder) {\n                        if (displayObject.hitArea) {\n                            displayObject.worldTransform.applyInverse(point, this._tempPoint);\n                            if (displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) {\n                                hit = displayObject.displayOrder;\n                            }\n                        }\n                        else if (displayObject.containsPoint) {\n                            if (displayObject.containsPoint(point)) {\n                                hit = displayObject.displayOrder;\n                            }\n                        }\n                    }\n                    if (displayObject.interactive) {\n                        this._queueAdd(displayObject, hit === Infinity ? 0 : hit);\n                    }\n                }\n                else {\n                    if (displayObject.interactive) {\n                        this._queueAdd(displayObject, 0);\n                    }\n                }\n            }\n            return hit;\n        },\n        processInteractive: function (strangeStuff, displayObject, func, hitTest, interactive) {\n            var interactionEvent = null;\n            var point = null;\n            if (strangeStuff.data &&\n                strangeStuff.data.global) {\n                interactionEvent = strangeStuff;\n                point = interactionEvent.data.global;\n            }\n            else {\n                point = strangeStuff;\n            }\n            this._startInteractionProcess();\n            this._displayProcessInteractive(point, displayObject, hitTest ? 0 : Infinity, false);\n            this._finishInteractionProcess(interactionEvent, func);\n        },\n        _startInteractionProcess: function () {\n            this._eventDisplayOrder = 1;\n            if (!this._queue) {\n                this._queue = [[], []];\n            }\n            this._queue[0].length = 0;\n            this._queue[1].length = 0;\n        },\n        _queueAdd: function (displayObject, order) {\n            var queue = this._queue;\n            if (order < this._eventDisplayOrder) {\n                queue[0].push(displayObject);\n            }\n            else {\n                if (order > this._eventDisplayOrder) {\n                    this._eventDisplayOrder = order;\n                    var q = queue[1];\n                    for (var i = 0; i < q.length; i++) {\n                        queue[0].push(q[i]);\n                    }\n                    queue[1].length = 0;\n                }\n                queue[1].push(displayObject);\n            }\n        },\n        _finishInteractionProcess: function (event, func) {\n            var queue = this._queue;\n            var q = queue[0];\n            var i = 0;\n            for (; i < q.length; i++) {\n                if (event) {\n                    if (func) {\n                        func(event, q[i], false);\n                    }\n                }\n                else {\n                    func(q[i], false);\n                }\n            }\n            q = queue[1];\n            for (i = 0; i < q.length; i++) {\n                if (event) {\n                    if (!event.target) {\n                        event.target = q[i];\n                    }\n                    if (func) {\n                        func(event, q[i], true);\n                    }\n                }\n                else {\n                    func(q[i], true);\n                }\n            }\n        }\n    });\n})(pixi_display || (pixi_display = {}));\nvar pixi_display;\n(function (pixi_display) {\n    var Container = PIXI.Container;\n    var Layer = (function (_super) {\n        __extends(Layer, _super);\n        function Layer(group) {\n            if (group === void 0) { group = null; }\n            var _this = _super.call(this) || this;\n            _this.isLayer = true;\n            _this.group = null;\n            _this._activeChildren = [];\n            _this._tempChildren = null;\n            _this._activeStageParent = null;\n            _this._sortedChildren = [];\n            _this._tempLayerParent = null;\n            _this.insertChildrenBeforeActive = true;\n            _this.insertChildrenAfterActive = true;\n            if (group != null) {\n                _this.group = group;\n                _this.zIndex = group.zIndex;\n            }\n            else {\n                _this.group = new pixi_display.Group(0, false);\n            }\n            _this._tempChildren = _this.children;\n            return _this;\n        }\n        Layer.prototype.beginWork = function (stage) {\n            var active = this._activeChildren;\n            this._activeStageParent = stage;\n            this.group.foundLayer(stage, this);\n            var groupChildren = this.group._activeChildren;\n            active.length = 0;\n            for (var i = 0; i < groupChildren.length; i++) {\n                groupChildren[i]._activeParentLayer = this;\n                active.push(groupChildren[i]);\n            }\n            groupChildren.length = 0;\n        };\n        Layer.prototype.endWork = function () {\n            var children = this.children;\n            var active = this._activeChildren;\n            var sorted = this._sortedChildren;\n            for (var i = 0; i < active.length; i++) {\n                this.emit(\"display\", active[i]);\n            }\n            sorted.length = 0;\n            if (this.insertChildrenBeforeActive) {\n                for (var i = 0; i < children.length; i++) {\n                    sorted.push(children[i]);\n                }\n            }\n            for (var i = 0; i < active.length; i++) {\n                sorted.push(active[i]);\n            }\n            if (!this.insertChildrenBeforeActive &&\n                this.insertChildrenAfterActive) {\n                for (var i = 0; i < children.length; i++) {\n                    sorted.push(children[i]);\n                }\n            }\n            if (this.group.enableSort) {\n                this.doSort();\n            }\n        };\n        Layer.prototype.updateDisplayLayers = function () {\n        };\n        Layer.prototype.doSort = function () {\n            this.group.doSort(this, this._sortedChildren);\n        };\n        Layer.prototype._preRender = function (renderer) {\n            if (this._activeParentLayer && this._activeParentLayer != renderer._activeLayer) {\n                return false;\n            }\n            if (!this.visible) {\n                this.displayOrder = 0;\n                return false;\n            }\n            this.displayOrder = renderer.incDisplayOrder();\n            if (this.worldAlpha <= 0 || !this.renderable) {\n                return false;\n            }\n            if (this.children !== this._sortedChildren &&\n                this._tempChildren != this.children) {\n                this._tempChildren = this.children;\n            }\n            this._boundsID++;\n            this.children = this._sortedChildren;\n            this._tempLayerParent = renderer._activeLayer;\n            renderer._activeLayer = this;\n            return true;\n        };\n        Layer.prototype._postRender = function (renderer) {\n            this.children = this._tempChildren;\n            renderer._activeLayer = this._tempLayerParent;\n            this._tempLayerParent = null;\n        };\n        Layer.prototype.renderWebGL = function (renderer) {\n            if (this._preRender(renderer)) {\n                this.containerRenderWebGL(renderer);\n                this._postRender(renderer);\n            }\n        };\n        Layer.prototype.renderCanvas = function (renderer) {\n            if (this._preRender(renderer)) {\n                this.containerRenderCanvas(renderer);\n                this._postRender(renderer);\n            }\n        };\n        return Layer;\n    }(Container));\n    pixi_display.Layer = Layer;\n})(pixi_display || (pixi_display = {}));\nvar pixi_display;\n(function (pixi_display) {\n    var WebGLRenderer = PIXI.WebGLRenderer;\n    var CanvasRenderer = PIXI.CanvasRenderer;\n    Object.assign(WebGLRenderer.prototype, {\n        _lastDisplayOrder: 0,\n        _activeLayer: null,\n        incDisplayOrder: function () {\n            return ++this._lastDisplayOrder;\n        },\n        _oldRender: WebGLRenderer.prototype.render,\n        render: function (displayObject, renderTexture, clear, transform, skipUpdateTransform) {\n            if (!renderTexture) {\n                this._lastDisplayOrder = 0;\n            }\n            this._activeLayer = null;\n            if (displayObject.isStage) {\n                displayObject.updateStage();\n            }\n            this._oldRender(displayObject, renderTexture, clear, transform, skipUpdateTransform);\n        }\n    });\n    Object.assign(CanvasRenderer.prototype, {\n        _lastDisplayOrder: 0,\n        _activeLayer: null,\n        incDisplayOrder: function () {\n            return ++this._lastDisplayOrder;\n        },\n        _oldRender: CanvasRenderer.prototype.render,\n        render: function (displayObject, renderTexture, clear, transform, skipUpdateTransform) {\n            if (!renderTexture) {\n                this._lastDisplayOrder = 0;\n            }\n            this._activeLayer = null;\n            if (displayObject.isStage) {\n                displayObject.updateStage();\n            }\n            this._oldRender(displayObject, renderTexture, clear, transform, skipUpdateTransform);\n        }\n    });\n})(pixi_display || (pixi_display = {}));\nvar pixi_display;\n(function (pixi_display) {\n    var Stage = (function (_super) {\n        __extends(Stage, _super);\n        function Stage() {\n            var _this = _super.call(this) || this;\n            _this.isStage = true;\n            _this._tempGroups = [];\n            _this._activeLayers = [];\n            _this._activeParentStage = null;\n            return _this;\n        }\n        Stage.prototype.clear = function () {\n            this._activeLayers.length = 0;\n            this._tempGroups.length = 0;\n        };\n        Stage.prototype.destroy = function (options) {\n            this.clear();\n            _super.prototype.destroy.call(this, options);\n        };\n        Stage.prototype._addRecursive = function (displayObject) {\n            if (!displayObject.visible) {\n                return;\n            }\n            if (displayObject.isLayer) {\n                var layer_1 = displayObject;\n                this._activeLayers.push(layer_1);\n                layer_1.beginWork(this);\n            }\n            if (displayObject != this && displayObject.isStage) {\n                var stage = displayObject;\n                stage.updateAsChildStage(this);\n                return;\n            }\n            var group = displayObject.parentGroup;\n            if (group != null) {\n                displayObject.parentGroup.addDisplayObject(this, displayObject);\n            }\n            var layer = displayObject.parentLayer;\n            if (layer != null) {\n                layer.group.addDisplayObject(this, displayObject);\n            }\n            displayObject.updateOrder = ++Stage._updateOrderCounter;\n            if (displayObject.alpha <= 0 || !displayObject.renderable || !displayObject.layerableChildren) {\n                return;\n            }\n            var children = displayObject.children;\n            if (children && children.length) {\n                for (var i = 0; i < children.length; i++) {\n                    this._addRecursive(children[i]);\n                }\n            }\n        };\n        Stage.prototype._updateStageInner = function () {\n            this.clear();\n            this._addRecursive(this);\n            var layers = this._activeLayers;\n            for (var i = 0; i < layers.length; i++) {\n                layers[i].endWork();\n            }\n        };\n        Stage.prototype.updateAsChildStage = function (stage) {\n            this._activeParentStage = stage;\n            Stage._updateOrderCounter = 0;\n            this._updateStageInner();\n        };\n        Stage.prototype.updateStage = function () {\n            this._activeParentStage = null;\n            pixi_display.Group._layerUpdateId++;\n            this._updateStageInner();\n        };\n        ;\n        return Stage;\n    }(pixi_display.Layer));\n    Stage._updateOrderCounter = 0;\n    pixi_display.Stage = Stage;\n})(pixi_display || (pixi_display = {}));\nObject.assign(PIXI, {\n    display: pixi_display\n});\n//# sourceMappingURL=pixi-layers.js.map"
  },
  {
    "path": "lib/pixi.min.4.6.1.js",
    "content": "/*!\n * pixi.js - v4.6.1\n * Compiled Thu, 16 Nov 2017 18:57:43 UTC\n *\n * pixi.js is licensed under the MIT License.\n * http://www.opensource.org/licenses/mit-license\n */\n!function(t){if(\"object\"==typeof exports&&\"undefined\"!=typeof module)module.exports=t();else if(\"function\"==typeof define&&define.amd)define([],t);else{var e;e=\"undefined\"!=typeof window?window:\"undefined\"!=typeof global?global:\"undefined\"!=typeof self?self:this,e.PIXI=t()}}(function(){var t;return function t(e,r,n){function i(s,a){if(!r[s]){if(!e[s]){var u=\"function\"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error(\"Cannot find module '\"+s+\"'\");throw h.code=\"MODULE_NOT_FOUND\",h}var l=r[s]={exports:{}};e[s][0].call(l.exports,function(t){var r=e[s][1][t];return i(r||t)},l,l.exports,t,e,r,n)}return r[s].exports}for(var o=\"function\"==typeof require&&require,s=0;s<n.length;s++)i(n[s]);return i}({1:[function(t,e,r){\"use strict\";\"use restrict\";function n(t){var e=32;return t&=-t,t&&e--,65535&t&&(e-=16),16711935&t&&(e-=8),252645135&t&&(e-=4),858993459&t&&(e-=2),1431655765&t&&(e-=1),e}r.INT_BITS=32,r.INT_MAX=2147483647,r.INT_MIN=-1<<31,r.sign=function(t){return(t>0)-(t<0)},r.abs=function(t){var e=t>>31;return(t^e)-e},r.min=function(t,e){return e^(t^e)&-(t<e)},r.max=function(t,e){return t^(t^e)&-(t<e)},r.isPow2=function(t){return!(t&t-1||!t)},r.log2=function(t){var e,r;return e=(t>65535)<<4,t>>>=e,r=(t>255)<<3,t>>>=r,e|=r,r=(t>15)<<2,t>>>=r,e|=r,r=(t>3)<<1,t>>>=r,(e|=r)|t>>1},r.log10=function(t){return t>=1e9?9:t>=1e8?8:t>=1e7?7:t>=1e6?6:t>=1e5?5:t>=1e4?4:t>=1e3?3:t>=100?2:t>=10?1:0},r.popCount=function(t){return t-=t>>>1&1431655765,16843009*((t=(858993459&t)+(t>>>2&858993459))+(t>>>4)&252645135)>>>24},r.countTrailingZeros=n,r.nextPow2=function(t){return t+=0===t,--t,t|=t>>>1,t|=t>>>2,t|=t>>>4,t|=t>>>8,(t|=t>>>16)+1},r.prevPow2=function(t){return t|=t>>>1,t|=t>>>2,t|=t>>>4,t|=t>>>8,(t|=t>>>16)-(t>>>1)},r.parity=function(t){return t^=t>>>16,t^=t>>>8,t^=t>>>4,27030>>>(t&=15)&1};var i=new Array(256);!function(t){for(var e=0;e<256;++e){var r=e,n=e,i=7;for(r>>>=1;r;r>>>=1)n<<=1,n|=1&r,--i;t[e]=n<<i&255}}(i),r.reverse=function(t){return i[255&t]<<24|i[t>>>8&255]<<16|i[t>>>16&255]<<8|i[t>>>24&255]},r.interleave2=function(t,e){return t&=65535,t=16711935&(t|t<<8),t=252645135&(t|t<<4),t=858993459&(t|t<<2),t=1431655765&(t|t<<1),e&=65535,e=16711935&(e|e<<8),e=252645135&(e|e<<4),e=858993459&(e|e<<2),e=1431655765&(e|e<<1),t|e<<1},r.deinterleave2=function(t,e){return t=t>>>e&1431655765,t=858993459&(t|t>>>1),t=252645135&(t|t>>>2),t=16711935&(t|t>>>4),(t=65535&(t|t>>>16))<<16>>16},r.interleave3=function(t,e,r){return t&=1023,t=4278190335&(t|t<<16),t=251719695&(t|t<<8),t=3272356035&(t|t<<4),t=1227133513&(t|t<<2),e&=1023,e=4278190335&(e|e<<16),e=251719695&(e|e<<8),e=3272356035&(e|e<<4),e=1227133513&(e|e<<2),t|=e<<1,r&=1023,r=4278190335&(r|r<<16),r=251719695&(r|r<<8),r=3272356035&(r|r<<4),r=1227133513&(r|r<<2),t|r<<2},r.deinterleave3=function(t,e){return t=t>>>e&1227133513,t=3272356035&(t|t>>>2),t=251719695&(t|t>>>4),t=4278190335&(t|t>>>8),(t=1023&(t|t>>>16))<<22>>22},r.nextCombination=function(t){var e=t|t-1;return e+1|(~e&-~e)-1>>>n(t)+1}},{}],2:[function(t,e,r){\"use strict\";function n(t,e,r){r=r||2;var n=e&&e.length,o=n?e[0]*r:t.length,a=i(t,0,o,r,!0),u=[];if(!a)return u;var h,l,d,f,p,v,y;if(n&&(a=c(t,e,a,r)),t.length>80*r){h=d=t[0],l=f=t[1];for(var g=r;g<o;g+=r)p=t[g],v=t[g+1],p<h&&(h=p),v<l&&(l=v),p>d&&(d=p),v>f&&(f=v);y=Math.max(d-h,f-l),y=0!==y?1/y:0}return s(a,u,r,h,l,y),u}function i(t,e,r,n,i){var o,s;if(i===A(t,e,r,n)>0)for(o=e;o<r;o+=n)s=P(o,t[o],t[o+1],s);else for(o=r-n;o>=e;o-=n)s=P(o,t[o],t[o+1],s);return s&&T(s,s.next)&&(C(s),s=s.next),s}function o(t,e){if(!t)return t;e||(e=t);var r,n=t;do{if(r=!1,n.steiner||!T(n,n.next)&&0!==x(n.prev,n,n.next))n=n.next;else{if(C(n),(n=e=n.prev)===n.next)break;r=!0}}while(r||n!==e);return e}function s(t,e,r,n,i,c,d){if(t){!d&&c&&v(t,n,i,c);for(var f,p,y=t;t.prev!==t.next;)if(f=t.prev,p=t.next,c?u(t,n,i,c):a(t))e.push(f.i/r),e.push(t.i/r),e.push(p.i/r),C(t),t=p.next,y=p.next;else if((t=p)===y){d?1===d?(t=h(t,e,r),s(t,e,r,n,i,c,2)):2===d&&l(t,e,r,n,i,c):s(o(t),e,r,n,i,c,1);break}}}function a(t){var e=t.prev,r=t,n=t.next;if(x(e,r,n)>=0)return!1;for(var i=t.next.next;i!==t.prev;){if(_(e.x,e.y,r.x,r.y,n.x,n.y,i.x,i.y)&&x(i.prev,i,i.next)>=0)return!1;i=i.next}return!0}function u(t,e,r,n){var i=t.prev,o=t,s=t.next;if(x(i,o,s)>=0)return!1;for(var a=i.x<o.x?i.x<s.x?i.x:s.x:o.x<s.x?o.x:s.x,u=i.y<o.y?i.y<s.y?i.y:s.y:o.y<s.y?o.y:s.y,h=i.x>o.x?i.x>s.x?i.x:s.x:o.x>s.x?o.x:s.x,l=i.y>o.y?i.y>s.y?i.y:s.y:o.y>s.y?o.y:s.y,c=g(a,u,e,r,n),d=g(h,l,e,r,n),f=t.nextZ;f&&f.z<=d;){if(f!==t.prev&&f!==t.next&&_(i.x,i.y,o.x,o.y,s.x,s.y,f.x,f.y)&&x(f.prev,f,f.next)>=0)return!1;f=f.nextZ}for(f=t.prevZ;f&&f.z>=c;){if(f!==t.prev&&f!==t.next&&_(i.x,i.y,o.x,o.y,s.x,s.y,f.x,f.y)&&x(f.prev,f,f.next)>=0)return!1;f=f.prevZ}return!0}function h(t,e,r){var n=t;do{var i=n.prev,o=n.next.next;!T(i,o)&&w(i,n,n.next,o)&&S(i,o)&&S(o,i)&&(e.push(i.i/r),e.push(n.i/r),e.push(o.i/r),C(n),C(n.next),n=t=o),n=n.next}while(n!==t);return n}function l(t,e,r,n,i,a){var u=t;do{for(var h=u.next.next;h!==u.prev;){if(u.i!==h.i&&b(u,h)){var l=M(u,h);return u=o(u,u.next),l=o(l,l.next),s(u,e,r,n,i,a),void s(l,e,r,n,i,a)}h=h.next}u=u.next}while(u!==t)}function c(t,e,r,n){var s,a,u,h,l,c=[];for(s=0,a=e.length;s<a;s++)u=e[s]*n,h=s<a-1?e[s+1]*n:t.length,l=i(t,u,h,n,!1),l===l.next&&(l.steiner=!0),c.push(m(l));for(c.sort(d),s=0;s<c.length;s++)f(c[s],r),r=o(r,r.next);return r}function d(t,e){return t.x-e.x}function f(t,e){if(e=p(t,e)){var r=M(e,t);o(r,r.next)}}function p(t,e){var r,n=e,i=t.x,o=t.y,s=-1/0;do{if(o<=n.y&&o>=n.next.y&&n.next.y!==n.y){var a=n.x+(o-n.y)*(n.next.x-n.x)/(n.next.y-n.y);if(a<=i&&a>s){if(s=a,a===i){if(o===n.y)return n;if(o===n.next.y)return n.next}r=n.x<n.next.x?n:n.next}}n=n.next}while(n!==e);if(!r)return null;if(i===s)return r.prev;var u,h=r,l=r.x,c=r.y,d=1/0;for(n=r.next;n!==h;)i>=n.x&&n.x>=l&&i!==n.x&&_(o<c?i:s,o,l,c,o<c?s:i,o,n.x,n.y)&&((u=Math.abs(o-n.y)/(i-n.x))<d||u===d&&n.x>r.x)&&S(n,t)&&(r=n,d=u),n=n.next;return r}function v(t,e,r,n){var i=t;do{null===i.z&&(i.z=g(i.x,i.y,e,r,n)),i.prevZ=i.prev,i.nextZ=i.next,i=i.next}while(i!==t);i.prevZ.nextZ=null,i.prevZ=null,y(i)}function y(t){var e,r,n,i,o,s,a,u,h=1;do{for(r=t,t=null,o=null,s=0;r;){for(s++,n=r,a=0,e=0;e<h&&(a++,n=n.nextZ);e++);for(u=h;a>0||u>0&&n;)0!==a&&(0===u||!n||r.z<=n.z)?(i=r,r=r.nextZ,a--):(i=n,n=n.nextZ,u--),o?o.nextZ=i:t=i,i.prevZ=o,o=i;r=n}o.nextZ=null,h*=2}while(s>1);return t}function g(t,e,r,n,i){return t=32767*(t-r)*i,e=32767*(e-n)*i,t=16711935&(t|t<<8),t=252645135&(t|t<<4),t=858993459&(t|t<<2),t=1431655765&(t|t<<1),e=16711935&(e|e<<8),e=252645135&(e|e<<4),e=858993459&(e|e<<2),e=1431655765&(e|e<<1),t|e<<1}function m(t){var e=t,r=t;do{e.x<r.x&&(r=e),e=e.next}while(e!==t);return r}function _(t,e,r,n,i,o,s,a){return(i-s)*(e-a)-(t-s)*(o-a)>=0&&(t-s)*(n-a)-(r-s)*(e-a)>=0&&(r-s)*(o-a)-(i-s)*(n-a)>=0}function b(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!E(t,e)&&S(t,e)&&S(e,t)&&O(t,e)}function x(t,e,r){return(e.y-t.y)*(r.x-e.x)-(e.x-t.x)*(r.y-e.y)}function T(t,e){return t.x===e.x&&t.y===e.y}function w(t,e,r,n){return!!(T(t,e)&&T(r,n)||T(t,n)&&T(r,e))||x(t,e,r)>0!=x(t,e,n)>0&&x(r,n,t)>0!=x(r,n,e)>0}function E(t,e){var r=t;do{if(r.i!==t.i&&r.next.i!==t.i&&r.i!==e.i&&r.next.i!==e.i&&w(r,r.next,t,e))return!0;r=r.next}while(r!==t);return!1}function S(t,e){return x(t.prev,t,t.next)<0?x(t,e,t.next)>=0&&x(t,t.prev,e)>=0:x(t,e,t.prev)<0||x(t,t.next,e)<0}function O(t,e){var r=t,n=!1,i=(t.x+e.x)/2,o=(t.y+e.y)/2;do{r.y>o!=r.next.y>o&&r.next.y!==r.y&&i<(r.next.x-r.x)*(o-r.y)/(r.next.y-r.y)+r.x&&(n=!n),r=r.next}while(r!==t);return n}function M(t,e){var r=new R(t.i,t.x,t.y),n=new R(e.i,e.x,e.y),i=t.next,o=e.prev;return t.next=e,e.prev=t,r.next=i,i.prev=r,n.next=r,r.prev=n,o.next=n,n.prev=o,n}function P(t,e,r,n){var i=new R(t,e,r);return n?(i.next=n.next,i.prev=n,n.next.prev=i,n.next=i):(i.prev=i,i.next=i),i}function C(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ)}function R(t,e,r){this.i=t,this.x=e,this.y=r,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}function A(t,e,r,n){for(var i=0,o=e,s=r-n;o<r;o+=n)i+=(t[s]-t[o])*(t[o+1]+t[s+1]),s=o;return i}e.exports=n,e.exports.default=n,n.deviation=function(t,e,r,n){var i=e&&e.length,o=i?e[0]*r:t.length,s=Math.abs(A(t,0,o,r));if(i)for(var a=0,u=e.length;a<u;a++){var h=e[a]*r,l=a<u-1?e[a+1]*r:t.length;s-=Math.abs(A(t,h,l,r))}var c=0;for(a=0;a<n.length;a+=3){var d=n[a]*r,f=n[a+1]*r,p=n[a+2]*r;c+=Math.abs((t[d]-t[p])*(t[f+1]-t[d+1])-(t[d]-t[f])*(t[p+1]-t[d+1]))}return 0===s&&0===c?0:Math.abs((c-s)/s)},n.flatten=function(t){for(var e=t[0][0].length,r={vertices:[],holes:[],dimensions:e},n=0,i=0;i<t.length;i++){for(var o=0;o<t[i].length;o++)for(var s=0;s<e;s++)r.vertices.push(t[i][o][s]);i>0&&(n+=t[i-1].length,r.holes.push(n))}return r}},{}],3:[function(t,e,r){\"use strict\";function n(){}function i(t,e,r){this.fn=t,this.context=e,this.once=r||!1}function o(){this._events=new n,this._eventsCount=0}var s=Object.prototype.hasOwnProperty,a=\"~\";Object.create&&(n.prototype=Object.create(null),(new n).__proto__||(a=!1)),o.prototype.eventNames=function(){var t,e,r=[];if(0===this._eventsCount)return r;for(e in t=this._events)s.call(t,e)&&r.push(a?e.slice(1):e);return Object.getOwnPropertySymbols?r.concat(Object.getOwnPropertySymbols(t)):r},o.prototype.listeners=function(t,e){var r=a?a+t:t,n=this._events[r];if(e)return!!n;if(!n)return[];if(n.fn)return[n.fn];for(var i=0,o=n.length,s=new Array(o);i<o;i++)s[i]=n[i].fn;return s},o.prototype.emit=function(t,e,r,n,i,o){var s=a?a+t:t;if(!this._events[s])return!1;var u,h,l=this._events[s],c=arguments.length;if(l.fn){switch(l.once&&this.removeListener(t,l.fn,void 0,!0),c){case 1:return l.fn.call(l.context),!0;case 2:return l.fn.call(l.context,e),!0;case 3:return l.fn.call(l.context,e,r),!0;case 4:return l.fn.call(l.context,e,r,n),!0;case 5:return l.fn.call(l.context,e,r,n,i),!0;case 6:return l.fn.call(l.context,e,r,n,i,o),!0}for(h=1,u=new Array(c-1);h<c;h++)u[h-1]=arguments[h];l.fn.apply(l.context,u)}else{var d,f=l.length;for(h=0;h<f;h++)switch(l[h].once&&this.removeListener(t,l[h].fn,void 0,!0),c){case 1:l[h].fn.call(l[h].context);break;case 2:l[h].fn.call(l[h].context,e);break;case 3:l[h].fn.call(l[h].context,e,r);break;case 4:l[h].fn.call(l[h].context,e,r,n);break;default:if(!u)for(d=1,u=new Array(c-1);d<c;d++)u[d-1]=arguments[d];l[h].fn.apply(l[h].context,u)}}return!0},o.prototype.on=function(t,e,r){var n=new i(e,r||this),o=a?a+t:t;return this._events[o]?this._events[o].fn?this._events[o]=[this._events[o],n]:this._events[o].push(n):(this._events[o]=n,this._eventsCount++),this},o.prototype.once=function(t,e,r){var n=new i(e,r||this,!0),o=a?a+t:t;return this._events[o]?this._events[o].fn?this._events[o]=[this._events[o],n]:this._events[o].push(n):(this._events[o]=n,this._eventsCount++),this},o.prototype.removeListener=function(t,e,r,i){var o=a?a+t:t;if(!this._events[o])return this;if(!e)return 0==--this._eventsCount?this._events=new n:delete this._events[o],this;var s=this._events[o];if(s.fn)s.fn!==e||i&&!s.once||r&&s.context!==r||(0==--this._eventsCount?this._events=new n:delete this._events[o]);else{for(var u=0,h=[],l=s.length;u<l;u++)(s[u].fn!==e||i&&!s[u].once||r&&s[u].context!==r)&&h.push(s[u]);h.length?this._events[o]=1===h.length?h[0]:h:0==--this._eventsCount?this._events=new n:delete this._events[o]}return this},o.prototype.removeAllListeners=function(t){var e;return t?(e=a?a+t:t,this._events[e]&&(0==--this._eventsCount?this._events=new n:delete this._events[e])):(this._events=new n,this._eventsCount=0),this},o.prototype.off=o.prototype.removeListener,o.prototype.addListener=o.prototype.on,o.prototype.setMaxListeners=function(){return this},o.prefixed=a,o.EventEmitter=o,void 0!==e&&(e.exports=o)},{}],4:[function(e,r,n){!function(e){var n=/iPhone/i,i=/iPod/i,o=/iPad/i,s=/(?=.*\\bAndroid\\b)(?=.*\\bMobile\\b)/i,a=/Android/i,u=/(?=.*\\bAndroid\\b)(?=.*\\bSD4930UR\\b)/i,h=/(?=.*\\bAndroid\\b)(?=.*\\b(?:KFOT|KFTT|KFJWI|KFJWA|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|KFARWI|KFASWI|KFSAWI|KFSAWA)\\b)/i,l=/Windows Phone/i,c=/(?=.*\\bWindows\\b)(?=.*\\bARM\\b)/i,d=/BlackBerry/i,f=/BB10/i,p=/Opera Mini/i,v=/(CriOS|Chrome)(?=.*\\bMobile\\b)/i,y=/(?=.*\\bFirefox\\b)(?=.*\\bMobile\\b)/i,g=new RegExp(\"(?:Nexus 7|BNTV250|Kindle Fire|Silk|GT-P1000)\",\"i\"),m=function(t,e){return t.test(e)},_=function(t){var e=t||navigator.userAgent,r=e.split(\"[FBAN\");if(void 0!==r[1]&&(e=r[0]),r=e.split(\"Twitter\"),void 0!==r[1]&&(e=r[0]),this.apple={phone:m(n,e),ipod:m(i,e),tablet:!m(n,e)&&m(o,e),device:m(n,e)||m(i,e)||m(o,e)},this.amazon={phone:m(u,e),tablet:!m(u,e)&&m(h,e),device:m(u,e)||m(h,e)},this.android={phone:m(u,e)||m(s,e),tablet:!m(u,e)&&!m(s,e)&&(m(h,e)||m(a,e)),device:m(u,e)||m(h,e)||m(s,e)||m(a,e)},this.windows={phone:m(l,e),tablet:m(c,e),device:m(l,e)||m(c,e)},this.other={blackberry:m(d,e),blackberry10:m(f,e),opera:m(p,e),firefox:m(y,e),chrome:m(v,e),device:m(d,e)||m(f,e)||m(p,e)||m(y,e)||m(v,e)},this.seven_inch=m(g,e),this.any=this.apple.device||this.android.device||this.windows.device||this.other.device||this.seven_inch,this.phone=this.apple.phone||this.android.phone||this.windows.phone,this.tablet=this.apple.tablet||this.android.tablet||this.windows.tablet,\"undefined\"==typeof window)return this},b=function(){var t=new _;return t.Class=_,t};void 0!==r&&r.exports&&\"undefined\"==typeof window?r.exports=_:void 0!==r&&r.exports&&\"undefined\"!=typeof window?r.exports=b():\"function\"==typeof t&&t.amd?t(\"isMobile\",[],e.isMobile=b()):e.isMobile=b()}(this)},{}],5:[function(t,e,r){\"use strict\";function n(t){if(null===t||void 0===t)throw new TypeError(\"Object.assign cannot be called with null or undefined\");return Object(t)}var i=Object.getOwnPropertySymbols,o=Object.prototype.hasOwnProperty,s=Object.prototype.propertyIsEnumerable;e.exports=function(){try{if(!Object.assign)return!1;var t=new String(\"abc\");if(t[5]=\"de\",\"5\"===Object.getOwnPropertyNames(t)[0])return!1;for(var e={},r=0;r<10;r++)e[\"_\"+String.fromCharCode(r)]=r;if(\"0123456789\"!==Object.getOwnPropertyNames(e).map(function(t){return e[t]}).join(\"\"))return!1;var n={};return\"abcdefghijklmnopqrst\".split(\"\").forEach(function(t){n[t]=t}),\"abcdefghijklmnopqrst\"===Object.keys(Object.assign({},n)).join(\"\")}catch(t){return!1}}()?Object.assign:function(t,e){for(var r,a,u=n(t),h=1;h<arguments.length;h++){r=Object(arguments[h]);for(var l in r)o.call(r,l)&&(u[l]=r[l]);if(i){a=i(r);for(var c=0;c<a.length;c++)s.call(r,a[c])&&(u[a[c]]=r[a[c]])}}return u}},{}],6:[function(t,e,r){var n=new ArrayBuffer(0),i=function(t,e,r,i){this.gl=t,this.buffer=t.createBuffer(),this.type=e||t.ARRAY_BUFFER,this.drawType=i||t.STATIC_DRAW,this.data=n,r&&this.upload(r),this._updateID=0};i.prototype.upload=function(t,e,r){r||this.bind();var n=this.gl;t=t||this.data,e=e||0,this.data.byteLength>=t.byteLength?n.bufferSubData(this.type,e,t):n.bufferData(this.type,t,this.drawType),this.data=t},i.prototype.bind=function(){this.gl.bindBuffer(this.type,this.buffer)},i.createVertexBuffer=function(t,e,r){return new i(t,t.ARRAY_BUFFER,e,r)},i.createIndexBuffer=function(t,e,r){return new i(t,t.ELEMENT_ARRAY_BUFFER,e,r)},i.create=function(t,e,r,n){return new i(t,e,r,n)},i.prototype.destroy=function(){this.gl.deleteBuffer(this.buffer)},e.exports=i},{}],7:[function(t,e,r){var n=t(\"./GLTexture\"),i=function(t,e,r){this.gl=t,this.framebuffer=t.createFramebuffer(),this.stencil=null,this.texture=null,this.width=e||100,this.height=r||100};i.prototype.enableTexture=function(t){var e=this.gl;this.texture=t||new n(e),this.texture.bind(),this.bind(),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,this.texture.texture,0)},i.prototype.enableStencil=function(){if(!this.stencil){var t=this.gl;this.stencil=t.createRenderbuffer(),t.bindRenderbuffer(t.RENDERBUFFER,this.stencil),t.framebufferRenderbuffer(t.FRAMEBUFFER,t.DEPTH_STENCIL_ATTACHMENT,t.RENDERBUFFER,this.stencil),t.renderbufferStorage(t.RENDERBUFFER,t.DEPTH_STENCIL,this.width,this.height)}},i.prototype.clear=function(t,e,r,n){this.bind();var i=this.gl;i.clearColor(t,e,r,n),i.clear(i.COLOR_BUFFER_BIT|i.DEPTH_BUFFER_BIT)},i.prototype.bind=function(){var t=this.gl;t.bindFramebuffer(t.FRAMEBUFFER,this.framebuffer)},i.prototype.unbind=function(){var t=this.gl;t.bindFramebuffer(t.FRAMEBUFFER,null)},i.prototype.resize=function(t,e){var r=this.gl;this.width=t,this.height=e,this.texture&&this.texture.uploadData(null,t,e),this.stencil&&(r.bindRenderbuffer(r.RENDERBUFFER,this.stencil),r.renderbufferStorage(r.RENDERBUFFER,r.DEPTH_STENCIL,t,e))},i.prototype.destroy=function(){var t=this.gl;this.texture&&this.texture.destroy(),t.deleteFramebuffer(this.framebuffer),this.gl=null,this.stencil=null,this.texture=null},i.createRGBA=function(t,e,r,o){var s=n.fromData(t,null,e,r);s.enableNearestScaling(),s.enableWrapClamp();var a=new i(t,e,r);return a.enableTexture(s),a.unbind(),a},i.createFloat32=function(t,e,r,o){var s=new n.fromData(t,o,e,r);s.enableNearestScaling(),s.enableWrapClamp();var a=new i(t,e,r);return a.enableTexture(s),a.unbind(),a},e.exports=i},{\"./GLTexture\":9}],8:[function(t,e,r){var n=t(\"./shader/compileProgram\"),i=t(\"./shader/extractAttributes\"),o=t(\"./shader/extractUniforms\"),s=t(\"./shader/setPrecision\"),a=t(\"./shader/generateUniformAccessObject\"),u=function(t,e,r,u,h){this.gl=t,u&&(e=s(e,u),r=s(r,u)),this.program=n(t,e,r,h),this.attributes=i(t,this.program),this.uniformData=o(t,this.program),this.uniforms=a(t,this.uniformData)};u.prototype.bind=function(){return this.gl.useProgram(this.program),this},u.prototype.destroy=function(){this.attributes=null,this.uniformData=null,this.uniforms=null,this.gl.deleteProgram(this.program)},e.exports=u},{\"./shader/compileProgram\":14,\"./shader/extractAttributes\":16,\"./shader/extractUniforms\":17,\"./shader/generateUniformAccessObject\":18,\"./shader/setPrecision\":22}],9:[function(t,e,r){var n=function(t,e,r,n,i){this.gl=t,this.texture=t.createTexture(),this.mipmap=!1,this.premultiplyAlpha=!1,this.width=e||-1,this.height=r||-1,this.format=n||t.RGBA,this.type=i||t.UNSIGNED_BYTE};n.prototype.upload=function(t){this.bind();var e=this.gl;e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,this.premultiplyAlpha);var r=t.videoWidth||t.width,n=t.videoHeight||t.height;n!==this.height||r!==this.width?e.texImage2D(e.TEXTURE_2D,0,this.format,this.format,this.type,t):e.texSubImage2D(e.TEXTURE_2D,0,0,0,this.format,this.type,t),this.width=r,this.height=n};var i=!1;n.prototype.uploadData=function(t,e,r){this.bind();var n=this.gl;if(t instanceof Float32Array){if(!i){if(!n.getExtension(\"OES_texture_float\"))throw new Error(\"floating point textures not available\");i=!0}this.type=n.FLOAT}else this.type=this.type||n.UNSIGNED_BYTE;n.pixelStorei(n.UNPACK_PREMULTIPLY_ALPHA_WEBGL,this.premultiplyAlpha),e!==this.width||r!==this.height?n.texImage2D(n.TEXTURE_2D,0,this.format,e,r,0,this.format,this.type,t||null):n.texSubImage2D(n.TEXTURE_2D,0,0,0,e,r,this.format,this.type,t||null),this.width=e,this.height=r},n.prototype.bind=function(t){var e=this.gl;void 0!==t&&e.activeTexture(e.TEXTURE0+t),e.bindTexture(e.TEXTURE_2D,this.texture)},n.prototype.unbind=function(){var t=this.gl;t.bindTexture(t.TEXTURE_2D,null)},n.prototype.minFilter=function(t){var e=this.gl;this.bind(),this.mipmap?e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,t?e.LINEAR_MIPMAP_LINEAR:e.NEAREST_MIPMAP_NEAREST):e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,t?e.LINEAR:e.NEAREST)},n.prototype.magFilter=function(t){var e=this.gl;this.bind(),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,t?e.LINEAR:e.NEAREST)},n.prototype.enableMipmap=function(){var t=this.gl;this.bind(),this.mipmap=!0,t.generateMipmap(t.TEXTURE_2D)},n.prototype.enableLinearScaling=function(){this.minFilter(!0),this.magFilter(!0)},n.prototype.enableNearestScaling=function(){this.minFilter(!1),this.magFilter(!1)},n.prototype.enableWrapClamp=function(){var t=this.gl;this.bind(),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE)},n.prototype.enableWrapRepeat=function(){var t=this.gl;this.bind(),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.REPEAT),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.REPEAT)},n.prototype.enableWrapMirrorRepeat=function(){var t=this.gl;this.bind(),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.MIRRORED_REPEAT),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.MIRRORED_REPEAT)},n.prototype.destroy=function(){this.gl.deleteTexture(this.texture)},n.fromSource=function(t,e,r){var i=new n(t);return i.premultiplyAlpha=r||!1,i.upload(e),i},n.fromData=function(t,e,r,i){var o=new n(t);return o.uploadData(e,r,i),o},e.exports=n},{}],10:[function(t,e,r){function n(t,e){if(this.nativeVaoExtension=null,n.FORCE_NATIVE||(this.nativeVaoExtension=t.getExtension(\"OES_vertex_array_object\")||t.getExtension(\"MOZ_OES_vertex_array_object\")||t.getExtension(\"WEBKIT_OES_vertex_array_object\")),this.nativeState=e,this.nativeVaoExtension){this.nativeVao=this.nativeVaoExtension.createVertexArrayOES();var r=t.getParameter(t.MAX_VERTEX_ATTRIBS);this.nativeState={tempAttribState:new Array(r),attribState:new Array(r)}}this.gl=t,this.attributes=[],this.indexBuffer=null,this.dirty=!1}var i=t(\"./setVertexAttribArrays\");n.prototype.constructor=n,e.exports=n,n.FORCE_NATIVE=!1,n.prototype.bind=function(){return this.nativeVao?(this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao),this.dirty&&(this.dirty=!1,this.activate())):this.activate(),this},n.prototype.unbind=function(){return this.nativeVao&&this.nativeVaoExtension.bindVertexArrayOES(null),this},n.prototype.activate=function(){for(var t=this.gl,e=null,r=0;r<this.attributes.length;r++){var n=this.attributes[r];e!==n.buffer&&(n.buffer.bind(),e=n.buffer),t.vertexAttribPointer(n.attribute.location,n.attribute.size,n.type||t.FLOAT,n.normalized||!1,n.stride||0,n.start||0)}return i(t,this.attributes,this.nativeState),this.indexBuffer&&this.indexBuffer.bind(),this},n.prototype.addAttribute=function(t,e,r,n,i,o){return this.attributes.push({buffer:t,attribute:e,location:e.location,type:r||this.gl.FLOAT,normalized:n||!1,stride:i||0,start:o||0}),this.dirty=!0,this},n.prototype.addIndex=function(t){return this.indexBuffer=t,this.dirty=!0,this},n.prototype.clear=function(){return this.nativeVao&&this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao),this.attributes.length=0,this.indexBuffer=null,this},n.prototype.draw=function(t,e,r){var n=this.gl;return this.indexBuffer?n.drawElements(t,e||this.indexBuffer.data.length,n.UNSIGNED_SHORT,2*(r||0)):n.drawArrays(t,r,e||this.getSize()),this},n.prototype.destroy=function(){this.gl=null,this.indexBuffer=null,this.attributes=null,this.nativeState=null,this.nativeVao&&this.nativeVaoExtension.deleteVertexArrayOES(this.nativeVao),this.nativeVaoExtension=null,this.nativeVao=null},n.prototype.getSize=function(){var t=this.attributes[0];return t.buffer.data.length/(t.stride/4||t.attribute.size)}},{\"./setVertexAttribArrays\":13}],11:[function(t,e,r){var n=function(t,e){var r=t.getContext(\"webgl\",e)||t.getContext(\"experimental-webgl\",e);if(!r)throw new Error(\"This browser does not support webGL. Try using the canvas renderer\");return r};e.exports=n},{}],12:[function(t,e,r){var n={createContext:t(\"./createContext\"),setVertexAttribArrays:t(\"./setVertexAttribArrays\"),GLBuffer:t(\"./GLBuffer\"),GLFramebuffer:t(\"./GLFramebuffer\"),GLShader:t(\"./GLShader\"),GLTexture:t(\"./GLTexture\"),VertexArrayObject:t(\"./VertexArrayObject\"),shader:t(\"./shader\")};void 0!==e&&e.exports&&(e.exports=n),\"undefined\"!=typeof window&&(window.PIXI=window.PIXI||{},window.PIXI.glCore=n)},{\"./GLBuffer\":6,\"./GLFramebuffer\":7,\"./GLShader\":8,\"./GLTexture\":9,\"./VertexArrayObject\":10,\"./createContext\":11,\"./setVertexAttribArrays\":13,\"./shader\":19}],13:[function(t,e,r){var n=function(t,e,r){var n;if(r){var i=r.tempAttribState,o=r.attribState;for(n=0;n<i.length;n++)i[n]=!1;for(n=0;n<e.length;n++)i[e[n].attribute.location]=!0;for(n=0;n<o.length;n++)o[n]!==i[n]&&(o[n]=i[n],r.attribState[n]?t.enableVertexAttribArray(n):t.disableVertexAttribArray(n))}else for(n=0;n<e.length;n++){var s=e[n];t.enableVertexAttribArray(s.attribute.location)}};e.exports=n},{}],14:[function(t,e,r){var n=function(t,e,r,n){var o=i(t,t.VERTEX_SHADER,e),s=i(t,t.FRAGMENT_SHADER,r),a=t.createProgram();if(t.attachShader(a,o),t.attachShader(a,s),n)for(var u in n)t.bindAttribLocation(a,n[u],u);return t.linkProgram(a),t.getProgramParameter(a,t.LINK_STATUS)||(console.error(\"Pixi.js Error: Could not initialize shader.\"),console.error(\"gl.VALIDATE_STATUS\",t.getProgramParameter(a,t.VALIDATE_STATUS)),console.error(\"gl.getError()\",t.getError()),\"\"!==t.getProgramInfoLog(a)&&console.warn(\"Pixi.js Warning: gl.getProgramInfoLog()\",t.getProgramInfoLog(a)),t.deleteProgram(a),a=null),t.deleteShader(o),t.deleteShader(s),a},i=function(t,e,r){var n=t.createShader(e);return t.shaderSource(n,r),t.compileShader(n),t.getShaderParameter(n,t.COMPILE_STATUS)?n:(console.log(t.getShaderInfoLog(n)),null)};e.exports=n},{}],15:[function(t,e,r){var n=function(t,e){switch(t){case\"float\":return 0;case\"vec2\":return new Float32Array(2*e);case\"vec3\":return new Float32Array(3*e);case\"vec4\":return new Float32Array(4*e);case\"int\":case\"sampler2D\":return 0;case\"ivec2\":return new Int32Array(2*e);case\"ivec3\":return new Int32Array(3*e);case\"ivec4\":return new Int32Array(4*e);case\"bool\":return!1;case\"bvec2\":return i(2*e);case\"bvec3\":return i(3*e);case\"bvec4\":return i(4*e);case\"mat2\":return new Float32Array([1,0,0,1]);case\"mat3\":return new Float32Array([1,0,0,0,1,0,0,0,1]);case\"mat4\":return new Float32Array([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1])}},i=function(t){for(var e=new Array(t),r=0;r<e.length;r++)e[r]=!1;return e};e.exports=n},{}],16:[function(t,e,r){var n=t(\"./mapType\"),i=t(\"./mapSize\"),o=function(t,e){for(var r={},o=t.getProgramParameter(e,t.ACTIVE_ATTRIBUTES),a=0;a<o;a++){var u=t.getActiveAttrib(e,a),h=n(t,u.type);r[u.name]={type:h,size:i(h),location:t.getAttribLocation(e,u.name),pointer:s}}return r},s=function(t,e,r,n){gl.vertexAttribPointer(this.location,this.size,t||gl.FLOAT,e||!1,r||0,n||0)};e.exports=o},{\"./mapSize\":20,\"./mapType\":21}],17:[function(t,e,r){var n=t(\"./mapType\"),i=t(\"./defaultValue\"),o=function(t,e){for(var r={},o=t.getProgramParameter(e,t.ACTIVE_UNIFORMS),s=0;s<o;s++){var a=t.getActiveUniform(e,s),u=a.name.replace(/\\[.*?\\]/,\"\"),h=n(t,a.type);r[u]={type:h,size:a.size,location:t.getUniformLocation(e,u),value:i(h,a.size)}}return r};e.exports=o},{\"./defaultValue\":15,\"./mapType\":21}],18:[function(t,e,r){var n=function(t,e){var r={data:{}};r.gl=t;for(var n=Object.keys(e),a=0;a<n.length;a++){var u=n[a],h=u.split(\".\"),l=h[h.length-1],c=s(h,r),d=e[u];c.data[l]=d,c.gl=t,Object.defineProperty(c,l,{get:i(l),set:o(l,d)})}return r},i=function(t){var e=a.replace(\"%%\",t);return new Function(e)},o=function(t,e){var r,n=u.replace(/%%/g,t);return r=1===e.size?h[e.type]:l[e.type],r&&(n+=\"\\nthis.gl.\"+r+\";\"),new Function(\"value\",n)},s=function(t,e){for(var r=e,n=0;n<t.length-1;n++){var i=r[t[n]]||{data:{}};r[t[n]]=i,r=i}return r},a=[\"return this.data.%%.value;\"].join(\"\\n\"),u=[\"this.data.%%.value = value;\",\"var location = this.data.%%.location;\"].join(\"\\n\"),h={float:\"uniform1f(location, value)\",vec2:\"uniform2f(location, value[0], value[1])\",vec3:\"uniform3f(location, value[0], value[1], value[2])\",vec4:\"uniform4f(location, value[0], value[1], value[2], value[3])\",int:\"uniform1i(location, value)\",ivec2:\"uniform2i(location, value[0], value[1])\",ivec3:\"uniform3i(location, value[0], value[1], value[2])\",ivec4:\"uniform4i(location, value[0], value[1], value[2], value[3])\",bool:\"uniform1i(location, value)\",bvec2:\"uniform2i(location, value[0], value[1])\",bvec3:\"uniform3i(location, value[0], value[1], value[2])\",bvec4:\"uniform4i(location, value[0], value[1], value[2], value[3])\",mat2:\"uniformMatrix2fv(location, false, value)\",mat3:\"uniformMatrix3fv(location, false, value)\",mat4:\"uniformMatrix4fv(location, false, value)\",sampler2D:\"uniform1i(location, value)\"},l={float:\"uniform1fv(location, value)\",vec2:\"uniform2fv(location, value)\",vec3:\"uniform3fv(location, value)\",vec4:\"uniform4fv(location, value)\",int:\"uniform1iv(location, value)\",ivec2:\"uniform2iv(location, value)\",ivec3:\"uniform3iv(location, value)\",ivec4:\"uniform4iv(location, value)\",bool:\"uniform1iv(location, value)\",bvec2:\"uniform2iv(location, value)\",bvec3:\"uniform3iv(location, value)\",bvec4:\"uniform4iv(location, value)\",sampler2D:\"uniform1iv(location, value)\"};e.exports=n},{}],19:[function(t,e,r){e.exports={compileProgram:t(\"./compileProgram\"),defaultValue:t(\"./defaultValue\"),extractAttributes:t(\"./extractAttributes\"),extractUniforms:t(\"./extractUniforms\"),generateUniformAccessObject:t(\"./generateUniformAccessObject\"),setPrecision:t(\"./setPrecision\"),mapSize:t(\"./mapSize\"),mapType:t(\"./mapType\")}},{\"./compileProgram\":14,\"./defaultValue\":15,\"./extractAttributes\":16,\"./extractUniforms\":17,\"./generateUniformAccessObject\":18,\"./mapSize\":20,\"./mapType\":21,\"./setPrecision\":22}],20:[function(t,e,r){var n=function(t){return i[t]},i={float:1,vec2:2,vec3:3,vec4:4,int:1,ivec2:2,ivec3:3,ivec4:4,bool:1,bvec2:2,bvec3:3,bvec4:4,mat2:4,mat3:9,mat4:16,sampler2D:1};e.exports=n},{}],21:[function(t,e,r){var n=function(t,e){if(!i){var r=Object.keys(o);i={};for(var n=0;n<r.length;++n){var s=r[n];i[t[s]]=o[s]}}return i[e]},i=null,o={FLOAT:\"float\",FLOAT_VEC2:\"vec2\",FLOAT_VEC3:\"vec3\",FLOAT_VEC4:\"vec4\",INT:\"int\",INT_VEC2:\"ivec2\",INT_VEC3:\"ivec3\",INT_VEC4:\"ivec4\",BOOL:\"bool\",BOOL_VEC2:\"bvec2\",BOOL_VEC3:\"bvec3\",BOOL_VEC4:\"bvec4\",FLOAT_MAT2:\"mat2\",FLOAT_MAT3:\"mat3\",FLOAT_MAT4:\"mat4\",SAMPLER_2D:\"sampler2D\"};e.exports=n},{}],22:[function(t,e,r){var n=function(t,e){return\"precision\"!==t.substring(0,9)?\"precision \"+e+\" float;\\n\"+t:t};e.exports=n},{}],23:[function(t,e,r){(function(t){function e(t,e){for(var r=0,n=t.length-1;n>=0;n--){var i=t[n];\".\"===i?t.splice(n,1):\"..\"===i?(t.splice(n,1),r++):r&&(t.splice(n,1),r--)}if(e)for(;r--;r)t.unshift(\"..\");return t}function n(t,e){if(t.filter)return t.filter(e);for(var r=[],n=0;n<t.length;n++)e(t[n],n,t)&&r.push(t[n]);return r}var i=/^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/,o=function(t){return i.exec(t).slice(1)};r.resolve=function(){for(var r=\"\",i=!1,o=arguments.length-1;o>=-1&&!i;o--){var s=o>=0?arguments[o]:t.cwd();if(\"string\"!=typeof s)throw new TypeError(\"Arguments to path.resolve must be strings\");s&&(r=s+\"/\"+r,i=\"/\"===s.charAt(0))}return r=e(n(r.split(\"/\"),function(t){return!!t}),!i).join(\"/\"),(i?\"/\":\"\")+r||\".\"},r.normalize=function(t){var i=r.isAbsolute(t),o=\"/\"===s(t,-1);return t=e(n(t.split(\"/\"),function(t){return!!t}),!i).join(\"/\"),t||i||(t=\".\"),t&&o&&(t+=\"/\"),(i?\"/\":\"\")+t},r.isAbsolute=function(t){return\"/\"===t.charAt(0)},r.join=function(){var t=Array.prototype.slice.call(arguments,0);return r.normalize(n(t,function(t,e){if(\"string\"!=typeof t)throw new TypeError(\"Arguments to path.join must be strings\");return t}).join(\"/\"))},r.relative=function(t,e){function n(t){for(var e=0;e<t.length&&\"\"===t[e];e++);for(var r=t.length-1;r>=0&&\"\"===t[r];r--);return e>r?[]:t.slice(e,r-e+1)}t=r.resolve(t).substr(1),e=r.resolve(e).substr(1);for(var i=n(t.split(\"/\")),o=n(e.split(\"/\")),s=Math.min(i.length,o.length),a=s,u=0;u<s;u++)if(i[u]!==o[u]){a=u;break}for(var h=[],u=a;u<i.length;u++)h.push(\"..\");return h=h.concat(o.slice(a)),h.join(\"/\")},r.sep=\"/\",r.delimiter=\":\",r.dirname=function(t){var e=o(t),r=e[0],n=e[1];return r||n?(n&&(n=n.substr(0,n.length-1)),r+n):\".\"},r.basename=function(t,e){var r=o(t)[2];return e&&r.substr(-1*e.length)===e&&(r=r.substr(0,r.length-e.length)),r},r.extname=function(t){return o(t)[3]};var s=\"b\"===\"ab\".substr(-1)?function(t,e,r){return t.substr(e,r)}:function(t,e,r){return e<0&&(e=t.length+e),t.substr(e,r)}}).call(this,t(\"_process\"))},{_process:24}],24:[function(t,e,r){function n(){throw new Error(\"setTimeout has not been defined\")}function i(){throw new Error(\"clearTimeout has not been defined\")}function o(t){if(c===setTimeout)return setTimeout(t,0);if((c===n||!c)&&setTimeout)return c=setTimeout,setTimeout(t,0);try{return c(t,0)}catch(e){try{return c.call(null,t,0)\n}catch(e){return c.call(this,t,0)}}}function s(t){if(d===clearTimeout)return clearTimeout(t);if((d===i||!d)&&clearTimeout)return d=clearTimeout,clearTimeout(t);try{return d(t)}catch(e){try{return d.call(null,t)}catch(e){return d.call(this,t)}}}function a(){y&&p&&(y=!1,p.length?v=p.concat(v):g=-1,v.length&&u())}function u(){if(!y){var t=o(a);y=!0;for(var e=v.length;e;){for(p=v,v=[];++g<e;)p&&p[g].run();g=-1,e=v.length}p=null,y=!1,s(t)}}function h(t,e){this.fun=t,this.array=e}function l(){}var c,d,f=e.exports={};!function(){try{c=\"function\"==typeof setTimeout?setTimeout:n}catch(t){c=n}try{d=\"function\"==typeof clearTimeout?clearTimeout:i}catch(t){d=i}}();var p,v=[],y=!1,g=-1;f.nextTick=function(t){var e=new Array(arguments.length-1);if(arguments.length>1)for(var r=1;r<arguments.length;r++)e[r-1]=arguments[r];v.push(new h(t,e)),1!==v.length||y||o(u)},h.prototype.run=function(){this.fun.apply(null,this.array)},f.title=\"browser\",f.browser=!0,f.env={},f.argv=[],f.version=\"\",f.versions={},f.on=l,f.addListener=l,f.once=l,f.off=l,f.removeListener=l,f.removeAllListeners=l,f.emit=l,f.prependListener=l,f.prependOnceListener=l,f.listeners=function(t){return[]},f.binding=function(t){throw new Error(\"process.binding is not supported\")},f.cwd=function(){return\"/\"},f.chdir=function(t){throw new Error(\"process.chdir is not supported\")},f.umask=function(){return 0}},{}],25:[function(e,r,n){(function(e){!function(i){function o(t){throw new RangeError(L[t])}function s(t,e){for(var r=t.length,n=[];r--;)n[r]=e(t[r]);return n}function a(t,e){var r=t.split(\"@\"),n=\"\";return r.length>1&&(n=r[0]+\"@\",t=r[1]),t=t.replace(D,\".\"),n+s(t.split(\".\"),e).join(\".\")}function u(t){for(var e,r,n=[],i=0,o=t.length;i<o;)e=t.charCodeAt(i++),e>=55296&&e<=56319&&i<o?(r=t.charCodeAt(i++),56320==(64512&r)?n.push(((1023&e)<<10)+(1023&r)+65536):(n.push(e),i--)):n.push(e);return n}function h(t){return s(t,function(t){var e=\"\";return t>65535&&(t-=65536,e+=B(t>>>10&1023|55296),t=56320|1023&t),e+=B(t)}).join(\"\")}function l(t){return t-48<10?t-22:t-65<26?t-65:t-97<26?t-97:w}function c(t,e){return t+22+75*(t<26)-((0!=e)<<5)}function d(t,e,r){var n=0;for(t=r?F(t/M):t>>1,t+=F(t/e);t>N*S>>1;n+=w)t=F(t/N);return F(n+(N+1)*t/(t+O))}function f(t){var e,r,n,i,s,a,u,c,f,p,v=[],y=t.length,g=0,m=C,_=P;for(r=t.lastIndexOf(R),r<0&&(r=0),n=0;n<r;++n)t.charCodeAt(n)>=128&&o(\"not-basic\"),v.push(t.charCodeAt(n));for(i=r>0?r+1:0;i<y;){for(s=g,a=1,u=w;i>=y&&o(\"invalid-input\"),c=l(t.charCodeAt(i++)),(c>=w||c>F((T-g)/a))&&o(\"overflow\"),g+=c*a,f=u<=_?E:u>=_+S?S:u-_,!(c<f);u+=w)p=w-f,a>F(T/p)&&o(\"overflow\"),a*=p;e=v.length+1,_=d(g-s,e,0==s),F(g/e)>T-m&&o(\"overflow\"),m+=F(g/e),g%=e,v.splice(g++,0,m)}return h(v)}function p(t){var e,r,n,i,s,a,h,l,f,p,v,y,g,m,_,b=[];for(t=u(t),y=t.length,e=C,r=0,s=P,a=0;a<y;++a)(v=t[a])<128&&b.push(B(v));for(n=i=b.length,i&&b.push(R);n<y;){for(h=T,a=0;a<y;++a)(v=t[a])>=e&&v<h&&(h=v);for(g=n+1,h-e>F((T-r)/g)&&o(\"overflow\"),r+=(h-e)*g,e=h,a=0;a<y;++a)if(v=t[a],v<e&&++r>T&&o(\"overflow\"),v==e){for(l=r,f=w;p=f<=s?E:f>=s+S?S:f-s,!(l<p);f+=w)_=l-p,m=w-p,b.push(B(c(p+_%m,0))),l=F(_/m);b.push(B(c(l,0))),s=d(r,g,n==i),r=0,++n}++r,++e}return b.join(\"\")}function v(t){return a(t,function(t){return A.test(t)?f(t.slice(4).toLowerCase()):t})}function y(t){return a(t,function(t){return I.test(t)?\"xn--\"+p(t):t})}var g=\"object\"==typeof n&&n&&!n.nodeType&&n,m=\"object\"==typeof r&&r&&!r.nodeType&&r,_=\"object\"==typeof e&&e;_.global!==_&&_.window!==_&&_.self!==_||(i=_);var b,x,T=2147483647,w=36,E=1,S=26,O=38,M=700,P=72,C=128,R=\"-\",A=/^xn--/,I=/[^\\x20-\\x7E]/,D=/[\\x2E\\u3002\\uFF0E\\uFF61]/g,L={overflow:\"Overflow: input needs wider integers to process\",\"not-basic\":\"Illegal input >= 0x80 (not a basic code point)\",\"invalid-input\":\"Invalid input\"},N=w-E,F=Math.floor,B=String.fromCharCode;if(b={version:\"1.4.1\",ucs2:{decode:u,encode:h},decode:f,encode:p,toASCII:y,toUnicode:v},\"function\"==typeof t&&\"object\"==typeof t.amd&&t.amd)t(\"punycode\",function(){return b});else if(g&&m)if(r.exports==g)m.exports=b;else for(x in b)b.hasOwnProperty(x)&&(g[x]=b[x]);else i.punycode=b}(this)}).call(this,\"undefined\"!=typeof global?global:\"undefined\"!=typeof self?self:\"undefined\"!=typeof window?window:{})},{}],26:[function(t,e,r){\"use strict\";function n(t,e){return Object.prototype.hasOwnProperty.call(t,e)}e.exports=function(t,e,r,o){e=e||\"&\",r=r||\"=\";var s={};if(\"string\"!=typeof t||0===t.length)return s;var a=/\\+/g;t=t.split(e);var u=1e3;o&&\"number\"==typeof o.maxKeys&&(u=o.maxKeys);var h=t.length;u>0&&h>u&&(h=u);for(var l=0;l<h;++l){var c,d,f,p,v=t[l].replace(a,\"%20\"),y=v.indexOf(r);y>=0?(c=v.substr(0,y),d=v.substr(y+1)):(c=v,d=\"\"),f=decodeURIComponent(c),p=decodeURIComponent(d),n(s,f)?i(s[f])?s[f].push(p):s[f]=[s[f],p]:s[f]=p}return s};var i=Array.isArray||function(t){return\"[object Array]\"===Object.prototype.toString.call(t)}},{}],27:[function(t,e,r){\"use strict\";function n(t,e){if(t.map)return t.map(e);for(var r=[],n=0;n<t.length;n++)r.push(e(t[n],n));return r}var i=function(t){switch(typeof t){case\"string\":return t;case\"boolean\":return t?\"true\":\"false\";case\"number\":return isFinite(t)?t:\"\";default:return\"\"}};e.exports=function(t,e,r,a){return e=e||\"&\",r=r||\"=\",null===t&&(t=void 0),\"object\"==typeof t?n(s(t),function(s){var a=encodeURIComponent(i(s))+r;return o(t[s])?n(t[s],function(t){return a+encodeURIComponent(i(t))}).join(e):a+encodeURIComponent(i(t[s]))}).join(e):a?encodeURIComponent(i(a))+r+encodeURIComponent(i(t)):\"\"};var o=Array.isArray||function(t){return\"[object Array]\"===Object.prototype.toString.call(t)},s=Object.keys||function(t){var e=[];for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&e.push(r);return e}},{}],28:[function(t,e,r){\"use strict\";r.decode=r.parse=t(\"./decode\"),r.encode=r.stringify=t(\"./encode\")},{\"./decode\":26,\"./encode\":27}],29:[function(t,e,r){\"use strict\";function n(){this.protocol=null,this.slashes=null,this.auth=null,this.host=null,this.port=null,this.hostname=null,this.hash=null,this.search=null,this.query=null,this.pathname=null,this.path=null,this.href=null}function i(t,e,r){if(t&&h.isObject(t)&&t instanceof n)return t;var i=new n;return i.parse(t,e,r),i}function o(t){return h.isString(t)&&(t=i(t)),t instanceof n?t.format():n.prototype.format.call(t)}function s(t,e){return i(t,!1,!0).resolve(e)}function a(t,e){return t?i(t,!1,!0).resolveObject(e):e}var u=t(\"punycode\"),h=t(\"./util\");r.parse=i,r.resolve=s,r.resolveObject=a,r.format=o,r.Url=n;var l=/^([a-z0-9.+-]+:)/i,c=/:[0-9]*$/,d=/^(\\/\\/?(?!\\/)[^\\?\\s]*)(\\?[^\\s]*)?$/,f=[\"<\",\">\",'\"',\"`\",\" \",\"\\r\",\"\\n\",\"\\t\"],p=[\"{\",\"}\",\"|\",\"\\\\\",\"^\",\"`\"].concat(f),v=[\"'\"].concat(p),y=[\"%\",\"/\",\"?\",\";\",\"#\"].concat(v),g=[\"/\",\"?\",\"#\"],m=/^[+a-z0-9A-Z_-]{0,63}$/,_=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,b={javascript:!0,\"javascript:\":!0},x={javascript:!0,\"javascript:\":!0},T={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,\"http:\":!0,\"https:\":!0,\"ftp:\":!0,\"gopher:\":!0,\"file:\":!0},w=t(\"querystring\");n.prototype.parse=function(t,e,r){if(!h.isString(t))throw new TypeError(\"Parameter 'url' must be a string, not \"+typeof t);var n=t.indexOf(\"?\"),i=-1!==n&&n<t.indexOf(\"#\")?\"?\":\"#\",o=t.split(i),s=/\\\\/g;o[0]=o[0].replace(s,\"/\"),t=o.join(i);var a=t;if(a=a.trim(),!r&&1===t.split(\"#\").length){var c=d.exec(a);if(c)return this.path=a,this.href=a,this.pathname=c[1],c[2]?(this.search=c[2],this.query=e?w.parse(this.search.substr(1)):this.search.substr(1)):e&&(this.search=\"\",this.query={}),this}var f=l.exec(a);if(f){f=f[0];var p=f.toLowerCase();this.protocol=p,a=a.substr(f.length)}if(r||f||a.match(/^\\/\\/[^@\\/]+@[^@\\/]+/)){var E=\"//\"===a.substr(0,2);!E||f&&x[f]||(a=a.substr(2),this.slashes=!0)}if(!x[f]&&(E||f&&!T[f])){for(var S=-1,O=0;O<g.length;O++){var M=a.indexOf(g[O]);-1!==M&&(-1===S||M<S)&&(S=M)}var P,C;C=-1===S?a.lastIndexOf(\"@\"):a.lastIndexOf(\"@\",S),-1!==C&&(P=a.slice(0,C),a=a.slice(C+1),this.auth=decodeURIComponent(P)),S=-1;for(var O=0;O<y.length;O++){var M=a.indexOf(y[O]);-1!==M&&(-1===S||M<S)&&(S=M)}-1===S&&(S=a.length),this.host=a.slice(0,S),a=a.slice(S),this.parseHost(),this.hostname=this.hostname||\"\";var R=\"[\"===this.hostname[0]&&\"]\"===this.hostname[this.hostname.length-1];if(!R)for(var A=this.hostname.split(/\\./),O=0,I=A.length;O<I;O++){var D=A[O];if(D&&!D.match(m)){for(var L=\"\",N=0,F=D.length;N<F;N++)D.charCodeAt(N)>127?L+=\"x\":L+=D[N];if(!L.match(m)){var B=A.slice(0,O),k=A.slice(O+1),j=D.match(_);j&&(B.push(j[1]),k.unshift(j[2])),k.length&&(a=\"/\"+k.join(\".\")+a),this.hostname=B.join(\".\");break}}}this.hostname.length>255?this.hostname=\"\":this.hostname=this.hostname.toLowerCase(),R||(this.hostname=u.toASCII(this.hostname));var U=this.port?\":\"+this.port:\"\",X=this.hostname||\"\";this.host=X+U,this.href+=this.host,R&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),\"/\"!==a[0]&&(a=\"/\"+a))}if(!b[p])for(var O=0,I=v.length;O<I;O++){var G=v[O];if(-1!==a.indexOf(G)){var W=encodeURIComponent(G);W===G&&(W=escape(G)),a=a.split(G).join(W)}}var H=a.indexOf(\"#\");-1!==H&&(this.hash=a.substr(H),a=a.slice(0,H));var Y=a.indexOf(\"?\");if(-1!==Y?(this.search=a.substr(Y),this.query=a.substr(Y+1),e&&(this.query=w.parse(this.query)),a=a.slice(0,Y)):e&&(this.search=\"\",this.query={}),a&&(this.pathname=a),T[p]&&this.hostname&&!this.pathname&&(this.pathname=\"/\"),this.pathname||this.search){var U=this.pathname||\"\",V=this.search||\"\";this.path=U+V}return this.href=this.format(),this},n.prototype.format=function(){var t=this.auth||\"\";t&&(t=encodeURIComponent(t),t=t.replace(/%3A/i,\":\"),t+=\"@\");var e=this.protocol||\"\",r=this.pathname||\"\",n=this.hash||\"\",i=!1,o=\"\";this.host?i=t+this.host:this.hostname&&(i=t+(-1===this.hostname.indexOf(\":\")?this.hostname:\"[\"+this.hostname+\"]\"),this.port&&(i+=\":\"+this.port)),this.query&&h.isObject(this.query)&&Object.keys(this.query).length&&(o=w.stringify(this.query));var s=this.search||o&&\"?\"+o||\"\";return e&&\":\"!==e.substr(-1)&&(e+=\":\"),this.slashes||(!e||T[e])&&!1!==i?(i=\"//\"+(i||\"\"),r&&\"/\"!==r.charAt(0)&&(r=\"/\"+r)):i||(i=\"\"),n&&\"#\"!==n.charAt(0)&&(n=\"#\"+n),s&&\"?\"!==s.charAt(0)&&(s=\"?\"+s),r=r.replace(/[?#]/g,function(t){return encodeURIComponent(t)}),s=s.replace(\"#\",\"%23\"),e+i+r+s+n},n.prototype.resolve=function(t){return this.resolveObject(i(t,!1,!0)).format()},n.prototype.resolveObject=function(t){if(h.isString(t)){var e=new n;e.parse(t,!1,!0),t=e}for(var r=new n,i=Object.keys(this),o=0;o<i.length;o++){var s=i[o];r[s]=this[s]}if(r.hash=t.hash,\"\"===t.href)return r.href=r.format(),r;if(t.slashes&&!t.protocol){for(var a=Object.keys(t),u=0;u<a.length;u++){var l=a[u];\"protocol\"!==l&&(r[l]=t[l])}return T[r.protocol]&&r.hostname&&!r.pathname&&(r.path=r.pathname=\"/\"),r.href=r.format(),r}if(t.protocol&&t.protocol!==r.protocol){if(!T[t.protocol]){for(var c=Object.keys(t),d=0;d<c.length;d++){var f=c[d];r[f]=t[f]}return r.href=r.format(),r}if(r.protocol=t.protocol,t.host||x[t.protocol])r.pathname=t.pathname;else{for(var p=(t.pathname||\"\").split(\"/\");p.length&&!(t.host=p.shift()););t.host||(t.host=\"\"),t.hostname||(t.hostname=\"\"),\"\"!==p[0]&&p.unshift(\"\"),p.length<2&&p.unshift(\"\"),r.pathname=p.join(\"/\")}if(r.search=t.search,r.query=t.query,r.host=t.host||\"\",r.auth=t.auth,r.hostname=t.hostname||t.host,r.port=t.port,r.pathname||r.search){var v=r.pathname||\"\",y=r.search||\"\";r.path=v+y}return r.slashes=r.slashes||t.slashes,r.href=r.format(),r}var g=r.pathname&&\"/\"===r.pathname.charAt(0),m=t.host||t.pathname&&\"/\"===t.pathname.charAt(0),_=m||g||r.host&&t.pathname,b=_,w=r.pathname&&r.pathname.split(\"/\")||[],p=t.pathname&&t.pathname.split(\"/\")||[],E=r.protocol&&!T[r.protocol];if(E&&(r.hostname=\"\",r.port=null,r.host&&(\"\"===w[0]?w[0]=r.host:w.unshift(r.host)),r.host=\"\",t.protocol&&(t.hostname=null,t.port=null,t.host&&(\"\"===p[0]?p[0]=t.host:p.unshift(t.host)),t.host=null),_=_&&(\"\"===p[0]||\"\"===w[0])),m)r.host=t.host||\"\"===t.host?t.host:r.host,r.hostname=t.hostname||\"\"===t.hostname?t.hostname:r.hostname,r.search=t.search,r.query=t.query,w=p;else if(p.length)w||(w=[]),w.pop(),w=w.concat(p),r.search=t.search,r.query=t.query;else if(!h.isNullOrUndefined(t.search)){if(E){r.hostname=r.host=w.shift();var S=!!(r.host&&r.host.indexOf(\"@\")>0)&&r.host.split(\"@\");S&&(r.auth=S.shift(),r.host=r.hostname=S.shift())}return r.search=t.search,r.query=t.query,h.isNull(r.pathname)&&h.isNull(r.search)||(r.path=(r.pathname?r.pathname:\"\")+(r.search?r.search:\"\")),r.href=r.format(),r}if(!w.length)return r.pathname=null,r.search?r.path=\"/\"+r.search:r.path=null,r.href=r.format(),r;for(var O=w.slice(-1)[0],M=(r.host||t.host||w.length>1)&&(\".\"===O||\"..\"===O)||\"\"===O,P=0,C=w.length;C>=0;C--)O=w[C],\".\"===O?w.splice(C,1):\"..\"===O?(w.splice(C,1),P++):P&&(w.splice(C,1),P--);if(!_&&!b)for(;P--;P)w.unshift(\"..\");!_||\"\"===w[0]||w[0]&&\"/\"===w[0].charAt(0)||w.unshift(\"\"),M&&\"/\"!==w.join(\"/\").substr(-1)&&w.push(\"\");var R=\"\"===w[0]||w[0]&&\"/\"===w[0].charAt(0);if(E){r.hostname=r.host=R?\"\":w.length?w.shift():\"\";var S=!!(r.host&&r.host.indexOf(\"@\")>0)&&r.host.split(\"@\");S&&(r.auth=S.shift(),r.host=r.hostname=S.shift())}return _=_||r.host&&w.length,_&&!R&&w.unshift(\"\"),w.length?r.pathname=w.join(\"/\"):(r.pathname=null,r.path=null),h.isNull(r.pathname)&&h.isNull(r.search)||(r.path=(r.pathname?r.pathname:\"\")+(r.search?r.search:\"\")),r.auth=t.auth||r.auth,r.slashes=r.slashes||t.slashes,r.href=r.format(),r},n.prototype.parseHost=function(){var t=this.host,e=c.exec(t);e&&(e=e[0],\":\"!==e&&(this.port=e.substr(1)),t=t.substr(0,t.length-e.length)),t&&(this.hostname=t)}},{\"./util\":30,punycode:25,querystring:28}],30:[function(t,e,r){\"use strict\";e.exports={isString:function(t){return\"string\"==typeof t},isObject:function(t){return\"object\"==typeof t&&null!==t},isNull:function(t){return null===t},isNullOrUndefined:function(t){return null==t}}},{}],31:[function(t,e,r){\"use strict\";e.exports=function(t,e,r){var n,i=t.length;if(!(e>=i||0===r)){r=e+r>i?i-e:r;var o=i-r;for(n=e;n<o;++n)t[n]=t[n+r];t.length=o}}},{}],32:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var o=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&\"function\"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?\"symbol\":typeof t},s=t(\"mini-signals\"),a=n(s),u=t(\"parse-uri\"),h=n(u),l=t(\"./async\"),c=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(l),d=t(\"./Resource\"),f=n(d),p=/(#[\\w-]+)?$/,v=function(){function t(){var e=this,r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:\"\",n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:10;i(this,t),this.baseUrl=r,this.progress=0,this.loading=!1,this.defaultQueryString=\"\",this._beforeMiddleware=[],this._afterMiddleware=[],this._resourcesParsing=[],this._boundLoadResource=function(t,r){return e._loadResource(t,r)},this._queue=c.queue(this._boundLoadResource,n),this._queue.pause(),this.resources={},this.onProgress=new a.default,this.onError=new a.default,this.onLoad=new a.default,this.onStart=new a.default,this.onComplete=new a.default}return t.prototype.add=function(t,e,r,n){if(Array.isArray(t)){for(var i=0;i<t.length;++i)this.add(t[i]);return this}if(\"object\"===(void 0===t?\"undefined\":o(t))&&(n=e||t.callback||t.onComplete,r=t,e=t.url,t=t.name||t.key||t.url),\"string\"!=typeof e&&(n=r,r=e,e=t),\"string\"!=typeof e)throw new Error(\"No url passed to add resource to loader.\");if(\"function\"==typeof r&&(n=r,r=null),this.loading&&(!r||!r.parentResource))throw new Error(\"Cannot add resources while the loader is running.\");if(this.resources[t])throw new Error('Resource named \"'+t+'\" already exists.');if(e=this._prepareUrl(e),this.resources[t]=new f.default(t,e,r),\"function\"==typeof n&&this.resources[t].onAfterMiddleware.once(n),this.loading){for(var s=r.parentResource,a=[],u=0;u<s.children.length;++u)s.children[u].isComplete||a.push(s.children[u]);var h=s.progressChunk*(a.length+1),l=h/(a.length+2);s.children.push(this.resources[t]),s.progressChunk=l;for(var c=0;c<a.length;++c)a[c].progressChunk=l;this.resources[t].progressChunk=l}return this._queue.push(this.resources[t]),this},t.prototype.pre=function(t){return this._beforeMiddleware.push(t),this},t.prototype.use=function(t){return this._afterMiddleware.push(t),this},t.prototype.reset=function(){this.progress=0,this.loading=!1,this._queue.kill(),this._queue.pause();for(var t in this.resources){var e=this.resources[t];e._onLoadBinding&&e._onLoadBinding.detach(),e.isLoading&&e.abort()}return this.resources={},this},t.prototype.load=function(t){if(\"function\"==typeof t&&this.onComplete.once(t),this.loading)return this;for(var e=100/this._queue._tasks.length,r=0;r<this._queue._tasks.length;++r)this._queue._tasks[r].data.progressChunk=e;return this.loading=!0,this.onStart.dispatch(this),this._queue.resume(),this},t.prototype._prepareUrl=function(t){var e=(0,h.default)(t,{strictMode:!0}),r=void 0;if(r=e.protocol||!e.path||0===t.indexOf(\"//\")?t:this.baseUrl.length&&this.baseUrl.lastIndexOf(\"/\")!==this.baseUrl.length-1&&\"/\"!==t.charAt(0)?this.baseUrl+\"/\"+t:this.baseUrl+t,this.defaultQueryString){var n=p.exec(r)[0];r=r.substr(0,r.length-n.length),-1!==r.indexOf(\"?\")?r+=\"&\"+this.defaultQueryString:r+=\"?\"+this.defaultQueryString,r+=n}return r},t.prototype._loadResource=function(t,e){var r=this;t._dequeue=e,c.eachSeries(this._beforeMiddleware,function(e,n){e.call(r,t,function(){n(t.isComplete?{}:null)})},function(){t.isComplete?r._onLoad(t):(t._onLoadBinding=t.onComplete.once(r._onLoad,r),t.load())},!0)},t.prototype._onComplete=function(){this.loading=!1,this.onComplete.dispatch(this,this.resources)},t.prototype._onLoad=function(t){var e=this;t._onLoadBinding=null,this._resourcesParsing.push(t),t._dequeue(),c.eachSeries(this._afterMiddleware,function(r,n){r.call(e,t,n)},function(){t.onAfterMiddleware.dispatch(t),e.progress+=t.progressChunk,e.onProgress.dispatch(e,t),t.error?e.onError.dispatch(t.error,e,t):e.onLoad.dispatch(e,t),e._resourcesParsing.splice(e._resourcesParsing.indexOf(t),1),e._queue.idle()&&0===e._resourcesParsing.length&&(e.progress=100,e._onComplete())},!0)},t}();r.default=v},{\"./Resource\":33,\"./async\":34,\"mini-signals\":38,\"parse-uri\":39}],33:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(){}function s(t,e,r){e&&0===e.indexOf(\".\")&&(e=e.substring(1)),e&&(t[e]=r)}function a(t){return t.toString().replace(\"object \",\"\")}r.__esModule=!0;var u=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),h=t(\"parse-uri\"),l=n(h),c=t(\"mini-signals\"),d=n(c),f=!(!window.XDomainRequest||\"withCredentials\"in new XMLHttpRequest),p=null,v=function(){function t(e,r,n){if(i(this,t),\"string\"!=typeof e||\"string\"!=typeof r)throw new Error(\"Both name and url are required for constructing a resource.\");n=n||{},this._flags=0,this._setFlag(t.STATUS_FLAGS.DATA_URL,0===r.indexOf(\"data:\")),this.name=e,this.url=r,this.extension=this._getExtension(),this.data=null,this.crossOrigin=!0===n.crossOrigin?\"anonymous\":n.crossOrigin,this.loadType=n.loadType||this._determineLoadType(),this.xhrType=n.xhrType,this.metadata=n.metadata||{},this.error=null,this.xhr=null,this.children=[],this.type=t.TYPE.UNKNOWN,this.progressChunk=0,this._dequeue=o,this._onLoadBinding=null,this._boundComplete=this.complete.bind(this),this._boundOnError=this._onError.bind(this),this._boundOnProgress=this._onProgress.bind(this),this._boundXhrOnError=this._xhrOnError.bind(this),this._boundXhrOnAbort=this._xhrOnAbort.bind(this),this._boundXhrOnLoad=this._xhrOnLoad.bind(this),this._boundXdrOnTimeout=this._xdrOnTimeout.bind(this),this.onStart=new d.default,this.onProgress=new d.default,this.onComplete=new d.default,this.onAfterMiddleware=new d.default}return t.setExtensionLoadType=function(e,r){s(t._loadTypeMap,e,r)},t.setExtensionXhrType=function(e,r){s(t._xhrTypeMap,e,r)},t.prototype.complete=function(){if(this.data&&this.data.removeEventListener&&(this.data.removeEventListener(\"error\",this._boundOnError,!1),this.data.removeEventListener(\"load\",this._boundComplete,!1),this.data.removeEventListener(\"progress\",this._boundOnProgress,!1),this.data.removeEventListener(\"canplaythrough\",this._boundComplete,!1)),this.xhr&&(this.xhr.removeEventListener?(this.xhr.removeEventListener(\"error\",this._boundXhrOnError,!1),this.xhr.removeEventListener(\"abort\",this._boundXhrOnAbort,!1),this.xhr.removeEventListener(\"progress\",this._boundOnProgress,!1),this.xhr.removeEventListener(\"load\",this._boundXhrOnLoad,!1)):(this.xhr.onerror=null,this.xhr.ontimeout=null,this.xhr.onprogress=null,this.xhr.onload=null)),this.isComplete)throw new Error(\"Complete called again for an already completed resource.\");this._setFlag(t.STATUS_FLAGS.COMPLETE,!0),this._setFlag(t.STATUS_FLAGS.LOADING,!1),this.onComplete.dispatch(this)},t.prototype.abort=function(e){if(!this.error){if(this.error=new Error(e),this.xhr)this.xhr.abort();else if(this.xdr)this.xdr.abort();else if(this.data)if(this.data.src)this.data.src=t.EMPTY_GIF;else for(;this.data.firstChild;)this.data.removeChild(this.data.firstChild);this.complete()}},t.prototype.load=function(e){var r=this;if(!this.isLoading){if(this.isComplete)return void(e&&setTimeout(function(){return e(r)},1));switch(e&&this.onComplete.once(e),this._setFlag(t.STATUS_FLAGS.LOADING,!0),this.onStart.dispatch(this),!1!==this.crossOrigin&&\"string\"==typeof this.crossOrigin||(this.crossOrigin=this._determineCrossOrigin(this.url)),this.loadType){case t.LOAD_TYPE.IMAGE:this.type=t.TYPE.IMAGE,this._loadElement(\"image\");break;case t.LOAD_TYPE.AUDIO:this.type=t.TYPE.AUDIO,this._loadSourceElement(\"audio\");break;case t.LOAD_TYPE.VIDEO:this.type=t.TYPE.VIDEO,this._loadSourceElement(\"video\");break;case t.LOAD_TYPE.XHR:default:f&&this.crossOrigin?this._loadXdr():this._loadXhr()}}},t.prototype._hasFlag=function(t){return!!(this._flags&t)},t.prototype._setFlag=function(t,e){this._flags=e?this._flags|t:this._flags&~t},t.prototype._loadElement=function(t){this.metadata.loadElement?this.data=this.metadata.loadElement:\"image\"===t&&void 0!==window.Image?this.data=new Image:this.data=document.createElement(t),this.crossOrigin&&(this.data.crossOrigin=this.crossOrigin),this.metadata.skipSource||(this.data.src=this.url),this.data.addEventListener(\"error\",this._boundOnError,!1),this.data.addEventListener(\"load\",this._boundComplete,!1),this.data.addEventListener(\"progress\",this._boundOnProgress,!1)},t.prototype._loadSourceElement=function(t){if(this.metadata.loadElement?this.data=this.metadata.loadElement:\"audio\"===t&&void 0!==window.Audio?this.data=new Audio:this.data=document.createElement(t),null===this.data)return void this.abort(\"Unsupported element: \"+t);if(!this.metadata.skipSource)if(navigator.isCocoonJS)this.data.src=Array.isArray(this.url)?this.url[0]:this.url;else if(Array.isArray(this.url))for(var e=this.metadata.mimeType,r=0;r<this.url.length;++r)this.data.appendChild(this._createSource(t,this.url[r],Array.isArray(e)?e[r]:e));else{var n=this.metadata.mimeType;this.data.appendChild(this._createSource(t,this.url,Array.isArray(n)?n[0]:n))}this.data.addEventListener(\"error\",this._boundOnError,!1),this.data.addEventListener(\"load\",this._boundComplete,!1),this.data.addEventListener(\"progress\",this._boundOnProgress,!1),this.data.addEventListener(\"canplaythrough\",this._boundComplete,!1),this.data.load()},t.prototype._loadXhr=function(){\"string\"!=typeof this.xhrType&&(this.xhrType=this._determineXhrType());var e=this.xhr=new XMLHttpRequest;e.open(\"GET\",this.url,!0),this.xhrType===t.XHR_RESPONSE_TYPE.JSON||this.xhrType===t.XHR_RESPONSE_TYPE.DOCUMENT?e.responseType=t.XHR_RESPONSE_TYPE.TEXT:e.responseType=this.xhrType,e.addEventListener(\"error\",this._boundXhrOnError,!1),e.addEventListener(\"abort\",this._boundXhrOnAbort,!1),e.addEventListener(\"progress\",this._boundOnProgress,!1),e.addEventListener(\"load\",this._boundXhrOnLoad,!1),e.send()},t.prototype._loadXdr=function(){\"string\"!=typeof this.xhrType&&(this.xhrType=this._determineXhrType());var t=this.xhr=new XDomainRequest;t.timeout=5e3,t.onerror=this._boundXhrOnError,t.ontimeout=this._boundXdrOnTimeout,t.onprogress=this._boundOnProgress,t.onload=this._boundXhrOnLoad,t.open(\"GET\",this.url,!0),setTimeout(function(){return t.send()},1)},t.prototype._createSource=function(t,e,r){r||(r=t+\"/\"+this._getExtension(e));var n=document.createElement(\"source\");return n.src=e,n.type=r,n},t.prototype._onError=function(t){this.abort(\"Failed to load element using: \"+t.target.nodeName)},t.prototype._onProgress=function(t){t&&t.lengthComputable&&this.onProgress.dispatch(this,t.loaded/t.total)},t.prototype._xhrOnError=function(){var t=this.xhr;this.abort(a(t)+\" Request failed. Status: \"+t.status+', text: \"'+t.statusText+'\"')},t.prototype._xhrOnAbort=function(){this.abort(a(this.xhr)+\" Request was aborted by the user.\")},t.prototype._xdrOnTimeout=function(){this.abort(a(this.xhr)+\" Request timed out.\")},t.prototype._xhrOnLoad=function(){var e=this.xhr,r=\"\",n=void 0===e.status?200:e.status;if(\"\"!==e.responseType&&\"text\"!==e.responseType&&void 0!==e.responseType||(r=e.responseText),0===n&&r.length>0?n=200:1223===n&&(n=204),2!=(n/100|0))return void this.abort(\"[\"+e.status+\"] \"+e.statusText+\": \"+e.responseURL);if(this.xhrType===t.XHR_RESPONSE_TYPE.TEXT)this.data=r,this.type=t.TYPE.TEXT;else if(this.xhrType===t.XHR_RESPONSE_TYPE.JSON)try{this.data=JSON.parse(r),this.type=t.TYPE.JSON}catch(t){return void this.abort(\"Error trying to parse loaded json: \"+t)}else if(this.xhrType===t.XHR_RESPONSE_TYPE.DOCUMENT)try{if(window.DOMParser){var i=new DOMParser;this.data=i.parseFromString(r,\"text/xml\")}else{var o=document.createElement(\"div\");o.innerHTML=r,this.data=o}this.type=t.TYPE.XML}catch(t){return void this.abort(\"Error trying to parse loaded xml: \"+t)}else this.data=e.response||r;this.complete()},t.prototype._determineCrossOrigin=function(t,e){if(0===t.indexOf(\"data:\"))return\"\";e=e||window.location,p||(p=document.createElement(\"a\")),p.href=t,t=(0,l.default)(p.href,{strictMode:!0});var r=!t.port&&\"\"===e.port||t.port===e.port,n=t.protocol?t.protocol+\":\":\"\";return t.host===e.hostname&&r&&n===e.protocol?\"\":\"anonymous\"},t.prototype._determineXhrType=function(){return t._xhrTypeMap[this.extension]||t.XHR_RESPONSE_TYPE.TEXT},t.prototype._determineLoadType=function(){return t._loadTypeMap[this.extension]||t.LOAD_TYPE.XHR},t.prototype._getExtension=function(){var t=this.url,e=\"\";if(this.isDataUrl){var r=t.indexOf(\"/\");e=t.substring(r+1,t.indexOf(\";\",r))}else{var n=t.indexOf(\"?\"),i=t.indexOf(\"#\"),o=Math.min(n>-1?n:t.length,i>-1?i:t.length);t=t.substring(0,o),e=t.substring(t.lastIndexOf(\".\")+1)}return e.toLowerCase()},t.prototype._getMimeFromXhrType=function(e){switch(e){case t.XHR_RESPONSE_TYPE.BUFFER:return\"application/octet-binary\";case t.XHR_RESPONSE_TYPE.BLOB:return\"application/blob\";case t.XHR_RESPONSE_TYPE.DOCUMENT:return\"application/xml\";case t.XHR_RESPONSE_TYPE.JSON:return\"application/json\";case t.XHR_RESPONSE_TYPE.DEFAULT:case t.XHR_RESPONSE_TYPE.TEXT:default:return\"text/plain\"}},u(t,[{key:\"isDataUrl\",get:function(){return this._hasFlag(t.STATUS_FLAGS.DATA_URL)}},{key:\"isComplete\",get:function(){return this._hasFlag(t.STATUS_FLAGS.COMPLETE)}},{key:\"isLoading\",get:function(){return this._hasFlag(t.STATUS_FLAGS.LOADING)}}]),t}();r.default=v,v.STATUS_FLAGS={NONE:0,DATA_URL:1,COMPLETE:2,LOADING:4},v.TYPE={UNKNOWN:0,JSON:1,XML:2,IMAGE:3,AUDIO:4,VIDEO:5,TEXT:6},v.LOAD_TYPE={XHR:1,IMAGE:2,AUDIO:3,VIDEO:4},v.XHR_RESPONSE_TYPE={DEFAULT:\"text\",BUFFER:\"arraybuffer\",BLOB:\"blob\",DOCUMENT:\"document\",JSON:\"json\",TEXT:\"text\"},v._loadTypeMap={gif:v.LOAD_TYPE.IMAGE,png:v.LOAD_TYPE.IMAGE,bmp:v.LOAD_TYPE.IMAGE,jpg:v.LOAD_TYPE.IMAGE,jpeg:v.LOAD_TYPE.IMAGE,tif:v.LOAD_TYPE.IMAGE,tiff:v.LOAD_TYPE.IMAGE,webp:v.LOAD_TYPE.IMAGE,tga:v.LOAD_TYPE.IMAGE,svg:v.LOAD_TYPE.IMAGE,\"svg+xml\":v.LOAD_TYPE.IMAGE,mp3:v.LOAD_TYPE.AUDIO,ogg:v.LOAD_TYPE.AUDIO,wav:v.LOAD_TYPE.AUDIO,mp4:v.LOAD_TYPE.VIDEO,webm:v.LOAD_TYPE.VIDEO},v._xhrTypeMap={xhtml:v.XHR_RESPONSE_TYPE.DOCUMENT,html:v.XHR_RESPONSE_TYPE.DOCUMENT,htm:v.XHR_RESPONSE_TYPE.DOCUMENT,xml:v.XHR_RESPONSE_TYPE.DOCUMENT,tmx:v.XHR_RESPONSE_TYPE.DOCUMENT,svg:v.XHR_RESPONSE_TYPE.DOCUMENT,tsx:v.XHR_RESPONSE_TYPE.DOCUMENT,gif:v.XHR_RESPONSE_TYPE.BLOB,png:v.XHR_RESPONSE_TYPE.BLOB,bmp:v.XHR_RESPONSE_TYPE.BLOB,jpg:v.XHR_RESPONSE_TYPE.BLOB,jpeg:v.XHR_RESPONSE_TYPE.BLOB,tif:v.XHR_RESPONSE_TYPE.BLOB,tiff:v.XHR_RESPONSE_TYPE.BLOB,webp:v.XHR_RESPONSE_TYPE.BLOB,tga:v.XHR_RESPONSE_TYPE.BLOB,json:v.XHR_RESPONSE_TYPE.JSON,text:v.XHR_RESPONSE_TYPE.TEXT,txt:v.XHR_RESPONSE_TYPE.TEXT,ttf:v.XHR_RESPONSE_TYPE.BUFFER,otf:v.XHR_RESPONSE_TYPE.BUFFER},v.EMPTY_GIF=\"data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==\"},{\"mini-signals\":38,\"parse-uri\":39}],34:[function(t,e,r){\"use strict\";function n(){}function i(t,e,r,n){var i=0,o=t.length;!function s(a){if(a||i===o)return void(r&&r(a));n?setTimeout(function(){e(t[i++],s)},1):e(t[i++],s)}()}function o(t){return function(){if(null===t)throw new Error(\"Callback was already called.\");var e=t;t=null,e.apply(this,arguments)}}function s(t,e){function r(t,e,r){if(null!=r&&\"function\"!=typeof r)throw new Error(\"task callback must be a function\");if(a.started=!0,null==t&&a.idle())return void setTimeout(function(){return a.drain()},1);var i={data:t,callback:\"function\"==typeof r?r:n};e?a._tasks.unshift(i):a._tasks.push(i),setTimeout(function(){return a.process()},1)}function i(t){return function(){s-=1,t.callback.apply(t,arguments),null!=arguments[0]&&a.error(arguments[0],t.data),s<=a.concurrency-a.buffer&&a.unsaturated(),a.idle()&&a.drain(),a.process()}}if(null==e)e=1;else if(0===e)throw new Error(\"Concurrency must not be zero\");var s=0,a={_tasks:[],concurrency:e,saturated:n,unsaturated:n,buffer:e/4,empty:n,drain:n,error:n,started:!1,paused:!1,push:function(t,e){r(t,!1,e)},kill:function(){s=0,a.drain=n,a.started=!1,a._tasks=[]},unshift:function(t,e){r(t,!0,e)},process:function(){for(;!a.paused&&s<a.concurrency&&a._tasks.length;){var e=a._tasks.shift();0===a._tasks.length&&a.empty(),s+=1,s===a.concurrency&&a.saturated(),t(e.data,o(i(e)))}},length:function(){return a._tasks.length},running:function(){return s},idle:function(){return a._tasks.length+s===0},pause:function(){!0!==a.paused&&(a.paused=!0)},resume:function(){if(!1!==a.paused){a.paused=!1;for(var t=1;t<=a.concurrency;t++)a.process()}}};return a}r.__esModule=!0,r.eachSeries=i,r.queue=s},{}],35:[function(t,e,r){\"use strict\";function n(t){for(var e=\"\",r=0;r<t.length;){for(var n=[0,0,0],o=[0,0,0,0],s=0;s<n.length;++s)r<t.length?n[s]=255&t.charCodeAt(r++):n[s]=0;o[0]=n[0]>>2,o[1]=(3&n[0])<<4|n[1]>>4,o[2]=(15&n[1])<<2|n[2]>>6,o[3]=63&n[2];switch(r-(t.length-1)){case 2:o[3]=64,o[2]=64;break;case 1:o[3]=64}for(var a=0;a<o.length;++a)e+=i.charAt(o[a])}return e}r.__esModule=!0,r.encodeBinary=n;var i=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\"},{}],36:[function(t,e,r){\"use strict\";var n=t(\"./Loader\").default,i=t(\"./Resource\").default,o=t(\"./async\"),s=t(\"./b64\");n.Resource=i,n.async=o,n.base64=s,e.exports=n,e.exports.default=n},{\"./Loader\":32,\"./Resource\":33,\"./async\":34,\"./b64\":35}],37:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(){return function(t,e){if(!t.data)return void e();if(t.xhr&&t.xhrType===a.default.XHR_RESPONSE_TYPE.BLOB)if(window.Blob&&\"string\"!=typeof t.data){if(0===t.data.type.indexOf(\"image\")){var r=function(){var r=l.createObjectURL(t.data);return t.blob=t.data,t.data=new Image,t.data.src=r,t.type=a.default.TYPE.IMAGE,t.data.onload=function(){l.revokeObjectURL(r),t.data.onload=null,e()},{v:void 0}}();if(\"object\"===(void 0===r?\"undefined\":o(r)))return r.v}}else{var n=t.xhr.getResponseHeader(\"content-type\");if(n&&0===n.indexOf(\"image\"))return t.data=new Image,\nt.data.src=\"data:\"+n+\";base64,\"+h.default.encodeBinary(t.xhr.responseText),t.type=a.default.TYPE.IMAGE,void(t.data.onload=function(){t.data.onload=null,e()})}e()}}r.__esModule=!0;var o=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&\"function\"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?\"symbol\":typeof t};r.blobMiddlewareFactory=i;var s=t(\"../../Resource\"),a=n(s),u=t(\"../../b64\"),h=n(u),l=window.URL||window.webkitURL},{\"../../Resource\":33,\"../../b64\":35}],38:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){return t._head?(t._tail._next=e,e._prev=t._tail,t._tail=e):(t._head=e,t._tail=e),e._owner=t,e}Object.defineProperty(r,\"__esModule\",{value:!0});var o=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),s=function(){function t(e,r,i){void 0===r&&(r=!1),n(this,t),this._fn=e,this._once=r,this._thisArg=i,this._next=this._prev=this._owner=null}return o(t,[{key:\"detach\",value:function(){return null!==this._owner&&(this._owner.detach(this),!0)}}]),t}(),a=function(){function t(){n(this,t),this._head=this._tail=void 0}return o(t,[{key:\"handlers\",value:function(){var t=!(arguments.length<=0||void 0===arguments[0])&&arguments[0],e=this._head;if(t)return!!e;for(var r=[];e;)r.push(e),e=e._next;return r}},{key:\"has\",value:function(t){if(!(t instanceof s))throw new Error(\"MiniSignal#has(): First arg must be a MiniSignalBinding object.\");return t._owner===this}},{key:\"dispatch\",value:function(){var t=this._head;if(!t)return!1;for(;t;)t._once&&this.detach(t),t._fn.apply(t._thisArg,arguments),t=t._next;return!0}},{key:\"add\",value:function(t){var e=arguments.length<=1||void 0===arguments[1]?null:arguments[1];if(\"function\"!=typeof t)throw new Error(\"MiniSignal#add(): First arg must be a Function.\");return i(this,new s(t,!1,e))}},{key:\"once\",value:function(t){var e=arguments.length<=1||void 0===arguments[1]?null:arguments[1];if(\"function\"!=typeof t)throw new Error(\"MiniSignal#once(): First arg must be a Function.\");return i(this,new s(t,!0,e))}},{key:\"detach\",value:function(t){if(!(t instanceof s))throw new Error(\"MiniSignal#detach(): First arg must be a MiniSignalBinding object.\");return t._owner!==this?this:(t._prev&&(t._prev._next=t._next),t._next&&(t._next._prev=t._prev),t===this._head?(this._head=t._next,null===t._next&&(this._tail=null)):t===this._tail&&(this._tail=t._prev,this._tail._next=null),t._owner=null,this)}},{key:\"detachAll\",value:function(){var t=this._head;if(!t)return this;for(this._head=this._tail=null;t;)t._owner=null,t=t._next;return this}}]),t}();a.MiniSignalBinding=s,r.default=a,e.exports=r.default},{}],39:[function(t,e,r){\"use strict\";e.exports=function(t,e){e=e||{};for(var r={key:[\"source\",\"protocol\",\"authority\",\"userInfo\",\"user\",\"password\",\"host\",\"port\",\"relative\",\"path\",\"directory\",\"file\",\"query\",\"anchor\"],q:{name:\"queryKey\",parser:/(?:^|&)([^&=]*)=?([^&]*)/g},parser:{strict:/^(?:([^:\\/?#]+):)?(?:\\/\\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\\/?#]*)(?::(\\d*))?))?((((?:[^?#\\/]*\\/)*)([^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/,loose:/^(?:(?![^:@]+:[^:@\\/]*@)([^:\\/?#.]+):)?(?:\\/\\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\\/?#]*)(?::(\\d*))?)(((\\/(?:[^?#](?![^?#\\/]*\\.[^?#\\/.]+(?:[?#]|$)))*\\/?)?([^?#\\/]*))(?:\\?([^#]*))?(?:#(.*))?)/}},n=r.parser[e.strictMode?\"strict\":\"loose\"].exec(t),i={},o=14;o--;)i[r.key[o]]=n[o]||\"\";return i[r.q.name]={},i[r.key[12]].replace(r.q.parser,function(t,e,n){e&&(i[r.q.name][e]=n)}),i}},{}],40:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var o=t(\"../core\"),s=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(o),a=t(\"ismobilejs\"),u=n(a),h=t(\"./accessibleTarget\"),l=n(h);s.utils.mixins.delayMixin(s.DisplayObject.prototype,l.default);var c=100,d=0,f=0,p=2,v=function(){function t(e){i(this,t),!u.default.tablet&&!u.default.phone||navigator.isCocoonJS||this.createTouchHook();var r=document.createElement(\"div\");r.style.width=c+\"px\",r.style.height=c+\"px\",r.style.position=\"absolute\",r.style.top=d+\"px\",r.style.left=f+\"px\",r.style.zIndex=p,this.div=r,this.pool=[],this.renderId=0,this.debug=!1,this.renderer=e,this.children=[],this._onKeyDown=this._onKeyDown.bind(this),this._onMouseMove=this._onMouseMove.bind(this),this.isActive=!1,this.isMobileAccessabillity=!1,window.addEventListener(\"keydown\",this._onKeyDown,!1)}return t.prototype.createTouchHook=function(){var t=this,e=document.createElement(\"button\");e.style.width=\"1px\",e.style.height=\"1px\",e.style.position=\"absolute\",e.style.top=\"-1000px\",e.style.left=\"-1000px\",e.style.zIndex=2,e.style.backgroundColor=\"#FF0000\",e.title=\"HOOK DIV\",e.addEventListener(\"focus\",function(){t.isMobileAccessabillity=!0,t.activate(),document.body.removeChild(e)}),document.body.appendChild(e)},t.prototype.activate=function(){this.isActive||(this.isActive=!0,window.document.addEventListener(\"mousemove\",this._onMouseMove,!0),window.removeEventListener(\"keydown\",this._onKeyDown,!1),this.renderer.on(\"postrender\",this.update,this),this.renderer.view.parentNode&&this.renderer.view.parentNode.appendChild(this.div))},t.prototype.deactivate=function(){this.isActive&&!this.isMobileAccessabillity&&(this.isActive=!1,window.document.removeEventListener(\"mousemove\",this._onMouseMove),window.addEventListener(\"keydown\",this._onKeyDown,!1),this.renderer.off(\"postrender\",this.update),this.div.parentNode&&this.div.parentNode.removeChild(this.div))},t.prototype.updateAccessibleObjects=function(t){if(t.visible){t.accessible&&t.interactive&&(t._accessibleActive||this.addChild(t),t.renderId=this.renderId);for(var e=t.children,r=e.length-1;r>=0;r--)this.updateAccessibleObjects(e[r])}},t.prototype.update=function(){if(this.renderer.renderingToScreen){this.updateAccessibleObjects(this.renderer._lastObjectRendered);var t=this.renderer.view.getBoundingClientRect(),e=t.width/this.renderer.width,r=t.height/this.renderer.height,n=this.div;n.style.left=t.left+\"px\",n.style.top=t.top+\"px\",n.style.width=this.renderer.width+\"px\",n.style.height=this.renderer.height+\"px\";for(var i=0;i<this.children.length;i++){var o=this.children[i];if(o.renderId!==this.renderId)o._accessibleActive=!1,s.utils.removeItems(this.children,i,1),this.div.removeChild(o._accessibleDiv),this.pool.push(o._accessibleDiv),o._accessibleDiv=null,i--,0===this.children.length&&this.deactivate();else{n=o._accessibleDiv;var a=o.hitArea,u=o.worldTransform;o.hitArea?(n.style.left=(u.tx+a.x*u.a)*e+\"px\",n.style.top=(u.ty+a.y*u.d)*r+\"px\",n.style.width=a.width*u.a*e+\"px\",n.style.height=a.height*u.d*r+\"px\"):(a=o.getBounds(),this.capHitArea(a),n.style.left=a.x*e+\"px\",n.style.top=a.y*r+\"px\",n.style.width=a.width*e+\"px\",n.style.height=a.height*r+\"px\")}}this.renderId++}},t.prototype.capHitArea=function(t){t.x<0&&(t.width+=t.x,t.x=0),t.y<0&&(t.height+=t.y,t.y=0),t.x+t.width>this.renderer.width&&(t.width=this.renderer.width-t.x),t.y+t.height>this.renderer.height&&(t.height=this.renderer.height-t.y)},t.prototype.addChild=function(t){var e=this.pool.pop();e||(e=document.createElement(\"button\"),e.style.width=c+\"px\",e.style.height=c+\"px\",e.style.backgroundColor=this.debug?\"rgba(255,0,0,0.5)\":\"transparent\",e.style.position=\"absolute\",e.style.zIndex=p,e.style.borderStyle=\"none\",e.addEventListener(\"click\",this._onClick.bind(this)),e.addEventListener(\"focus\",this._onFocus.bind(this)),e.addEventListener(\"focusout\",this._onFocusOut.bind(this))),t.accessibleTitle?e.title=t.accessibleTitle:t.accessibleTitle||t.accessibleHint||(e.title=\"displayObject \"+this.tabIndex),t.accessibleHint&&e.setAttribute(\"aria-label\",t.accessibleHint),t._accessibleActive=!0,t._accessibleDiv=e,e.displayObject=t,this.children.push(t),this.div.appendChild(t._accessibleDiv),t._accessibleDiv.tabIndex=t.tabIndex},t.prototype._onClick=function(t){var e=this.renderer.plugins.interaction;e.dispatchEvent(t.target.displayObject,\"click\",e.eventData)},t.prototype._onFocus=function(t){var e=this.renderer.plugins.interaction;e.dispatchEvent(t.target.displayObject,\"mouseover\",e.eventData)},t.prototype._onFocusOut=function(t){var e=this.renderer.plugins.interaction;e.dispatchEvent(t.target.displayObject,\"mouseout\",e.eventData)},t.prototype._onKeyDown=function(t){9===t.keyCode&&this.activate()},t.prototype._onMouseMove=function(){this.deactivate()},t.prototype.destroy=function(){this.div=null;for(var t=0;t<this.children.length;t++)this.children[t].div=null;window.document.removeEventListener(\"mousemove\",this._onMouseMove),window.removeEventListener(\"keydown\",this._onKeyDown),this.pool=null,this.children=null,this.renderer=null},t}();r.default=v,s.WebGLRenderer.registerPlugin(\"accessibility\",v),s.CanvasRenderer.registerPlugin(\"accessibility\",v)},{\"../core\":65,\"./accessibleTarget\":41,ismobilejs:4}],41:[function(t,e,r){\"use strict\";r.__esModule=!0,r.default={accessible:!1,accessibleTitle:null,accessibleHint:null,tabIndex:0,_accessibleActive:!1,_accessibleDiv:!1}},{}],42:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0;var i=t(\"./accessibleTarget\");Object.defineProperty(r,\"accessibleTarget\",{enumerable:!0,get:function(){return n(i).default}});var o=t(\"./AccessibilityManager\");Object.defineProperty(r,\"AccessibilityManager\",{enumerable:!0,get:function(){return n(o).default}})},{\"./AccessibilityManager\":40,\"./accessibleTarget\":41}],43:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var o=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),s=t(\"./autoDetectRenderer\"),a=t(\"./display/Container\"),u=n(a),h=t(\"./ticker\"),l=t(\"./settings\"),c=n(l),d=t(\"./const\"),f=function(){function t(e,r,n,o,a){i(this,t),\"number\"==typeof e&&(e=Object.assign({width:e,height:r||c.default.RENDER_OPTIONS.height,forceCanvas:!!o,sharedTicker:!!a},n)),this._options=e=Object.assign({autoStart:!0,sharedTicker:!1,forceCanvas:!1,sharedLoader:!1},e),this.renderer=(0,s.autoDetectRenderer)(e),this.stage=new u.default,this._ticker=null,this.ticker=e.sharedTicker?h.shared:new h.Ticker,e.autoStart&&this.start()}return t.prototype.render=function(){this.renderer.render(this.stage)},t.prototype.stop=function(){this._ticker.stop()},t.prototype.start=function(){this._ticker.start()},t.prototype.destroy=function(t){var e=this._ticker;this.ticker=null,e.destroy(),this.stage.destroy(),this.stage=null,this.renderer.destroy(t),this.renderer=null,this._options=null},o(t,[{key:\"ticker\",set:function(t){this._ticker&&this._ticker.remove(this.render,this),this._ticker=t,t&&t.add(this.render,this,d.UPDATE_PRIORITY.LOW)},get:function(){return this._ticker}},{key:\"view\",get:function(){return this.renderer.view}},{key:\"screen\",get:function(){return this.renderer.screen}}]),t}();r.default=f},{\"./autoDetectRenderer\":45,\"./const\":46,\"./display/Container\":48,\"./settings\":101,\"./ticker\":121}],44:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function s(t,e){if(t instanceof Array){if(\"precision\"!==t[0].substring(0,9)){var r=t.slice(0);return r.unshift(\"precision \"+e+\" float;\"),r}}else if(\"precision\"!==t.substring(0,9))return\"precision \"+e+\" float;\\n\"+t;return t}r.__esModule=!0;var a=t(\"pixi-gl-core\"),u=t(\"./settings\"),h=function(t){return t&&t.__esModule?t:{default:t}}(u),l=function(t){function e(r,o,a){return n(this,e),i(this,t.call(this,r,s(o,h.default.PRECISION_VERTEX),s(a,h.default.PRECISION_FRAGMENT)))}return o(e,t),e}(a.GLShader);r.default=l},{\"./settings\":101,\"pixi-gl-core\":12}],45:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e,r,n){var i=t&&t.forceCanvas;return void 0!==n&&(i=n),!i&&s.isWebGLSupported()?new l.default(t,e,r):new u.default(t,e,r)}r.__esModule=!0,r.autoDetectRenderer=i;var o=t(\"./utils\"),s=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(o),a=t(\"./renderers/canvas/CanvasRenderer\"),u=n(a),h=t(\"./renderers/webgl/WebGLRenderer\"),l=n(h)},{\"./renderers/canvas/CanvasRenderer\":77,\"./renderers/webgl/WebGLRenderer\":84,\"./utils\":125}],46:[function(t,e,r){\"use strict\";r.__esModule=!0;r.VERSION=\"4.6.1\",r.PI_2=2*Math.PI,r.RAD_TO_DEG=180/Math.PI,r.DEG_TO_RAD=Math.PI/180,r.RENDERER_TYPE={UNKNOWN:0,WEBGL:1,CANVAS:2},r.BLEND_MODES={NORMAL:0,ADD:1,MULTIPLY:2,SCREEN:3,OVERLAY:4,DARKEN:5,LIGHTEN:6,COLOR_DODGE:7,COLOR_BURN:8,HARD_LIGHT:9,SOFT_LIGHT:10,DIFFERENCE:11,EXCLUSION:12,HUE:13,SATURATION:14,COLOR:15,LUMINOSITY:16,NORMAL_NPM:17,ADD_NPM:18,SCREEN_NPM:19},r.DRAW_MODES={POINTS:0,LINES:1,LINE_LOOP:2,LINE_STRIP:3,TRIANGLES:4,TRIANGLE_STRIP:5,TRIANGLE_FAN:6},r.SCALE_MODES={LINEAR:0,NEAREST:1},r.WRAP_MODES={CLAMP:0,REPEAT:1,MIRRORED_REPEAT:2},r.GC_MODES={AUTO:0,MANUAL:1},r.URL_FILE_EXTENSION=/\\.(\\w{3,4})(?:$|\\?|#)/i,r.DATA_URI=/^\\s*data:(?:([\\w-]+)\\/([\\w+.-]+))?(?:;(charset=[\\w-]+|base64))?,(.*)/i,r.SVG_SIZE=/<svg[^>]*(?:\\s(width|height)=('|\")(\\d*(?:\\.\\d+)?)(?:px)?('|\"))[^>]*(?:\\s(width|height)=('|\")(\\d*(?:\\.\\d+)?)(?:px)?('|\"))[^>]*>/i,r.SHAPES={POLY:0,RECT:1,CIRC:2,ELIP:3,RREC:4},r.PRECISION={LOW:\"lowp\",MEDIUM:\"mediump\",HIGH:\"highp\"},r.TRANSFORM_MODE={STATIC:0,DYNAMIC:1},r.TEXT_GRADIENT={LINEAR_VERTICAL:0,LINEAR_HORIZONTAL:1},r.UPDATE_PRIORITY={INTERACTION:50,HIGH:25,NORMAL:0,LOW:-25,UTILITY:-50}},{}],47:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../math\"),o=function(){function t(){n(this,t),this.minX=1/0,this.minY=1/0,this.maxX=-1/0,this.maxY=-1/0,this.rect=null}return t.prototype.isEmpty=function(){return this.minX>this.maxX||this.minY>this.maxY},t.prototype.clear=function(){this.updateID++,this.minX=1/0,this.minY=1/0,this.maxX=-1/0,this.maxY=-1/0},t.prototype.getRectangle=function(t){return this.minX>this.maxX||this.minY>this.maxY?i.Rectangle.EMPTY:(t=t||new i.Rectangle(0,0,1,1),t.x=this.minX,t.y=this.minY,t.width=this.maxX-this.minX,t.height=this.maxY-this.minY,t)},t.prototype.addPoint=function(t){this.minX=Math.min(this.minX,t.x),this.maxX=Math.max(this.maxX,t.x),this.minY=Math.min(this.minY,t.y),this.maxY=Math.max(this.maxY,t.y)},t.prototype.addQuad=function(t){var e=this.minX,r=this.minY,n=this.maxX,i=this.maxY,o=t[0],s=t[1];e=o<e?o:e,r=s<r?s:r,n=o>n?o:n,i=s>i?s:i,o=t[2],s=t[3],e=o<e?o:e,r=s<r?s:r,n=o>n?o:n,i=s>i?s:i,o=t[4],s=t[5],e=o<e?o:e,r=s<r?s:r,n=o>n?o:n,i=s>i?s:i,o=t[6],s=t[7],e=o<e?o:e,r=s<r?s:r,n=o>n?o:n,i=s>i?s:i,this.minX=e,this.minY=r,this.maxX=n,this.maxY=i},t.prototype.addFrame=function(t,e,r,n,i){var o=t.worldTransform,s=o.a,a=o.b,u=o.c,h=o.d,l=o.tx,c=o.ty,d=this.minX,f=this.minY,p=this.maxX,v=this.maxY,y=s*e+u*r+l,g=a*e+h*r+c;d=y<d?y:d,f=g<f?g:f,p=y>p?y:p,v=g>v?g:v,y=s*n+u*r+l,g=a*n+h*r+c,d=y<d?y:d,f=g<f?g:f,p=y>p?y:p,v=g>v?g:v,y=s*e+u*i+l,g=a*e+h*i+c,d=y<d?y:d,f=g<f?g:f,p=y>p?y:p,v=g>v?g:v,y=s*n+u*i+l,g=a*n+h*i+c,d=y<d?y:d,f=g<f?g:f,p=y>p?y:p,v=g>v?g:v,this.minX=d,this.minY=f,this.maxX=p,this.maxY=v},t.prototype.addVertices=function(t,e,r,n){for(var i=t.worldTransform,o=i.a,s=i.b,a=i.c,u=i.d,h=i.tx,l=i.ty,c=this.minX,d=this.minY,f=this.maxX,p=this.maxY,v=r;v<n;v+=2){var y=e[v],g=e[v+1],m=o*y+a*g+h,_=u*g+s*y+l;c=m<c?m:c,d=_<d?_:d,f=m>f?m:f,p=_>p?_:p}this.minX=c,this.minY=d,this.maxX=f,this.maxY=p},t.prototype.addBounds=function(t){var e=this.minX,r=this.minY,n=this.maxX,i=this.maxY;this.minX=t.minX<e?t.minX:e,this.minY=t.minY<r?t.minY:r,this.maxX=t.maxX>n?t.maxX:n,this.maxY=t.maxY>i?t.maxY:i},t.prototype.addBoundsMask=function(t,e){var r=t.minX>e.minX?t.minX:e.minX,n=t.minY>e.minY?t.minY:e.minY,i=t.maxX<e.maxX?t.maxX:e.maxX,o=t.maxY<e.maxY?t.maxY:e.maxY;if(r<=i&&n<=o){var s=this.minX,a=this.minY,u=this.maxX,h=this.maxY;this.minX=r<s?r:s,this.minY=n<a?n:a,this.maxX=i>u?i:u,this.maxY=o>h?o:h}},t.prototype.addBoundsArea=function(t,e){var r=t.minX>e.x?t.minX:e.x,n=t.minY>e.y?t.minY:e.y,i=t.maxX<e.x+e.width?t.maxX:e.x+e.width,o=t.maxY<e.y+e.height?t.maxY:e.y+e.height;if(r<=i&&n<=o){var s=this.minX,a=this.minY,u=this.maxX,h=this.maxY;this.minX=r<s?r:s,this.minY=n<a?n:a,this.maxX=i>u?i:u,this.maxY=o>h?o:h}},t}();r.default=o},{\"../math\":70}],48:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"../utils\"),u=t(\"./DisplayObject\"),h=function(t){return t&&t.__esModule?t:{default:t}}(u),l=function(t){function e(){n(this,e);var r=i(this,t.call(this));return r.children=[],r}return o(e,t),e.prototype.onChildrenChange=function(){},e.prototype.addChild=function(t){var e=arguments.length;if(e>1)for(var r=0;r<e;r++)this.addChild(arguments[r]);else t.parent&&t.parent.removeChild(t),t.parent=this,t.transform._parentID=-1,this.children.push(t),this._boundsID++,this.onChildrenChange(this.children.length-1),t.emit(\"added\",this);return t},e.prototype.addChildAt=function(t,e){if(e<0||e>this.children.length)throw new Error(t+\"addChildAt: The index \"+e+\" supplied is out of bounds \"+this.children.length);return t.parent&&t.parent.removeChild(t),t.parent=this,t.transform._parentID=-1,this.children.splice(e,0,t),this._boundsID++,this.onChildrenChange(e),t.emit(\"added\",this),t},e.prototype.swapChildren=function(t,e){if(t!==e){var r=this.getChildIndex(t),n=this.getChildIndex(e);this.children[r]=e,this.children[n]=t,this.onChildrenChange(r<n?r:n)}},e.prototype.getChildIndex=function(t){var e=this.children.indexOf(t);if(-1===e)throw new Error(\"The supplied DisplayObject must be a child of the caller\");return e},e.prototype.setChildIndex=function(t,e){if(e<0||e>=this.children.length)throw new Error(\"The supplied index is out of bounds\");var r=this.getChildIndex(t);(0,a.removeItems)(this.children,r,1),this.children.splice(e,0,t),this.onChildrenChange(e)},e.prototype.getChildAt=function(t){if(t<0||t>=this.children.length)throw new Error(\"getChildAt: Index (\"+t+\") does not exist.\");return this.children[t]},e.prototype.removeChild=function(t){var e=arguments.length;if(e>1)for(var r=0;r<e;r++)this.removeChild(arguments[r]);else{var n=this.children.indexOf(t);if(-1===n)return null;t.parent=null,t.transform._parentID=-1,(0,a.removeItems)(this.children,n,1),this._boundsID++,this.onChildrenChange(n),t.emit(\"removed\",this)}return t},e.prototype.removeChildAt=function(t){var e=this.getChildAt(t);return e.parent=null,e.transform._parentID=-1,(0,a.removeItems)(this.children,t,1),this._boundsID++,this.onChildrenChange(t),e.emit(\"removed\",this),e},e.prototype.removeChildren=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments[1],r=t,n=\"number\"==typeof e?e:this.children.length,i=n-r,o=void 0;if(i>0&&i<=n){o=this.children.splice(r,i);for(var s=0;s<o.length;++s)o[s].parent=null,o[s].transform&&(o[s].transform._parentID=-1);this._boundsID++,this.onChildrenChange(t);for(var a=0;a<o.length;++a)o[a].emit(\"removed\",this);return o}if(0===i&&0===this.children.length)return[];throw new RangeError(\"removeChildren: numeric values are outside the acceptable range.\")},e.prototype.updateTransform=function(){this._boundsID++,this.transform.updateTransform(this.parent.transform),this.worldAlpha=this.alpha*this.parent.worldAlpha;for(var t=0,e=this.children.length;t<e;++t){var r=this.children[t];r.visible&&r.updateTransform()}},e.prototype.calculateBounds=function(){this._bounds.clear(),this._calculateBounds();for(var t=0;t<this.children.length;t++){var e=this.children[t];e.visible&&e.renderable&&(e.calculateBounds(),e._mask?(e._mask.calculateBounds(),this._bounds.addBoundsMask(e._bounds,e._mask._bounds)):e.filterArea?this._bounds.addBoundsArea(e._bounds,e.filterArea):this._bounds.addBounds(e._bounds))}this._lastBoundsID=this._boundsID},e.prototype._calculateBounds=function(){},e.prototype.renderWebGL=function(t){if(this.visible&&!(this.worldAlpha<=0)&&this.renderable)if(this._mask||this._filters)this.renderAdvancedWebGL(t);else{this._renderWebGL(t);for(var e=0,r=this.children.length;e<r;++e)this.children[e].renderWebGL(t)}},e.prototype.renderAdvancedWebGL=function(t){t.flush();var e=this._filters,r=this._mask;if(e){this._enabledFilters||(this._enabledFilters=[]),this._enabledFilters.length=0;for(var n=0;n<e.length;n++)e[n].enabled&&this._enabledFilters.push(e[n]);this._enabledFilters.length&&t.filterManager.pushFilter(this,this._enabledFilters)}r&&t.maskManager.pushMask(this,this._mask),this._renderWebGL(t);for(var i=0,o=this.children.length;i<o;i++)this.children[i].renderWebGL(t);t.flush(),r&&t.maskManager.popMask(this,this._mask),e&&this._enabledFilters&&this._enabledFilters.length&&t.filterManager.popFilter()},e.prototype._renderWebGL=function(t){},e.prototype._renderCanvas=function(t){},e.prototype.renderCanvas=function(t){if(this.visible&&!(this.worldAlpha<=0)&&this.renderable){this._mask&&t.maskManager.pushMask(this._mask),this._renderCanvas(t);for(var e=0,r=this.children.length;e<r;++e)this.children[e].renderCanvas(t);this._mask&&t.maskManager.popMask(t)}},e.prototype.destroy=function(e){t.prototype.destroy.call(this);var r=\"boolean\"==typeof e?e:e&&e.children,n=this.removeChildren(0,this.children.length);if(r)for(var i=0;i<n.length;++i)n[i].destroy(e)},s(e,[{key:\"width\",get:function(){return this.scale.x*this.getLocalBounds().width},set:function(t){var e=this.getLocalBounds().width;this.scale.x=0!==e?t/e:1,this._width=t}},{key:\"height\",get:function(){return this.scale.y*this.getLocalBounds().height},set:function(t){var e=this.getLocalBounds().height;this.scale.y=0!==e?t/e:1,this._height=t}}]),e}(h.default);r.default=l,l.prototype.containerUpdateTransform=l.prototype.updateTransform},{\"../utils\":125,\"./DisplayObject\":49}],49:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),u=t(\"eventemitter3\"),h=n(u),l=t(\"../const\"),c=t(\"../settings\"),d=n(c),f=t(\"./TransformStatic\"),p=n(f),v=t(\"./Transform\"),y=n(v),g=t(\"./Bounds\"),m=n(g),_=t(\"../math\"),b=function(t){function e(){i(this,e);var r=o(this,t.call(this)),n=d.default.TRANSFORM_MODE===l.TRANSFORM_MODE.STATIC?p.default:y.default;return r.tempDisplayObjectParent=null,r.transform=new n,r.alpha=1,r.visible=!0,r.renderable=!0,r.parent=null,r.worldAlpha=1,r.filterArea=null,r._filters=null,r._enabledFilters=null,r._bounds=new m.default,r._boundsID=0,r._lastBoundsID=-1,r._boundsRect=null,r._localBoundsRect=null,r._mask=null,r._destroyed=!1,r}return s(e,t),e.prototype.updateTransform=function(){this.transform.updateTransform(this.parent.transform),this.worldAlpha=this.alpha*this.parent.worldAlpha,this._bounds.updateID++},e.prototype._recursivePostUpdateTransform=function(){this.parent?(this.parent._recursivePostUpdateTransform(),this.transform.updateTransform(this.parent.transform)):this.transform.updateTransform(this._tempDisplayObjectParent.transform)},e.prototype.getBounds=function(t,e){return t||(this.parent?(this._recursivePostUpdateTransform(),this.updateTransform()):(this.parent=this._tempDisplayObjectParent,this.updateTransform(),this.parent=null)),this._boundsID!==this._lastBoundsID&&this.calculateBounds(),e||(this._boundsRect||(this._boundsRect=new _.Rectangle),e=this._boundsRect),this._bounds.getRectangle(e)},e.prototype.getLocalBounds=function(t){var e=this.transform,r=this.parent;this.parent=null,this.transform=this._tempDisplayObjectParent.transform,t||(this._localBoundsRect||(this._localBoundsRect=new _.Rectangle),t=this._localBoundsRect);var n=this.getBounds(!1,t);return this.parent=r,this.transform=e,n},e.prototype.toGlobal=function(t,e){return arguments.length>2&&void 0!==arguments[2]&&arguments[2]||(this._recursivePostUpdateTransform(),this.parent?this.displayObjectUpdateTransform():(this.parent=this._tempDisplayObjectParent,this.displayObjectUpdateTransform(),this.parent=null)),this.worldTransform.apply(t,e)},e.prototype.toLocal=function(t,e,r,n){return e&&(t=e.toGlobal(t,r,n)),n||(this._recursivePostUpdateTransform(),this.parent?this.displayObjectUpdateTransform():(this.parent=this._tempDisplayObjectParent,this.displayObjectUpdateTransform(),this.parent=null)),this.worldTransform.applyInverse(t,r)},e.prototype.renderWebGL=function(t){},e.prototype.renderCanvas=function(t){},e.prototype.setParent=function(t){if(!t||!t.addChild)throw new Error(\"setParent: Argument must be a Container\");return t.addChild(this),t},e.prototype.setTransform=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:1,i=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,o=arguments.length>5&&void 0!==arguments[5]?arguments[5]:0,s=arguments.length>6&&void 0!==arguments[6]?arguments[6]:0,a=arguments.length>7&&void 0!==arguments[7]?arguments[7]:0,u=arguments.length>8&&void 0!==arguments[8]?arguments[8]:0;return this.position.x=t,this.position.y=e,this.scale.x=r||1,this.scale.y=n||1,this.rotation=i,this.skew.x=o,this.skew.y=s,this.pivot.x=a,this.pivot.y=u,this},e.prototype.destroy=function(){this.removeAllListeners(),this.parent&&this.parent.removeChild(this),this.transform=null,this.parent=null,this._bounds=null,this._currentBounds=null,this._mask=null,this.filterArea=null,this.interactive=!1,this.interactiveChildren=!1,this._destroyed=!0},a(e,[{key:\"_tempDisplayObjectParent\",get:function(){return null===this.tempDisplayObjectParent&&(this.tempDisplayObjectParent=new e),this.tempDisplayObjectParent}},{key:\"x\",get:function(){return this.position.x},set:function(t){this.transform.position.x=t}},{key:\"y\",get:function(){return this.position.y},set:function(t){this.transform.position.y=t}},{key:\"worldTransform\",get:function(){return this.transform.worldTransform}},{key:\"localTransform\",get:function(){return this.transform.localTransform}},{key:\"position\",get:function(){return this.transform.position},set:function(t){this.transform.position.copy(t)}},{key:\"scale\",get:function(){return this.transform.scale},set:function(t){this.transform.scale.copy(t)}},{key:\"pivot\",get:function(){return this.transform.pivot},set:function(t){this.transform.pivot.copy(t)}},{key:\"skew\",get:function(){return this.transform.skew},set:function(t){this.transform.skew.copy(t)}},{key:\"rotation\",get:function(){return this.transform.rotation},set:function(t){this.transform.rotation=t}},{key:\"worldVisible\",get:function(){var t=this;do{if(!t.visible)return!1;t=t.parent}while(t);return!0}},{key:\"mask\",get:function(){return this._mask},set:function(t){this._mask&&(this._mask.renderable=!0),this._mask=t,this._mask&&(this._mask.renderable=!1)}},{key:\"filters\",get:function(){return this._filters&&this._filters.slice()},set:function(t){this._filters=t&&t.slice()}}]),e}(h.default);r.default=b,b.prototype.displayObjectUpdateTransform=b.prototype.updateTransform},{\"../const\":46,\"../math\":70,\"../settings\":101,\"./Bounds\":47,\"./Transform\":50,\"./TransformStatic\":52,eventemitter3:3}],50:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"../math\"),u=t(\"./TransformBase\"),h=function(t){return t&&t.__esModule?t:{default:t}}(u),l=function(t){function e(){n(this,e);var r=i(this,t.call(this));return r.position=new a.Point(0,0),r.scale=new a.Point(1,1),r.skew=new a.ObservablePoint(r.updateSkew,r,0,0),r.pivot=new a.Point(0,0),r._rotation=0,r._cx=1,r._sx=0,r._cy=0,r._sy=1,r}return o(e,t),e.prototype.updateSkew=function(){this._cx=Math.cos(this._rotation+this.skew._y),this._sx=Math.sin(this._rotation+this.skew._y),this._cy=-Math.sin(this._rotation-this.skew._x),this._sy=Math.cos(this._rotation-this.skew._x)},e.prototype.updateLocalTransform=function(){var t=this.localTransform;t.a=this._cx*this.scale.x,t.b=this._sx*this.scale.x,t.c=this._cy*this.scale.y,t.d=this._sy*this.scale.y,t.tx=this.position.x-(this.pivot.x*t.a+this.pivot.y*t.c),t.ty=this.position.y-(this.pivot.x*t.b+this.pivot.y*t.d)},e.prototype.updateTransform=function(t){var e=this.localTransform;e.a=this._cx*this.scale.x,e.b=this._sx*this.scale.x,e.c=this._cy*this.scale.y,e.d=this._sy*this.scale.y,e.tx=this.position.x-(this.pivot.x*e.a+this.pivot.y*e.c),e.ty=this.position.y-(this.pivot.x*e.b+this.pivot.y*e.d);var r=t.worldTransform,n=this.worldTransform;n.a=e.a*r.a+e.b*r.c,n.b=e.a*r.b+e.b*r.d,n.c=e.c*r.a+e.d*r.c,n.d=e.c*r.b+e.d*r.d,n.tx=e.tx*r.a+e.ty*r.c+r.tx,n.ty=e.tx*r.b+e.ty*r.d+r.ty,this._worldID++},e.prototype.setFromMatrix=function(t){t.decompose(this)},s(e,[{key:\"rotation\",get:function(){return this._rotation},set:function(t){this._rotation=t,this.updateSkew()}}]),e}(h.default);r.default=l},{\"../math\":70,\n\"./TransformBase\":51}],51:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../math\"),o=function(){function t(){n(this,t),this.worldTransform=new i.Matrix,this.localTransform=new i.Matrix,this._worldID=0,this._parentID=0}return t.prototype.updateLocalTransform=function(){},t.prototype.updateTransform=function(t){var e=t.worldTransform,r=this.worldTransform,n=this.localTransform;r.a=n.a*e.a+n.b*e.c,r.b=n.a*e.b+n.b*e.d,r.c=n.c*e.a+n.d*e.c,r.d=n.c*e.b+n.d*e.d,r.tx=n.tx*e.a+n.ty*e.c+e.tx,r.ty=n.tx*e.b+n.ty*e.d+e.ty,this._worldID++},t}();r.default=o,o.prototype.updateWorldTransform=o.prototype.updateTransform,o.IDENTITY=new o},{\"../math\":70}],52:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"../math\"),u=t(\"./TransformBase\"),h=function(t){return t&&t.__esModule?t:{default:t}}(u),l=function(t){function e(){n(this,e);var r=i(this,t.call(this));return r.position=new a.ObservablePoint(r.onChange,r,0,0),r.scale=new a.ObservablePoint(r.onChange,r,1,1),r.pivot=new a.ObservablePoint(r.onChange,r,0,0),r.skew=new a.ObservablePoint(r.updateSkew,r,0,0),r._rotation=0,r._cx=1,r._sx=0,r._cy=0,r._sy=1,r._localID=0,r._currentLocalID=0,r}return o(e,t),e.prototype.onChange=function(){this._localID++},e.prototype.updateSkew=function(){this._cx=Math.cos(this._rotation+this.skew._y),this._sx=Math.sin(this._rotation+this.skew._y),this._cy=-Math.sin(this._rotation-this.skew._x),this._sy=Math.cos(this._rotation-this.skew._x),this._localID++},e.prototype.updateLocalTransform=function(){var t=this.localTransform;this._localID!==this._currentLocalID&&(t.a=this._cx*this.scale._x,t.b=this._sx*this.scale._x,t.c=this._cy*this.scale._y,t.d=this._sy*this.scale._y,t.tx=this.position._x-(this.pivot._x*t.a+this.pivot._y*t.c),t.ty=this.position._y-(this.pivot._x*t.b+this.pivot._y*t.d),this._currentLocalID=this._localID,this._parentID=-1)},e.prototype.updateTransform=function(t){var e=this.localTransform;if(this._localID!==this._currentLocalID&&(e.a=this._cx*this.scale._x,e.b=this._sx*this.scale._x,e.c=this._cy*this.scale._y,e.d=this._sy*this.scale._y,e.tx=this.position._x-(this.pivot._x*e.a+this.pivot._y*e.c),e.ty=this.position._y-(this.pivot._x*e.b+this.pivot._y*e.d),this._currentLocalID=this._localID,this._parentID=-1),this._parentID!==t._worldID){var r=t.worldTransform,n=this.worldTransform;n.a=e.a*r.a+e.b*r.c,n.b=e.a*r.b+e.b*r.d,n.c=e.c*r.a+e.d*r.c,n.d=e.c*r.b+e.d*r.d,n.tx=e.tx*r.a+e.ty*r.c+r.tx,n.ty=e.tx*r.b+e.ty*r.d+r.ty,this._parentID=t._worldID,this._worldID++}},e.prototype.setFromMatrix=function(t){t.decompose(this),this._localID++},s(e,[{key:\"rotation\",get:function(){return this._rotation},set:function(t){this._rotation=t,this.updateSkew()}}]),e}(h.default);r.default=l},{\"../math\":70,\"./TransformBase\":51}],53:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"../display/Container\"),u=n(a),h=t(\"../textures/RenderTexture\"),l=n(h),c=t(\"../textures/Texture\"),d=n(c),f=t(\"./GraphicsData\"),p=n(f),v=t(\"../sprites/Sprite\"),y=n(v),g=t(\"../math\"),m=t(\"../utils\"),_=t(\"../const\"),b=t(\"../display/Bounds\"),x=n(b),T=t(\"./utils/bezierCurveTo\"),w=n(T),E=t(\"../renderers/canvas/CanvasRenderer\"),S=n(E),O=void 0,M=new g.Matrix,P=new g.Point,C=new Float32Array(4),R=new Float32Array(4),A=function(t){function e(){var r=arguments.length>0&&void 0!==arguments[0]&&arguments[0];i(this,e);var n=o(this,t.call(this));return n.fillAlpha=1,n.lineWidth=0,n.nativeLines=r,n.lineColor=0,n.graphicsData=[],n.tint=16777215,n._prevTint=16777215,n.blendMode=_.BLEND_MODES.NORMAL,n.currentPath=null,n._webGL={},n.isMask=!1,n.boundsPadding=0,n._localBounds=new x.default,n.dirty=0,n.fastRectDirty=-1,n.clearDirty=0,n.boundsDirty=-1,n.cachedSpriteDirty=!1,n._spriteRect=null,n._fastRect=!1,n}return s(e,t),e.prototype.clone=function(){var t=new e;t.renderable=this.renderable,t.fillAlpha=this.fillAlpha,t.lineWidth=this.lineWidth,t.lineColor=this.lineColor,t.tint=this.tint,t.blendMode=this.blendMode,t.isMask=this.isMask,t.boundsPadding=this.boundsPadding,t.dirty=0,t.cachedSpriteDirty=this.cachedSpriteDirty;for(var r=0;r<this.graphicsData.length;++r)t.graphicsData.push(this.graphicsData[r].clone());return t.currentPath=t.graphicsData[t.graphicsData.length-1],t.updateLocalBounds(),t},e.prototype.lineStyle=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1;if(this.lineWidth=t,this.lineColor=e,this.lineAlpha=r,this.currentPath)if(this.currentPath.shape.points.length){var n=new g.Polygon(this.currentPath.shape.points.slice(-2));n.closed=!1,this.drawShape(n)}else this.currentPath.lineWidth=this.lineWidth,this.currentPath.lineColor=this.lineColor,this.currentPath.lineAlpha=this.lineAlpha;return this},e.prototype.moveTo=function(t,e){var r=new g.Polygon([t,e]);return r.closed=!1,this.drawShape(r),this},e.prototype.lineTo=function(t,e){return this.currentPath.shape.points.push(t,e),this.dirty++,this},e.prototype.quadraticCurveTo=function(t,e,r,n){this.currentPath?0===this.currentPath.shape.points.length&&(this.currentPath.shape.points=[0,0]):this.moveTo(0,0);var i=this.currentPath.shape.points,o=0,s=0;0===i.length&&this.moveTo(0,0);for(var a=i[i.length-2],u=i[i.length-1],h=1;h<=20;++h){var l=h/20;o=a+(t-a)*l,s=u+(e-u)*l,i.push(o+(t+(r-t)*l-o)*l,s+(e+(n-e)*l-s)*l)}return this.dirty++,this},e.prototype.bezierCurveTo=function(t,e,r,n,i,o){this.currentPath?0===this.currentPath.shape.points.length&&(this.currentPath.shape.points=[0,0]):this.moveTo(0,0);var s=this.currentPath.shape.points,a=s[s.length-2],u=s[s.length-1];return s.length-=2,(0,w.default)(a,u,t,e,r,n,i,o,s),this.dirty++,this},e.prototype.arcTo=function(t,e,r,n,i){this.currentPath?0===this.currentPath.shape.points.length&&this.currentPath.shape.points.push(t,e):this.moveTo(t,e);var o=this.currentPath.shape.points,s=o[o.length-2],a=o[o.length-1],u=a-e,h=s-t,l=n-e,c=r-t,d=Math.abs(u*c-h*l);if(d<1e-8||0===i)o[o.length-2]===t&&o[o.length-1]===e||o.push(t,e);else{var f=u*u+h*h,p=l*l+c*c,v=u*l+h*c,y=i*Math.sqrt(f)/d,g=i*Math.sqrt(p)/d,m=y*v/f,_=g*v/p,b=y*c+g*h,x=y*l+g*u,T=h*(g+m),w=u*(g+m),E=c*(y+_),S=l*(y+_),O=Math.atan2(w-x,T-b),M=Math.atan2(S-x,E-b);this.arc(b+t,x+e,i,O,M,h*l>c*u)}return this.dirty++,this},e.prototype.arc=function(t,e,r,n,i){var o=arguments.length>5&&void 0!==arguments[5]&&arguments[5];if(n===i)return this;!o&&i<=n?i+=2*Math.PI:o&&n<=i&&(n+=2*Math.PI);var s=i-n,a=40*Math.ceil(Math.abs(s)/(2*Math.PI));if(0===s)return this;var u=t+Math.cos(n)*r,h=e+Math.sin(n)*r,l=this.currentPath?this.currentPath.shape.points:null;l?l[l.length-2]===u&&l[l.length-1]===h||l.push(u,h):(this.moveTo(u,h),l=this.currentPath.shape.points);for(var c=s/(2*a),d=2*c,f=Math.cos(c),p=Math.sin(c),v=a-1,y=v%1/v,g=0;g<=v;++g){var m=g+y*g,_=c+n+d*m,b=Math.cos(_),x=-Math.sin(_);l.push((f*b+p*x)*r+t,(f*-x+p*b)*r+e)}return this.dirty++,this},e.prototype.beginFill=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;return this.filling=!0,this.fillColor=t,this.fillAlpha=e,this.currentPath&&this.currentPath.shape.points.length<=2&&(this.currentPath.fill=this.filling,this.currentPath.fillColor=this.fillColor,this.currentPath.fillAlpha=this.fillAlpha),this},e.prototype.endFill=function(){return this.filling=!1,this.fillColor=null,this.fillAlpha=1,this},e.prototype.drawRect=function(t,e,r,n){return this.drawShape(new g.Rectangle(t,e,r,n)),this},e.prototype.drawRoundedRect=function(t,e,r,n,i){return this.drawShape(new g.RoundedRectangle(t,e,r,n,i)),this},e.prototype.drawCircle=function(t,e,r){return this.drawShape(new g.Circle(t,e,r)),this},e.prototype.drawEllipse=function(t,e,r,n){return this.drawShape(new g.Ellipse(t,e,r,n)),this},e.prototype.drawPolygon=function(t){var e=t,r=!0;if(e instanceof g.Polygon&&(r=e.closed,e=e.points),!Array.isArray(e)){e=new Array(arguments.length);for(var n=0;n<e.length;++n)e[n]=arguments[n]}var i=new g.Polygon(e);return i.closed=r,this.drawShape(i),this},e.prototype.clear=function(){return(this.lineWidth||this.filling||this.graphicsData.length>0)&&(this.lineWidth=0,this.filling=!1,this.boundsDirty=-1,this.dirty++,this.clearDirty++,this.graphicsData.length=0),this.currentPath=null,this._spriteRect=null,this},e.prototype.isFastRect=function(){return 1===this.graphicsData.length&&this.graphicsData[0].shape.type===_.SHAPES.RECT&&!this.graphicsData[0].lineWidth},e.prototype._renderWebGL=function(t){this.dirty!==this.fastRectDirty&&(this.fastRectDirty=this.dirty,this._fastRect=this.isFastRect()),this._fastRect?this._renderSpriteRect(t):(t.setObjectRenderer(t.plugins.graphics),t.plugins.graphics.render(this))},e.prototype._renderSpriteRect=function(t){var e=this.graphicsData[0].shape;this._spriteRect||(this._spriteRect=new y.default(new d.default(d.default.WHITE)));var r=this._spriteRect;if(16777215===this.tint)r.tint=this.graphicsData[0].fillColor;else{var n=C,i=R;(0,m.hex2rgb)(this.graphicsData[0].fillColor,n),(0,m.hex2rgb)(this.tint,i),n[0]*=i[0],n[1]*=i[1],n[2]*=i[2],r.tint=(0,m.rgb2hex)(n)}r.alpha=this.graphicsData[0].fillAlpha,r.worldAlpha=this.worldAlpha*r.alpha,r.blendMode=this.blendMode,r._texture._frame.width=e.width,r._texture._frame.height=e.height,r.transform.worldTransform=this.transform.worldTransform,r.anchor.set(-e.x/e.width,-e.y/e.height),r._onAnchorUpdate(),r._renderWebGL(t)},e.prototype._renderCanvas=function(t){!0!==this.isMask&&t.plugins.graphics.render(this)},e.prototype._calculateBounds=function(){this.boundsDirty!==this.dirty&&(this.boundsDirty=this.dirty,this.updateLocalBounds(),this.cachedSpriteDirty=!0);var t=this._localBounds;this._bounds.addFrame(this.transform,t.minX,t.minY,t.maxX,t.maxY)},e.prototype.containsPoint=function(t){this.worldTransform.applyInverse(t,P);for(var e=this.graphicsData,r=0;r<e.length;++r){var n=e[r];if(n.fill&&(n.shape&&n.shape.contains(P.x,P.y))){if(n.holes)for(var i=0;i<n.holes.length;i++){var o=n.holes[i];if(o.contains(P.x,P.y))return!1}return!0}}return!1},e.prototype.updateLocalBounds=function(){var t=1/0,e=-1/0,r=1/0,n=-1/0;if(this.graphicsData.length)for(var i=0,o=0,s=0,a=0,u=0,h=0;h<this.graphicsData.length;h++){var l=this.graphicsData[h],c=l.type,d=l.lineWidth;if(i=l.shape,c===_.SHAPES.RECT||c===_.SHAPES.RREC)o=i.x-d/2,s=i.y-d/2,a=i.width+d,u=i.height+d,t=o<t?o:t,e=o+a>e?o+a:e,r=s<r?s:r,n=s+u>n?s+u:n;else if(c===_.SHAPES.CIRC)o=i.x,s=i.y,a=i.radius+d/2,u=i.radius+d/2,t=o-a<t?o-a:t,e=o+a>e?o+a:e,r=s-u<r?s-u:r,n=s+u>n?s+u:n;else if(c===_.SHAPES.ELIP)o=i.x,s=i.y,a=i.width+d/2,u=i.height+d/2,t=o-a<t?o-a:t,e=o+a>e?o+a:e,r=s-u<r?s-u:r,n=s+u>n?s+u:n;else for(var f=i.points,p=0,v=0,y=0,g=0,m=0,b=0,x=0,T=0,w=0;w+2<f.length;w+=2)o=f[w],s=f[w+1],p=f[w+2],v=f[w+3],y=Math.abs(p-o),g=Math.abs(v-s),u=d,(a=Math.sqrt(y*y+g*g))<1e-9||(m=(u/a*g+y)/2,b=(u/a*y+g)/2,x=(p+o)/2,T=(v+s)/2,t=x-m<t?x-m:t,e=x+m>e?x+m:e,r=T-b<r?T-b:r,n=T+b>n?T+b:n)}else t=0,e=0,r=0,n=0;var E=this.boundsPadding;this._localBounds.minX=t-E,this._localBounds.maxX=e+E,this._localBounds.minY=r-E,this._localBounds.maxY=n+E},e.prototype.drawShape=function(t){this.currentPath&&this.currentPath.shape.points.length<=2&&this.graphicsData.pop(),this.currentPath=null;var e=new p.default(this.lineWidth,this.lineColor,this.lineAlpha,this.fillColor,this.fillAlpha,this.filling,this.nativeLines,t);return this.graphicsData.push(e),e.type===_.SHAPES.POLY&&(e.shape.closed=e.shape.closed||this.filling,this.currentPath=e),this.dirty++,e},e.prototype.generateCanvasTexture=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,r=this.getLocalBounds(),n=l.default.create(r.width,r.height,t,e);O||(O=new S.default),this.transform.updateLocalTransform(),this.transform.localTransform.copy(M),M.invert(),M.tx-=r.x,M.ty-=r.y,O.render(this,n,!0,M);var i=d.default.fromCanvas(n.baseTexture._canvasRenderTarget.canvas,t,\"graphics\");return i.baseTexture.resolution=e,i.baseTexture.update(),i},e.prototype.closePath=function(){var t=this.currentPath;return t&&t.shape&&t.shape.close(),this},e.prototype.addHole=function(){var t=this.graphicsData.pop();return this.currentPath=this.graphicsData[this.graphicsData.length-1],this.currentPath.addHole(t.shape),this.currentPath=null,this},e.prototype.destroy=function(e){t.prototype.destroy.call(this,e);for(var r=0;r<this.graphicsData.length;++r)this.graphicsData[r].destroy();for(var n in this._webgl)for(var i=0;i<this._webgl[n].data.length;++i)this._webgl[n].data[i].destroy();this._spriteRect&&this._spriteRect.destroy(),this.graphicsData=null,this.currentPath=null,this._webgl=null,this._localBounds=null},e}(u.default);r.default=A,A._SPRITE_TEXTURE=null},{\"../const\":46,\"../display/Bounds\":47,\"../display/Container\":48,\"../math\":70,\"../renderers/canvas/CanvasRenderer\":77,\"../sprites/Sprite\":102,\"../textures/RenderTexture\":113,\"../textures/Texture\":115,\"../utils\":125,\"./GraphicsData\":54,\"./utils/bezierCurveTo\":56}],54:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(e,r,i,o,s,a,u,h){n(this,t),this.lineWidth=e,this.nativeLines=u,this.lineColor=r,this.lineAlpha=i,this._lineTint=r,this.fillColor=o,this.fillAlpha=s,this._fillTint=o,this.fill=a,this.holes=[],this.shape=h,this.type=h.type}return t.prototype.clone=function(){return new t(this.lineWidth,this.lineColor,this.lineAlpha,this.fillColor,this.fillAlpha,this.fill,this.nativeLines,this.shape)},t.prototype.addHole=function(t){this.holes.push(t)},t.prototype.destroy=function(){this.shape=null,this.holes=null},t}();r.default=i},{}],55:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../../renderers/canvas/CanvasRenderer\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=t(\"../../const\"),a=function(){function t(e){n(this,t),this.renderer=e}return t.prototype.render=function(t){var e=this.renderer,r=e.context,n=t.worldAlpha,i=t.transform.worldTransform,o=e.resolution;this._prevTint!==this.tint&&(this.dirty=!0),r.setTransform(i.a*o,i.b*o,i.c*o,i.d*o,i.tx*o,i.ty*o),t.dirty&&(this.updateGraphicsTint(t),t.dirty=!1),e.setBlendMode(t.blendMode);for(var a=0;a<t.graphicsData.length;a++){var u=t.graphicsData[a],h=u.shape,l=u._fillTint,c=u._lineTint;if(r.lineWidth=u.lineWidth,u.type===s.SHAPES.POLY){r.beginPath(),this.renderPolygon(h.points,h.closed,r);for(var d=0;d<u.holes.length;d++)this.renderPolygon(u.holes[d].points,!0,r);u.fill&&(r.globalAlpha=u.fillAlpha*n,r.fillStyle=\"#\"+(\"00000\"+(0|l).toString(16)).substr(-6),r.fill()),u.lineWidth&&(r.globalAlpha=u.lineAlpha*n,r.strokeStyle=\"#\"+(\"00000\"+(0|c).toString(16)).substr(-6),r.stroke())}else if(u.type===s.SHAPES.RECT)(u.fillColor||0===u.fillColor)&&(r.globalAlpha=u.fillAlpha*n,r.fillStyle=\"#\"+(\"00000\"+(0|l).toString(16)).substr(-6),r.fillRect(h.x,h.y,h.width,h.height)),u.lineWidth&&(r.globalAlpha=u.lineAlpha*n,r.strokeStyle=\"#\"+(\"00000\"+(0|c).toString(16)).substr(-6),r.strokeRect(h.x,h.y,h.width,h.height));else if(u.type===s.SHAPES.CIRC)r.beginPath(),r.arc(h.x,h.y,h.radius,0,2*Math.PI),r.closePath(),u.fill&&(r.globalAlpha=u.fillAlpha*n,r.fillStyle=\"#\"+(\"00000\"+(0|l).toString(16)).substr(-6),r.fill()),u.lineWidth&&(r.globalAlpha=u.lineAlpha*n,r.strokeStyle=\"#\"+(\"00000\"+(0|c).toString(16)).substr(-6),r.stroke());else if(u.type===s.SHAPES.ELIP){var f=2*h.width,p=2*h.height,v=h.x-f/2,y=h.y-p/2;r.beginPath();var g=f/2*.5522848,m=p/2*.5522848,_=v+f,b=y+p,x=v+f/2,T=y+p/2;r.moveTo(v,T),r.bezierCurveTo(v,T-m,x-g,y,x,y),r.bezierCurveTo(x+g,y,_,T-m,_,T),r.bezierCurveTo(_,T+m,x+g,b,x,b),r.bezierCurveTo(x-g,b,v,T+m,v,T),r.closePath(),u.fill&&(r.globalAlpha=u.fillAlpha*n,r.fillStyle=\"#\"+(\"00000\"+(0|l).toString(16)).substr(-6),r.fill()),u.lineWidth&&(r.globalAlpha=u.lineAlpha*n,r.strokeStyle=\"#\"+(\"00000\"+(0|c).toString(16)).substr(-6),r.stroke())}else if(u.type===s.SHAPES.RREC){var w=h.x,E=h.y,S=h.width,O=h.height,M=h.radius,P=Math.min(S,O)/2|0;M=M>P?P:M,r.beginPath(),r.moveTo(w,E+M),r.lineTo(w,E+O-M),r.quadraticCurveTo(w,E+O,w+M,E+O),r.lineTo(w+S-M,E+O),r.quadraticCurveTo(w+S,E+O,w+S,E+O-M),r.lineTo(w+S,E+M),r.quadraticCurveTo(w+S,E,w+S-M,E),r.lineTo(w+M,E),r.quadraticCurveTo(w,E,w,E+M),r.closePath(),(u.fillColor||0===u.fillColor)&&(r.globalAlpha=u.fillAlpha*n,r.fillStyle=\"#\"+(\"00000\"+(0|l).toString(16)).substr(-6),r.fill()),u.lineWidth&&(r.globalAlpha=u.lineAlpha*n,r.strokeStyle=\"#\"+(\"00000\"+(0|c).toString(16)).substr(-6),r.stroke())}}},t.prototype.updateGraphicsTint=function(t){t._prevTint=t.tint;for(var e=(t.tint>>16&255)/255,r=(t.tint>>8&255)/255,n=(255&t.tint)/255,i=0;i<t.graphicsData.length;++i){var o=t.graphicsData[i],s=0|o.fillColor,a=0|o.lineColor;o._fillTint=((s>>16&255)/255*e*255<<16)+((s>>8&255)/255*r*255<<8)+(255&s)/255*n*255,o._lineTint=((a>>16&255)/255*e*255<<16)+((a>>8&255)/255*r*255<<8)+(255&a)/255*n*255}},t.prototype.renderPolygon=function(t,e,r){r.moveTo(t[0],t[1]);for(var n=1;n<t.length/2;++n)r.lineTo(t[2*n],t[2*n+1]);e&&r.closePath()},t.prototype.destroy=function(){this.renderer=null},t}();r.default=a,o.default.registerPlugin(\"graphics\",a)},{\"../../const\":46,\"../../renderers/canvas/CanvasRenderer\":77}],56:[function(t,e,r){\"use strict\";function n(t,e,r,n,i,o,s,a){var u=arguments.length>8&&void 0!==arguments[8]?arguments[8]:[],h=0,l=0,c=0,d=0,f=0;u.push(t,e);for(var p=1,v=0;p<=20;++p)v=p/20,h=1-v,l=h*h,c=l*h,d=v*v,f=d*v,u.push(c*t+3*l*v*r+3*h*d*i+f*s,c*e+3*l*v*n+3*h*d*o+f*a);return u}r.__esModule=!0,r.default=n},{}],57:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"../../utils\"),u=t(\"../../const\"),h=t(\"../../renderers/webgl/utils/ObjectRenderer\"),l=n(h),c=t(\"../../renderers/webgl/WebGLRenderer\"),d=n(c),f=t(\"./WebGLGraphicsData\"),p=n(f),v=t(\"./shaders/PrimitiveShader\"),y=n(v),g=t(\"./utils/buildPoly\"),m=n(g),_=t(\"./utils/buildRectangle\"),b=n(_),x=t(\"./utils/buildRoundedRectangle\"),T=n(x),w=t(\"./utils/buildCircle\"),E=n(w),S=function(t){function e(r){i(this,e);var n=o(this,t.call(this,r));return n.graphicsDataPool=[],n.primitiveShader=null,n.gl=r.gl,n.CONTEXT_UID=0,n}return s(e,t),e.prototype.onContextChange=function(){this.gl=this.renderer.gl,this.CONTEXT_UID=this.renderer.CONTEXT_UID,this.primitiveShader=new y.default(this.gl)},e.prototype.destroy=function(){l.default.prototype.destroy.call(this);for(var t=0;t<this.graphicsDataPool.length;++t)this.graphicsDataPool[t].destroy();this.graphicsDataPool=null},e.prototype.render=function(t){var e=this.renderer,r=e.gl,n=void 0,i=t._webGL[this.CONTEXT_UID];i&&t.dirty===i.dirty||(this.updateGraphics(t),i=t._webGL[this.CONTEXT_UID]);var o=this.primitiveShader;e.bindShader(o),e.state.setBlendMode(t.blendMode);for(var s=0,u=i.data.length;s<u;s++){n=i.data[s];var h=n.shader;e.bindShader(h),h.uniforms.translationMatrix=t.transform.worldTransform.toArray(!0),h.uniforms.tint=(0,a.hex2rgb)(t.tint),h.uniforms.alpha=t.worldAlpha,e.bindVao(n.vao),n.nativeLines?r.drawArrays(r.LINES,0,n.points.length/6):n.vao.draw(r.TRIANGLE_STRIP,n.indices.length)}},e.prototype.updateGraphics=function(t){var e=this.renderer.gl,r=t._webGL[this.CONTEXT_UID];if(r||(r=t._webGL[this.CONTEXT_UID]={lastIndex:0,data:[],gl:e,clearDirty:-1,dirty:-1}),r.dirty=t.dirty,t.clearDirty!==r.clearDirty){r.clearDirty=t.clearDirty;for(var n=0;n<r.data.length;n++)this.graphicsDataPool.push(r.data[n]);r.data.length=0,r.lastIndex=0}for(var i=void 0,o=void 0,s=r.lastIndex;s<t.graphicsData.length;s++){var a=t.graphicsData[s];i=this.getWebGLData(r,0),a.nativeLines&&a.lineWidth&&(o=this.getWebGLData(r,0,!0),r.lastIndex++),a.type===u.SHAPES.POLY&&(0,m.default)(a,i,o),a.type===u.SHAPES.RECT?(0,b.default)(a,i,o):a.type===u.SHAPES.CIRC||a.type===u.SHAPES.ELIP?(0,E.default)(a,i,o):a.type===u.SHAPES.RREC&&(0,T.default)(a,i,o),r.lastIndex++}this.renderer.bindVao(null);for(var h=0;h<r.data.length;h++)i=r.data[h],i.dirty&&i.upload()},e.prototype.getWebGLData=function(t,e,r){var n=t.data[t.data.length-1];return(!n||n.nativeLines!==r||n.points.length>32e4)&&(n=this.graphicsDataPool.pop()||new p.default(this.renderer.gl,this.primitiveShader,this.renderer.state.attribsState),n.nativeLines=r,n.reset(e),t.data.push(n)),n.dirty=!0,n},e}(l.default);r.default=S,d.default.registerPlugin(\"graphics\",S)},{\"../../const\":46,\"../../renderers/webgl/WebGLRenderer\":84,\"../../renderers/webgl/utils/ObjectRenderer\":94,\"../../utils\":125,\"./WebGLGraphicsData\":58,\"./shaders/PrimitiveShader\":59,\"./utils/buildCircle\":60,\"./utils/buildPoly\":62,\"./utils/buildRectangle\":63,\"./utils/buildRoundedRectangle\":64}],58:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"pixi-gl-core\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=function(){function t(e,r,i){n(this,t),this.gl=e,this.color=[0,0,0],this.points=[],this.indices=[],this.buffer=o.default.GLBuffer.createVertexBuffer(e),this.indexBuffer=o.default.GLBuffer.createIndexBuffer(e),this.dirty=!0,this.nativeLines=!1,this.glPoints=null,this.glIndices=null,this.shader=r,this.vao=new o.default.VertexArrayObject(e,i).addIndex(this.indexBuffer).addAttribute(this.buffer,r.attributes.aVertexPosition,e.FLOAT,!1,24,0).addAttribute(this.buffer,r.attributes.aColor,e.FLOAT,!1,24,8)}return t.prototype.reset=function(){this.points.length=0,this.indices.length=0},t.prototype.upload=function(){this.glPoints=new Float32Array(this.points),this.buffer.upload(this.glPoints),this.glIndices=new Uint16Array(this.indices),this.indexBuffer.upload(this.glIndices),this.dirty=!1},t.prototype.destroy=function(){this.color=null,this.points=null,this.indices=null,this.vao.destroy(),this.buffer.destroy(),this.indexBuffer.destroy(),this.gl=null,this.buffer=null,this.indexBuffer=null,this.glPoints=null,this.glIndices=null},t}();r.default=s},{\"pixi-gl-core\":12}],59:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=t(\"../../../Shader\"),a=function(t){return t&&t.__esModule?t:{default:t}}(s),u=function(t){function e(r){return n(this,e),i(this,t.call(this,r,[\"attribute vec2 aVertexPosition;\",\"attribute vec4 aColor;\",\"uniform mat3 translationMatrix;\",\"uniform mat3 projectionMatrix;\",\"uniform float alpha;\",\"uniform vec3 tint;\",\"varying vec4 vColor;\",\"void main(void){\",\"   gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\",\"   vColor = aColor * vec4(tint * alpha, alpha);\",\"}\"].join(\"\\n\"),[\"varying vec4 vColor;\",\"void main(void){\",\"   gl_FragColor = vColor;\",\"}\"].join(\"\\n\")))}return o(e,t),e}(a.default);r.default=u},{\"../../../Shader\":44}],60:[function(t,e,r){\"use strict\";function n(t,e,r){var n=t.shape,i=n.x,u=n.y,h=void 0,l=void 0;if(t.type===s.SHAPES.CIRC?(h=n.radius,l=n.radius):(h=n.width,l=n.height),0!==h&&0!==l){var c=Math.floor(30*Math.sqrt(n.radius))||Math.floor(15*Math.sqrt(n.width+n.height)),d=2*Math.PI/c;if(t.fill){var f=(0,a.hex2rgb)(t.fillColor),p=t.fillAlpha,v=f[0]*p,y=f[1]*p,g=f[2]*p,m=e.points,_=e.indices,b=m.length/6;_.push(b);for(var x=0;x<c+1;x++)m.push(i,u,v,y,g,p),m.push(i+Math.sin(d*x)*h,u+Math.cos(d*x)*l,v,y,g,p),_.push(b++,b++);_.push(b-1)}if(t.lineWidth){var T=t.points;t.points=[];for(var w=0;w<c+1;w++)t.points.push(i+Math.sin(d*w)*h,u+Math.cos(d*w)*l);(0,o.default)(t,e,r),t.points=T}}}r.__esModule=!0,r.default=n;var i=t(\"./buildLine\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=t(\"../../../const\"),a=t(\"../../../utils\")},{\"../../../const\":46,\"../../../utils\":125,\"./buildLine\":61}],61:[function(t,e,r){\"use strict\";function n(t,e){var r=t.points;if(0!==r.length){var n=new o.Point(r[0],r[1]),i=new o.Point(r[r.length-2],r[r.length-1]);if(n.x===i.x&&n.y===i.y){r=r.slice(),r.pop(),r.pop(),i=new o.Point(r[r.length-2],r[r.length-1]);var a=i.x+.5*(n.x-i.x),u=i.y+.5*(n.y-i.y);r.unshift(a,u),r.push(a,u)}var h=e.points,l=e.indices,c=r.length/2,d=r.length,f=h.length/6,p=t.lineWidth/2,v=(0,s.hex2rgb)(t.lineColor),y=t.lineAlpha,g=v[0]*y,m=v[1]*y,_=v[2]*y,b=r[0],x=r[1],T=r[2],w=r[3],E=0,S=0,O=-(x-w),M=b-T,P=0,C=0,R=0,A=0,I=Math.sqrt(O*O+M*M);O/=I,M/=I,O*=p,M*=p,h.push(b-O,x-M,g,m,_,y),h.push(b+O,x+M,g,m,_,y);for(var D=1;D<c-1;++D){b=r[2*(D-1)],x=r[2*(D-1)+1],T=r[2*D],w=r[2*D+1],E=r[2*(D+1)],S=r[2*(D+1)+1],O=-(x-w),M=b-T,I=Math.sqrt(O*O+M*M),O/=I,M/=I,O*=p,M*=p,P=-(w-S),C=T-E,I=Math.sqrt(P*P+C*C),P/=I,C/=I,P*=p,C*=p;var L=-M+x-(-M+w),N=-O+T-(-O+b),F=(-O+b)*(-M+w)-(-O+T)*(-M+x),B=-C+S-(-C+w),k=-P+T-(-P+E),j=(-P+E)*(-C+w)-(-P+T)*(-C+S),U=L*k-B*N;if(Math.abs(U)<.1)U+=10.1,h.push(T-O,w-M,g,m,_,y),h.push(T+O,w+M,g,m,_,y);else{var X=(N*j-k*F)/U,G=(B*F-L*j)/U;(X-T)*(X-T)+(G-w)*(G-w)>196*p*p?(R=O-P,A=M-C,I=Math.sqrt(R*R+A*A),R/=I,A/=I,R*=p,A*=p,h.push(T-R,w-A),h.push(g,m,_,y),h.push(T+R,w+A),h.push(g,m,_,y),h.push(T-R,w-A),h.push(g,m,_,y),d++):(h.push(X,G),h.push(g,m,_,y),h.push(T-(X-T),w-(G-w)),h.push(g,m,_,y))}}b=r[2*(c-2)],x=r[2*(c-2)+1],T=r[2*(c-1)],w=r[2*(c-1)+1],O=-(x-w),M=b-T,I=Math.sqrt(O*O+M*M),O/=I,M/=I,O*=p,M*=p,h.push(T-O,w-M),h.push(g,m,_,y),h.push(T+O,w+M),h.push(g,m,_,y),l.push(f);for(var W=0;W<d;++W)l.push(f++);l.push(f-1)}}function i(t,e){var r=0,n=t.points;if(0!==n.length){var i=e.points,o=n.length/2,a=(0,s.hex2rgb)(t.lineColor),u=t.lineAlpha,h=a[0]*u,l=a[1]*u,c=a[2]*u;for(r=1;r<o;r++){var d=n[2*(r-1)],f=n[2*(r-1)+1],p=n[2*r],v=n[2*r+1];i.push(d,f),i.push(h,l,c,u),i.push(p,v),i.push(h,l,c,u)}}}r.__esModule=!0,r.default=function(t,e,r){t.nativeLines?i(t,r):n(t,e)};var o=t(\"../../../math\"),s=t(\"../../../utils\")},{\"../../../math\":70,\"../../../utils\":125}],62:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e,r){t.points=t.shape.points.slice();var n=t.points;if(t.fill&&n.length>=6){for(var i=[],o=t.holes,u=0;u<o.length;u++){var l=o[u];i.push(n.length/2),n=n.concat(l.points)}var c=e.points,d=e.indices,f=n.length/2,p=(0,a.hex2rgb)(t.fillColor),v=t.fillAlpha,y=p[0]*v,g=p[1]*v,m=p[2]*v,_=(0,h.default)(n,i,2);if(!_)return;for(var b=c.length/6,x=0;x<_.length;x+=3)d.push(_[x]+b),d.push(_[x]+b),d.push(_[x+1]+b),d.push(_[x+2]+b),d.push(_[x+2]+b);for(var T=0;T<f;T++)c.push(n[2*T],n[2*T+1],y,g,m,v)}t.lineWidth>0&&(0,s.default)(t,e,r)}r.__esModule=!0,r.default=i;var o=t(\"./buildLine\"),s=n(o),a=t(\"../../../utils\"),u=t(\"earcut\"),h=n(u)},{\"../../../utils\":125,\"./buildLine\":61,earcut:2}],63:[function(t,e,r){\"use strict\";function n(t,e,r){var n=t.shape,i=n.x,a=n.y,u=n.width,h=n.height;if(t.fill){var l=(0,s.hex2rgb)(t.fillColor),c=t.fillAlpha,d=l[0]*c,f=l[1]*c,p=l[2]*c,v=e.points,y=e.indices,g=v.length/6;v.push(i,a),v.push(d,f,p,c),v.push(i+u,a),v.push(d,f,p,c),v.push(i,a+h),v.push(d,f,p,c),v.push(i+u,a+h),v.push(d,f,p,c),y.push(g,g,g+1,g+2,g+3,g+3)}if(t.lineWidth){var m=t.points;t.points=[i,a,i+u,a,i+u,a+h,i,a+h,i,a],(0,o.default)(t,e,r),t.points=m}}r.__esModule=!0,r.default=n;var i=t(\"./buildLine\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=t(\"../../../utils\")},{\"../../../utils\":125,\"./buildLine\":61}],64:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e,r){var n=t.shape,i=n.x,o=n.y,a=n.width,h=n.height,d=n.radius,f=[];if(f.push(i,o+d),s(i,o+h-d,i,o+h,i+d,o+h,f),s(i+a-d,o+h,i+a,o+h,i+a,o+h-d,f),s(i+a,o+d,i+a,o,i+a-d,o,f),s(i+d,o,i,o,i,o+d+1e-10,f),t.fill){for(var p=(0,c.hex2rgb)(t.fillColor),v=t.fillAlpha,y=p[0]*v,g=p[1]*v,m=p[2]*v,_=e.points,b=e.indices,x=_.length/6,T=(0,u.default)(f,null,2),w=0,E=T.length;w<E;w+=3)b.push(T[w]+x),b.push(T[w]+x),b.push(T[w+1]+x),b.push(T[w+2]+x),b.push(T[w+2]+x);for(var S=0,O=f.length;S<O;S++)_.push(f[S],f[++S],y,g,m,v)}if(t.lineWidth){var M=t.points;t.points=f,(0,l.default)(t,e,r),t.points=M}}function o(t,e,r){return t+(e-t)*r}function s(t,e,r,n,i,s){for(var a=arguments.length>6&&void 0!==arguments[6]?arguments[6]:[],u=a,h=0,l=0,c=0,d=0,f=0,p=0,v=0,y=0;v<=20;++v)y=v/20,h=o(t,r,y),l=o(e,n,y),c=o(r,i,y),d=o(n,s,y),f=o(h,c,y),p=o(l,d,y),u.push(f,p);return u}r.__esModule=!0,r.default=i;var a=t(\"earcut\"),u=n(a),h=t(\"./buildLine\"),l=n(h),c=t(\"../../../utils\")},{\"../../../utils\":125,\"./buildLine\":61,earcut:2}],65:[function(t,e,r){\"use strict\";function n(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}function i(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0,r.autoDetectRenderer=r.Application=r.Filter=r.SpriteMaskFilter=r.Quad=r.RenderTarget=r.ObjectRenderer=r.WebGLManager=r.Shader=r.CanvasRenderTarget=r.TextureUvs=r.VideoBaseTexture=r.BaseRenderTexture=r.RenderTexture=r.BaseTexture=r.TextureMatrix=r.Texture=r.Spritesheet=r.CanvasGraphicsRenderer=r.GraphicsRenderer=r.GraphicsData=r.Graphics=r.TextMetrics=r.TextStyle=r.Text=r.SpriteRenderer=r.CanvasTinter=r.CanvasSpriteRenderer=r.Sprite=r.TransformBase=r.TransformStatic=r.Transform=r.Container=r.DisplayObject=r.Bounds=r.glCore=r.WebGLRenderer=r.CanvasRenderer=r.ticker=r.utils=r.settings=void 0;var o=t(\"./const\");Object.keys(o).forEach(function(t){\"default\"!==t&&\"__esModule\"!==t&&Object.defineProperty(r,t,{enumerable:!0,get:function(){return o[t]}})});var s=t(\"./math\");Object.keys(s).forEach(function(t){\"default\"!==t&&\"__esModule\"!==t&&Object.defineProperty(r,t,{enumerable:!0,get:function(){return s[t]}})});var a=t(\"pixi-gl-core\");Object.defineProperty(r,\"glCore\",{enumerable:!0,get:function(){return i(a).default}});var u=t(\"./display/Bounds\")\n;Object.defineProperty(r,\"Bounds\",{enumerable:!0,get:function(){return i(u).default}});var h=t(\"./display/DisplayObject\");Object.defineProperty(r,\"DisplayObject\",{enumerable:!0,get:function(){return i(h).default}});var l=t(\"./display/Container\");Object.defineProperty(r,\"Container\",{enumerable:!0,get:function(){return i(l).default}});var c=t(\"./display/Transform\");Object.defineProperty(r,\"Transform\",{enumerable:!0,get:function(){return i(c).default}});var d=t(\"./display/TransformStatic\");Object.defineProperty(r,\"TransformStatic\",{enumerable:!0,get:function(){return i(d).default}});var f=t(\"./display/TransformBase\");Object.defineProperty(r,\"TransformBase\",{enumerable:!0,get:function(){return i(f).default}});var p=t(\"./sprites/Sprite\");Object.defineProperty(r,\"Sprite\",{enumerable:!0,get:function(){return i(p).default}});var v=t(\"./sprites/canvas/CanvasSpriteRenderer\");Object.defineProperty(r,\"CanvasSpriteRenderer\",{enumerable:!0,get:function(){return i(v).default}});var y=t(\"./sprites/canvas/CanvasTinter\");Object.defineProperty(r,\"CanvasTinter\",{enumerable:!0,get:function(){return i(y).default}});var g=t(\"./sprites/webgl/SpriteRenderer\");Object.defineProperty(r,\"SpriteRenderer\",{enumerable:!0,get:function(){return i(g).default}});var m=t(\"./text/Text\");Object.defineProperty(r,\"Text\",{enumerable:!0,get:function(){return i(m).default}});var _=t(\"./text/TextStyle\");Object.defineProperty(r,\"TextStyle\",{enumerable:!0,get:function(){return i(_).default}});var b=t(\"./text/TextMetrics\");Object.defineProperty(r,\"TextMetrics\",{enumerable:!0,get:function(){return i(b).default}});var x=t(\"./graphics/Graphics\");Object.defineProperty(r,\"Graphics\",{enumerable:!0,get:function(){return i(x).default}});var T=t(\"./graphics/GraphicsData\");Object.defineProperty(r,\"GraphicsData\",{enumerable:!0,get:function(){return i(T).default}});var w=t(\"./graphics/webgl/GraphicsRenderer\");Object.defineProperty(r,\"GraphicsRenderer\",{enumerable:!0,get:function(){return i(w).default}});var E=t(\"./graphics/canvas/CanvasGraphicsRenderer\");Object.defineProperty(r,\"CanvasGraphicsRenderer\",{enumerable:!0,get:function(){return i(E).default}});var S=t(\"./textures/Spritesheet\");Object.defineProperty(r,\"Spritesheet\",{enumerable:!0,get:function(){return i(S).default}});var O=t(\"./textures/Texture\");Object.defineProperty(r,\"Texture\",{enumerable:!0,get:function(){return i(O).default}});var M=t(\"./textures/TextureMatrix\");Object.defineProperty(r,\"TextureMatrix\",{enumerable:!0,get:function(){return i(M).default}});var P=t(\"./textures/BaseTexture\");Object.defineProperty(r,\"BaseTexture\",{enumerable:!0,get:function(){return i(P).default}});var C=t(\"./textures/RenderTexture\");Object.defineProperty(r,\"RenderTexture\",{enumerable:!0,get:function(){return i(C).default}});var R=t(\"./textures/BaseRenderTexture\");Object.defineProperty(r,\"BaseRenderTexture\",{enumerable:!0,get:function(){return i(R).default}});var A=t(\"./textures/VideoBaseTexture\");Object.defineProperty(r,\"VideoBaseTexture\",{enumerable:!0,get:function(){return i(A).default}});var I=t(\"./textures/TextureUvs\");Object.defineProperty(r,\"TextureUvs\",{enumerable:!0,get:function(){return i(I).default}});var D=t(\"./renderers/canvas/utils/CanvasRenderTarget\");Object.defineProperty(r,\"CanvasRenderTarget\",{enumerable:!0,get:function(){return i(D).default}});var L=t(\"./Shader\");Object.defineProperty(r,\"Shader\",{enumerable:!0,get:function(){return i(L).default}});var N=t(\"./renderers/webgl/managers/WebGLManager\");Object.defineProperty(r,\"WebGLManager\",{enumerable:!0,get:function(){return i(N).default}});var F=t(\"./renderers/webgl/utils/ObjectRenderer\");Object.defineProperty(r,\"ObjectRenderer\",{enumerable:!0,get:function(){return i(F).default}});var B=t(\"./renderers/webgl/utils/RenderTarget\");Object.defineProperty(r,\"RenderTarget\",{enumerable:!0,get:function(){return i(B).default}});var k=t(\"./renderers/webgl/utils/Quad\");Object.defineProperty(r,\"Quad\",{enumerable:!0,get:function(){return i(k).default}});var j=t(\"./renderers/webgl/filters/spriteMask/SpriteMaskFilter\");Object.defineProperty(r,\"SpriteMaskFilter\",{enumerable:!0,get:function(){return i(j).default}});var U=t(\"./renderers/webgl/filters/Filter\");Object.defineProperty(r,\"Filter\",{enumerable:!0,get:function(){return i(U).default}});var X=t(\"./Application\");Object.defineProperty(r,\"Application\",{enumerable:!0,get:function(){return i(X).default}});var G=t(\"./autoDetectRenderer\");Object.defineProperty(r,\"autoDetectRenderer\",{enumerable:!0,get:function(){return G.autoDetectRenderer}});var W=t(\"./utils\"),H=n(W),Y=t(\"./ticker\"),V=n(Y),z=t(\"./settings\"),q=i(z),K=t(\"./renderers/canvas/CanvasRenderer\"),Z=i(K),J=t(\"./renderers/webgl/WebGLRenderer\"),Q=i(J);r.settings=q.default,r.utils=H,r.ticker=V,r.CanvasRenderer=Z.default,r.WebGLRenderer=Q.default},{\"./Application\":43,\"./Shader\":44,\"./autoDetectRenderer\":45,\"./const\":46,\"./display/Bounds\":47,\"./display/Container\":48,\"./display/DisplayObject\":49,\"./display/Transform\":50,\"./display/TransformBase\":51,\"./display/TransformStatic\":52,\"./graphics/Graphics\":53,\"./graphics/GraphicsData\":54,\"./graphics/canvas/CanvasGraphicsRenderer\":55,\"./graphics/webgl/GraphicsRenderer\":57,\"./math\":70,\"./renderers/canvas/CanvasRenderer\":77,\"./renderers/canvas/utils/CanvasRenderTarget\":79,\"./renderers/webgl/WebGLRenderer\":84,\"./renderers/webgl/filters/Filter\":86,\"./renderers/webgl/filters/spriteMask/SpriteMaskFilter\":89,\"./renderers/webgl/managers/WebGLManager\":93,\"./renderers/webgl/utils/ObjectRenderer\":94,\"./renderers/webgl/utils/Quad\":95,\"./renderers/webgl/utils/RenderTarget\":96,\"./settings\":101,\"./sprites/Sprite\":102,\"./sprites/canvas/CanvasSpriteRenderer\":103,\"./sprites/canvas/CanvasTinter\":104,\"./sprites/webgl/SpriteRenderer\":106,\"./text/Text\":108,\"./text/TextMetrics\":109,\"./text/TextStyle\":110,\"./textures/BaseRenderTexture\":111,\"./textures/BaseTexture\":112,\"./textures/RenderTexture\":113,\"./textures/Spritesheet\":114,\"./textures/Texture\":115,\"./textures/TextureMatrix\":116,\"./textures/TextureUvs\":117,\"./textures/VideoBaseTexture\":118,\"./ticker\":121,\"./utils\":125,\"pixi-gl-core\":12}],66:[function(t,e,r){\"use strict\";function n(t){return t<0?-1:t>0?1:0}r.__esModule=!0;var i=t(\"./Matrix\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=[1,1,0,-1,-1,-1,0,1,1,1,0,-1,-1,-1,0,1],a=[0,1,1,1,0,-1,-1,-1,0,1,1,1,0,-1,-1,-1],u=[0,-1,-1,-1,0,1,1,1,0,1,1,1,0,-1,-1,-1],h=[1,1,0,-1,-1,-1,0,1,-1,-1,0,1,1,1,0,-1],l=[],c=[];!function(){for(var t=0;t<16;t++){var e=[];c.push(e);for(var r=0;r<16;r++)for(var i=n(s[t]*s[r]+u[t]*a[r]),d=n(a[t]*s[r]+h[t]*a[r]),f=n(s[t]*u[r]+u[t]*h[r]),p=n(a[t]*u[r]+h[t]*h[r]),v=0;v<16;v++)if(s[v]===i&&a[v]===d&&u[v]===f&&h[v]===p){e.push(v);break}}for(var y=0;y<16;y++){var g=new o.default;g.set(s[y],a[y],u[y],h[y],0,0),l.push(g)}}();var d={E:0,SE:1,S:2,SW:3,W:4,NW:5,N:6,NE:7,MIRROR_VERTICAL:8,MIRROR_HORIZONTAL:12,uX:function(t){return s[t]},uY:function(t){return a[t]},vX:function(t){return u[t]},vY:function(t){return h[t]},inv:function(t){return 8&t?15&t:7&-t},add:function(t,e){return c[t][e]},sub:function(t,e){return c[t][d.inv(e)]},rotate180:function(t){return 4^t},isVertical:function(t){return 2==(3&t)},byDirection:function(t,e){return 2*Math.abs(t)<=Math.abs(e)?e>=0?d.S:d.N:2*Math.abs(e)<=Math.abs(t)?t>0?d.E:d.W:e>0?t>0?d.SE:d.SW:t>0?d.NE:d.NW},matrixAppendRotationInv:function(t,e){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,i=l[d.inv(e)];i.tx=r,i.ty=n,t.append(i)}};r.default=d},{\"./Matrix\":67}],67:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),o=t(\"./Point\"),s=function(t){return t&&t.__esModule?t:{default:t}}(o),a=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:1,s=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,a=arguments.length>5&&void 0!==arguments[5]?arguments[5]:0;n(this,t),this.a=e,this.b=r,this.c=i,this.d=o,this.tx=s,this.ty=a,this.array=null}return t.prototype.fromArray=function(t){this.a=t[0],this.b=t[1],this.c=t[3],this.d=t[4],this.tx=t[2],this.ty=t[5]},t.prototype.set=function(t,e,r,n,i,o){return this.a=t,this.b=e,this.c=r,this.d=n,this.tx=i,this.ty=o,this},t.prototype.toArray=function(t,e){this.array||(this.array=new Float32Array(9));var r=e||this.array;return t?(r[0]=this.a,r[1]=this.b,r[2]=0,r[3]=this.c,r[4]=this.d,r[5]=0,r[6]=this.tx,r[7]=this.ty,r[8]=1):(r[0]=this.a,r[1]=this.c,r[2]=this.tx,r[3]=this.b,r[4]=this.d,r[5]=this.ty,r[6]=0,r[7]=0,r[8]=1),r},t.prototype.apply=function(t,e){e=e||new s.default;var r=t.x,n=t.y;return e.x=this.a*r+this.c*n+this.tx,e.y=this.b*r+this.d*n+this.ty,e},t.prototype.applyInverse=function(t,e){e=e||new s.default;var r=1/(this.a*this.d+this.c*-this.b),n=t.x,i=t.y;return e.x=this.d*r*n+-this.c*r*i+(this.ty*this.c-this.tx*this.d)*r,e.y=this.a*r*i+-this.b*r*n+(-this.ty*this.a+this.tx*this.b)*r,e},t.prototype.translate=function(t,e){return this.tx+=t,this.ty+=e,this},t.prototype.scale=function(t,e){return this.a*=t,this.d*=e,this.c*=t,this.b*=e,this.tx*=t,this.ty*=e,this},t.prototype.rotate=function(t){var e=Math.cos(t),r=Math.sin(t),n=this.a,i=this.c,o=this.tx;return this.a=n*e-this.b*r,this.b=n*r+this.b*e,this.c=i*e-this.d*r,this.d=i*r+this.d*e,this.tx=o*e-this.ty*r,this.ty=o*r+this.ty*e,this},t.prototype.append=function(t){var e=this.a,r=this.b,n=this.c,i=this.d;return this.a=t.a*e+t.b*n,this.b=t.a*r+t.b*i,this.c=t.c*e+t.d*n,this.d=t.c*r+t.d*i,this.tx=t.tx*e+t.ty*n+this.tx,this.ty=t.tx*r+t.ty*i+this.ty,this},t.prototype.setTransform=function(t,e,r,n,i,o,s,a,u){var h=Math.sin(s),l=Math.cos(s),c=Math.cos(u),d=Math.sin(u),f=-Math.sin(a),p=Math.cos(a),v=l*i,y=h*i,g=-h*o,m=l*o;return this.a=c*v+d*g,this.b=c*y+d*m,this.c=f*v+p*g,this.d=f*y+p*m,this.tx=t+(r*v+n*g),this.ty=e+(r*y+n*m),this},t.prototype.prepend=function(t){var e=this.tx;if(1!==t.a||0!==t.b||0!==t.c||1!==t.d){var r=this.a,n=this.c;this.a=r*t.a+this.b*t.c,this.b=r*t.b+this.b*t.d,this.c=n*t.a+this.d*t.c,this.d=n*t.b+this.d*t.d}return this.tx=e*t.a+this.ty*t.c+t.tx,this.ty=e*t.b+this.ty*t.d+t.ty,this},t.prototype.decompose=function(t){var e=this.a,r=this.b,n=this.c,i=this.d,o=-Math.atan2(-n,i),s=Math.atan2(r,e);return Math.abs(o+s)<1e-5?(t.rotation=s,e<0&&i>=0&&(t.rotation+=t.rotation<=0?Math.PI:-Math.PI),t.skew.x=t.skew.y=0):(t.skew.x=o,t.skew.y=s),t.scale.x=Math.sqrt(e*e+r*r),t.scale.y=Math.sqrt(n*n+i*i),t.position.x=this.tx,t.position.y=this.ty,t},t.prototype.invert=function(){var t=this.a,e=this.b,r=this.c,n=this.d,i=this.tx,o=t*n-e*r;return this.a=n/o,this.b=-e/o,this.c=-r/o,this.d=t/o,this.tx=(r*this.ty-n*i)/o,this.ty=-(t*this.ty-e*i)/o,this},t.prototype.identity=function(){return this.a=1,this.b=0,this.c=0,this.d=1,this.tx=0,this.ty=0,this},t.prototype.clone=function(){var e=new t;return e.a=this.a,e.b=this.b,e.c=this.c,e.d=this.d,e.tx=this.tx,e.ty=this.ty,e},t.prototype.copy=function(t){return t.a=this.a,t.b=this.b,t.c=this.c,t.d=this.d,t.tx=this.tx,t.ty=this.ty,t},i(t,null,[{key:\"IDENTITY\",get:function(){return new t}},{key:\"TEMP_MATRIX\",get:function(){return new t}}]),t}();r.default=a},{\"./Point\":69}],68:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),o=function(){function t(e,r){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0;n(this,t),this._x=i,this._y=o,this.cb=e,this.scope=r}return t.prototype.set=function(t,e){var r=t||0,n=e||(0!==e?r:0);this._x===r&&this._y===n||(this._x=r,this._y=n,this.cb.call(this.scope))},t.prototype.copy=function(t){this._x===t.x&&this._y===t.y||(this._x=t.x,this._y=t.y,this.cb.call(this.scope))},i(t,[{key:\"x\",get:function(){return this._x},set:function(t){this._x!==t&&(this._x=t,this.cb.call(this.scope))}},{key:\"y\",get:function(){return this._y},set:function(t){this._y!==t&&(this._y=t,this.cb.call(this.scope))}}]),t}();r.default=o},{}],69:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;n(this,t),this.x=e,this.y=r}return t.prototype.clone=function(){return new t(this.x,this.y)},t.prototype.copy=function(t){this.set(t.x,t.y)},t.prototype.equals=function(t){return t.x===this.x&&t.y===this.y},t.prototype.set=function(t,e){this.x=t||0,this.y=e||(0!==e?this.x:0)},t}();r.default=i},{}],70:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0;var i=t(\"./Point\");Object.defineProperty(r,\"Point\",{enumerable:!0,get:function(){return n(i).default}});var o=t(\"./ObservablePoint\");Object.defineProperty(r,\"ObservablePoint\",{enumerable:!0,get:function(){return n(o).default}});var s=t(\"./Matrix\");Object.defineProperty(r,\"Matrix\",{enumerable:!0,get:function(){return n(s).default}});var a=t(\"./GroupD8\");Object.defineProperty(r,\"GroupD8\",{enumerable:!0,get:function(){return n(a).default}});var u=t(\"./shapes/Circle\");Object.defineProperty(r,\"Circle\",{enumerable:!0,get:function(){return n(u).default}});var h=t(\"./shapes/Ellipse\");Object.defineProperty(r,\"Ellipse\",{enumerable:!0,get:function(){return n(h).default}});var l=t(\"./shapes/Polygon\");Object.defineProperty(r,\"Polygon\",{enumerable:!0,get:function(){return n(l).default}});var c=t(\"./shapes/Rectangle\");Object.defineProperty(r,\"Rectangle\",{enumerable:!0,get:function(){return n(c).default}});var d=t(\"./shapes/RoundedRectangle\");Object.defineProperty(r,\"RoundedRectangle\",{enumerable:!0,get:function(){return n(d).default}})},{\"./GroupD8\":66,\"./Matrix\":67,\"./ObservablePoint\":68,\"./Point\":69,\"./shapes/Circle\":71,\"./shapes/Ellipse\":72,\"./shapes/Polygon\":73,\"./shapes/Rectangle\":74,\"./shapes/RoundedRectangle\":75}],71:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"./Rectangle\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=t(\"../../const\"),a=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;n(this,t),this.x=e,this.y=r,this.radius=i,this.type=s.SHAPES.CIRC}return t.prototype.clone=function(){return new t(this.x,this.y,this.radius)},t.prototype.contains=function(t,e){if(this.radius<=0)return!1;var r=this.radius*this.radius,n=this.x-t,i=this.y-e;return n*=n,i*=i,n+i<=r},t.prototype.getBounds=function(){return new o.default(this.x-this.radius,this.y-this.radius,2*this.radius,2*this.radius)},t}();r.default=a},{\"../../const\":46,\"./Rectangle\":74}],72:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"./Rectangle\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=t(\"../../const\"),a=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0;n(this,t),this.x=e,this.y=r,this.width=i,this.height=o,this.type=s.SHAPES.ELIP}return t.prototype.clone=function(){return new t(this.x,this.y,this.width,this.height)},t.prototype.contains=function(t,e){if(this.width<=0||this.height<=0)return!1;var r=(t-this.x)/this.width,n=(e-this.y)/this.height;return r*=r,n*=n,r+n<=1},t.prototype.getBounds=function(){return new o.default(this.x-this.width,this.y-this.height,this.width,this.height)},t}();r.default=a},{\"../../const\":46,\"./Rectangle\":74}],73:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../Point\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=t(\"../../const\"),a=function(){function t(){for(var e=arguments.length,r=Array(e),i=0;i<e;i++)r[i]=arguments[i];if(n(this,t),Array.isArray(r[0])&&(r=r[0]),r[0]instanceof o.default){for(var a=[],u=0,h=r.length;u<h;u++)a.push(r[u].x,r[u].y);r=a}this.closed=!0,this.points=r,this.type=s.SHAPES.POLY}return t.prototype.clone=function(){return new t(this.points.slice())},t.prototype.close=function(){var t=this.points;t[0]===t[t.length-2]&&t[1]===t[t.length-1]||t.push(t[0],t[1])},t.prototype.contains=function(t,e){for(var r=!1,n=this.points.length/2,i=0,o=n-1;i<n;o=i++){var s=this.points[2*i],a=this.points[2*i+1],u=this.points[2*o],h=this.points[2*o+1];a>e!=h>e&&t<(e-a)/(h-a)*(u-s)+s&&(r=!r)}return r},t}();r.default=a},{\"../../const\":46,\"../Point\":69}],74:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),o=t(\"../../const\"),s=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,s=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0;n(this,t),this.x=Number(e),this.y=Number(r),this.width=Number(i),this.height=Number(s),this.type=o.SHAPES.RECT}return t.prototype.clone=function(){return new t(this.x,this.y,this.width,this.height)},t.prototype.copy=function(t){return this.x=t.x,this.y=t.y,this.width=t.width,this.height=t.height,this},t.prototype.contains=function(t,e){return!(this.width<=0||this.height<=0)&&(t>=this.x&&t<this.x+this.width&&e>=this.y&&e<this.y+this.height)},t.prototype.pad=function(t,e){t=t||0,e=e||(0!==e?t:0),this.x-=t,this.y-=e,this.width+=2*t,this.height+=2*e},t.prototype.fit=function(t){this.x<t.x&&(this.width+=this.x,this.width<0&&(this.width=0),this.x=t.x),this.y<t.y&&(this.height+=this.y,this.height<0&&(this.height=0),this.y=t.y),this.x+this.width>t.x+t.width&&(this.width=t.width-this.x,this.width<0&&(this.width=0)),this.y+this.height>t.y+t.height&&(this.height=t.height-this.y,this.height<0&&(this.height=0))},t.prototype.enlarge=function(t){var e=Math.min(this.x,t.x),r=Math.max(this.x+this.width,t.x+t.width),n=Math.min(this.y,t.y),i=Math.max(this.y+this.height,t.y+t.height);this.x=e,this.width=r-e,this.y=n,this.height=i-n},i(t,[{key:\"left\",get:function(){return this.x}},{key:\"right\",get:function(){return this.x+this.width}},{key:\"top\",get:function(){return this.y}},{key:\"bottom\",get:function(){return this.y+this.height}}],[{key:\"EMPTY\",get:function(){return new t(0,0,0,0)}}]),t}();r.default=s},{\"../../const\":46}],75:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../../const\"),o=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,s=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,a=arguments.length>4&&void 0!==arguments[4]?arguments[4]:20;n(this,t),this.x=e,this.y=r,this.width=o,this.height=s,this.radius=a,this.type=i.SHAPES.RREC}return t.prototype.clone=function(){return new t(this.x,this.y,this.width,this.height,this.radius)},t.prototype.contains=function(t,e){if(this.width<=0||this.height<=0)return!1;if(t>=this.x&&t<=this.x+this.width&&e>=this.y&&e<=this.y+this.height){if(e>=this.y+this.radius&&e<=this.y+this.height-this.radius||t>=this.x+this.radius&&t<=this.x+this.width-this.radius)return!0;var r=t-(this.x+this.radius),n=e-(this.y+this.radius),i=this.radius*this.radius;if(r*r+n*n<=i)return!0;if((r=t-(this.x+this.width-this.radius))*r+n*n<=i)return!0;if(n=e-(this.y+this.height-this.radius),r*r+n*n<=i)return!0;if((r=t-(this.x+this.radius))*r+n*n<=i)return!0}return!1},t}();r.default=o},{\"../../const\":46}],76:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),u=t(\"../utils\"),h=t(\"../math\"),l=t(\"../const\"),c=t(\"../settings\"),d=n(c),f=t(\"../display/Container\"),p=n(f),v=t(\"../textures/RenderTexture\"),y=n(v),g=t(\"eventemitter3\"),m=n(g),_=new h.Matrix,b=function(t){function e(r,n,s,a){i(this,e);var c=o(this,t.call(this));return(0,u.sayHello)(r),\"number\"==typeof n&&(n=Object.assign({width:n,height:s||d.default.RENDER_OPTIONS.height},a)),n=Object.assign({},d.default.RENDER_OPTIONS,n),c.options=n,c.type=l.RENDERER_TYPE.UNKNOWN,c.screen=new h.Rectangle(0,0,n.width,n.height),c.view=n.view||document.createElement(\"canvas\"),c.resolution=n.resolution||d.default.RESOLUTION,c.transparent=n.transparent,c.autoResize=n.autoResize||!1,c.blendModes=null,c.preserveDrawingBuffer=n.preserveDrawingBuffer,c.clearBeforeRender=n.clearBeforeRender,c.roundPixels=n.roundPixels,c._backgroundColor=0,c._backgroundColorRgba=[0,0,0,0],c._backgroundColorString=\"#000000\",c.backgroundColor=n.backgroundColor||c._backgroundColor,c._tempDisplayObjectParent=new p.default,c._lastObjectRendered=c._tempDisplayObjectParent,c}return s(e,t),e.prototype.resize=function(t,e){this.screen.width=t,this.screen.height=e,this.view.width=t*this.resolution,this.view.height=e*this.resolution,this.autoResize&&(this.view.style.width=t+\"px\",this.view.style.height=e+\"px\")},e.prototype.generateTexture=function(t,e,r){var n=t.getLocalBounds(),i=y.default.create(0|n.width,0|n.height,e,r);return _.tx=-n.x,_.ty=-n.y,this.render(t,i,!1,_,!0),i},e.prototype.destroy=function(t){t&&this.view.parentNode&&this.view.parentNode.removeChild(this.view),this.type=l.RENDERER_TYPE.UNKNOWN,this.view=null,this.screen=null,this.resolution=0,this.transparent=!1,this.autoResize=!1,this.blendModes=null,this.options=null,this.preserveDrawingBuffer=!1,this.clearBeforeRender=!1,this.roundPixels=!1,this._backgroundColor=0,this._backgroundColorRgba=null,this._backgroundColorString=null,this._tempDisplayObjectParent=null,this._lastObjectRendered=null},a(e,[{key:\"width\",get:function(){return this.view.width}},{key:\"height\",get:function(){return this.view.height}},{key:\"backgroundColor\",get:function(){return this._backgroundColor},set:function(t){this._backgroundColor=t,this._backgroundColorString=(0,u.hex2string)(t),(0,u.hex2rgb)(t,this._backgroundColorRgba)}}]),e}(m.default);r.default=b},{\"../const\":46,\"../display/Container\":48,\"../math\":70,\"../settings\":101,\"../textures/RenderTexture\":113,\"../utils\":125,eventemitter3:3}],77:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"../SystemRenderer\"),u=n(a),h=t(\"./utils/CanvasMaskManager\"),l=n(h),c=t(\"./utils/CanvasRenderTarget\"),d=n(c),f=t(\"./utils/mapCanvasBlendModesToPixi\"),p=n(f),v=t(\"../../utils\"),y=t(\"../../const\"),g=t(\"../../settings\"),m=n(g),_=function(t){function e(r,n,s){i(this,e);var a=o(this,t.call(this,\"Canvas\",r,n,s));return a.type=y.RENDERER_TYPE.CANVAS,a.rootContext=a.view.getContext(\"2d\",{alpha:a.transparent}),a.context=a.rootContext,a.refresh=!0,a.maskManager=new l.default(a),a.smoothProperty=\"imageSmoothingEnabled\",a.rootContext.imageSmoothingEnabled||(a.rootContext.webkitImageSmoothingEnabled?a.smoothProperty=\"webkitImageSmoothingEnabled\":a.rootContext.mozImageSmoothingEnabled?a.smoothProperty=\"mozImageSmoothingEnabled\":a.rootContext.oImageSmoothingEnabled?a.smoothProperty=\"oImageSmoothingEnabled\":a.rootContext.msImageSmoothingEnabled&&(a.smoothProperty=\"msImageSmoothingEnabled\")),a.initPlugins(),a.blendModes=(0,p.default)(),a._activeBlendMode=null,a.renderingToScreen=!1,a.resize(a.options.width,a.options.height),a}return s(e,t),e.prototype.render=function(t,e,r,n,i){if(this.view){this.renderingToScreen=!e,this.emit(\"prerender\");var o=this.resolution;e?(e=e.baseTexture||e,e._canvasRenderTarget||(e._canvasRenderTarget=new d.default(e.width,e.height,e.resolution),e.source=e._canvasRenderTarget.canvas,e.valid=!0),this.context=e._canvasRenderTarget.context,this.resolution=e._canvasRenderTarget.resolution):this.context=this.rootContext;var s=this.context;if(e||(this._lastObjectRendered=t),!i){var a=t.parent,u=this._tempDisplayObjectParent.transform.worldTransform;n?(n.copy(u),this._tempDisplayObjectParent.transform._worldID=-1):u.identity(),t.parent=this._tempDisplayObjectParent,t.updateTransform(),t.parent=a}s.save(),s.setTransform(1,0,0,1,0,0),s.globalAlpha=1,this._activeBlendMode=y.BLEND_MODES.NORMAL,s.globalCompositeOperation=this.blendModes[y.BLEND_MODES.NORMAL],navigator.isCocoonJS&&this.view.screencanvas&&(s.fillStyle=\"black\",s.clear()),(void 0!==r?r:this.clearBeforeRender)&&this.renderingToScreen&&(this.transparent?s.clearRect(0,0,this.width,this.height):(s.fillStyle=this._backgroundColorString,s.fillRect(0,0,this.width,this.height)));var h=this.context;this.context=s,t.renderCanvas(this),this.context=h,s.restore(),this.resolution=o,this.emit(\"postrender\")}},e.prototype.clear=function(t){var e=this.context;t=t||this._backgroundColorString,!this.transparent&&t?(e.fillStyle=t,e.fillRect(0,0,this.width,this.height)):e.clearRect(0,0,this.width,this.height)},e.prototype.setBlendMode=function(t){this._activeBlendMode!==t&&(this._activeBlendMode=t,this.context.globalCompositeOperation=this.blendModes[t])},e.prototype.destroy=function(e){this.destroyPlugins(),t.prototype.destroy.call(this,e),this.context=null,this.refresh=!0,this.maskManager.destroy(),this.maskManager=null,this.smoothProperty=null},e.prototype.resize=function(e,r){t.prototype.resize.call(this,e,r),this.smoothProperty&&(this.rootContext[this.smoothProperty]=m.default.SCALE_MODE===y.SCALE_MODES.LINEAR)},e.prototype.invalidateBlendMode=function(){this._activeBlendMode=this.blendModes.indexOf(this.context.globalCompositeOperation)},e}(u.default);r.default=_,v.pluginTarget.mixin(_)},{\"../../const\":46,\"../../settings\":101,\"../../utils\":125,\"../SystemRenderer\":76,\"./utils/CanvasMaskManager\":78,\"./utils/CanvasRenderTarget\":79,\"./utils/mapCanvasBlendModesToPixi\":81}],78:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../../../const\"),o=function(){function t(e){n(this,t),this.renderer=e}return t.prototype.pushMask=function(t){var e=this.renderer;e.context.save();var r=t.alpha,n=t.transform.worldTransform,i=e.resolution;e.context.setTransform(n.a*i,n.b*i,n.c*i,n.d*i,n.tx*i,n.ty*i),t._texture||(this.renderGraphicsShape(t),e.context.clip()),t.worldAlpha=r},t.prototype.renderGraphicsShape=function(t){var e=this.renderer.context,r=t.graphicsData.length;if(0!==r){e.beginPath();for(var n=0;n<r;n++){var o=t.graphicsData[n],s=o.shape;if(o.type===i.SHAPES.POLY){var a=s.points;e.moveTo(a[0],a[1]);for(var u=1;u<a.length/2;u++)e.lineTo(a[2*u],a[2*u+1]);a[0]===a[a.length-2]&&a[1]===a[a.length-1]&&e.closePath()}else if(o.type===i.SHAPES.RECT)e.rect(s.x,s.y,s.width,s.height),e.closePath();else if(o.type===i.SHAPES.CIRC)e.arc(s.x,s.y,s.radius,0,2*Math.PI),e.closePath();else if(o.type===i.SHAPES.ELIP){var h=2*s.width,l=2*s.height,c=s.x-h/2,d=s.y-l/2,f=h/2*.5522848,p=l/2*.5522848,v=c+h,y=d+l,g=c+h/2,m=d+l/2;e.moveTo(c,m),e.bezierCurveTo(c,m-p,g-f,d,g,d),e.bezierCurveTo(g+f,d,v,m-p,v,m),e.bezierCurveTo(v,m+p,g+f,y,g,y),e.bezierCurveTo(g-f,y,c,m+p,c,m),e.closePath()}else if(o.type===i.SHAPES.RREC){var _=s.x,b=s.y,x=s.width,T=s.height,w=s.radius,E=Math.min(x,T)/2|0;w=w>E?E:w,e.moveTo(_,b+w),e.lineTo(_,b+T-w),e.quadraticCurveTo(_,b+T,_+w,b+T),e.lineTo(_+x-w,b+T),e.quadraticCurveTo(_+x,b+T,_+x,b+T-w),e.lineTo(_+x,b+w),e.quadraticCurveTo(_+x,b,_+x-w,b),e.lineTo(_+w,b),e.quadraticCurveTo(_,b,_,b+w),e.closePath()}}}},t.prototype.popMask=function(t){t.context.restore(),t.invalidateBlendMode()},t.prototype.destroy=function(){},t}();r.default=o},{\"../../../const\":46}],79:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),o=t(\"../../../settings\"),s=function(t){return t&&t.__esModule?t:{default:t}}(o),a=function(){function t(e,r,i){n(this,t),this.canvas=document.createElement(\"canvas\"),this.context=this.canvas.getContext(\"2d\"),this.resolution=i||s.default.RESOLUTION,this.resize(e,r)}return t.prototype.clear=function(){this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.canvas.width,this.canvas.height)},t.prototype.resize=function(t,e){this.canvas.width=t*this.resolution,this.canvas.height=e*this.resolution},t.prototype.destroy=function(){this.context=null,this.canvas=null},i(t,[{key:\"width\",get:function(){return this.canvas.width},set:function(t){this.canvas.width=t}},{key:\"height\",get:function(){return this.canvas.height},set:function(t){this.canvas.height=t}}]),t}();r.default=a},{\"../../../settings\":101}],80:[function(t,e,r){\"use strict\";function n(t){var e=document.createElement(\"canvas\");e.width=6,e.height=1;var r=e.getContext(\"2d\");return r.fillStyle=t,r.fillRect(0,0,6,1),e}function i(){if(\"undefined\"==typeof document)return!1;var t=n(\"#ff00ff\"),e=n(\"#ffff00\"),r=document.createElement(\"canvas\");r.width=6,r.height=1;var i=r.getContext(\"2d\");i.globalCompositeOperation=\"multiply\",i.drawImage(t,0,0),i.drawImage(e,2,0);var o=i.getImageData(2,0,1,1);if(!o)return!1;var s=o.data;return 255===s[0]&&0===s[1]&&0===s[2]}r.__esModule=!0,r.default=i},{}],81:[function(t,e,r){\"use strict\";function n(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];return(0,s.default)()?(t[i.BLEND_MODES.NORMAL]=\"source-over\",t[i.BLEND_MODES.ADD]=\"lighter\",\nt[i.BLEND_MODES.MULTIPLY]=\"multiply\",t[i.BLEND_MODES.SCREEN]=\"screen\",t[i.BLEND_MODES.OVERLAY]=\"overlay\",t[i.BLEND_MODES.DARKEN]=\"darken\",t[i.BLEND_MODES.LIGHTEN]=\"lighten\",t[i.BLEND_MODES.COLOR_DODGE]=\"color-dodge\",t[i.BLEND_MODES.COLOR_BURN]=\"color-burn\",t[i.BLEND_MODES.HARD_LIGHT]=\"hard-light\",t[i.BLEND_MODES.SOFT_LIGHT]=\"soft-light\",t[i.BLEND_MODES.DIFFERENCE]=\"difference\",t[i.BLEND_MODES.EXCLUSION]=\"exclusion\",t[i.BLEND_MODES.HUE]=\"hue\",t[i.BLEND_MODES.SATURATION]=\"saturate\",t[i.BLEND_MODES.COLOR]=\"color\",t[i.BLEND_MODES.LUMINOSITY]=\"luminosity\"):(t[i.BLEND_MODES.NORMAL]=\"source-over\",t[i.BLEND_MODES.ADD]=\"lighter\",t[i.BLEND_MODES.MULTIPLY]=\"source-over\",t[i.BLEND_MODES.SCREEN]=\"source-over\",t[i.BLEND_MODES.OVERLAY]=\"source-over\",t[i.BLEND_MODES.DARKEN]=\"source-over\",t[i.BLEND_MODES.LIGHTEN]=\"source-over\",t[i.BLEND_MODES.COLOR_DODGE]=\"source-over\",t[i.BLEND_MODES.COLOR_BURN]=\"source-over\",t[i.BLEND_MODES.HARD_LIGHT]=\"source-over\",t[i.BLEND_MODES.SOFT_LIGHT]=\"source-over\",t[i.BLEND_MODES.DIFFERENCE]=\"source-over\",t[i.BLEND_MODES.EXCLUSION]=\"source-over\",t[i.BLEND_MODES.HUE]=\"source-over\",t[i.BLEND_MODES.SATURATION]=\"source-over\",t[i.BLEND_MODES.COLOR]=\"source-over\",t[i.BLEND_MODES.LUMINOSITY]=\"source-over\"),t[i.BLEND_MODES.NORMAL_NPM]=t[i.BLEND_MODES.NORMAL],t[i.BLEND_MODES.ADD_NPM]=t[i.BLEND_MODES.ADD],t[i.BLEND_MODES.SCREEN_NPM]=t[i.BLEND_MODES.SCREEN],t}r.__esModule=!0,r.default=n;var i=t(\"../../../const\"),o=t(\"./canUseNewCanvasBlendModes\"),s=function(t){return t&&t.__esModule?t:{default:t}}(o)},{\"../../../const\":46,\"./canUseNewCanvasBlendModes\":80}],82:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../../const\"),o=t(\"../../settings\"),s=function(t){return t&&t.__esModule?t:{default:t}}(o),a=function(){function t(e){n(this,t),this.renderer=e,this.count=0,this.checkCount=0,this.maxIdle=s.default.GC_MAX_IDLE,this.checkCountMax=s.default.GC_MAX_CHECK_COUNT,this.mode=s.default.GC_MODE}return t.prototype.update=function(){this.count++,this.mode!==i.GC_MODES.MANUAL&&++this.checkCount>this.checkCountMax&&(this.checkCount=0,this.run())},t.prototype.run=function(){for(var t=this.renderer.textureManager,e=t._managedTextures,r=!1,n=0;n<e.length;n++){var i=e[n];!i._glRenderTargets&&this.count-i.touched>this.maxIdle&&(t.destroyTexture(i,!0),e[n]=null,r=!0)}if(r){for(var o=0,s=0;s<e.length;s++)null!==e[s]&&(e[o++]=e[s]);e.length=o}},t.prototype.unload=function(t){var e=this.renderer.textureManager;t._texture&&t._texture._glRenderTargets&&e.destroyTexture(t._texture,!0);for(var r=t.children.length-1;r>=0;r--)this.unload(t.children[r])},t}();r.default=a},{\"../../const\":46,\"../../settings\":101}],83:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"pixi-gl-core\"),o=t(\"../../const\"),s=t(\"./utils/RenderTarget\"),a=function(t){return t&&t.__esModule?t:{default:t}}(s),u=t(\"../../utils\"),h=function(){function t(e){n(this,t),this.renderer=e,this.gl=e.gl,this._managedTextures=[]}return t.prototype.bindTexture=function(){},t.prototype.getTexture=function(){},t.prototype.updateTexture=function(t,e){var r=this.gl,n=!!t._glRenderTargets;if(!t.hasLoaded)return null;var s=this.renderer.boundTextures;if(void 0===e){e=0;for(var u=0;u<s.length;++u)if(s[u]===t){e=u;break}}s[e]=t,r.activeTexture(r.TEXTURE0+e);var h=t._glTextures[this.renderer.CONTEXT_UID];if(h)n?t._glRenderTargets[this.renderer.CONTEXT_UID].resize(t.width,t.height):h.upload(t.source);else{if(n){var l=new a.default(this.gl,t.width,t.height,t.scaleMode,t.resolution);l.resize(t.width,t.height),t._glRenderTargets[this.renderer.CONTEXT_UID]=l,h=l.texture}else h=new i.GLTexture(this.gl,null,null,null,null),h.bind(e),h.premultiplyAlpha=!0,h.upload(t.source);t._glTextures[this.renderer.CONTEXT_UID]=h,t.on(\"update\",this.updateTexture,this),t.on(\"dispose\",this.destroyTexture,this),this._managedTextures.push(t),t.isPowerOfTwo?(t.mipmap&&h.enableMipmap(),t.wrapMode===o.WRAP_MODES.CLAMP?h.enableWrapClamp():t.wrapMode===o.WRAP_MODES.REPEAT?h.enableWrapRepeat():h.enableWrapMirrorRepeat()):h.enableWrapClamp(),t.scaleMode===o.SCALE_MODES.NEAREST?h.enableNearestScaling():h.enableLinearScaling()}return h},t.prototype.destroyTexture=function(t,e){if(t=t.baseTexture||t,t.hasLoaded){var r=this.renderer.CONTEXT_UID,n=t._glTextures,i=t._glRenderTargets;if(n[r]&&(this.renderer.unbindTexture(t),n[r].destroy(),t.off(\"update\",this.updateTexture,this),t.off(\"dispose\",this.destroyTexture,this),delete n[r],!e)){var o=this._managedTextures.indexOf(t);-1!==o&&(0,u.removeItems)(this._managedTextures,o,1)}i&&i[r]&&(i[r].destroy(),delete i[r])}},t.prototype.removeAll=function(){for(var t=0;t<this._managedTextures.length;++t){var e=this._managedTextures[t];e._glTextures[this.renderer.CONTEXT_UID]&&delete e._glTextures[this.renderer.CONTEXT_UID]}},t.prototype.destroy=function(){for(var t=0;t<this._managedTextures.length;++t){var e=this._managedTextures[t];this.destroyTexture(e,!0),e.off(\"update\",this.updateTexture,this),e.off(\"dispose\",this.destroyTexture,this)}this._managedTextures=null},t}();r.default=h},{\"../../const\":46,\"../../utils\":125,\"./utils/RenderTarget\":96,\"pixi-gl-core\":12}],84:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"../SystemRenderer\"),u=n(a),h=t(\"./managers/MaskManager\"),l=n(h),c=t(\"./managers/StencilManager\"),d=n(c),f=t(\"./managers/FilterManager\"),p=n(f),v=t(\"./utils/RenderTarget\"),y=n(v),g=t(\"./utils/ObjectRenderer\"),m=n(g),_=t(\"./TextureManager\"),b=n(_),x=t(\"../../textures/BaseTexture\"),T=n(x),w=t(\"./TextureGarbageCollector\"),E=n(w),S=t(\"./WebGLState\"),O=n(S),M=t(\"./utils/mapWebGLDrawModesToPixi\"),P=n(M),C=t(\"./utils/validateContext\"),R=n(C),A=t(\"../../utils\"),I=t(\"pixi-gl-core\"),D=n(I),L=t(\"../../const\"),N=0,F=function(t){function e(r,n,s){i(this,e);var a=o(this,t.call(this,\"WebGL\",r,n,s));return a.legacy=a.options.legacy,a.legacy&&(D.default.VertexArrayObject.FORCE_NATIVE=!0),a.type=L.RENDERER_TYPE.WEBGL,a.handleContextLost=a.handleContextLost.bind(a),a.handleContextRestored=a.handleContextRestored.bind(a),a.view.addEventListener(\"webglcontextlost\",a.handleContextLost,!1),a.view.addEventListener(\"webglcontextrestored\",a.handleContextRestored,!1),a._contextOptions={alpha:a.transparent,antialias:a.options.antialias,premultipliedAlpha:a.transparent&&\"notMultiplied\"!==a.transparent,stencil:!0,preserveDrawingBuffer:a.options.preserveDrawingBuffer,powerPreference:a.options.powerPreference},a._backgroundColorRgba[3]=a.transparent?0:1,a.maskManager=new l.default(a),a.stencilManager=new d.default(a),a.emptyRenderer=new m.default(a),a.currentRenderer=a.emptyRenderer,a.textureManager=null,a.filterManager=null,a.initPlugins(),a.options.context&&(0,R.default)(a.options.context),a.gl=a.options.context||D.default.createContext(a.view,a._contextOptions),a.CONTEXT_UID=N++,a.state=new O.default(a.gl),a.renderingToScreen=!0,a.boundTextures=null,a._activeShader=null,a._activeVao=null,a._activeRenderTarget=null,a._initContext(),a.drawModes=(0,P.default)(a.gl),a._nextTextureLocation=0,a.setBlendMode(0),a}return s(e,t),e.prototype._initContext=function(){var t=this.gl;t.isContextLost()&&t.getExtension(\"WEBGL_lose_context\")&&t.getExtension(\"WEBGL_lose_context\").restoreContext();var e=t.getParameter(t.MAX_TEXTURE_IMAGE_UNITS);this._activeShader=null,this._activeVao=null,this.boundTextures=new Array(e),this.emptyTextures=new Array(e),this.textureManager=new b.default(this),this.filterManager=new p.default(this),this.textureGC=new E.default(this),this.state.resetToDefault(),this.rootRenderTarget=new y.default(t,this.width,this.height,null,this.resolution,!0),this.rootRenderTarget.clearColor=this._backgroundColorRgba,this.bindRenderTarget(this.rootRenderTarget);var r=new D.default.GLTexture.fromData(t,null,1,1),n={_glTextures:{}};n._glTextures[this.CONTEXT_UID]={};for(var i=0;i<e;i++){var o=new T.default;o._glTextures[this.CONTEXT_UID]=r,this.boundTextures[i]=n,this.emptyTextures[i]=o,this.bindTexture(null,i)}this.emit(\"context\",t),this.resize(this.screen.width,this.screen.height)},e.prototype.render=function(t,e,r,n,i){if(this.renderingToScreen=!e,this.emit(\"prerender\"),this.gl&&!this.gl.isContextLost()){if(this._nextTextureLocation=0,e||(this._lastObjectRendered=t),!i){var o=t.parent;t.parent=this._tempDisplayObjectParent,t.updateTransform(),t.parent=o}this.bindRenderTexture(e,n),this.currentRenderer.start(),(void 0!==r?r:this.clearBeforeRender)&&this._activeRenderTarget.clear(),t.renderWebGL(this),this.currentRenderer.flush(),this.textureGC.update(),this.emit(\"postrender\")}},e.prototype.setObjectRenderer=function(t){this.currentRenderer!==t&&(this.currentRenderer.stop(),this.currentRenderer=t,this.currentRenderer.start())},e.prototype.flush=function(){this.setObjectRenderer(this.emptyRenderer)},e.prototype.resize=function(t,e){u.default.prototype.resize.call(this,t,e),this.rootRenderTarget.resize(t,e),this._activeRenderTarget===this.rootRenderTarget&&(this.rootRenderTarget.activate(),this._activeShader&&(this._activeShader.uniforms.projectionMatrix=this.rootRenderTarget.projectionMatrix.toArray(!0)))},e.prototype.setBlendMode=function(t){this.state.setBlendMode(t)},e.prototype.clear=function(t){this._activeRenderTarget.clear(t)},e.prototype.setTransform=function(t){this._activeRenderTarget.transform=t},e.prototype.clearRenderTexture=function(t,e){var r=t.baseTexture,n=r._glRenderTargets[this.CONTEXT_UID];return n&&n.clear(e),this},e.prototype.bindRenderTexture=function(t,e){var r=void 0;if(t){var n=t.baseTexture;n._glRenderTargets[this.CONTEXT_UID]||this.textureManager.updateTexture(n,0),this.unbindTexture(n),r=n._glRenderTargets[this.CONTEXT_UID],r.setFrame(t.frame)}else r=this.rootRenderTarget;return r.transform=e,this.bindRenderTarget(r),this},e.prototype.bindRenderTarget=function(t){return t!==this._activeRenderTarget&&(this._activeRenderTarget=t,t.activate(),this._activeShader&&(this._activeShader.uniforms.projectionMatrix=t.projectionMatrix.toArray(!0)),this.stencilManager.setMaskStack(t.stencilMaskStack)),this},e.prototype.bindShader=function(t,e){return this._activeShader!==t&&(this._activeShader=t,t.bind(),!1!==e&&(t.uniforms.projectionMatrix=this._activeRenderTarget.projectionMatrix.toArray(!0))),this},e.prototype.bindTexture=function(t,e,r){if(t=t||this.emptyTextures[e],t=t.baseTexture||t,t.touched=this.textureGC.count,r)e=e||0;else{for(var n=0;n<this.boundTextures.length;n++)if(this.boundTextures[n]===t)return n;void 0===e&&(this._nextTextureLocation++,this._nextTextureLocation%=this.boundTextures.length,e=this.boundTextures.length-this._nextTextureLocation-1)}var i=this.gl,o=t._glTextures[this.CONTEXT_UID];return o?(this.boundTextures[e]=t,i.activeTexture(i.TEXTURE0+e),i.bindTexture(i.TEXTURE_2D,o.texture)):this.textureManager.updateTexture(t,e),e},e.prototype.unbindTexture=function(t){var e=this.gl;t=t.baseTexture||t;for(var r=0;r<this.boundTextures.length;r++)this.boundTextures[r]===t&&(this.boundTextures[r]=this.emptyTextures[r],e.activeTexture(e.TEXTURE0+r),e.bindTexture(e.TEXTURE_2D,this.emptyTextures[r]._glTextures[this.CONTEXT_UID].texture));return this},e.prototype.createVao=function(){return new D.default.VertexArrayObject(this.gl,this.state.attribState)},e.prototype.bindVao=function(t){return this._activeVao===t?this:(t?t.bind():this._activeVao&&this._activeVao.unbind(),this._activeVao=t,this)},e.prototype.reset=function(){this.setObjectRenderer(this.emptyRenderer),this._activeShader=null,this._activeVao=null,this._activeRenderTarget=this.rootRenderTarget;for(var t=0;t<this.boundTextures.length;t++)this.boundTextures[t]=this.emptyTextures[t];return this.rootRenderTarget.activate(),this.state.resetToDefault(),this},e.prototype.handleContextLost=function(t){t.preventDefault()},e.prototype.handleContextRestored=function(){this.textureManager.removeAll(),this.filterManager.destroy(!0),this._initContext()},e.prototype.destroy=function(e){this.destroyPlugins(),this.view.removeEventListener(\"webglcontextlost\",this.handleContextLost),this.view.removeEventListener(\"webglcontextrestored\",this.handleContextRestored),this.textureManager.destroy(),t.prototype.destroy.call(this,e),this.uid=0,this.maskManager.destroy(),this.stencilManager.destroy(),this.filterManager.destroy(),this.maskManager=null,this.filterManager=null,this.textureManager=null,this.currentRenderer=null,this.handleContextLost=null,this.handleContextRestored=null,this._contextOptions=null,this.gl.useProgram(null),this.gl.getExtension(\"WEBGL_lose_context\")&&this.gl.getExtension(\"WEBGL_lose_context\").loseContext(),this.gl=null},e}(u.default);r.default=F,A.pluginTarget.mixin(F)},{\"../../const\":46,\"../../textures/BaseTexture\":112,\"../../utils\":125,\"../SystemRenderer\":76,\"./TextureGarbageCollector\":82,\"./TextureManager\":83,\"./WebGLState\":85,\"./managers/FilterManager\":90,\"./managers/MaskManager\":91,\"./managers/StencilManager\":92,\"./utils/ObjectRenderer\":94,\"./utils/RenderTarget\":96,\"./utils/mapWebGLDrawModesToPixi\":99,\"./utils/validateContext\":100,\"pixi-gl-core\":12}],85:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"./utils/mapWebGLBlendModesToPixi\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=function(){function t(e){n(this,t),this.activeState=new Uint8Array(16),this.defaultState=new Uint8Array(16),this.defaultState[0]=1,this.stackIndex=0,this.stack=[],this.gl=e,this.maxAttribs=e.getParameter(e.MAX_VERTEX_ATTRIBS),this.attribState={tempAttribState:new Array(this.maxAttribs),attribState:new Array(this.maxAttribs)},this.blendModes=(0,o.default)(e),this.nativeVaoExtension=e.getExtension(\"OES_vertex_array_object\")||e.getExtension(\"MOZ_OES_vertex_array_object\")||e.getExtension(\"WEBKIT_OES_vertex_array_object\")}return t.prototype.push=function(){var t=this.stack[this.stackIndex];t||(t=this.stack[this.stackIndex]=new Uint8Array(16)),++this.stackIndex;for(var e=0;e<this.activeState.length;e++)t[e]=this.activeState[e]},t.prototype.pop=function(){var t=this.stack[--this.stackIndex];this.setState(t)},t.prototype.setState=function(t){this.setBlend(t[0]),this.setDepthTest(t[1]),this.setFrontFace(t[2]),this.setCullFace(t[3]),this.setBlendMode(t[4])},t.prototype.setBlend=function(t){t=t?1:0,this.activeState[0]!==t&&(this.activeState[0]=t,this.gl[t?\"enable\":\"disable\"](this.gl.BLEND))},t.prototype.setBlendMode=function(t){if(t!==this.activeState[4]){this.activeState[4]=t;var e=this.blendModes[t];2===e.length?this.gl.blendFunc(e[0],e[1]):this.gl.blendFuncSeparate(e[0],e[1],e[2],e[3])}},t.prototype.setDepthTest=function(t){t=t?1:0,this.activeState[1]!==t&&(this.activeState[1]=t,this.gl[t?\"enable\":\"disable\"](this.gl.DEPTH_TEST))},t.prototype.setCullFace=function(t){t=t?1:0,this.activeState[3]!==t&&(this.activeState[3]=t,this.gl[t?\"enable\":\"disable\"](this.gl.CULL_FACE))},t.prototype.setFrontFace=function(t){t=t?1:0,this.activeState[2]!==t&&(this.activeState[2]=t,this.gl.frontFace(this.gl[t?\"CW\":\"CCW\"]))},t.prototype.resetAttributes=function(){for(var t=0;t<this.attribState.tempAttribState.length;t++)this.attribState.tempAttribState[t]=0;for(var e=0;e<this.attribState.attribState.length;e++)this.attribState.attribState[e]=0;for(var r=1;r<this.maxAttribs;r++)this.gl.disableVertexAttribArray(r)},t.prototype.resetToDefault=function(){this.nativeVaoExtension&&this.nativeVaoExtension.bindVertexArrayOES(null),this.resetAttributes();for(var t=0;t<this.activeState.length;++t)this.activeState[t]=32;this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,!1),this.setState(this.defaultState)},t}();r.default=s},{\"./utils/mapWebGLBlendModesToPixi\":98}],86:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var o=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),s=t(\"./extractUniformsFromSrc\"),a=n(s),u=t(\"../../../utils\"),h=t(\"../../../const\"),l=t(\"../../../settings\"),c=n(l),d={},f=function(){function t(e,r,n){i(this,t),this.vertexSrc=e||t.defaultVertexSrc,this.fragmentSrc=r||t.defaultFragmentSrc,this._blendMode=h.BLEND_MODES.NORMAL,this.uniformData=n||(0,a.default)(this.vertexSrc,this.fragmentSrc,\"projectionMatrix|uSampler\"),this.uniforms={};for(var o in this.uniformData)this.uniforms[o]=this.uniformData[o].value,this.uniformData[o].type&&(this.uniformData[o].type=this.uniformData[o].type.toLowerCase());this.glShaders={},d[this.vertexSrc+this.fragmentSrc]||(d[this.vertexSrc+this.fragmentSrc]=(0,u.uid)()),this.glShaderKey=d[this.vertexSrc+this.fragmentSrc],this.padding=4,this.resolution=c.default.RESOLUTION,this.enabled=!0,this.autoFit=!0}return t.prototype.apply=function(t,e,r,n,i){t.applyFilter(this,e,r,n)},o(t,[{key:\"blendMode\",get:function(){return this._blendMode},set:function(t){this._blendMode=t}}],[{key:\"defaultVertexSrc\",get:function(){return[\"attribute vec2 aVertexPosition;\",\"attribute vec2 aTextureCoord;\",\"uniform mat3 projectionMatrix;\",\"uniform mat3 filterMatrix;\",\"varying vec2 vTextureCoord;\",\"varying vec2 vFilterCoord;\",\"void main(void){\",\"   gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\",\"   vFilterCoord = ( filterMatrix * vec3( aTextureCoord, 1.0)  ).xy;\",\"   vTextureCoord = aTextureCoord ;\",\"}\"].join(\"\\n\")}},{key:\"defaultFragmentSrc\",get:function(){return[\"varying vec2 vTextureCoord;\",\"varying vec2 vFilterCoord;\",\"uniform sampler2D uSampler;\",\"uniform sampler2D filterSampler;\",\"void main(void){\",\"   vec4 masky = texture2D(filterSampler, vFilterCoord);\",\"   vec4 sample = texture2D(uSampler, vTextureCoord);\",\"   vec4 color;\",\"   if(mod(vFilterCoord.x, 1.0) > 0.5)\",\"   {\",\"     color = vec4(1.0, 0.0, 0.0, 1.0);\",\"   }\",\"   else\",\"   {\",\"     color = vec4(0.0, 1.0, 0.0, 1.0);\",\"   }\",\"   gl_FragColor = mix(sample, masky, 0.5);\",\"   gl_FragColor *= sample.a;\",\"}\"].join(\"\\n\")}}]),t}();r.default=f},{\"../../../const\":46,\"../../../settings\":101,\"../../../utils\":125,\"./extractUniformsFromSrc\":87}],87:[function(t,e,r){\"use strict\";function n(t,e,r){var n=i(t),o=i(e);return Object.assign(n,o)}function i(t){for(var e=new RegExp(\"^(projectionMatrix|uSampler|filterArea|filterClamp)$\"),r={},n=void 0,i=t.replace(/\\s+/g,\" \").split(/\\s*;\\s*/),o=0;o<i.length;o++){var s=i[o].trim();if(s.indexOf(\"uniform\")>-1){var u=s.split(\" \"),h=u[1],l=u[2],c=1;l.indexOf(\"[\")>-1&&(n=l.split(/\\[|]/),l=n[0],c*=Number(n[1])),l.match(e)||(r[l]={value:a(h,c),name:l,type:h})}}return r}r.__esModule=!0,r.default=n;var o=t(\"pixi-gl-core\"),s=function(t){return t&&t.__esModule?t:{default:t}}(o),a=s.default.shader.defaultValue},{\"pixi-gl-core\":12}],88:[function(t,e,r){\"use strict\";function n(t,e,r){var n=t.identity();return n.translate(e.x/r.width,e.y/r.height),n.scale(r.width,r.height),n}function i(t,e,r){var n=t.identity();n.translate(e.x/r.width,e.y/r.height);var i=r.width/e.width,o=r.height/e.height;return n.scale(i,o),n}function o(t,e,r,n){var i=n._texture.orig,o=t.set(r.width,0,0,r.height,e.x,e.y),a=n.worldTransform.copy(s.Matrix.TEMP_MATRIX);return a.invert(),o.prepend(a),o.scale(1/i.width,1/i.height),o.translate(n.anchor.x,n.anchor.y),o}r.__esModule=!0,r.calculateScreenSpaceMatrix=n,r.calculateNormalizedScreenSpaceMatrix=i,r.calculateSpriteMatrix=o;var s=t(\"../../../math\")},{\"../../../math\":70}],89:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"../Filter\"),u=n(a),h=t(\"../../../../math\"),l=(t(\"path\"),t(\"../../../../textures/TextureMatrix\")),c=n(l),d=function(t){function e(r){i(this,e);var n=new h.Matrix,s=o(this,t.call(this,\"attribute vec2 aVertexPosition;\\nattribute vec2 aTextureCoord;\\n\\nuniform mat3 projectionMatrix;\\nuniform mat3 otherMatrix;\\n\\nvarying vec2 vMaskCoord;\\nvarying vec2 vTextureCoord;\\n\\nvoid main(void)\\n{\\n    gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\\n\\n    vTextureCoord = aTextureCoord;\\n    vMaskCoord = ( otherMatrix * vec3( aTextureCoord, 1.0)  ).xy;\\n}\\n\",\"varying vec2 vMaskCoord;\\nvarying vec2 vTextureCoord;\\n\\nuniform sampler2D uSampler;\\nuniform sampler2D mask;\\nuniform float alpha;\\nuniform vec4 maskClamp;\\n\\nvoid main(void)\\n{\\n    float clip = step(3.5,\\n        step(maskClamp.x, vMaskCoord.x) +\\n        step(maskClamp.y, vMaskCoord.y) +\\n        step(vMaskCoord.x, maskClamp.z) +\\n        step(vMaskCoord.y, maskClamp.w));\\n\\n    vec4 original = texture2D(uSampler, vTextureCoord);\\n    vec4 masky = texture2D(mask, vMaskCoord);\\n\\n    original *= (masky.r * masky.a * alpha * clip);\\n\\n    gl_FragColor = original;\\n}\\n\"));return r.renderable=!1,s.maskSprite=r,s.maskMatrix=n,s}return s(e,t),e.prototype.apply=function(t,e,r){var n=this.maskSprite,i=this.maskSprite.texture;i.valid&&(i.transform||(i.transform=new c.default(i,0)),i.transform.update(),this.uniforms.mask=i,this.uniforms.otherMatrix=t.calculateSpriteMatrix(this.maskMatrix,n).prepend(i.transform.mapCoord),this.uniforms.alpha=n.worldAlpha,this.uniforms.maskClamp=i.transform.uClampFrame,t.applyFilter(this,e,r))},e}(u.default);r.default=d},{\"../../../../math\":70,\"../../../../textures/TextureMatrix\":116,\"../Filter\":86,path:23}],90:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function s(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var a=t(\"./WebGLManager\"),u=n(a),h=t(\"../utils/RenderTarget\"),l=n(h),c=t(\"../utils/Quad\"),d=n(c),f=t(\"../../../math\"),p=t(\"../../../Shader\"),v=n(p),y=t(\"../filters/filterTransforms\"),g=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(y),m=t(\"bit-twiddle\"),_=n(m),b=function t(){s(this,t),this.renderTarget=null,this.sourceFrame=new f.Rectangle,this.destinationFrame=new f.Rectangle,this.filters=[],this.target=null,this.resolution=1},x=function(t){function e(r){s(this,e);var n=i(this,t.call(this,r));return n.gl=n.renderer.gl,n.quad=new d.default(n.gl,r.state.attribState),n.shaderCache={},n.pool={},n.filterData=null,n.managedFilters=[],n}return o(e,t),e.prototype.pushFilter=function(t,e){var r=this.renderer,n=this.filterData;if(!n){n=this.renderer._activeRenderTarget.filterStack;var i=new b;i.sourceFrame=i.destinationFrame=this.renderer._activeRenderTarget.size,i.renderTarget=r._activeRenderTarget,this.renderer._activeRenderTarget.filterData=n={index:0,stack:[i]},this.filterData=n}var o=n.stack[++n.index];o||(o=n.stack[n.index]=new b);var s=e[0].resolution,a=0|e[0].padding,u=t.filterArea||t.getBounds(!0),h=o.sourceFrame,l=o.destinationFrame;h.x=(u.x*s|0)/s,h.y=(u.y*s|0)/s,h.width=(u.width*s|0)/s,h.height=(u.height*s|0)/s,n.stack[0].renderTarget.transform||e[0].autoFit&&h.fit(n.stack[0].destinationFrame),h.pad(a),l.width=h.width,l.height=h.height;var c=this.getPotRenderTarget(r.gl,h.width,h.height,s);o.target=t,o.filters=e,o.resolution=s,o.renderTarget=c,c.setFrame(l,h),r.bindRenderTarget(c),c.clear()},e.prototype.popFilter=function(){var t=this.filterData,e=t.stack[t.index-1],r=t.stack[t.index];this.quad.map(r.renderTarget.size,r.sourceFrame).upload();var n=r.filters;if(1===n.length)n[0].apply(this,r.renderTarget,e.renderTarget,!1,r),this.freePotRenderTarget(r.renderTarget);else{var i=r.renderTarget,o=this.getPotRenderTarget(this.renderer.gl,r.sourceFrame.width,r.sourceFrame.height,r.resolution);o.setFrame(r.destinationFrame,r.sourceFrame),o.clear();var s=0;for(s=0;s<n.length-1;++s){n[s].apply(this,i,o,!0,r);var a=i;i=o,o=a}n[s].apply(this,i,e.renderTarget,!1,r),this.freePotRenderTarget(i),this.freePotRenderTarget(o)}0===--t.index&&(this.filterData=null)},e.prototype.applyFilter=function(t,e,r,n){var i=this.renderer,o=i.gl,s=t.glShaders[i.CONTEXT_UID];s||(t.glShaderKey?(s=this.shaderCache[t.glShaderKey])||(s=new v.default(this.gl,t.vertexSrc,t.fragmentSrc),t.glShaders[i.CONTEXT_UID]=this.shaderCache[t.glShaderKey]=s,this.managedFilters.push(t)):(s=t.glShaders[i.CONTEXT_UID]=new v.default(this.gl,t.vertexSrc,t.fragmentSrc),this.managedFilters.push(t)),i.bindVao(null),this.quad.initVao(s)),i.bindVao(this.quad.vao),i.bindRenderTarget(r),n&&(o.disable(o.SCISSOR_TEST),i.clear(),o.enable(o.SCISSOR_TEST)),r===i.maskManager.scissorRenderTarget&&i.maskManager.pushScissorMask(null,i.maskManager.scissorData),i.bindShader(s);var a=this.renderer.emptyTextures[0];this.renderer.boundTextures[0]=a,this.syncUniforms(s,t),i.state.setBlendMode(t.blendMode),o.activeTexture(o.TEXTURE0),o.bindTexture(o.TEXTURE_2D,e.texture.texture),this.quad.vao.draw(this.renderer.gl.TRIANGLES,6,0),o.bindTexture(o.TEXTURE_2D,a._glTextures[this.renderer.CONTEXT_UID].texture)},e.prototype.syncUniforms=function(t,e){var r=e.uniformData,n=e.uniforms,i=1,o=void 0;if(t.uniforms.filterArea){o=this.filterData.stack[this.filterData.index];var s=t.uniforms.filterArea;s[0]=o.renderTarget.size.width,s[1]=o.renderTarget.size.height,s[2]=o.sourceFrame.x,s[3]=o.sourceFrame.y,t.uniforms.filterArea=s}if(t.uniforms.filterClamp){o=o||this.filterData.stack[this.filterData.index];var a=t.uniforms.filterClamp;a[0]=0,a[1]=0,a[2]=(o.sourceFrame.width-1)/o.renderTarget.size.width,a[3]=(o.sourceFrame.height-1)/o.renderTarget.size.height,t.uniforms.filterClamp=a}for(var u in r){var h=r[u].type;if(\"sampler2d\"===h&&0!==n[u]){if(n[u].baseTexture)t.uniforms[u]=this.renderer.bindTexture(n[u].baseTexture,i);else{t.uniforms[u]=i;var l=this.renderer.gl;this.renderer.boundTextures[i]=this.renderer.emptyTextures[i],l.activeTexture(l.TEXTURE0+i),n[u].texture.bind()}i++}else if(\"mat3\"===h)void 0!==n[u].a?t.uniforms[u]=n[u].toArray(!0):t.uniforms[u]=n[u];else if(\"vec2\"===h)if(void 0!==n[u].x){var c=t.uniforms[u]||new Float32Array(2);c[0]=n[u].x,c[1]=n[u].y,t.uniforms[u]=c}else t.uniforms[u]=n[u];else\"float\"===h?t.uniforms.data[u].value!==r[u]&&(t.uniforms[u]=n[u]):t.uniforms[u]=n[u]}},e.prototype.getRenderTarget=function(t,e){var r=this.filterData.stack[this.filterData.index],n=this.getPotRenderTarget(this.renderer.gl,r.sourceFrame.width,r.sourceFrame.height,e||r.resolution);return n.setFrame(r.destinationFrame,r.sourceFrame),n},e.prototype.returnRenderTarget=function(t){this.freePotRenderTarget(t)},e.prototype.calculateScreenSpaceMatrix=function(t){var e=this.filterData.stack[this.filterData.index];return g.calculateScreenSpaceMatrix(t,e.sourceFrame,e.renderTarget.size)},e.prototype.calculateNormalizedScreenSpaceMatrix=function(t){var e=this.filterData.stack[this.filterData.index];return g.calculateNormalizedScreenSpaceMatrix(t,e.sourceFrame,e.renderTarget.size,e.destinationFrame)},e.prototype.calculateSpriteMatrix=function(t,e){var r=this.filterData.stack[this.filterData.index];return g.calculateSpriteMatrix(t,r.sourceFrame,r.renderTarget.size,e)},e.prototype.destroy=function(){for(var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0],e=this.renderer,r=this.managedFilters,n=0;n<r.length;n++)t||r[n].glShaders[e.CONTEXT_UID].destroy(),delete r[n].glShaders[e.CONTEXT_UID];this.shaderCache={},t?this.pool={}:this.emptyPool()},e.prototype.getPotRenderTarget=function(t,e,r,n){e=_.default.nextPow2(e*n),r=_.default.nextPow2(r*n);var i=(65535&e)<<16|65535&r;this.pool[i]||(this.pool[i]=[]);var o=this.pool[i].pop();if(!o){var s=this.renderer.boundTextures[0];t.activeTexture(t.TEXTURE0),o=new l.default(t,e,r,null,1),t.bindTexture(t.TEXTURE_2D,s._glTextures[this.renderer.CONTEXT_UID].texture)}return o.resolution=n,o.defaultFrame.width=o.size.width=e/n,o.defaultFrame.height=o.size.height=r/n,o},e.prototype.emptyPool=function(){for(var t in this.pool){var e=this.pool[t];if(e)for(var r=0;r<e.length;r++)e[r].destroy(!0)}this.pool={}},e.prototype.freePotRenderTarget=function(t){var e=t.size.width*t.resolution,r=t.size.height*t.resolution,n=(65535&e)<<16|65535&r;this.pool[n].push(t)},e}(u.default);r.default=x},{\"../../../Shader\":44,\"../../../math\":70,\"../filters/filterTransforms\":88,\"../utils/Quad\":95,\"../utils/RenderTarget\":96,\"./WebGLManager\":93,\"bit-twiddle\":1}],91:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"./WebGLManager\"),u=n(a),h=t(\"../filters/spriteMask/SpriteMaskFilter\"),l=n(h),c=function(t){function e(r){i(this,e);var n=o(this,t.call(this,r));return n.scissor=!1,n.scissorData=null,n.scissorRenderTarget=null,n.enableScissor=!0,n.alphaMaskPool=[],n.alphaMaskIndex=0,n}return s(e,t),e.prototype.pushMask=function(t,e){if(e.texture)this.pushSpriteMask(t,e);else if(this.enableScissor&&!this.scissor&&this.renderer._activeRenderTarget.root&&!this.renderer.stencilManager.stencilMaskStack.length&&e.isFastRect()){var r=e.worldTransform,n=Math.atan2(r.b,r.a);n=Math.round(n*(180/Math.PI)),n%90?this.pushStencilMask(e):this.pushScissorMask(t,e)}else this.pushStencilMask(e)},e.prototype.popMask=function(t,e){e.texture?this.popSpriteMask(t,e):this.enableScissor&&!this.renderer.stencilManager.stencilMaskStack.length?this.popScissorMask(t,e):this.popStencilMask(t,e)},e.prototype.pushSpriteMask=function(t,e){var r=this.alphaMaskPool[this.alphaMaskIndex];r||(r=this.alphaMaskPool[this.alphaMaskIndex]=[new l.default(e)]),r[0].resolution=this.renderer.resolution,r[0].maskSprite=e,t.filterArea=e.getBounds(!0),this.renderer.filterManager.pushFilter(t,r),this.alphaMaskIndex++},e.prototype.popSpriteMask=function(){this.renderer.filterManager.popFilter(),this.alphaMaskIndex--},e.prototype.pushStencilMask=function(t){this.renderer.currentRenderer.stop(),this.renderer.stencilManager.pushStencil(t)},e.prototype.popStencilMask=function(){\nthis.renderer.currentRenderer.stop(),this.renderer.stencilManager.popStencil()},e.prototype.pushScissorMask=function(t,e){e.renderable=!0;var r=this.renderer._activeRenderTarget,n=e.getBounds();n.fit(r.size),e.renderable=!1,this.renderer.gl.enable(this.renderer.gl.SCISSOR_TEST);var i=this.renderer.resolution;this.renderer.gl.scissor(n.x*i,(r.root?r.size.height-n.y-n.height:n.y)*i,n.width*i,n.height*i),this.scissorRenderTarget=r,this.scissorData=e,this.scissor=!0},e.prototype.popScissorMask=function(){this.scissorRenderTarget=null,this.scissorData=null,this.scissor=!1;var t=this.renderer.gl;t.disable(t.SCISSOR_TEST)},e}(u.default);r.default=c},{\"../filters/spriteMask/SpriteMaskFilter\":89,\"./WebGLManager\":93}],92:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=t(\"./WebGLManager\"),a=function(t){return t&&t.__esModule?t:{default:t}}(s),u=function(t){function e(r){n(this,e);var o=i(this,t.call(this,r));return o.stencilMaskStack=null,o}return o(e,t),e.prototype.setMaskStack=function(t){this.stencilMaskStack=t;var e=this.renderer.gl;0===t.length?e.disable(e.STENCIL_TEST):e.enable(e.STENCIL_TEST)},e.prototype.pushStencil=function(t){this.renderer.setObjectRenderer(this.renderer.plugins.graphics),this.renderer._activeRenderTarget.attachStencilBuffer();var e=this.renderer.gl,r=this.stencilMaskStack.length;0===r&&e.enable(e.STENCIL_TEST),this.stencilMaskStack.push(t),e.colorMask(!1,!1,!1,!1),e.stencilFunc(e.EQUAL,r,this._getBitwiseMask()),e.stencilOp(e.KEEP,e.KEEP,e.INCR),this.renderer.plugins.graphics.render(t),this._useCurrent()},e.prototype.popStencil=function(){this.renderer.setObjectRenderer(this.renderer.plugins.graphics);var t=this.renderer.gl,e=this.stencilMaskStack.pop();0===this.stencilMaskStack.length?(t.disable(t.STENCIL_TEST),t.clear(t.STENCIL_BUFFER_BIT),t.clearStencil(0)):(t.colorMask(!1,!1,!1,!1),t.stencilOp(t.KEEP,t.KEEP,t.DECR),this.renderer.plugins.graphics.render(e),this._useCurrent())},e.prototype._useCurrent=function(){var t=this.renderer.gl;t.colorMask(!0,!0,!0,!0),t.stencilFunc(t.EQUAL,this.stencilMaskStack.length,this._getBitwiseMask()),t.stencilOp(t.KEEP,t.KEEP,t.KEEP)},e.prototype._getBitwiseMask=function(){return(1<<this.stencilMaskStack.length)-1},e.prototype.destroy=function(){a.default.prototype.destroy.call(this),this.stencilMaskStack.stencilStack=null},e}(a.default);r.default=u},{\"./WebGLManager\":93}],93:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(e){n(this,t),this.renderer=e,this.renderer.on(\"context\",this.onContextChange,this)}return t.prototype.onContextChange=function(){},t.prototype.destroy=function(){this.renderer.off(\"context\",this.onContextChange,this),this.renderer=null},t}();r.default=i},{}],94:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=t(\"../managers/WebGLManager\"),a=function(t){return t&&t.__esModule?t:{default:t}}(s),u=function(t){function e(){return n(this,e),i(this,t.apply(this,arguments))}return o(e,t),e.prototype.start=function(){},e.prototype.stop=function(){this.flush()},e.prototype.flush=function(){},e.prototype.render=function(t){},e}(a.default);r.default=u},{\"../managers/WebGLManager\":93}],95:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var o=t(\"pixi-gl-core\"),s=n(o),a=t(\"../../../utils/createIndicesForQuads\"),u=n(a),h=function(){function t(e,r){i(this,t),this.gl=e,this.vertices=new Float32Array([-1,-1,1,-1,1,1,-1,1]),this.uvs=new Float32Array([0,0,1,0,1,1,0,1]),this.interleaved=new Float32Array(16);for(var n=0;n<4;n++)this.interleaved[4*n]=this.vertices[2*n],this.interleaved[4*n+1]=this.vertices[2*n+1],this.interleaved[4*n+2]=this.uvs[2*n],this.interleaved[4*n+3]=this.uvs[2*n+1];this.indices=(0,u.default)(1),this.vertexBuffer=s.default.GLBuffer.createVertexBuffer(e,this.interleaved,e.STATIC_DRAW),this.indexBuffer=s.default.GLBuffer.createIndexBuffer(e,this.indices,e.STATIC_DRAW),this.vao=new s.default.VertexArrayObject(e,r)}return t.prototype.initVao=function(t){this.vao.clear().addIndex(this.indexBuffer).addAttribute(this.vertexBuffer,t.attributes.aVertexPosition,this.gl.FLOAT,!1,16,0).addAttribute(this.vertexBuffer,t.attributes.aTextureCoord,this.gl.FLOAT,!1,16,8)},t.prototype.map=function(t,e){var r=0,n=0;return this.uvs[0]=r,this.uvs[1]=n,this.uvs[2]=r+e.width/t.width,this.uvs[3]=n,this.uvs[4]=r+e.width/t.width,this.uvs[5]=n+e.height/t.height,this.uvs[6]=r,this.uvs[7]=n+e.height/t.height,r=e.x,n=e.y,this.vertices[0]=r,this.vertices[1]=n,this.vertices[2]=r+e.width,this.vertices[3]=n,this.vertices[4]=r+e.width,this.vertices[5]=n+e.height,this.vertices[6]=r,this.vertices[7]=n+e.height,this},t.prototype.upload=function(){for(var t=0;t<4;t++)this.interleaved[4*t]=this.vertices[2*t],this.interleaved[4*t+1]=this.vertices[2*t+1],this.interleaved[4*t+2]=this.uvs[2*t],this.interleaved[4*t+3]=this.uvs[2*t+1];return this.vertexBuffer.upload(this.interleaved),this},t.prototype.destroy=function(){var t=this.gl;t.deleteBuffer(this.vertexBuffer),t.deleteBuffer(this.indexBuffer)},t}();r.default=h},{\"../../../utils/createIndicesForQuads\":123,\"pixi-gl-core\":12}],96:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../../../math\"),o=t(\"../../../const\"),s=t(\"../../../settings\"),a=function(t){return t&&t.__esModule?t:{default:t}}(s),u=t(\"pixi-gl-core\"),h=function(){function t(e,r,s,h,l,c){n(this,t),this.gl=e,this.frameBuffer=null,this.texture=null,this.clearColor=[0,0,0,0],this.size=new i.Rectangle(0,0,1,1),this.resolution=l||a.default.RESOLUTION,this.projectionMatrix=new i.Matrix,this.transform=null,this.frame=null,this.defaultFrame=new i.Rectangle,this.destinationFrame=null,this.sourceFrame=null,this.stencilBuffer=null,this.stencilMaskStack=[],this.filterData=null,this.scaleMode=void 0!==h?h:a.default.SCALE_MODE,this.root=c,this.root?(this.frameBuffer=new u.GLFramebuffer(e,100,100),this.frameBuffer.framebuffer=null):(this.frameBuffer=u.GLFramebuffer.createRGBA(e,100,100),this.scaleMode===o.SCALE_MODES.NEAREST?this.frameBuffer.texture.enableNearestScaling():this.frameBuffer.texture.enableLinearScaling(),this.texture=this.frameBuffer.texture),this.setFrame(),this.resize(r,s)}return t.prototype.clear=function(t){var e=t||this.clearColor;this.frameBuffer.clear(e[0],e[1],e[2],e[3])},t.prototype.attachStencilBuffer=function(){this.root||this.frameBuffer.enableStencil()},t.prototype.setFrame=function(t,e){this.destinationFrame=t||this.destinationFrame||this.defaultFrame,this.sourceFrame=e||this.sourceFrame||this.destinationFrame},t.prototype.activate=function(){var t=this.gl;this.frameBuffer.bind(),this.calculateProjection(this.destinationFrame,this.sourceFrame),this.transform&&this.projectionMatrix.append(this.transform),this.destinationFrame!==this.sourceFrame?(t.enable(t.SCISSOR_TEST),t.scissor(0|this.destinationFrame.x,0|this.destinationFrame.y,this.destinationFrame.width*this.resolution|0,this.destinationFrame.height*this.resolution|0)):t.disable(t.SCISSOR_TEST),t.viewport(0|this.destinationFrame.x,0|this.destinationFrame.y,this.destinationFrame.width*this.resolution|0,this.destinationFrame.height*this.resolution|0)},t.prototype.calculateProjection=function(t,e){var r=this.projectionMatrix;e=e||t,r.identity(),this.root?(r.a=1/t.width*2,r.d=-1/t.height*2,r.tx=-1-e.x*r.a,r.ty=1-e.y*r.d):(r.a=1/t.width*2,r.d=1/t.height*2,r.tx=-1-e.x*r.a,r.ty=-1-e.y*r.d)},t.prototype.resize=function(t,e){if(t|=0,e|=0,this.size.width!==t||this.size.height!==e){this.size.width=t,this.size.height=e,this.defaultFrame.width=t,this.defaultFrame.height=e,this.frameBuffer.resize(t*this.resolution,e*this.resolution);var r=this.frame||this.size;this.calculateProjection(r)}},t.prototype.destroy=function(){this.frameBuffer.destroy(),this.frameBuffer=null,this.texture=null},t}();r.default=h},{\"../../../const\":46,\"../../../math\":70,\"../../../settings\":101,\"pixi-gl-core\":12}],97:[function(t,e,r){\"use strict\";function n(t,e){var r=!e;if(r){var n=document.createElement(\"canvas\");n.width=1,n.height=1,e=s.default.createContext(n)}for(var o=e.createShader(e.FRAGMENT_SHADER);;){var u=a.replace(/%forloop%/gi,i(t));if(e.shaderSource(o,u),e.compileShader(o),e.getShaderParameter(o,e.COMPILE_STATUS))break;t=t/2|0}return r&&e.getExtension(\"WEBGL_lose_context\")&&e.getExtension(\"WEBGL_lose_context\").loseContext(),t}function i(t){for(var e=\"\",r=0;r<t;++r)r>0&&(e+=\"\\nelse \"),r<t-1&&(e+=\"if(test == \"+r+\".0){}\");return e}r.__esModule=!0,r.default=n;var o=t(\"pixi-gl-core\"),s=function(t){return t&&t.__esModule?t:{default:t}}(o),a=[\"precision mediump float;\",\"void main(void){\",\"float test = 0.1;\",\"%forloop%\",\"gl_FragColor = vec4(0.0);\",\"}\"].join(\"\\n\")},{\"pixi-gl-core\":12}],98:[function(t,e,r){\"use strict\";function n(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];return e[i.BLEND_MODES.NORMAL]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.ADD]=[t.ONE,t.DST_ALPHA],e[i.BLEND_MODES.MULTIPLY]=[t.DST_COLOR,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.SCREEN]=[t.ONE,t.ONE_MINUS_SRC_COLOR],e[i.BLEND_MODES.OVERLAY]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.DARKEN]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.LIGHTEN]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.COLOR_DODGE]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.COLOR_BURN]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.HARD_LIGHT]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.SOFT_LIGHT]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.DIFFERENCE]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.EXCLUSION]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.HUE]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.SATURATION]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.COLOR]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.LUMINOSITY]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.NORMAL_NPM]=[t.SRC_ALPHA,t.ONE_MINUS_SRC_ALPHA,t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.ADD_NPM]=[t.SRC_ALPHA,t.DST_ALPHA,t.ONE,t.DST_ALPHA],e[i.BLEND_MODES.SCREEN_NPM]=[t.SRC_ALPHA,t.ONE_MINUS_SRC_COLOR,t.ONE,t.ONE_MINUS_SRC_COLOR],e}r.__esModule=!0,r.default=n;var i=t(\"../../../const\")},{\"../../../const\":46}],99:[function(t,e,r){\"use strict\";function n(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return e[i.DRAW_MODES.POINTS]=t.POINTS,e[i.DRAW_MODES.LINES]=t.LINES,e[i.DRAW_MODES.LINE_LOOP]=t.LINE_LOOP,e[i.DRAW_MODES.LINE_STRIP]=t.LINE_STRIP,e[i.DRAW_MODES.TRIANGLES]=t.TRIANGLES,e[i.DRAW_MODES.TRIANGLE_STRIP]=t.TRIANGLE_STRIP,e[i.DRAW_MODES.TRIANGLE_FAN]=t.TRIANGLE_FAN,e}r.__esModule=!0,r.default=n;var i=t(\"../../../const\")},{\"../../../const\":46}],100:[function(t,e,r){\"use strict\";function n(t){t.getContextAttributes().stencil||console.warn(\"Provided WebGL context does not have a stencil buffer, masks may not render correctly\")}r.__esModule=!0,r.default=n},{}],101:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0;var i=t(\"./utils/maxRecommendedTextures\"),o=n(i),s=t(\"./utils/canUploadSameBuffer\"),a=n(s);r.default={TARGET_FPMS:.06,MIPMAP_TEXTURES:!0,RESOLUTION:1,FILTER_RESOLUTION:1,SPRITE_MAX_TEXTURES:(0,o.default)(32),SPRITE_BATCH_SIZE:4096,RETINA_PREFIX:/@([0-9\\.]+)x/,RENDER_OPTIONS:{view:null,antialias:!1,forceFXAA:!1,autoResize:!1,transparent:!1,backgroundColor:0,clearBeforeRender:!0,preserveDrawingBuffer:!1,roundPixels:!1,width:800,height:600,legacy:!1},TRANSFORM_MODE:0,GC_MODE:0,GC_MAX_IDLE:3600,GC_MAX_CHECK_COUNT:600,WRAP_MODE:0,SCALE_MODE:0,PRECISION_VERTEX:\"highp\",PRECISION_FRAGMENT:\"mediump\",CAN_UPLOAD_SAME_BUFFER:(0,a.default)()}},{\"./utils/canUploadSameBuffer\":122,\"./utils/maxRecommendedTextures\":127}],102:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),u=t(\"../math\"),h=t(\"../utils\"),l=t(\"../const\"),c=t(\"../textures/Texture\"),d=n(c),f=t(\"../display/Container\"),p=n(f),v=new u.Point,y=function(t){function e(r){i(this,e);var n=o(this,t.call(this));return n._anchor=new u.ObservablePoint(n._onAnchorUpdate,n),n._texture=null,n._width=0,n._height=0,n._tint=null,n._tintRGB=null,n.tint=16777215,n.blendMode=l.BLEND_MODES.NORMAL,n.shader=null,n.cachedTint=16777215,n.texture=r||d.default.EMPTY,n.vertexData=new Float32Array(8),n.vertexTrimmedData=null,n._transformID=-1,n._textureID=-1,n._transformTrimmedID=-1,n._textureTrimmedID=-1,n.pluginName=\"sprite\",n}return s(e,t),e.prototype._onTextureUpdate=function(){this._textureID=-1,this._textureTrimmedID=-1,this.cachedTint=16777215,this._width&&(this.scale.x=(0,h.sign)(this.scale.x)*this._width/this._texture.orig.width),this._height&&(this.scale.y=(0,h.sign)(this.scale.y)*this._height/this._texture.orig.height)},e.prototype._onAnchorUpdate=function(){this._transformID=-1,this._transformTrimmedID=-1},e.prototype.calculateVertices=function(){if(this._transformID!==this.transform._worldID||this._textureID!==this._texture._updateID){this._transformID=this.transform._worldID,this._textureID=this._texture._updateID;var t=this._texture,e=this.transform.worldTransform,r=e.a,n=e.b,i=e.c,o=e.d,s=e.tx,a=e.ty,u=this.vertexData,h=t.trim,l=t.orig,c=this._anchor,d=0,f=0,p=0,v=0;h?(f=h.x-c._x*l.width,d=f+h.width,v=h.y-c._y*l.height,p=v+h.height):(f=-c._x*l.width,d=f+l.width,v=-c._y*l.height,p=v+l.height),u[0]=r*f+i*v+s,u[1]=o*v+n*f+a,u[2]=r*d+i*v+s,u[3]=o*v+n*d+a,u[4]=r*d+i*p+s,u[5]=o*p+n*d+a,u[6]=r*f+i*p+s,u[7]=o*p+n*f+a}},e.prototype.calculateTrimmedVertices=function(){if(this.vertexTrimmedData){if(this._transformTrimmedID===this.transform._worldID&&this._textureTrimmedID===this._texture._updateID)return}else this.vertexTrimmedData=new Float32Array(8);this._transformTrimmedID=this.transform._worldID,this._textureTrimmedID=this._texture._updateID;var t=this._texture,e=this.vertexTrimmedData,r=t.orig,n=this._anchor,i=this.transform.worldTransform,o=i.a,s=i.b,a=i.c,u=i.d,h=i.tx,l=i.ty,c=-n._x*r.width,d=c+r.width,f=-n._y*r.height,p=f+r.height;e[0]=o*c+a*f+h,e[1]=u*f+s*c+l,e[2]=o*d+a*f+h,e[3]=u*f+s*d+l,e[4]=o*d+a*p+h,e[5]=u*p+s*d+l,e[6]=o*c+a*p+h,e[7]=u*p+s*c+l},e.prototype._renderWebGL=function(t){this.calculateVertices(),t.setObjectRenderer(t.plugins[this.pluginName]),t.plugins[this.pluginName].render(this)},e.prototype._renderCanvas=function(t){t.plugins[this.pluginName].render(this)},e.prototype._calculateBounds=function(){var t=this._texture.trim,e=this._texture.orig;!t||t.width===e.width&&t.height===e.height?(this.calculateVertices(),this._bounds.addQuad(this.vertexData)):(this.calculateTrimmedVertices(),this._bounds.addQuad(this.vertexTrimmedData))},e.prototype.getLocalBounds=function(e){return 0===this.children.length?(this._bounds.minX=this._texture.orig.width*-this._anchor._x,this._bounds.minY=this._texture.orig.height*-this._anchor._y,this._bounds.maxX=this._texture.orig.width*(1-this._anchor._x),this._bounds.maxY=this._texture.orig.height*(1-this._anchor._y),e||(this._localBoundsRect||(this._localBoundsRect=new u.Rectangle),e=this._localBoundsRect),this._bounds.getRectangle(e)):t.prototype.getLocalBounds.call(this,e)},e.prototype.containsPoint=function(t){this.worldTransform.applyInverse(t,v);var e=this._texture.orig.width,r=this._texture.orig.height,n=-e*this.anchor.x,i=0;return v.x>=n&&v.x<n+e&&(i=-r*this.anchor.y,v.y>=i&&v.y<i+r)},e.prototype.destroy=function(e){if(t.prototype.destroy.call(this,e),this._anchor=null,\"boolean\"==typeof e?e:e&&e.texture){var r=\"boolean\"==typeof e?e:e&&e.baseTexture;this._texture.destroy(!!r)}this._texture=null,this.shader=null},e.from=function(t){return new e(d.default.from(t))},e.fromFrame=function(t){var r=h.TextureCache[t];if(!r)throw new Error('The frameId \"'+t+'\" does not exist in the texture cache');return new e(r)},e.fromImage=function(t,r,n){return new e(d.default.fromImage(t,r,n))},a(e,[{key:\"width\",get:function(){return Math.abs(this.scale.x)*this._texture.orig.width},set:function(t){var e=(0,h.sign)(this.scale.x)||1;this.scale.x=e*t/this._texture.orig.width,this._width=t}},{key:\"height\",get:function(){return Math.abs(this.scale.y)*this._texture.orig.height},set:function(t){var e=(0,h.sign)(this.scale.y)||1;this.scale.y=e*t/this._texture.orig.height,this._height=t}},{key:\"anchor\",get:function(){return this._anchor},set:function(t){this._anchor.copy(t)}},{key:\"tint\",get:function(){return this._tint},set:function(t){this._tint=t,this._tintRGB=(t>>16)+(65280&t)+((255&t)<<16)}},{key:\"texture\",get:function(){return this._texture},set:function(t){this._texture!==t&&(this._texture=t,this.cachedTint=16777215,this._textureID=-1,this._textureTrimmedID=-1,t&&(t.baseTexture.hasLoaded?this._onTextureUpdate():t.once(\"update\",this._onTextureUpdate,this)))}}]),e}(p.default);r.default=y},{\"../const\":46,\"../display/Container\":48,\"../math\":70,\"../textures/Texture\":115,\"../utils\":125}],103:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var o=t(\"../../renderers/canvas/CanvasRenderer\"),s=n(o),a=t(\"../../const\"),u=t(\"../../math\"),h=t(\"./CanvasTinter\"),l=n(h),c=new u.Matrix,d=function(){function t(e){i(this,t),this.renderer=e}return t.prototype.render=function(t){var e=t._texture,r=this.renderer,n=e._frame.width,i=e._frame.height,o=t.transform.worldTransform,s=0,h=0;if(!(e.orig.width<=0||e.orig.height<=0)&&e.baseTexture.source&&(r.setBlendMode(t.blendMode),e.valid)){r.context.globalAlpha=t.worldAlpha;var d=e.baseTexture.scaleMode===a.SCALE_MODES.LINEAR;r.smoothProperty&&r.context[r.smoothProperty]!==d&&(r.context[r.smoothProperty]=d),e.trim?(s=e.trim.width/2+e.trim.x-t.anchor.x*e.orig.width,h=e.trim.height/2+e.trim.y-t.anchor.y*e.orig.height):(s=(.5-t.anchor.x)*e.orig.width,h=(.5-t.anchor.y)*e.orig.height),e.rotate&&(o.copy(c),o=c,u.GroupD8.matrixAppendRotationInv(o,e.rotate,s,h),s=0,h=0),s-=n/2,h-=i/2,r.roundPixels?(r.context.setTransform(o.a,o.b,o.c,o.d,o.tx*r.resolution|0,o.ty*r.resolution|0),s|=0,h|=0):r.context.setTransform(o.a,o.b,o.c,o.d,o.tx*r.resolution,o.ty*r.resolution);var f=e.baseTexture.resolution;16777215!==t.tint?(t.cachedTint===t.tint&&t.tintedTexture.tintId===t._texture._updateID||(t.cachedTint=t.tint,t.tintedTexture=l.default.getTintedTexture(t,t.tint)),r.context.drawImage(t.tintedTexture,0,0,n*f,i*f,s*r.resolution,h*r.resolution,n*r.resolution,i*r.resolution)):r.context.drawImage(e.baseTexture.source,e._frame.x*f,e._frame.y*f,n*f,i*f,s*r.resolution,h*r.resolution,n*r.resolution,i*r.resolution)}},t.prototype.destroy=function(){this.renderer=null},t}();r.default=d,s.default.registerPlugin(\"sprite\",d)},{\"../../const\":46,\"../../math\":70,\"../../renderers/canvas/CanvasRenderer\":77,\"./CanvasTinter\":104}],104:[function(t,e,r){\"use strict\";r.__esModule=!0;var n=t(\"../../utils\"),i=t(\"../../renderers/canvas/utils/canUseNewCanvasBlendModes\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s={getTintedTexture:function(t,e){var r=t._texture;e=s.roundColor(e);var n=\"#\"+(\"00000\"+(0|e).toString(16)).substr(-6);r.tintCache=r.tintCache||{};var i=r.tintCache[n],o=void 0;if(i){if(i.tintId===r._updateID)return r.tintCache[n];o=r.tintCache[n]}else o=s.canvas||document.createElement(\"canvas\");if(s.tintMethod(r,e,o),o.tintId=r._updateID,s.convertTintToImage){var a=new Image;a.src=o.toDataURL(),r.tintCache[n]=a}else r.tintCache[n]=o,s.canvas=null;return o},tintWithMultiply:function(t,e,r){var n=r.getContext(\"2d\"),i=t._frame.clone(),o=t.baseTexture.resolution;i.x*=o,i.y*=o,i.width*=o,i.height*=o,r.width=Math.ceil(i.width),r.height=Math.ceil(i.height),n.save(),n.fillStyle=\"#\"+(\"00000\"+(0|e).toString(16)).substr(-6),n.fillRect(0,0,i.width,i.height),n.globalCompositeOperation=\"multiply\",n.drawImage(t.baseTexture.source,i.x,i.y,i.width,i.height,0,0,i.width,i.height),n.globalCompositeOperation=\"destination-atop\",n.drawImage(t.baseTexture.source,i.x,i.y,i.width,i.height,0,0,i.width,i.height),n.restore()},tintWithOverlay:function(t,e,r){var n=r.getContext(\"2d\"),i=t._frame.clone(),o=t.baseTexture.resolution;i.x*=o,i.y*=o,i.width*=o,i.height*=o,r.width=Math.ceil(i.width),r.height=Math.ceil(i.height),n.save(),n.globalCompositeOperation=\"copy\",n.fillStyle=\"#\"+(\"00000\"+(0|e).toString(16)).substr(-6),n.fillRect(0,0,i.width,i.height),n.globalCompositeOperation=\"destination-atop\",n.drawImage(t.baseTexture.source,i.x,i.y,i.width,i.height,0,0,i.width,i.height),n.restore()},tintWithPerPixel:function(t,e,r){var i=r.getContext(\"2d\"),o=t._frame.clone(),s=t.baseTexture.resolution;o.x*=s,o.y*=s,o.width*=s,o.height*=s,r.width=Math.ceil(o.width),r.height=Math.ceil(o.height),i.save(),i.globalCompositeOperation=\"copy\",i.drawImage(t.baseTexture.source,o.x,o.y,o.width,o.height,0,0,o.width,o.height),i.restore();for(var a=(0,n.hex2rgb)(e),u=a[0],h=a[1],l=a[2],c=i.getImageData(0,0,o.width,o.height),d=c.data,f=0;f<d.length;f+=4)d[f+0]*=u,d[f+1]*=h,d[f+2]*=l;i.putImageData(c,0,0)},roundColor:function(t){var e=s.cacheStepsPerColorChannel,r=(0,n.hex2rgb)(t);return r[0]=Math.min(255,r[0]/e*e),r[1]=Math.min(255,r[1]/e*e),r[2]=Math.min(255,r[2]/e*e),(0,n.rgb2hex)(r)},cacheStepsPerColorChannel:8,convertTintToImage:!1,canUseMultiply:(0,o.default)(),tintMethod:0};s.tintMethod=s.canUseMultiply?s.tintWithMultiply:s.tintWithPerPixel,r.default=s},{\"../../renderers/canvas/utils/canUseNewCanvasBlendModes\":80,\"../../utils\":125}],105:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(e){n(this,t),this.vertices=new ArrayBuffer(e),this.float32View=new Float32Array(this.vertices),this.uint32View=new Uint32Array(this.vertices)}return t.prototype.destroy=function(){this.vertices=null,this.positions=null,this.uvs=null,this.colors=null},t}();r.default=i},{}],106:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"../../renderers/webgl/utils/ObjectRenderer\"),u=n(a),h=t(\"../../renderers/webgl/WebGLRenderer\"),l=n(h),c=t(\"../../utils/createIndicesForQuads\"),d=n(c),f=t(\"./generateMultiTextureShader\"),p=n(f),v=t(\"../../renderers/webgl/utils/checkMaxIfStatmentsInShader\"),y=n(v),g=t(\"./BatchBuffer\"),m=n(g),_=t(\"../../settings\"),b=n(_),x=t(\"../../utils\"),T=t(\"pixi-gl-core\"),w=n(T),E=t(\"bit-twiddle\"),S=n(E),O=0,M=0,P=function(t){function e(r){i(this,e);var n=o(this,t.call(this,r));n.vertSize=5,n.vertByteSize=4*n.vertSize,n.size=b.default.SPRITE_BATCH_SIZE,n.buffers=[];for(var s=1;s<=S.default.nextPow2(n.size);s*=2)n.buffers.push(new m.default(4*s*n.vertByteSize));n.indices=(0,d.default)(n.size),n.shader=null,n.currentIndex=0,n.groups=[];for(var a=0;a<n.size;a++)n.groups[a]={textures:[],textureCount:0,ids:[],size:0,start:0,blend:0};return n.sprites=[],n.vertexBuffers=[],n.vaos=[],n.vaoMax=2,n.vertexCount=0,n.renderer.on(\"prerender\",n.onPrerender,n),n}return s(e,t),e.prototype.onContextChange=function(){var t=this.renderer.gl;this.renderer.legacy?this.MAX_TEXTURES=1:(this.MAX_TEXTURES=Math.min(t.getParameter(t.MAX_TEXTURE_IMAGE_UNITS),b.default.SPRITE_MAX_TEXTURES),this.MAX_TEXTURES=(0,y.default)(this.MAX_TEXTURES,t)),this.shader=(0,p.default)(t,this.MAX_TEXTURES),this.indexBuffer=w.default.GLBuffer.createIndexBuffer(t,this.indices,t.STATIC_DRAW),this.renderer.bindVao(null);for(var e=this.shader.attributes,r=0;r<this.vaoMax;r++){var n=this.vertexBuffers[r]=w.default.GLBuffer.createVertexBuffer(t,null,t.STREAM_DRAW),i=this.renderer.createVao().addIndex(this.indexBuffer).addAttribute(n,e.aVertexPosition,t.FLOAT,!1,this.vertByteSize,0).addAttribute(n,e.aTextureCoord,t.UNSIGNED_SHORT,!0,this.vertByteSize,8).addAttribute(n,e.aColor,t.UNSIGNED_BYTE,!0,this.vertByteSize,12);e.aTextureId&&i.addAttribute(n,e.aTextureId,t.FLOAT,!1,this.vertByteSize,16),this.vaos[r]=i}this.vao=this.vaos[0],this.currentBlendMode=99999,this.boundTextures=new Array(this.MAX_TEXTURES)},e.prototype.onPrerender=function(){this.vertexCount=0},e.prototype.render=function(t){this.currentIndex>=this.size&&this.flush(),t._texture._uvs&&(this.sprites[this.currentIndex++]=t)},e.prototype.flush=function(){if(0!==this.currentIndex){var t=this.renderer.gl,e=this.MAX_TEXTURES,r=S.default.nextPow2(this.currentIndex),n=S.default.log2(r),i=this.buffers[n],o=this.sprites,s=this.groups,a=i.float32View,u=i.uint32View,h=this.boundTextures,l=this.renderer.boundTextures,c=this.renderer.textureGC.count,d=0,f=void 0,p=void 0,v=1,y=0,g=s[0],m=void 0,_=void 0,T=x.premultiplyBlendMode[o[0]._texture.baseTexture.premultipliedAlpha?1:0][o[0].blendMode];g.textureCount=0,g.start=0,g.blend=T,O++;var E=void 0;for(E=0;E<e;++E){var P=l[E];P._enabled!==O?(h[E]=P,P._virtalBoundId=E,P._enabled=O):h[E]=this.renderer.emptyTextures[E]}for(O++,E=0;E<this.currentIndex;++E){var C=o[E];f=C._texture.baseTexture;var R=x.premultiplyBlendMode[Number(f.premultipliedAlpha)][C.blendMode];if(T!==R&&(T=R,p=null,y=e,O++),p!==f&&(p=f,f._enabled!==O)){if(y===e&&(O++,g.size=E-g.start,y=0,g=s[v++],g.blend=T,g.textureCount=0,g.start=E),f.touched=c,-1===f._virtalBoundId)for(var A=0;A<e;++A){var I=(A+M)%e,D=h[I];if(D._enabled!==O){M++,D._virtalBoundId=-1,f._virtalBoundId=I,h[I]=f;break}}f._enabled=O,g.textureCount++,g.ids[y]=f._virtalBoundId,g.textures[y++]=f}if(m=C.vertexData,_=C._texture._uvs.uvsUint32,this.renderer.roundPixels){var L=this.renderer.resolution;a[d]=(m[0]*L|0)/L,a[d+1]=(m[1]*L|0)/L,a[d+5]=(m[2]*L|0)/L,a[d+6]=(m[3]*L|0)/L,a[d+10]=(m[4]*L|0)/L,a[d+11]=(m[5]*L|0)/L,a[d+15]=(m[6]*L|0)/L,a[d+16]=(m[7]*L|0)/L}else a[d]=m[0],a[d+1]=m[1],a[d+5]=m[2],a[d+6]=m[3],a[d+10]=m[4],a[d+11]=m[5],a[d+15]=m[6],a[d+16]=m[7];u[d+2]=_[0],u[d+7]=_[1],u[d+12]=_[2],u[d+17]=_[3];var N=Math.min(C.worldAlpha,1),F=N<1&&f.premultipliedAlpha?(0,x.premultiplyTint)(C._tintRGB,N):C._tintRGB+(255*N<<24);u[d+3]=u[d+8]=u[d+13]=u[d+18]=F,a[d+4]=a[d+9]=a[d+14]=a[d+19]=f._virtalBoundId,d+=20}if(g.size=E-g.start,b.default.CAN_UPLOAD_SAME_BUFFER)this.vertexBuffers[this.vertexCount].upload(i.vertices,0,!0);else{if(this.vaoMax<=this.vertexCount){this.vaoMax++;var B=this.shader.attributes,k=this.vertexBuffers[this.vertexCount]=w.default.GLBuffer.createVertexBuffer(t,null,t.STREAM_DRAW),j=this.renderer.createVao().addIndex(this.indexBuffer).addAttribute(k,B.aVertexPosition,t.FLOAT,!1,this.vertByteSize,0).addAttribute(k,B.aTextureCoord,t.UNSIGNED_SHORT,!0,this.vertByteSize,8).addAttribute(k,B.aColor,t.UNSIGNED_BYTE,!0,this.vertByteSize,12);B.aTextureId&&j.addAttribute(k,B.aTextureId,t.FLOAT,!1,this.vertByteSize,16),this.vaos[this.vertexCount]=j}this.renderer.bindVao(this.vaos[this.vertexCount]),this.vertexBuffers[this.vertexCount].upload(i.vertices,0,!1),this.vertexCount++}for(E=0;E<e;++E)l[E]._virtalBoundId=-1;for(E=0;E<v;++E){for(var U=s[E],X=U.textureCount,G=0;G<X;G++)p=U.textures[G],l[U.ids[G]]!==p&&this.renderer.bindTexture(p,U.ids[G],!0),p._virtalBoundId=-1;this.renderer.state.setBlendMode(U.blend),t.drawElements(t.TRIANGLES,6*U.size,t.UNSIGNED_SHORT,6*U.start*2)}this.currentIndex=0}},e.prototype.start=function(){this.renderer.bindShader(this.shader),b.default.CAN_UPLOAD_SAME_BUFFER&&(this.renderer.bindVao(this.vaos[this.vertexCount]),this.vertexBuffers[this.vertexCount].bind())},e.prototype.stop=function(){this.flush()},e.prototype.destroy=function(){for(var e=0;e<this.vaoMax;e++)this.vertexBuffers[e]&&this.vertexBuffers[e].destroy(),this.vaos[e]&&this.vaos[e].destroy();this.indexBuffer&&this.indexBuffer.destroy(),this.renderer.off(\"prerender\",this.onPrerender,this),t.prototype.destroy.call(this),this.shader&&(this.shader.destroy(),this.shader=null),this.vertexBuffers=null,this.vaos=null,this.indexBuffer=null,this.indices=null,this.sprites=null;for(var r=0;r<this.buffers.length;++r)this.buffers[r].destroy()},e}(u.default);r.default=P,l.default.registerPlugin(\"sprite\",P)},{\"../../renderers/webgl/WebGLRenderer\":84,\"../../renderers/webgl/utils/ObjectRenderer\":94,\"../../renderers/webgl/utils/checkMaxIfStatmentsInShader\":97,\"../../settings\":101,\"../../utils\":125,\"../../utils/createIndicesForQuads\":123,\"./BatchBuffer\":105,\"./generateMultiTextureShader\":107,\"bit-twiddle\":1,\"pixi-gl-core\":12}],107:[function(t,e,r){\"use strict\";function n(t,e){var r=a;r=r.replace(/%count%/gi,e),r=r.replace(/%forloop%/gi,i(e));for(var n=new s.default(t,\"precision highp float;\\nattribute vec2 aVertexPosition;\\nattribute vec2 aTextureCoord;\\nattribute vec4 aColor;\\nattribute float aTextureId;\\n\\nuniform mat3 projectionMatrix;\\n\\nvarying vec2 vTextureCoord;\\nvarying vec4 vColor;\\nvarying float vTextureId;\\n\\nvoid main(void){\\n    gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\\n\\n    vTextureCoord = aTextureCoord;\\n    vTextureId = aTextureId;\\n    vColor = aColor;\\n}\\n\",r),o=[],u=0;u<e;u++)o[u]=u;return n.bind(),n.uniforms.uSamplers=o,n}function i(t){var e=\"\";e+=\"\\n\",e+=\"\\n\";for(var r=0;r<t;r++)r>0&&(e+=\"\\nelse \"),r<t-1&&(e+=\"if(textureId == \"+r+\".0)\"),e+=\"\\n{\",e+=\"\\n\\tcolor = texture2D(uSamplers[\"+r+\"], vTextureCoord);\",e+=\"\\n}\";return e+=\"\\n\",e+=\"\\n\"}r.__esModule=!0,r.default=n;var o=t(\"../../Shader\"),s=function(t){return t&&t.__esModule?t:{default:t}}(o),a=(t(\"path\"),[\"varying vec2 vTextureCoord;\",\"varying vec4 vColor;\",\"varying float vTextureId;\",\"uniform sampler2D uSamplers[%count%];\",\"void main(void){\",\"vec4 color;\",\"float textureId = floor(vTextureId+0.5);\",\"%forloop%\",\"gl_FragColor = color * vColor;\",\"}\"].join(\"\\n\"))},{\"../../Shader\":44,path:23}],108:[function(t,e,r){\"use strict\";function n(t){\nreturn t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),u=t(\"../sprites/Sprite\"),h=n(u),l=t(\"../textures/Texture\"),c=n(l),d=t(\"../math\"),f=t(\"../utils\"),p=t(\"../const\"),v=t(\"../settings\"),y=n(v),g=t(\"./TextStyle\"),m=n(g),_=t(\"./TextMetrics\"),b=n(_),x=t(\"../utils/trimCanvas\"),T=n(x),w={texture:!0,children:!1,baseTexture:!0},E=function(t){function e(r,n,s){i(this,e),s=s||document.createElement(\"canvas\"),s.width=3,s.height=3;var a=c.default.fromCanvas(s,y.default.SCALE_MODE,\"text\");a.orig=new d.Rectangle,a.trim=new d.Rectangle;var u=o(this,t.call(this,a));return c.default.addToCache(u._texture,u._texture.baseTexture.textureCacheIds[0]),u.canvas=s,u.context=u.canvas.getContext(\"2d\"),u.resolution=y.default.RESOLUTION,u._text=null,u._style=null,u._styleListener=null,u._font=\"\",u.text=r,u.style=n,u.localStyleID=-1,u}return s(e,t),e.prototype.updateText=function(t){var e=this._style;if(this.localStyleID!==e.styleID&&(this.dirty=!0,this.localStyleID=e.styleID),this.dirty||!t){this._font=this._style.toFontString();var r=this.context,n=b.default.measureText(this._text,this._style,this._style.wordWrap,this.canvas),i=n.width,o=n.height,s=n.lines,a=n.lineHeight,u=n.lineWidths,h=n.maxLineWidth,l=n.fontProperties;this.canvas.width=Math.ceil((i+2*e.padding)*this.resolution),this.canvas.height=Math.ceil((o+2*e.padding)*this.resolution),r.scale(this.resolution,this.resolution),r.clearRect(0,0,this.canvas.width,this.canvas.height),r.font=this._font,r.strokeStyle=e.stroke,r.lineWidth=e.strokeThickness,r.textBaseline=e.textBaseline,r.lineJoin=e.lineJoin,r.miterLimit=e.miterLimit;var c=void 0,d=void 0;if(e.dropShadow){r.fillStyle=e.dropShadowColor,r.globalAlpha=e.dropShadowAlpha,r.shadowBlur=e.dropShadowBlur,e.dropShadowBlur>0&&(r.shadowColor=e.dropShadowColor);for(var f=Math.cos(e.dropShadowAngle)*e.dropShadowDistance,p=Math.sin(e.dropShadowAngle)*e.dropShadowDistance,v=0;v<s.length;v++)c=e.strokeThickness/2,d=e.strokeThickness/2+v*a+l.ascent,\"right\"===e.align?c+=h-u[v]:\"center\"===e.align&&(c+=(h-u[v])/2),e.fill&&(this.drawLetterSpacing(s[v],c+f+e.padding,d+p+e.padding),e.stroke&&e.strokeThickness&&(r.strokeStyle=e.dropShadowColor,this.drawLetterSpacing(s[v],c+f+e.padding,d+p+e.padding,!0),r.strokeStyle=e.stroke))}r.shadowBlur=0,r.globalAlpha=1,r.fillStyle=this._generateFillStyle(e,s);for(var y=0;y<s.length;y++)c=e.strokeThickness/2,d=e.strokeThickness/2+y*a+l.ascent,\"right\"===e.align?c+=h-u[y]:\"center\"===e.align&&(c+=(h-u[y])/2),e.stroke&&e.strokeThickness&&this.drawLetterSpacing(s[y],c+e.padding,d+e.padding,!0),e.fill&&this.drawLetterSpacing(s[y],c+e.padding,d+e.padding);this.updateTexture()}},e.prototype.drawLetterSpacing=function(t,e,r){var n=arguments.length>3&&void 0!==arguments[3]&&arguments[3],i=this._style,o=i.letterSpacing;if(0===o)return void(n?this.context.strokeText(t,e,r):this.context.fillText(t,e,r));for(var s=String.prototype.split.call(t,\"\"),a=e,u=0,h=\"\";u<t.length;)h=s[u++],n?this.context.strokeText(h,a,r):this.context.fillText(h,a,r),a+=this.context.measureText(h).width+o},e.prototype.updateTexture=function(){var t=this.canvas;if(this._style.trim){var e=(0,T.default)(t);t.width=e.width,t.height=e.height,this.context.putImageData(e.data,0,0)}var r=this._texture,n=this._style,i=n.trim?0:n.padding,o=r.baseTexture;o.hasLoaded=!0,o.resolution=this.resolution,o.realWidth=t.width,o.realHeight=t.height,o.width=t.width/this.resolution,o.height=t.height/this.resolution,r.trim.width=r._frame.width=t.width/this.resolution,r.trim.height=r._frame.height=t.height/this.resolution,r.trim.x=-i,r.trim.y=-i,r.orig.width=r._frame.width-2*i,r.orig.height=r._frame.height-2*i,this._onTextureUpdate(),o.emit(\"update\",o),this.dirty=!1},e.prototype.renderWebGL=function(e){this.resolution!==e.resolution&&(this.resolution=e.resolution,this.dirty=!0),this.updateText(!0),t.prototype.renderWebGL.call(this,e)},e.prototype._renderCanvas=function(e){this.resolution!==e.resolution&&(this.resolution=e.resolution,this.dirty=!0),this.updateText(!0),t.prototype._renderCanvas.call(this,e)},e.prototype.getLocalBounds=function(e){return this.updateText(!0),t.prototype.getLocalBounds.call(this,e)},e.prototype._calculateBounds=function(){this.updateText(!0),this.calculateVertices(),this._bounds.addQuad(this.vertexData)},e.prototype._onStyleChange=function(){this.dirty=!0},e.prototype._generateFillStyle=function(t,e){if(!Array.isArray(t.fill))return t.fill;if(navigator.isCocoonJS)return t.fill[0];var r=void 0,n=void 0,i=void 0,o=void 0,s=this.canvas.width/this.resolution,a=this.canvas.height/this.resolution,u=t.fill.slice(),h=t.fillGradientStops.slice();if(!h.length)for(var l=u.length+1,c=1;c<l;++c)h.push(c/l);if(u.unshift(t.fill[0]),h.unshift(0),u.push(t.fill[t.fill.length-1]),h.push(1),t.fillGradientType===p.TEXT_GRADIENT.LINEAR_VERTICAL){r=this.context.createLinearGradient(s/2,0,s/2,a),n=(u.length+1)*e.length,i=0;for(var d=0;d<e.length;d++){i+=1;for(var f=0;f<u.length;f++)o=\"number\"==typeof h[f]?h[f]/e.length+d/e.length:i/n,r.addColorStop(o,u[f]),i++}}else{r=this.context.createLinearGradient(0,a/2,s,a/2),n=u.length+1,i=1;for(var v=0;v<u.length;v++)o=\"number\"==typeof h[v]?h[v]:i/n,r.addColorStop(o,u[v]),i++}return r},e.prototype.destroy=function(e){\"boolean\"==typeof e&&(e={children:e}),e=Object.assign({},w,e),t.prototype.destroy.call(this,e),this.context=null,this.canvas=null,this._style=null},a(e,[{key:\"width\",get:function(){return this.updateText(!0),Math.abs(this.scale.x)*this._texture.orig.width},set:function(t){this.updateText(!0);var e=(0,f.sign)(this.scale.x)||1;this.scale.x=e*t/this._texture.orig.width,this._width=t}},{key:\"height\",get:function(){return this.updateText(!0),Math.abs(this.scale.y)*this._texture.orig.height},set:function(t){this.updateText(!0);var e=(0,f.sign)(this.scale.y)||1;this.scale.y=e*t/this._texture.orig.height,this._height=t}},{key:\"style\",get:function(){return this._style},set:function(t){t=t||{},t instanceof m.default?this._style=t:this._style=new m.default(t),this.localStyleID=-1,this.dirty=!0}},{key:\"text\",get:function(){return this._text},set:function(t){t=String(\"\"===t||null===t||void 0===t?\" \":t),this._text!==t&&(this._text=t,this.dirty=!0)}}]),e}(h.default);r.default=E},{\"../const\":46,\"../math\":70,\"../settings\":101,\"../sprites/Sprite\":102,\"../textures/Texture\":115,\"../utils\":125,\"../utils/trimCanvas\":130,\"./TextMetrics\":109,\"./TextStyle\":110}],109:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(e,r,i,o,s,a,u,h,l){n(this,t),this.text=e,this.style=r,this.width=i,this.height=o,this.lines=s,this.lineWidths=a,this.lineHeight=u,this.maxLineWidth=h,this.fontProperties=l}return t.measureText=function(e,r,n){var i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:t._canvas;n=n||r.wordWrap;var o=r.toFontString(),s=t.measureFont(o),a=i.getContext(\"2d\");a.font=o;for(var u=n?t.wordWrap(e,r,i):e,h=u.split(/(?:\\r\\n|\\r|\\n)/),l=new Array(h.length),c=0,d=0;d<h.length;d++){var f=a.measureText(h[d]).width+(h[d].length-1)*r.letterSpacing;l[d]=f,c=Math.max(c,f)}var p=c+r.strokeThickness;r.dropShadow&&(p+=r.dropShadowDistance);var v=r.lineHeight||s.fontSize+r.strokeThickness,y=Math.max(v,s.fontSize+r.strokeThickness)+(h.length-1)*(v+r.leading);return r.dropShadow&&(y+=r.dropShadowDistance),new t(e,r,p,y,h,l,v+r.leading,c,s)},t.wordWrap=function(e,r){for(var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t._canvas,i=n.getContext(\"2d\"),o=\"\",s=e.charAt(0),a=e.split(\"\\n\"),u=r.wordWrapWidth,h={},l=0;l<a.length;l++){for(var c=u,d=a[l].split(\" \"),f=0;f<d.length;f++){var p=i.measureText(d[f]).width;if(r.breakWords&&p>u)for(var v=d[f].split(\"\"),y=0;y<v.length;y++){var g=v[y],m=h[g];void 0===m&&(m=i.measureText(g).width,h[g]=m),m>c?(o+=\"\\n\"+g,c=u-m):(0===y&&(f>0||\" \"===s)&&(o+=\" \"),o+=g,c-=m)}else{var _=p+i.measureText(\" \").width;0===f||_>c?(f>0&&(o+=\"\\n\"),o+=d[f],c=u-p):(c-=_,o+=\" \"+d[f])}}l<a.length-1&&(o+=\"\\n\")}return o},t.measureFont=function(e){if(t._fonts[e])return t._fonts[e];var r={},n=t._canvas,i=t._context;i.font=e;var o=Math.ceil(i.measureText(\"|MÉq\").width),s=Math.ceil(i.measureText(\"M\").width),a=2*s;s=1.4*s|0,n.width=o,n.height=a,i.fillStyle=\"#f00\",i.fillRect(0,0,o,a),i.font=e,i.textBaseline=\"alphabetic\",i.fillStyle=\"#000\",i.fillText(\"|MÉq\",0,s);var u=i.getImageData(0,0,o,a).data,h=u.length,l=4*o,c=0,d=0,f=!1;for(c=0;c<s;++c){for(var p=0;p<l;p+=4)if(255!==u[d+p]){f=!0;break}if(f)break;d+=l}for(r.ascent=s-c,d=h-l,f=!1,c=a;c>s;--c){for(var v=0;v<l;v+=4)if(255!==u[d+v]){f=!0;break}if(f)break;d-=l}return r.descent=c-s,r.fontSize=r.ascent+r.descent,t._fonts[e]=r,r},t}();r.default=i;var o=document.createElement(\"canvas\");o.width=o.height=10,i._canvas=o,i._context=o.getContext(\"2d\"),i._fonts={}},{}],110:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t){return\"number\"==typeof t?(0,l.hex2string)(t):(\"string\"==typeof t&&0===t.indexOf(\"0x\")&&(t=t.replace(\"0x\",\"#\")),t)}function o(t){if(Array.isArray(t)){for(var e=0;e<t.length;++e)t[e]=i(t[e]);return t}return i(t)}function s(t,e){if(!Array.isArray(t)||!Array.isArray(e))return!1;if(t.length!==e.length)return!1;for(var r=0;r<t.length;++r)if(t[r]!==e[r])return!1;return!0}function a(t,e,r){for(var n in r)Array.isArray(e[n])?t[n]=e[n].slice():t[n]=e[n]}r.__esModule=!0;var u=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),h=t(\"../const\"),l=t(\"../utils\"),c={align:\"left\",breakWords:!1,dropShadow:!1,dropShadowAlpha:1,dropShadowAngle:Math.PI/6,dropShadowBlur:0,dropShadowColor:\"black\",dropShadowDistance:5,fill:\"black\",fillGradientType:h.TEXT_GRADIENT.LINEAR_VERTICAL,fillGradientStops:[],fontFamily:\"Arial\",fontSize:26,fontStyle:\"normal\",fontVariant:\"normal\",fontWeight:\"normal\",letterSpacing:0,lineHeight:0,lineJoin:\"miter\",miterLimit:10,padding:0,stroke:\"black\",strokeThickness:0,textBaseline:\"alphabetic\",trim:!1,wordWrap:!1,wordWrapWidth:100,leading:0},d=function(){function t(e){n(this,t),this.styleID=0,this.reset(),a(this,e,e)}return t.prototype.clone=function(){var e={};return a(e,this,c),new t(e)},t.prototype.reset=function(){a(this,c,c)},t.prototype.toFontString=function(){var t=\"number\"==typeof this.fontSize?this.fontSize+\"px\":this.fontSize,e=this.fontFamily;Array.isArray(this.fontFamily)||(e=this.fontFamily.split(\",\"));for(var r=e.length-1;r>=0;r--){var n=e[r].trim();/([\\\"\\'])[^\\'\\\"]+\\1/.test(n)||(n='\"'+n+'\"'),e[r]=n}return this.fontStyle+\" \"+this.fontVariant+\" \"+this.fontWeight+\" \"+t+\" \"+e.join(\",\")},u(t,[{key:\"align\",get:function(){return this._align},set:function(t){this._align!==t&&(this._align=t,this.styleID++)}},{key:\"breakWords\",get:function(){return this._breakWords},set:function(t){this._breakWords!==t&&(this._breakWords=t,this.styleID++)}},{key:\"dropShadow\",get:function(){return this._dropShadow},set:function(t){this._dropShadow!==t&&(this._dropShadow=t,this.styleID++)}},{key:\"dropShadowAlpha\",get:function(){return this._dropShadowAlpha},set:function(t){this._dropShadowAlpha!==t&&(this._dropShadowAlpha=t,this.styleID++)}},{key:\"dropShadowAngle\",get:function(){return this._dropShadowAngle},set:function(t){this._dropShadowAngle!==t&&(this._dropShadowAngle=t,this.styleID++)}},{key:\"dropShadowBlur\",get:function(){return this._dropShadowBlur},set:function(t){this._dropShadowBlur!==t&&(this._dropShadowBlur=t,this.styleID++)}},{key:\"dropShadowColor\",get:function(){return this._dropShadowColor},set:function(t){var e=o(t);this._dropShadowColor!==e&&(this._dropShadowColor=e,this.styleID++)}},{key:\"dropShadowDistance\",get:function(){return this._dropShadowDistance},set:function(t){this._dropShadowDistance!==t&&(this._dropShadowDistance=t,this.styleID++)}},{key:\"fill\",get:function(){return this._fill},set:function(t){var e=o(t);this._fill!==e&&(this._fill=e,this.styleID++)}},{key:\"fillGradientType\",get:function(){return this._fillGradientType},set:function(t){this._fillGradientType!==t&&(this._fillGradientType=t,this.styleID++)}},{key:\"fillGradientStops\",get:function(){return this._fillGradientStops},set:function(t){s(this._fillGradientStops,t)||(this._fillGradientStops=t,this.styleID++)}},{key:\"fontFamily\",get:function(){return this._fontFamily},set:function(t){this.fontFamily!==t&&(this._fontFamily=t,this.styleID++)}},{key:\"fontSize\",get:function(){return this._fontSize},set:function(t){this._fontSize!==t&&(this._fontSize=t,this.styleID++)}},{key:\"fontStyle\",get:function(){return this._fontStyle},set:function(t){this._fontStyle!==t&&(this._fontStyle=t,this.styleID++)}},{key:\"fontVariant\",get:function(){return this._fontVariant},set:function(t){this._fontVariant!==t&&(this._fontVariant=t,this.styleID++)}},{key:\"fontWeight\",get:function(){return this._fontWeight},set:function(t){this._fontWeight!==t&&(this._fontWeight=t,this.styleID++)}},{key:\"letterSpacing\",get:function(){return this._letterSpacing},set:function(t){this._letterSpacing!==t&&(this._letterSpacing=t,this.styleID++)}},{key:\"lineHeight\",get:function(){return this._lineHeight},set:function(t){this._lineHeight!==t&&(this._lineHeight=t,this.styleID++)}},{key:\"leading\",get:function(){return this._leading},set:function(t){this._leading!==t&&(this._leading=t,this.styleID++)}},{key:\"lineJoin\",get:function(){return this._lineJoin},set:function(t){this._lineJoin!==t&&(this._lineJoin=t,this.styleID++)}},{key:\"miterLimit\",get:function(){return this._miterLimit},set:function(t){this._miterLimit!==t&&(this._miterLimit=t,this.styleID++)}},{key:\"padding\",get:function(){return this._padding},set:function(t){this._padding!==t&&(this._padding=t,this.styleID++)}},{key:\"stroke\",get:function(){return this._stroke},set:function(t){var e=o(t);this._stroke!==e&&(this._stroke=e,this.styleID++)}},{key:\"strokeThickness\",get:function(){return this._strokeThickness},set:function(t){this._strokeThickness!==t&&(this._strokeThickness=t,this.styleID++)}},{key:\"textBaseline\",get:function(){return this._textBaseline},set:function(t){this._textBaseline!==t&&(this._textBaseline=t,this.styleID++)}},{key:\"trim\",get:function(){return this._trim},set:function(t){this._trim!==t&&(this._trim=t,this.styleID++)}},{key:\"wordWrap\",get:function(){return this._wordWrap},set:function(t){this._wordWrap!==t&&(this._wordWrap=t,this.styleID++)}},{key:\"wordWrapWidth\",get:function(){return this._wordWrapWidth},set:function(t){this._wordWrapWidth!==t&&(this._wordWrapWidth=t,this.styleID++)}}]),t}();r.default=d},{\"../const\":46,\"../utils\":125}],111:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"./BaseTexture\"),u=n(a),h=t(\"../settings\"),l=n(h),c=function(t){function e(){var r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:100,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:100,s=arguments[2],a=arguments[3];i(this,e);var u=o(this,t.call(this,null,s));return u.resolution=a||l.default.RESOLUTION,u.width=Math.ceil(r),u.height=Math.ceil(n),u.realWidth=u.width*u.resolution,u.realHeight=u.height*u.resolution,u.scaleMode=void 0!==s?s:l.default.SCALE_MODE,u.hasLoaded=!0,u._glRenderTargets={},u._canvasRenderTarget=null,u.valid=!1,u}return s(e,t),e.prototype.resize=function(t,e){t=Math.ceil(t),e=Math.ceil(e),t===this.width&&e===this.height||(this.valid=t>0&&e>0,this.width=t,this.height=e,this.realWidth=this.width*this.resolution,this.realHeight=this.height*this.resolution,this.valid&&this.emit(\"update\",this))},e.prototype.destroy=function(){t.prototype.destroy.call(this,!0),this.renderer=null},e}(u.default);r.default=c},{\"../settings\":101,\"./BaseTexture\":112}],112:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"../utils\"),u=t(\"../settings\"),h=n(u),l=t(\"eventemitter3\"),c=n(l),d=t(\"../utils/determineCrossOrigin\"),f=n(d),p=t(\"bit-twiddle\"),v=n(p),y=function(t){function e(r,n,s){i(this,e);var u=o(this,t.call(this));return u.uid=(0,a.uid)(),u.touched=0,u.resolution=s||h.default.RESOLUTION,u.width=100,u.height=100,u.realWidth=100,u.realHeight=100,u.scaleMode=void 0!==n?n:h.default.SCALE_MODE,u.hasLoaded=!1,u.isLoading=!1,u.source=null,u.origSource=null,u.imageType=null,u.sourceScale=1,u.premultipliedAlpha=!0,u.imageUrl=null,u.isPowerOfTwo=!1,u.mipmap=h.default.MIPMAP_TEXTURES,u.wrapMode=h.default.WRAP_MODE,u._glTextures={},u._enabled=0,u._virtalBoundId=-1,u._destroyed=!1,u.textureCacheIds=[],r&&u.loadSource(r),u}return s(e,t),e.prototype.update=function(){\"svg\"!==this.imageType&&(this.realWidth=this.source.naturalWidth||this.source.videoWidth||this.source.width,this.realHeight=this.source.naturalHeight||this.source.videoHeight||this.source.height,this._updateDimensions()),this.emit(\"update\",this)},e.prototype._updateDimensions=function(){this.width=this.realWidth/this.resolution,this.height=this.realHeight/this.resolution,this.isPowerOfTwo=v.default.isPow2(this.realWidth)&&v.default.isPow2(this.realHeight)},e.prototype.loadSource=function(t){var e=this.isLoading;this.hasLoaded=!1,this.isLoading=!1,e&&this.source&&(this.source.onload=null,this.source.onerror=null);var r=!this.source;if(this.source=t,(t.src&&t.complete||t.getContext)&&t.width&&t.height)this._updateImageType(),\"svg\"===this.imageType?this._loadSvgSource():this._sourceLoaded(),r&&this.emit(\"loaded\",this);else if(!t.getContext){this.isLoading=!0;var n=this;if(t.onload=function(){if(n._updateImageType(),t.onload=null,t.onerror=null,n.isLoading){if(n.isLoading=!1,n._sourceLoaded(),\"svg\"===n.imageType)return void n._loadSvgSource();n.emit(\"loaded\",n)}},t.onerror=function(){t.onload=null,t.onerror=null,n.isLoading&&(n.isLoading=!1,n.emit(\"error\",n))},t.complete&&t.src){if(t.onload=null,t.onerror=null,\"svg\"===n.imageType)return void n._loadSvgSource();this.isLoading=!1,t.width&&t.height?(this._sourceLoaded(),e&&this.emit(\"loaded\",this)):e&&this.emit(\"error\",this)}}},e.prototype._updateImageType=function(){if(this.imageUrl){var t=(0,a.decomposeDataUri)(this.imageUrl),e=void 0;if(t&&\"image\"===t.mediaType){var r=t.subType.split(\"+\")[0];if(!(e=(0,a.getUrlFileExtension)(\".\"+r)))throw new Error(\"Invalid image type in data URI.\")}else(e=(0,a.getUrlFileExtension)(this.imageUrl))||(e=\"png\");this.imageType=e}},e.prototype._loadSvgSource=function(){if(\"svg\"===this.imageType){var t=(0,a.decomposeDataUri)(this.imageUrl);t?this._loadSvgSourceUsingDataUri(t):this._loadSvgSourceUsingXhr()}},e.prototype._loadSvgSourceUsingDataUri=function(t){var e=void 0;if(\"base64\"===t.encoding){if(!atob)throw new Error(\"Your browser doesn't support base64 conversions.\");e=atob(t.data)}else e=t.data;this._loadSvgSourceUsingString(e)},e.prototype._loadSvgSourceUsingXhr=function(){var t=this,e=new XMLHttpRequest;e.onload=function(){if(e.readyState!==e.DONE||200!==e.status)throw new Error(\"Failed to load SVG using XHR.\");t._loadSvgSourceUsingString(e.response)},e.onerror=function(){return t.emit(\"error\",t)},e.open(\"GET\",this.imageUrl,!0),e.send()},e.prototype._loadSvgSourceUsingString=function(t){var r=(0,a.getSvgSize)(t),n=r.width,i=r.height;if(!n||!i)throw new Error(\"The SVG image must have width and height defined (in pixels), canvas API needs them.\");this.realWidth=Math.round(n*this.sourceScale),this.realHeight=Math.round(i*this.sourceScale),this._updateDimensions();var o=document.createElement(\"canvas\");o.width=this.realWidth,o.height=this.realHeight,o._pixiId=\"canvas_\"+(0,a.uid)(),o.getContext(\"2d\").drawImage(this.source,0,0,n,i,0,0,this.realWidth,this.realHeight),this.origSource=this.source,this.source=o,e.addToCache(this,o._pixiId),this.isLoading=!1,this._sourceLoaded(),this.emit(\"loaded\",this)},e.prototype._sourceLoaded=function(){this.hasLoaded=!0,this.update()},e.prototype.destroy=function(){this.imageUrl&&(delete a.TextureCache[this.imageUrl],this.imageUrl=null,navigator.isCocoonJS||(this.source.src=\"\")),this.source=null,this.dispose(),e.removeFromCache(this),this.textureCacheIds=null,this._destroyed=!0},e.prototype.dispose=function(){this.emit(\"dispose\",this)},e.prototype.updateSourceImage=function(t){this.source.src=t,this.loadSource(this.source)},e.fromImage=function(t,r,n,i){var o=a.BaseTextureCache[t];if(!o){var s=new Image;void 0===r&&0!==t.indexOf(\"data:\")?s.crossOrigin=(0,f.default)(t):r&&(s.crossOrigin=\"string\"==typeof r?r:\"anonymous\"),o=new e(s,n),o.imageUrl=t,i&&(o.sourceScale=i),o.resolution=(0,a.getResolutionOfUrl)(t),s.src=t,e.addToCache(o,t)}return o},e.fromCanvas=function(t,r){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:\"canvas\";t._pixiId||(t._pixiId=n+\"_\"+(0,a.uid)());var i=a.BaseTextureCache[t._pixiId];return i||(i=new e(t,r),e.addToCache(i,t._pixiId)),i},e.from=function(t,r,n){if(\"string\"==typeof t)return e.fromImage(t,void 0,r,n);if(t instanceof HTMLImageElement){var i=t.src,o=a.BaseTextureCache[i];return o||(o=new e(t,r),o.imageUrl=i,n&&(o.sourceScale=n),o.resolution=(0,a.getResolutionOfUrl)(i),e.addToCache(o,i)),o}return t instanceof HTMLCanvasElement?e.fromCanvas(t,r):t},e.addToCache=function(t,e){e&&(-1===t.textureCacheIds.indexOf(e)&&t.textureCacheIds.push(e),a.BaseTextureCache[e]=t)},e.removeFromCache=function(t){if(\"string\"==typeof t){var e=a.BaseTextureCache[t];if(e){var r=e.textureCacheIds.indexOf(t);return r>-1&&e.textureCacheIds.splice(r,1),delete a.BaseTextureCache[t],e}}else if(t&&t.textureCacheIds){for(var n=0;n<t.textureCacheIds.length;++n)delete a.BaseTextureCache[t.textureCacheIds[n]];return t.textureCacheIds.length=0,t}return null},e}(c.default);r.default=y},{\"../settings\":101,\"../utils\":125,\"../utils/determineCrossOrigin\":124,\"bit-twiddle\":1,eventemitter3:3}],113:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"./BaseRenderTexture\"),u=n(a),h=t(\"./Texture\"),l=n(h),c=function(t){function e(r,n){i(this,e);var s=null;if(!(r instanceof u.default)){var a=arguments[1],h=arguments[2],l=arguments[3],c=arguments[4];console.warn(\"Please use RenderTexture.create(\"+a+\", \"+h+\") instead of the ctor directly.\"),s=arguments[0],n=null,r=new u.default(a,h,l,c)}var d=o(this,t.call(this,r,n));return d.legacyRenderer=s,d.valid=!0,d._updateUvs(),d}return s(e,t),e.prototype.resize=function(t,e,r){t=Math.ceil(t),e=Math.ceil(e),this.valid=t>0&&e>0,this._frame.width=this.orig.width=t,this._frame.height=this.orig.height=e,r||this.baseTexture.resize(t,e),this._updateUvs()},e.create=function(t,r,n,i){return new e(new u.default(t,r,n,i))},e}(l.default);r.default=c},{\"./BaseRenderTexture\":111,\"./Texture\":115}],114:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),o=t(\"../\"),s=t(\"../utils\"),a=function(){function t(e,r){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;n(this,t),this.baseTexture=e,this.textures={},this.data=r,this.resolution=this._updateResolution(i||this.baseTexture.imageUrl),this._frames=this.data.frames,this._frameKeys=Object.keys(this._frames),this._batchIndex=0,this._callback=null}return i(t,null,[{key:\"BATCH_SIZE\",get:function(){return 1e3}}]),t.prototype._updateResolution=function(t){var e=this.data.meta.scale,r=(0,s.getResolutionOfUrl)(t,null);return null===r&&(r=void 0!==e?parseFloat(e):1),1!==r&&(this.baseTexture.resolution=r,this.baseTexture.update()),r},t.prototype.parse=function(e){this._batchIndex=0,this._callback=e,this._frameKeys.length<=t.BATCH_SIZE?(this._processFrames(0),this._parseComplete()):this._nextBatch()},t.prototype._processFrames=function(e){for(var r=e,n=t.BATCH_SIZE,i=this.baseTexture.sourceScale;r-e<n&&r<this._frameKeys.length;){var s=this._frameKeys[r],a=this._frames[s].frame;if(a){var u=null,h=null,l=new o.Rectangle(0,0,Math.floor(this._frames[s].sourceSize.w*i)/this.resolution,Math.floor(this._frames[s].sourceSize.h*i)/this.resolution);u=this._frames[s].rotated?new o.Rectangle(Math.floor(a.x*i)/this.resolution,Math.floor(a.y*i)/this.resolution,Math.floor(a.h*i)/this.resolution,Math.floor(a.w*i)/this.resolution):new o.Rectangle(Math.floor(a.x*i)/this.resolution,Math.floor(a.y*i)/this.resolution,Math.floor(a.w*i)/this.resolution,Math.floor(a.h*i)/this.resolution),this._frames[s].trimmed&&(h=new o.Rectangle(Math.floor(this._frames[s].spriteSourceSize.x*i)/this.resolution,Math.floor(this._frames[s].spriteSourceSize.y*i)/this.resolution,Math.floor(a.w*i)/this.resolution,Math.floor(a.h*i)/this.resolution)),this.textures[s]=new o.Texture(this.baseTexture,u,l,h,this._frames[s].rotated?2:0),o.Texture.addToCache(this.textures[s],s)}r++}},t.prototype._parseComplete=function(){var t=this._callback;this._callback=null,this._batchIndex=0,t.call(this,this.textures)},t.prototype._nextBatch=function(){var e=this;this._processFrames(this._batchIndex*t.BATCH_SIZE),this._batchIndex++,setTimeout(function(){e._batchIndex*t.BATCH_SIZE<e._frameKeys.length?e._nextBatch():e._parseComplete()},0)},t.prototype.destroy=function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];for(var e in this.textures)this.textures[e].destroy();this._frames=null,this._frameKeys=null,this.data=null,this.textures=null,t&&this.baseTexture.destroy(),this.baseTexture=null},t}();r.default=a},{\"../\":65,\"../utils\":125}],115:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function a(t){t.destroy=function(){},t.on=function(){},t.once=function(){},t.emit=function(){}}r.__esModule=!0;var u=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),h=t(\"./BaseTexture\"),l=n(h),c=t(\"./VideoBaseTexture\"),d=n(c),f=t(\"./TextureUvs\"),p=n(f),v=t(\"eventemitter3\"),y=n(v),g=t(\"../math\"),m=t(\"../utils\"),_=t(\"../settings\"),b=n(_),x=function(t){function e(r,n,s,a,u){i(this,e);var h=o(this,t.call(this));if(h.noFrame=!1,n||(h.noFrame=!0,n=new g.Rectangle(0,0,1,1)),r instanceof e&&(r=r.baseTexture),h.baseTexture=r,h._frame=n,h.trim=a,h.valid=!1,h.requiresUpdate=!1,h._uvs=null,h.orig=s||n,h._rotate=Number(u||0),!0===u)h._rotate=2;else if(h._rotate%2!=0)throw new Error(\"attempt to use diamond-shaped UVs. If you are sure, set rotation manually\");return r.hasLoaded?(h.noFrame&&(n=new g.Rectangle(0,0,r.width,r.height),r.on(\"update\",h.onBaseTextureUpdated,h)),h.frame=n):r.once(\"loaded\",h.onBaseTextureLoaded,h),h._updateID=0,h.transform=null,h.textureCacheIds=[],h}return s(e,t),e.prototype.update=function(){this.baseTexture.update()},e.prototype.onBaseTextureLoaded=function(t){this._updateID++,this.noFrame?this.frame=new g.Rectangle(0,0,t.width,t.height):this.frame=this._frame,this.baseTexture.on(\"update\",this.onBaseTextureUpdated,this),this.emit(\"update\",this)},e.prototype.onBaseTextureUpdated=function(t){this._updateID++,this._frame.width=t.width,this._frame.height=t.height,this.emit(\"update\",this)},e.prototype.destroy=function(t){this.baseTexture&&(t&&(m.TextureCache[this.baseTexture.imageUrl]&&e.removeFromCache(this.baseTexture.imageUrl),this.baseTexture.destroy()),this.baseTexture.off(\"update\",this.onBaseTextureUpdated,this),this.baseTexture.off(\"loaded\",this.onBaseTextureLoaded,this),this.baseTexture=null),this._frame=null,this._uvs=null,this.trim=null,this.orig=null,this.valid=!1,e.removeFromCache(this),this.textureCacheIds=null},e.prototype.clone=function(){return new e(this.baseTexture,this.frame,this.orig,this.trim,this.rotate)},e.prototype._updateUvs=function(){this._uvs||(this._uvs=new p.default),this._uvs.set(this._frame,this.baseTexture,this.rotate),this._updateID++},e.fromImage=function(t,r,n,i){var o=m.TextureCache[t];return o||(o=new e(l.default.fromImage(t,r,n,i)),e.addToCache(o,t)),o},e.fromFrame=function(t){var e=m.TextureCache[t];if(!e)throw new Error('The frameId \"'+t+'\" does not exist in the texture cache');return e},e.fromCanvas=function(t,r){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:\"canvas\";return new e(l.default.fromCanvas(t,r,n))},e.fromVideo=function(t,r){return\"string\"==typeof t?e.fromVideoUrl(t,r):new e(d.default.fromVideo(t,r))},e.fromVideoUrl=function(t,r){return new e(d.default.fromUrl(t,r))},e.from=function(t){if(\"string\"==typeof t){var r=m.TextureCache[t];if(!r){return null!==t.match(/\\.(mp4|webm|ogg|h264|avi|mov)$/)?e.fromVideoUrl(t):e.fromImage(t)}return r}return t instanceof HTMLImageElement?new e(l.default.from(t)):t instanceof HTMLCanvasElement?e.fromCanvas(t,b.default.SCALE_MODE,\"HTMLCanvasElement\"):t instanceof HTMLVideoElement?e.fromVideo(t):t instanceof l.default?new e(t):t},\ne.fromLoader=function(t,r,n){var i=new l.default(t,void 0,(0,m.getResolutionOfUrl)(r)),o=new e(i);return i.imageUrl=r,n||(n=r),l.default.addToCache(o.baseTexture,n),e.addToCache(o,n),n!==r&&(l.default.addToCache(o.baseTexture,r),e.addToCache(o,r)),o},e.addToCache=function(t,e){e&&(-1===t.textureCacheIds.indexOf(e)&&t.textureCacheIds.push(e),m.TextureCache[e]=t)},e.removeFromCache=function(t){if(\"string\"==typeof t){var e=m.TextureCache[t];if(e){var r=e.textureCacheIds.indexOf(t);return r>-1&&e.textureCacheIds.splice(r,1),delete m.TextureCache[t],e}}else if(t&&t.textureCacheIds){for(var n=0;n<t.textureCacheIds.length;++n)m.TextureCache[t.textureCacheIds[n]]===t&&delete m.TextureCache[t.textureCacheIds[n]];return t.textureCacheIds.length=0,t}return null},u(e,[{key:\"frame\",get:function(){return this._frame},set:function(t){this._frame=t,this.noFrame=!1;var e=t.x,r=t.y,n=t.width,i=t.height,o=e+n>this.baseTexture.width,s=r+i>this.baseTexture.height;if(o||s){var a=o&&s?\"and\":\"or\",u=\"X: \"+e+\" + \"+n+\" = \"+(e+n)+\" > \"+this.baseTexture.width,h=\"Y: \"+r+\" + \"+i+\" = \"+(r+i)+\" > \"+this.baseTexture.height;throw new Error(\"Texture Error: frame does not fit inside the base Texture dimensions: \"+u+\" \"+a+\" \"+h)}this.valid=n&&i&&this.baseTexture.hasLoaded,this.trim||this.rotate||(this.orig=t),this.valid&&this._updateUvs()}},{key:\"rotate\",get:function(){return this._rotate},set:function(t){this._rotate=t,this.valid&&this._updateUvs()}},{key:\"width\",get:function(){return this.orig.width}},{key:\"height\",get:function(){return this.orig.height}}]),e}(y.default);r.default=x,x.EMPTY=new x(new l.default),a(x.EMPTY),a(x.EMPTY.baseTexture),x.WHITE=function(){var t=document.createElement(\"canvas\");t.width=10,t.height=10;var e=t.getContext(\"2d\");return e.fillStyle=\"white\",e.fillRect(0,0,10,10),new x(new l.default(t))}(),a(x.WHITE),a(x.WHITE.baseTexture)},{\"../math\":70,\"../settings\":101,\"../utils\":125,\"./BaseTexture\":112,\"./TextureUvs\":117,\"./VideoBaseTexture\":118,eventemitter3:3}],116:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),o=t(\"../math/Matrix\"),s=function(t){return t&&t.__esModule?t:{default:t}}(o),a=new s.default,u=function(){function t(e,r){n(this,t),this._texture=e,this.mapCoord=new s.default,this.uClampFrame=new Float32Array(4),this.uClampOffset=new Float32Array(2),this._lastTextureID=-1,this.clampOffset=0,this.clampMargin=void 0===r?.5:r}return t.prototype.multiplyUvs=function(t,e){void 0===e&&(e=t);for(var r=this.mapCoord,n=0;n<t.length;n+=2){var i=t[n],o=t[n+1];e[n]=i*r.a+o*r.c+r.tx,e[n+1]=i*r.b+o*r.d+r.ty}return e},t.prototype.update=function(t){var e=this._texture;if(!e||!e.valid)return!1;if(!t&&this._lastTextureID===e._updateID)return!1;this._lastTextureID=e._updateID;var r=e._uvs;this.mapCoord.set(r.x1-r.x0,r.y1-r.y0,r.x3-r.x0,r.y3-r.y0,r.x0,r.y0);var n=e.orig,i=e.trim;i&&(a.set(n.width/i.width,0,0,n.height/i.height,-i.x/i.width,-i.y/i.height),this.mapCoord.append(a));var o=e.baseTexture,s=this.uClampFrame,u=this.clampMargin/o.resolution,h=this.clampOffset;return s[0]=(e._frame.x+u+h)/o.width,s[1]=(e._frame.y+u+h)/o.height,s[2]=(e._frame.x+e._frame.width-u+h)/o.width,s[3]=(e._frame.y+e._frame.height-u+h)/o.height,this.uClampOffset[0]=h/o.realWidth,this.uClampOffset[1]=h/o.realHeight,!0},i(t,[{key:\"texture\",get:function(){return this._texture},set:function(t){this._texture=t,this._lastTextureID=-1}}]),t}();r.default=u},{\"../math/Matrix\":67}],117:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../math/GroupD8\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=function(){function t(){n(this,t),this.x0=0,this.y0=0,this.x1=1,this.y1=0,this.x2=1,this.y2=1,this.x3=0,this.y3=1,this.uvsUint32=new Uint32Array(4)}return t.prototype.set=function(t,e,r){var n=e.width,i=e.height;if(r){var s=t.width/2/n,a=t.height/2/i,u=t.x/n+s,h=t.y/i+a;r=o.default.add(r,o.default.NW),this.x0=u+s*o.default.uX(r),this.y0=h+a*o.default.uY(r),r=o.default.add(r,2),this.x1=u+s*o.default.uX(r),this.y1=h+a*o.default.uY(r),r=o.default.add(r,2),this.x2=u+s*o.default.uX(r),this.y2=h+a*o.default.uY(r),r=o.default.add(r,2),this.x3=u+s*o.default.uX(r),this.y3=h+a*o.default.uY(r)}else this.x0=t.x/n,this.y0=t.y/i,this.x1=(t.x+t.width)/n,this.y1=t.y/i,this.x2=(t.x+t.width)/n,this.y2=(t.y+t.height)/i,this.x3=t.x/n,this.y3=(t.y+t.height)/i;this.uvsUint32[0]=(65535*this.y0&65535)<<16|65535*this.x0&65535,this.uvsUint32[1]=(65535*this.y1&65535)<<16|65535*this.x1&65535,this.uvsUint32[2]=(65535*this.y2&65535)<<16|65535*this.x2&65535,this.uvsUint32[3]=(65535*this.y3&65535)<<16|65535*this.x3&65535},t}();r.default=s},{\"../math/GroupD8\":66}],118:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function a(t,e){e||(e=\"video/\"+t.substr(t.lastIndexOf(\".\")+1));var r=document.createElement(\"source\");return r.src=t,r.type=e,r}r.__esModule=!0;var u=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),h=t(\"./BaseTexture\"),l=n(h),c=t(\"../utils\"),d=t(\"../ticker\"),f=t(\"../const\"),p=t(\"../utils/determineCrossOrigin\"),v=n(p),y=function(t){function e(r,n){if(i(this,e),!r)throw new Error(\"No video source element specified.\");(r.readyState===r.HAVE_ENOUGH_DATA||r.readyState===r.HAVE_FUTURE_DATA)&&r.width&&r.height&&(r.complete=!0);var s=o(this,t.call(this,r,n));return s.width=r.videoWidth,s.height=r.videoHeight,s._autoUpdate=!0,s._isAutoUpdating=!1,s.autoPlay=!0,s.update=s.update.bind(s),s._onCanPlay=s._onCanPlay.bind(s),r.addEventListener(\"play\",s._onPlayStart.bind(s)),r.addEventListener(\"pause\",s._onPlayStop.bind(s)),s.hasLoaded=!1,s.__loaded=!1,s._isSourceReady()?s._onCanPlay():(r.addEventListener(\"canplay\",s._onCanPlay),r.addEventListener(\"canplaythrough\",s._onCanPlay)),s}return s(e,t),e.prototype._isSourcePlaying=function(){var t=this.source;return t.currentTime>0&&!1===t.paused&&!1===t.ended&&t.readyState>2},e.prototype._isSourceReady=function(){return 3===this.source.readyState||4===this.source.readyState},e.prototype._onPlayStart=function(){this.hasLoaded||this._onCanPlay(),!this._isAutoUpdating&&this.autoUpdate&&(d.shared.add(this.update,this,f.UPDATE_PRIORITY.HIGH),this._isAutoUpdating=!0)},e.prototype._onPlayStop=function(){this._isAutoUpdating&&(d.shared.remove(this.update,this),this._isAutoUpdating=!1)},e.prototype._onCanPlay=function(){this.hasLoaded=!0,this.source&&(this.source.removeEventListener(\"canplay\",this._onCanPlay),this.source.removeEventListener(\"canplaythrough\",this._onCanPlay),this.width=this.source.videoWidth,this.height=this.source.videoHeight,this.__loaded||(this.__loaded=!0,this.emit(\"loaded\",this)),this._isSourcePlaying()?this._onPlayStart():this.autoPlay&&this.source.play())},e.prototype.destroy=function(){this._isAutoUpdating&&d.shared.remove(this.update,this),this.source&&this.source._pixiId&&(l.default.removeFromCache(this.source._pixiId),delete this.source._pixiId,this.source.pause(),this.source.src=\"\",this.source.load()),t.prototype.destroy.call(this)},e.fromVideo=function(t,r){t._pixiId||(t._pixiId=\"video_\"+(0,c.uid)());var n=c.BaseTextureCache[t._pixiId];return n||(n=new e(t,r),l.default.addToCache(n,t._pixiId)),n},e.fromUrl=function(t,r,n){var i=document.createElement(\"video\");i.setAttribute(\"webkit-playsinline\",\"\"),i.setAttribute(\"playsinline\",\"\");var o=Array.isArray(t)?t[0].src||t[0]:t.src||t;if(void 0===n&&0!==o.indexOf(\"data:\")?i.crossOrigin=(0,v.default)(o):n&&(i.crossOrigin=\"string\"==typeof n?n:\"anonymous\"),Array.isArray(t))for(var s=0;s<t.length;++s)i.appendChild(a(t[s].src||t[s],t[s].mime));else i.appendChild(a(o,t.mime));return i.load(),e.fromVideo(i,r)},u(e,[{key:\"autoUpdate\",get:function(){return this._autoUpdate},set:function(t){t!==this._autoUpdate&&(this._autoUpdate=t,!this._autoUpdate&&this._isAutoUpdating?(d.shared.remove(this.update,this),this._isAutoUpdating=!1):this._autoUpdate&&!this._isAutoUpdating&&(d.shared.add(this.update,this,f.UPDATE_PRIORITY.HIGH),this._isAutoUpdating=!0))}}]),e}(l.default);r.default=y,y.fromUrls=y.fromUrl},{\"../const\":46,\"../ticker\":121,\"../utils\":125,\"../utils/determineCrossOrigin\":124,\"./BaseTexture\":112}],119:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var o=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),s=t(\"../settings\"),a=n(s),u=t(\"../const\"),h=t(\"./TickerListener\"),l=n(h),c=function(){function t(){var e=this;i(this,t),this._head=new l.default(null,null,1/0),this._requestId=null,this._maxElapsedMS=100,this.autoStart=!1,this.deltaTime=1,this.elapsedMS=1/a.default.TARGET_FPMS,this.lastTime=-1,this.speed=1,this.started=!1,this._tick=function(t){e._requestId=null,e.started&&(e.update(t),e.started&&null===e._requestId&&e._head.next&&(e._requestId=requestAnimationFrame(e._tick)))}}return t.prototype._requestIfNeeded=function(){null===this._requestId&&this._head.next&&(this.lastTime=performance.now(),this._requestId=requestAnimationFrame(this._tick))},t.prototype._cancelIfNeeded=function(){null!==this._requestId&&(cancelAnimationFrame(this._requestId),this._requestId=null)},t.prototype._startIfPossible=function(){this.started?this._requestIfNeeded():this.autoStart&&this.start()},t.prototype.add=function(t,e){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:u.UPDATE_PRIORITY.NORMAL;return this._addListener(new l.default(t,e,r))},t.prototype.addOnce=function(t,e){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:u.UPDATE_PRIORITY.NORMAL;return this._addListener(new l.default(t,e,r,!0))},t.prototype._addListener=function(t){var e=this._head.next,r=this._head;if(e){for(;e;){if(t.priority>e.priority){t.connect(r);break}r=e,e=e.next}t.previous||t.connect(r)}else t.connect(r);return this._startIfPossible(),this},t.prototype.remove=function(t,e){for(var r=this._head.next;r;)r=r.match(t,e)?r.destroy():r.next;return this._head.next||this._cancelIfNeeded(),this},t.prototype.start=function(){this.started||(this.started=!0,this._requestIfNeeded())},t.prototype.stop=function(){this.started&&(this.started=!1,this._cancelIfNeeded())},t.prototype.destroy=function(){this.stop();for(var t=this._head.next;t;)t=t.destroy(!0);this._head.destroy(),this._head=null},t.prototype.update=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:performance.now(),e=void 0;if(t>this.lastTime){e=this.elapsedMS=t-this.lastTime,e>this._maxElapsedMS&&(e=this._maxElapsedMS),this.deltaTime=e*a.default.TARGET_FPMS*this.speed;for(var r=this._head,n=r.next;n;)n=n.emit(this.deltaTime);r.next||this._cancelIfNeeded()}else this.deltaTime=this.elapsedMS=0;this.lastTime=t},o(t,[{key:\"FPS\",get:function(){return 1e3/this.elapsedMS}},{key:\"minFPS\",get:function(){return 1e3/this._maxElapsedMS},set:function(t){var e=Math.min(Math.max(0,t)/1e3,a.default.TARGET_FPMS);this._maxElapsedMS=1/e}}]),t}();r.default=c},{\"../const\":46,\"../settings\":101,\"./TickerListener\":120}],120:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(e){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=arguments.length>3&&void 0!==arguments[3]&&arguments[3];n(this,t),this.fn=e,this.context=r,this.priority=i,this.once=o,this.next=null,this.previous=null,this._destroyed=!1}return t.prototype.match=function(t,e){return e=e||null,this.fn===t&&this.context===e},t.prototype.emit=function(t){this.fn&&(this.context?this.fn.call(this.context,t):this.fn(t));var e=this.next;return this.once&&this.destroy(!0),this._destroyed&&(this.next=null),e},t.prototype.connect=function(t){this.previous=t,t.next&&(t.next.previous=this),this.next=t.next,t.next=this},t.prototype.destroy=function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];this._destroyed=!0,this.fn=null,this.context=null,this.previous&&(this.previous.next=this.next),this.next&&(this.next.previous=this.previous);var e=this.previous;return this.next=t?null:e,this.previous=null,e},t}();r.default=i},{}],121:[function(t,e,r){\"use strict\";r.__esModule=!0,r.Ticker=r.shared=void 0;var n=t(\"./Ticker\"),i=function(t){return t&&t.__esModule?t:{default:t}}(n),o=new i.default;o.autoStart=!0,o.destroy=function(){},r.shared=o,r.Ticker=i.default},{\"./Ticker\":119}],122:[function(t,e,r){\"use strict\";function n(){return!(!!navigator.platform&&/iPad|iPhone|iPod/.test(navigator.platform))}r.__esModule=!0,r.default=n},{}],123:[function(t,e,r){\"use strict\";function n(t){for(var e=6*t,r=new Uint16Array(e),n=0,i=0;n<e;n+=6,i+=4)r[n+0]=i+0,r[n+1]=i+1,r[n+2]=i+2,r[n+3]=i+0,r[n+4]=i+2,r[n+5]=i+3;return r}r.__esModule=!0,r.default=n},{}],124:[function(t,e,r){\"use strict\";function n(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:window.location;if(0===t.indexOf(\"data:\"))return\"\";e=e||window.location,s||(s=document.createElement(\"a\")),s.href=t,t=o.default.parse(s.href);var r=!t.port&&\"\"===e.port||t.port===e.port;return t.hostname===e.hostname&&r&&t.protocol===e.protocol?\"\":\"anonymous\"}r.__esModule=!0,r.default=n;var i=t(\"url\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=void 0},{url:29}],125:[function(t,e,r){\"use strict\";function n(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}function i(t){return t&&t.__esModule?t:{default:t}}function o(){return++k}function s(t,e){return e=e||[],e[0]=(t>>16&255)/255,e[1]=(t>>8&255)/255,e[2]=(255&t)/255,e}function a(t){return t=t.toString(16),\"#\"+(t=\"000000\".substr(0,6-t.length)+t)}function u(t){return(255*t[0]<<16)+(255*t[1]<<8)+(255*t[2]|0)}function h(t,e){var r=S.default.RETINA_PREFIX.exec(t);return r?parseFloat(r[1]):void 0!==e?e:1}function l(t){var e=w.DATA_URI.exec(t);if(e)return{mediaType:e[1]?e[1].toLowerCase():void 0,subType:e[2]?e[2].toLowerCase():void 0,encoding:e[3]?e[3].toLowerCase():void 0,data:e[4]}}function c(t){var e=w.URL_FILE_EXTENSION.exec(t);if(e)return e[1].toLowerCase()}function d(t){var e=w.SVG_SIZE.exec(t),r={};return e&&(r[e[1]]=Math.round(parseFloat(e[3])),r[e[5]]=Math.round(parseFloat(e[7]))),r}function f(){j=!0}function p(t){if(!j){if(navigator.userAgent.toLowerCase().indexOf(\"chrome\")>-1){var e=[\"\\n %c %c %c PixiJS \"+w.VERSION+\" - ✰ \"+t+\" ✰  %c  %c  http://www.pixijs.com/  %c %c ♥%c♥%c♥ \\n\\n\",\"background: #ff66a5; padding:5px 0;\",\"background: #ff66a5; padding:5px 0;\",\"color: #ff66a5; background: #030307; padding:5px 0;\",\"background: #ff66a5; padding:5px 0;\",\"background: #ffc3dc; padding:5px 0;\",\"background: #ff66a5; padding:5px 0;\",\"color: #ff2424; background: #fff; padding:5px 0;\",\"color: #ff2424; background: #fff; padding:5px 0;\",\"color: #ff2424; background: #fff; padding:5px 0;\"];window.console.log.apply(console,e)}else window.console&&window.console.log(\"PixiJS \"+w.VERSION+\" - \"+t+\" - http://www.pixijs.com/\");j=!0}}function v(){var t={stencil:!0,failIfMajorPerformanceCaveat:!0};try{if(!window.WebGLRenderingContext)return!1;var e=document.createElement(\"canvas\"),r=e.getContext(\"webgl\",t)||e.getContext(\"experimental-webgl\",t),n=!(!r||!r.getContextAttributes().stencil);if(r){var i=r.getExtension(\"WEBGL_lose_context\");i&&i.loseContext()}return r=null,n}catch(t){return!1}}function y(t){return 0===t?0:t<0?-1:1}function g(){var t=void 0;for(t in U)U[t].destroy();for(t in X)X[t].destroy()}function m(){var t=void 0;for(t in U)delete U[t];for(t in X)delete X[t]}function _(t,e){return G[e?1:0][t]}function b(t,e){if(1===e)return(255*e<<24)+t;if(0===e)return 0;var r=t>>16&255,n=t>>8&255,i=255&t;return r=r*e+.5|0,n=n*e+.5|0,i=i*e+.5|0,(255*e<<24)+(r<<16)+(n<<8)+i}function x(t,e,r,n){return r=r||new Float32Array(4),n||void 0===n?(r[0]=t[0]*e,r[1]=t[1]*e,r[2]=t[2]*e):(r[0]=t[0],r[1]=t[1],r[2]=t[2]),r[3]=e,r}function T(t,e,r,n){return r=r||new Float32Array(4),r[0]=(t>>16&255)/255,r[1]=(t>>8&255)/255,r[2]=(255&t)/255,(n||void 0===n)&&(r[0]*=e,r[1]*=e,r[2]*=e),r[3]=e,r}r.__esModule=!0,r.premultiplyBlendMode=r.BaseTextureCache=r.TextureCache=r.mixins=r.pluginTarget=r.EventEmitter=r.removeItems=r.isMobile=void 0,r.uid=o,r.hex2rgb=s,r.hex2string=a,r.rgb2hex=u,r.getResolutionOfUrl=h,r.decomposeDataUri=l,r.getUrlFileExtension=c,r.getSvgSize=d,r.skipHello=f,r.sayHello=p,r.isWebGLSupported=v,r.sign=y,r.destroyTextureCache=g,r.clearTextureCache=m,r.correctBlendMode=_,r.premultiplyTint=b,r.premultiplyRgba=x,r.premultiplyTintToRgba=T;var w=t(\"../const\"),E=t(\"../settings\"),S=i(E),O=t(\"eventemitter3\"),M=i(O),P=t(\"./pluginTarget\"),C=i(P),R=t(\"./mixin\"),A=n(R),I=t(\"ismobilejs\"),D=n(I),L=t(\"remove-array-items\"),N=i(L),F=t(\"./mapPremultipliedBlendModes\"),B=i(F),k=0,j=!1;r.isMobile=D,r.removeItems=N.default,r.EventEmitter=M.default,r.pluginTarget=C.default,r.mixins=A;var U=r.TextureCache=Object.create(null),X=r.BaseTextureCache=Object.create(null),G=r.premultiplyBlendMode=(0,B.default)()},{\"../const\":46,\"../settings\":101,\"./mapPremultipliedBlendModes\":126,\"./mixin\":128,\"./pluginTarget\":129,eventemitter3:3,ismobilejs:4,\"remove-array-items\":31}],126:[function(t,e,r){\"use strict\";function n(){for(var t=[],e=[],r=0;r<32;r++)t[r]=r,e[r]=r;t[i.BLEND_MODES.NORMAL_NPM]=i.BLEND_MODES.NORMAL,t[i.BLEND_MODES.ADD_NPM]=i.BLEND_MODES.ADD,t[i.BLEND_MODES.SCREEN_NPM]=i.BLEND_MODES.SCREEN,e[i.BLEND_MODES.NORMAL]=i.BLEND_MODES.NORMAL_NPM,e[i.BLEND_MODES.ADD]=i.BLEND_MODES.ADD_NPM,e[i.BLEND_MODES.SCREEN]=i.BLEND_MODES.SCREEN_NPM;var n=[];return n.push(e),n.push(t),n}r.__esModule=!0,r.default=n;var i=t(\"../const\")},{\"../const\":46}],127:[function(t,e,r){\"use strict\";function n(t){return o.default.tablet||o.default.phone?4:t}r.__esModule=!0,r.default=n;var i=t(\"ismobilejs\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i)},{ismobilejs:4}],128:[function(t,e,r){\"use strict\";function n(t,e){if(t&&e)for(var r=Object.keys(e),n=0;n<r.length;++n){var i=r[n];Object.defineProperty(t,i,Object.getOwnPropertyDescriptor(e,i))}}function i(t,e){s.push(t,e)}function o(){for(var t=0;t<s.length;t+=2)n(s[t],s[t+1]);s.length=0}r.__esModule=!0,r.mixin=n,r.delayMixin=i,r.performMixins=o;var s=[]},{}],129:[function(t,e,r){\"use strict\";function n(t){t.__plugins={},t.registerPlugin=function(e,r){t.__plugins[e]=r},t.prototype.initPlugins=function(){this.plugins=this.plugins||{};for(var e in t.__plugins)this.plugins[e]=new t.__plugins[e](this)},t.prototype.destroyPlugins=function(){for(var t in this.plugins)this.plugins[t].destroy(),this.plugins[t]=null;this.plugins=null}}r.__esModule=!0,r.default={mixin:function(t){n(t)}}},{}],130:[function(t,e,r){\"use strict\";function n(t){var e=t.width,r=t.height,n=t.getContext(\"2d\"),i=n.getImageData(0,0,e,r),o=i.data,s=o.length,a={top:null,left:null,right:null,bottom:null},u=void 0,h=void 0,l=void 0;for(u=0;u<s;u+=4)0!==o[u+3]&&(h=u/4%e,l=~~(u/4/e),null===a.top&&(a.top=l),null===a.left?a.left=h:h<a.left&&(a.left=h),null===a.right?a.right=h+1:a.right<h&&(a.right=h+1),null===a.bottom?a.bottom=l:a.bottom<l&&(a.bottom=l));return e=a.right-a.left,r=a.bottom-a.top+1,{height:r,width:e,data:n.getImageData(a.left,a.top,e,r)}}r.__esModule=!0,r.default=n},{}],131:[function(t,e,r){\"use strict\";function n(t){}function i(t){var e=t.mesh,r=t.particles,i=t.extras,o=t.filters,s=t.prepare,a=t.loaders,u=t.interaction;Object.defineProperties(t,{SpriteBatch:{get:function(){throw new ReferenceError(\"SpriteBatch does not exist any more, please use the new ParticleContainer instead.\")}},AssetLoader:{get:function(){throw new ReferenceError(\"The loader system was overhauled in PixiJS v3, please see the new PIXI.loaders.Loader class.\")}},Stage:{get:function(){return n(\"You do not need to use a PIXI Stage any more, you can simply render any container.\"),t.Container}},DisplayObjectContainer:{get:function(){return n(\"DisplayObjectContainer has been shortened to Container, please use Container from now on.\"),t.Container}},Strip:{get:function(){return n(\"The Strip class has been renamed to Mesh and moved to mesh.Mesh, please use mesh.Mesh from now on.\"),e.Mesh}},Rope:{get:function(){return n(\"The Rope class has been moved to mesh.Rope, please use mesh.Rope from now on.\"),e.Rope}},ParticleContainer:{get:function(){return n(\"The ParticleContainer class has been moved to particles.ParticleContainer, please use particles.ParticleContainer from now on.\"),r.ParticleContainer}},MovieClip:{get:function(){return n(\"The MovieClip class has been moved to extras.AnimatedSprite, please use extras.AnimatedSprite.\"),i.AnimatedSprite}},TilingSprite:{get:function(){return n(\"The TilingSprite class has been moved to extras.TilingSprite, please use extras.TilingSprite from now on.\"),i.TilingSprite}},BitmapText:{get:function(){return n(\"The BitmapText class has been moved to extras.BitmapText, please use extras.BitmapText from now on.\"),i.BitmapText}},blendModes:{get:function(){return n(\"The blendModes has been moved to BLEND_MODES, please use BLEND_MODES from now on.\"),t.BLEND_MODES}},scaleModes:{get:function(){return n(\"The scaleModes has been moved to SCALE_MODES, please use SCALE_MODES from now on.\"),t.SCALE_MODES}},BaseTextureCache:{get:function(){return n(\"The BaseTextureCache class has been moved to utils.BaseTextureCache, please use utils.BaseTextureCache from now on.\"),t.utils.BaseTextureCache}},TextureCache:{get:function(){return n(\"The TextureCache class has been moved to utils.TextureCache, please use utils.TextureCache from now on.\"),t.utils.TextureCache}},math:{get:function(){return n(\"The math namespace is deprecated, please access members already accessible on PIXI.\"),t}},AbstractFilter:{get:function(){return n(\"AstractFilter has been renamed to Filter, please use PIXI.Filter\"),t.Filter}},TransformManual:{get:function(){return n(\"TransformManual has been renamed to TransformBase, please update your pixi-spine\"),t.TransformBase}},TARGET_FPMS:{get:function(){return n(\"PIXI.TARGET_FPMS has been deprecated, please use PIXI.settings.TARGET_FPMS\"),t.settings.TARGET_FPMS},set:function(e){n(\"PIXI.TARGET_FPMS has been deprecated, please use PIXI.settings.TARGET_FPMS\"),t.settings.TARGET_FPMS=e}},FILTER_RESOLUTION:{get:function(){return n(\"PIXI.FILTER_RESOLUTION has been deprecated, please use PIXI.settings.FILTER_RESOLUTION\"),t.settings.FILTER_RESOLUTION},set:function(e){n(\"PIXI.FILTER_RESOLUTION has been deprecated, please use PIXI.settings.FILTER_RESOLUTION\"),t.settings.FILTER_RESOLUTION=e}},RESOLUTION:{get:function(){return n(\"PIXI.RESOLUTION has been deprecated, please use PIXI.settings.RESOLUTION\"),t.settings.RESOLUTION},set:function(e){n(\"PIXI.RESOLUTION has been deprecated, please use PIXI.settings.RESOLUTION\"),t.settings.RESOLUTION=e}},MIPMAP_TEXTURES:{get:function(){return n(\"PIXI.MIPMAP_TEXTURES has been deprecated, please use PIXI.settings.MIPMAP_TEXTURES\"),t.settings.MIPMAP_TEXTURES},set:function(e){n(\"PIXI.MIPMAP_TEXTURES has been deprecated, please use PIXI.settings.MIPMAP_TEXTURES\"),t.settings.MIPMAP_TEXTURES=e}},SPRITE_BATCH_SIZE:{get:function(){return n(\"PIXI.SPRITE_BATCH_SIZE has been deprecated, please use PIXI.settings.SPRITE_BATCH_SIZE\"),t.settings.SPRITE_BATCH_SIZE},set:function(e){n(\"PIXI.SPRITE_BATCH_SIZE has been deprecated, please use PIXI.settings.SPRITE_BATCH_SIZE\"),t.settings.SPRITE_BATCH_SIZE=e}},SPRITE_MAX_TEXTURES:{get:function(){return n(\"PIXI.SPRITE_MAX_TEXTURES has been deprecated, please use PIXI.settings.SPRITE_MAX_TEXTURES\"),t.settings.SPRITE_MAX_TEXTURES},set:function(e){n(\"PIXI.SPRITE_MAX_TEXTURES has been deprecated, please use PIXI.settings.SPRITE_MAX_TEXTURES\"),t.settings.SPRITE_MAX_TEXTURES=e}},RETINA_PREFIX:{get:function(){return n(\"PIXI.RETINA_PREFIX has been deprecated, please use PIXI.settings.RETINA_PREFIX\"),t.settings.RETINA_PREFIX},set:function(e){n(\"PIXI.RETINA_PREFIX has been deprecated, please use PIXI.settings.RETINA_PREFIX\"),t.settings.RETINA_PREFIX=e}},DEFAULT_RENDER_OPTIONS:{get:function(){return n(\"PIXI.DEFAULT_RENDER_OPTIONS has been deprecated, please use PIXI.settings.DEFAULT_RENDER_OPTIONS\"),t.settings.RENDER_OPTIONS}}});for(var h=[{parent:\"TRANSFORM_MODE\",target:\"TRANSFORM_MODE\"},{parent:\"GC_MODES\",target:\"GC_MODE\"},{parent:\"WRAP_MODES\",target:\"WRAP_MODE\"},{parent:\"SCALE_MODES\",target:\"SCALE_MODE\"},{parent:\"PRECISION\",target:\"PRECISION_FRAGMENT\"}],l=0;l<h.length;l++)!function(e){var r=h[e];Object.defineProperty(t[r.parent],\"DEFAULT\",{get:function(){return n(\"PIXI.\"+r.parent+\".DEFAULT has been deprecated, please use PIXI.settings.\"+r.target),t.settings[r.target]},set:function(e){n(\"PIXI.\"+r.parent+\".DEFAULT has been deprecated, please use PIXI.settings.\"+r.target),t.settings[r.target]=e}})}(l);Object.defineProperties(t.settings,{PRECISION:{get:function(){return n(\"PIXI.settings.PRECISION has been deprecated, please use PIXI.settings.PRECISION_FRAGMENT\"),t.settings.PRECISION_FRAGMENT},set:function(e){n(\"PIXI.settings.PRECISION has been deprecated, please use PIXI.settings.PRECISION_FRAGMENT\"),t.settings.PRECISION_FRAGMENT=e}}}),i.AnimatedSprite&&Object.defineProperties(i,{MovieClip:{get:function(){return n(\"The MovieClip class has been renamed to AnimatedSprite, please use AnimatedSprite from now on.\"),i.AnimatedSprite}}}),i&&Object.defineProperties(i,{TextureTransform:{get:function(){return n(\"The TextureTransform class has been renamed to TextureMatrix, please use PIXI.TextureMatrix from now on.\"),t.TextureMatrix}}}),t.DisplayObject.prototype.generateTexture=function(t,e,r){return n(\"generateTexture has moved to the renderer, please use renderer.generateTexture(displayObject)\"),t.generateTexture(this,e,r)},t.Graphics.prototype.generateTexture=function(t,e){return n(\"graphics generate texture has moved to the renderer. Or to render a graphics to a texture using canvas please use generateCanvasTexture\"),this.generateCanvasTexture(t,e)},t.GroupD8.isSwapWidthHeight=function(e){return n(\"GroupD8.isSwapWidthHeight was renamed to GroupD8.isVertical\"),t.GroupD8.isVertical(e)},t.RenderTexture.prototype.render=function(t,e,r,i){this.legacyRenderer.render(t,this,r,e,!i),n(\"RenderTexture.render is now deprecated, please use renderer.render(displayObject, renderTexture)\")},t.RenderTexture.prototype.getImage=function(t){return n(\"RenderTexture.getImage is now deprecated, please use renderer.extract.image(target)\"),this.legacyRenderer.extract.image(t)},t.RenderTexture.prototype.getBase64=function(t){return n(\"RenderTexture.getBase64 is now deprecated, please use renderer.extract.base64(target)\"),this.legacyRenderer.extract.base64(t)},t.RenderTexture.prototype.getCanvas=function(t){return n(\"RenderTexture.getCanvas is now deprecated, please use renderer.extract.canvas(target)\"),this.legacyRenderer.extract.canvas(t)},t.RenderTexture.prototype.getPixels=function(t){return n(\"RenderTexture.getPixels is now deprecated, please use renderer.extract.pixels(target)\"),this.legacyRenderer.pixels(t)},t.Sprite.prototype.setTexture=function(t){this.texture=t,n(\"setTexture is now deprecated, please use the texture property, e.g : sprite.texture = texture;\")},i.BitmapText&&(i.BitmapText.prototype.setText=function(t){this.text=t,n(\"setText is now deprecated, please use the text property, e.g : myBitmapText.text = 'my text';\")}),t.Text.prototype.setText=function(t){this.text=t,n(\"setText is now deprecated, please use the text property, e.g : myText.text = 'my text';\")},t.Text.calculateFontProperties=function(e){return n(\"Text.calculateFontProperties is now deprecated, please use the TextMetrics.measureFont\"),t.TextMetrics.measureFont(e)},Object.defineProperties(t.Text,{fontPropertiesCache:{get:function(){return n(\"Text.fontPropertiesCache is deprecated\"),t.TextMetrics._fonts}},fontPropertiesCanvas:{get:function(){return n(\"Text.fontPropertiesCanvas is deprecated\"),t.TextMetrics._canvas}},fontPropertiesContext:{get:function(){return n(\"Text.fontPropertiesContext is deprecated\"),t.TextMetrics._context}}}),t.Text.prototype.setStyle=function(t){this.style=t,n(\"setStyle is now deprecated, please use the style property, e.g : myText.style = style;\")},t.Text.prototype.determineFontProperties=function(e){return n(\"determineFontProperties is now deprecated, please use TextMetrics.measureFont method\"),t.TextMetrics.measureFont(e)},t.Text.getFontStyle=function(e){return n(\"getFontStyle is now deprecated, please use TextStyle.toFontString() instead\"),e=e||{},e instanceof t.TextStyle||(e=new t.TextStyle(e)),e.toFontString()},Object.defineProperties(t.TextStyle.prototype,{font:{get:function(){n(\"text style property 'font' is now deprecated, please use the 'fontFamily', 'fontSize', 'fontStyle', 'fontVariant' and 'fontWeight' properties from now on\");var t=\"number\"==typeof this._fontSize?this._fontSize+\"px\":this._fontSize;return this._fontStyle+\" \"+this._fontVariant+\" \"+this._fontWeight+\" \"+t+\" \"+this._fontFamily},set:function(t){n(\"text style property 'font' is now deprecated, please use the 'fontFamily','fontSize',fontStyle','fontVariant' and 'fontWeight' properties from now on\"),t.indexOf(\"italic\")>1?this._fontStyle=\"italic\":t.indexOf(\"oblique\")>-1?this._fontStyle=\"oblique\":this._fontStyle=\"normal\",t.indexOf(\"small-caps\")>-1?this._fontVariant=\"small-caps\":this._fontVariant=\"normal\";var e=t.split(\" \"),r=-1;this._fontSize=26;for(var i=0;i<e.length;++i)if(e[i].match(/(px|pt|em|%)/)){r=i,this._fontSize=e[i];break}this._fontWeight=\"normal\";for(var o=0;o<r;++o)if(e[o].match(/(bold|bolder|lighter|100|200|300|400|500|600|700|800|900)/)){this._fontWeight=e[o];break}if(r>-1&&r<e.length-1){this._fontFamily=\"\";for(var s=r+1;s<e.length;++s)this._fontFamily+=e[s]+\" \";this._fontFamily=this._fontFamily.slice(0,-1)}else this._fontFamily=\"Arial\";this.styleID++}}}),t.Texture.prototype.setFrame=function(t){this.frame=t,n(\"setFrame is now deprecated, please use the frame property, e.g: myTexture.frame = frame;\")},t.Texture.addTextureToCache=function(e,r){t.Texture.addToCache(e,r),n(\"Texture.addTextureToCache is deprecated, please use Texture.addToCache from now on.\")},t.Texture.removeTextureFromCache=function(e){return n(\"Texture.removeTextureFromCache is deprecated, please use Texture.removeFromCache from now on. Be aware that Texture.removeFromCache does not automatically its BaseTexture from the BaseTextureCache. For that, use BaseTexture.removeFromCache\"),t.BaseTexture.removeFromCache(e),t.Texture.removeFromCache(e)},Object.defineProperties(o,{AbstractFilter:{get:function(){return n(\"AstractFilter has been renamed to Filter, please use PIXI.Filter\"),t.AbstractFilter}},SpriteMaskFilter:{get:function(){return n(\"filters.SpriteMaskFilter is an undocumented alias, please use SpriteMaskFilter from now on.\"),t.SpriteMaskFilter}},VoidFilter:{get:function(){return n(\"VoidFilter has been renamed to AlphaFilter, please use PIXI.filters.AlphaFilter\"),\no.AlphaFilter}}}),t.utils.uuid=function(){return n(\"utils.uuid() is deprecated, please use utils.uid() from now on.\"),t.utils.uid()},t.utils.canUseNewCanvasBlendModes=function(){return n(\"utils.canUseNewCanvasBlendModes() is deprecated, please use CanvasTinter.canUseMultiply from now on\"),t.CanvasTinter.canUseMultiply};var c=!0;if(Object.defineProperty(t.utils,\"_saidHello\",{set:function(t){t&&(n(\"PIXI.utils._saidHello is deprecated, please use PIXI.utils.skipHello()\"),this.skipHello()),c=t},get:function(){return c}}),s.BasePrepare&&(s.BasePrepare.prototype.register=function(t,e){return n(\"renderer.plugins.prepare.register is now deprecated, please use renderer.plugins.prepare.registerFindHook & renderer.plugins.prepare.registerUploadHook\"),t&&this.registerFindHook(t),e&&this.registerUploadHook(e),this}),s.canvas&&Object.defineProperty(s.canvas,\"UPLOADS_PER_FRAME\",{set:function(){n(\"PIXI.CanvasPrepare.UPLOADS_PER_FRAME has been removed. Please set renderer.plugins.prepare.limiter.maxItemsPerFrame on your renderer\")},get:function(){return n(\"PIXI.CanvasPrepare.UPLOADS_PER_FRAME has been removed. Please use renderer.plugins.prepare.limiter\"),NaN}}),s.webgl&&Object.defineProperty(s.webgl,\"UPLOADS_PER_FRAME\",{set:function(){n(\"PIXI.WebGLPrepare.UPLOADS_PER_FRAME has been removed. Please set renderer.plugins.prepare.limiter.maxItemsPerFrame on your renderer\")},get:function(){return n(\"PIXI.WebGLPrepare.UPLOADS_PER_FRAME has been removed. Please use renderer.plugins.prepare.limiter\"),NaN}}),a.Loader){var d=a.Resource,f=a.Loader;Object.defineProperties(d.prototype,{isJson:{get:function(){return n(\"The isJson property is deprecated, please use `resource.type === Resource.TYPE.JSON`.\"),this.type===d.TYPE.JSON}},isXml:{get:function(){return n(\"The isXml property is deprecated, please use `resource.type === Resource.TYPE.XML`.\"),this.type===d.TYPE.XML}},isImage:{get:function(){return n(\"The isImage property is deprecated, please use `resource.type === Resource.TYPE.IMAGE`.\"),this.type===d.TYPE.IMAGE}},isAudio:{get:function(){return n(\"The isAudio property is deprecated, please use `resource.type === Resource.TYPE.AUDIO`.\"),this.type===d.TYPE.AUDIO}},isVideo:{get:function(){return n(\"The isVideo property is deprecated, please use `resource.type === Resource.TYPE.VIDEO`.\"),this.type===d.TYPE.VIDEO}}}),Object.defineProperties(f.prototype,{before:{get:function(){return n(\"The before() method is deprecated, please use pre().\"),this.pre}},after:{get:function(){return n(\"The after() method is deprecated, please use use().\"),this.use}}})}u.interactiveTarget&&Object.defineProperty(u.interactiveTarget,\"defaultCursor\",{set:function(t){n(\"Property defaultCursor has been replaced with 'cursor'. \"),this.cursor=t},get:function(){return n(\"Property defaultCursor has been replaced with 'cursor'. \"),this.cursor}}),u.InteractionManager&&(Object.defineProperty(u.InteractionManager,\"defaultCursorStyle\",{set:function(t){n(\"Property defaultCursorStyle has been replaced with 'cursorStyles.default'. \"),this.cursorStyles.default=t},get:function(){return n(\"Property defaultCursorStyle has been replaced with 'cursorStyles.default'. \"),this.cursorStyles.default}}),Object.defineProperty(u.InteractionManager,\"currentCursorStyle\",{set:function(t){n(\"Property currentCursorStyle has been removed.See the currentCursorMode property, which works differently.\"),this.currentCursorMode=t},get:function(){return n(\"Property currentCursorStyle has been removed.See the currentCursorMode property, which works differently.\"),this.currentCursorMode}}))}r.__esModule=!0,r.default=i},{}],132:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../../core\"),o=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(i),s=new o.Rectangle,a=function(){function t(e){n(this,t),this.renderer=e,e.extract=this}return t.prototype.image=function(t){var e=new Image;return e.src=this.base64(t),e},t.prototype.base64=function(t){return this.canvas(t).toDataURL()},t.prototype.canvas=function(t){var e=this.renderer,r=void 0,n=void 0,i=void 0,a=void 0;t&&(a=t instanceof o.RenderTexture?t:e.generateTexture(t)),a?(r=a.baseTexture._canvasRenderTarget.context,n=a.baseTexture._canvasRenderTarget.resolution,i=a.frame):(r=e.rootContext,i=s,i.width=this.renderer.width,i.height=this.renderer.height);var u=i.width*n,h=i.height*n,l=new o.CanvasRenderTarget(u,h),c=r.getImageData(i.x*n,i.y*n,u,h);return l.context.putImageData(c,0,0),l.canvas},t.prototype.pixels=function(t){var e=this.renderer,r=void 0,n=void 0,i=void 0,a=void 0;return t&&(a=t instanceof o.RenderTexture?t:e.generateTexture(t)),a?(r=a.baseTexture._canvasRenderTarget.context,n=a.baseTexture._canvasRenderTarget.resolution,i=a.frame):(r=e.rootContext,i=s,i.width=e.width,i.height=e.height),r.getImageData(0,0,i.width*n,i.height*n).data},t.prototype.destroy=function(){this.renderer.extract=null,this.renderer=null},t}();r.default=a,o.CanvasRenderer.registerPlugin(\"extract\",a)},{\"../../core\":65}],133:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0;var i=t(\"./webgl/WebGLExtract\");Object.defineProperty(r,\"webgl\",{enumerable:!0,get:function(){return n(i).default}});var o=t(\"./canvas/CanvasExtract\");Object.defineProperty(r,\"canvas\",{enumerable:!0,get:function(){return n(o).default}})},{\"./canvas/CanvasExtract\":132,\"./webgl/WebGLExtract\":134}],134:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../../core\"),o=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(i),s=new o.Rectangle,a=function(){function t(e){n(this,t),this.renderer=e,e.extract=this}return t.prototype.image=function(t){var e=new Image;return e.src=this.base64(t),e},t.prototype.base64=function(t){return this.canvas(t).toDataURL()},t.prototype.canvas=function(t){var e=this.renderer,r=void 0,n=void 0,i=void 0,a=!1,u=void 0;t&&(u=t instanceof o.RenderTexture?t:this.renderer.generateTexture(t)),u?(r=u.baseTexture._glRenderTargets[this.renderer.CONTEXT_UID],n=r.resolution,i=u.frame,a=!1):(r=this.renderer.rootRenderTarget,n=r.resolution,a=!0,i=s,i.width=r.size.width,i.height=r.size.height);var h=i.width*n,l=i.height*n,c=new o.CanvasRenderTarget(h,l);if(r){e.bindRenderTarget(r);var d=new Uint8Array(4*h*l),f=e.gl;f.readPixels(i.x*n,i.y*n,h,l,f.RGBA,f.UNSIGNED_BYTE,d);var p=c.context.getImageData(0,0,h,l);p.data.set(d),c.context.putImageData(p,0,0),a&&(c.context.scale(1,-1),c.context.drawImage(c.canvas,0,-l))}return c.canvas},t.prototype.pixels=function(t){var e=this.renderer,r=void 0,n=void 0,i=void 0,a=void 0;t&&(a=t instanceof o.RenderTexture?t:this.renderer.generateTexture(t)),a?(r=a.baseTexture._glRenderTargets[this.renderer.CONTEXT_UID],n=r.resolution,i=a.frame):(r=this.renderer.rootRenderTarget,n=r.resolution,i=s,i.width=r.size.width,i.height=r.size.height);var u=i.width*n,h=i.height*n,l=new Uint8Array(4*u*h);if(r){e.bindRenderTarget(r);var c=e.gl;c.readPixels(i.x*n,i.y*n,u,h,c.RGBA,c.UNSIGNED_BYTE,l)}return l},t.prototype.destroy=function(){this.renderer.extract=null,this.renderer=null},t}();r.default=a,o.WebGLRenderer.registerPlugin(\"extract\",a)},{\"../../core\":65}],135:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"../core\"),u=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(a),h=function(t){function e(r,o){n(this,e);var s=i(this,t.call(this,r[0]instanceof u.Texture?r[0]:r[0].texture));return s._textures=null,s._durations=null,s.textures=r,s._autoUpdate=!1!==o,s.animationSpeed=1,s.loop=!0,s.onComplete=null,s.onFrameChange=null,s.onLoop=null,s._currentTime=0,s.playing=!1,s}return o(e,t),e.prototype.stop=function(){this.playing&&(this.playing=!1,this._autoUpdate&&u.ticker.shared.remove(this.update,this))},e.prototype.play=function(){this.playing||(this.playing=!0,this._autoUpdate&&u.ticker.shared.add(this.update,this,u.UPDATE_PRIORITY.HIGH))},e.prototype.gotoAndStop=function(t){this.stop();var e=this.currentFrame;this._currentTime=t,e!==this.currentFrame&&this.updateTexture()},e.prototype.gotoAndPlay=function(t){var e=this.currentFrame;this._currentTime=t,e!==this.currentFrame&&this.updateTexture(),this.play()},e.prototype.update=function(t){var e=this.animationSpeed*t,r=this.currentFrame;if(null!==this._durations){var n=this._currentTime%1*this._durations[this.currentFrame];for(n+=e/60*1e3;n<0;)this._currentTime--,n+=this._durations[this.currentFrame];var i=Math.sign(this.animationSpeed*t);for(this._currentTime=Math.floor(this._currentTime);n>=this._durations[this.currentFrame];)n-=this._durations[this.currentFrame]*i,this._currentTime+=i;this._currentTime+=n/this._durations[this.currentFrame]}else this._currentTime+=e;this._currentTime<0&&!this.loop?(this.gotoAndStop(0),this.onComplete&&this.onComplete()):this._currentTime>=this._textures.length&&!this.loop?(this.gotoAndStop(this._textures.length-1),this.onComplete&&this.onComplete()):r!==this.currentFrame&&(this.loop&&this.onLoop&&(this.animationSpeed>0&&this.currentFrame<r?this.onLoop():this.animationSpeed<0&&this.currentFrame>r&&this.onLoop()),this.updateTexture())},e.prototype.updateTexture=function(){this._texture=this._textures[this.currentFrame],this._textureID=-1,this.cachedTint=16777215,this.onFrameChange&&this.onFrameChange(this.currentFrame)},e.prototype.destroy=function(e){this.stop(),t.prototype.destroy.call(this,e)},e.fromFrames=function(t){for(var r=[],n=0;n<t.length;++n)r.push(u.Texture.fromFrame(t[n]));return new e(r)},e.fromImages=function(t){for(var r=[],n=0;n<t.length;++n)r.push(u.Texture.fromImage(t[n]));return new e(r)},s(e,[{key:\"totalFrames\",get:function(){return this._textures.length}},{key:\"textures\",get:function(){return this._textures},set:function(t){if(t[0]instanceof u.Texture)this._textures=t,this._durations=null;else{this._textures=[],this._durations=[];for(var e=0;e<t.length;e++)this._textures.push(t[e].texture),this._durations.push(t[e].time)}this.gotoAndStop(0),this.updateTexture()}},{key:\"currentFrame\",get:function(){var t=Math.floor(this._currentTime)%this._textures.length;return t<0&&(t+=this._textures.length),t}}]),e}(u.Sprite);r.default=h},{\"../core\":65}],136:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),u=t(\"../core\"),h=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(u),l=t(\"../core/math/ObservablePoint\"),c=n(l),d=t(\"../core/utils\"),f=t(\"../core/settings\"),p=n(f),v=function(t){function e(r){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};i(this,e);var s=o(this,t.call(this));return s._textWidth=0,s._textHeight=0,s._glyphs=[],s._font={tint:void 0!==n.tint?n.tint:16777215,align:n.align||\"left\",name:null,size:0},s.font=n.font,s._text=r,s._maxWidth=0,s._maxLineHeight=0,s._anchor=new c.default(function(){s.dirty=!0},s,0,0),s.dirty=!1,s.updateText(),s}return s(e,t),e.prototype.updateText=function(){for(var t=e.fonts[this._font.name],r=this._font.size/t.size,n=new h.Point,i=[],o=[],s=null,a=0,u=0,l=0,c=-1,d=0,f=0,p=0,v=0;v<this.text.length;v++){var y=this.text.charCodeAt(v);if(/(\\s)/.test(this.text.charAt(v))&&(c=v,d=a),/(?:\\r\\n|\\r|\\n)/.test(this.text.charAt(v)))o.push(a),u=Math.max(u,a),l++,n.x=0,n.y+=t.lineHeight,s=null;else if(-1!==c&&this._maxWidth>0&&n.x*r>this._maxWidth)h.utils.removeItems(i,c-f,v-c),v=c,c=-1,++f,o.push(d),u=Math.max(u,d),l++,n.x=0,n.y+=t.lineHeight,s=null;else{var g=t.chars[y];g&&(s&&g.kerning[s]&&(n.x+=g.kerning[s]),i.push({texture:g.texture,line:l,charCode:y,position:new h.Point(n.x+g.xOffset,n.y+g.yOffset)}),a=n.x+(g.texture.width+g.xOffset),n.x+=g.xAdvance,p=Math.max(p,g.yOffset+g.texture.height),s=y)}}o.push(a),u=Math.max(u,a);for(var m=[],_=0;_<=l;_++){var b=0;\"right\"===this._font.align?b=u-o[_]:\"center\"===this._font.align&&(b=(u-o[_])/2),m.push(b)}for(var x=i.length,T=this.tint,w=0;w<x;w++){var E=this._glyphs[w];E?E.texture=i[w].texture:(E=new h.Sprite(i[w].texture),this._glyphs.push(E)),E.position.x=(i[w].position.x+m[i[w].line])*r,E.position.y=i[w].position.y*r,E.scale.x=E.scale.y=r,E.tint=T,E.parent||this.addChild(E)}for(var S=x;S<this._glyphs.length;++S)this.removeChild(this._glyphs[S]);if(this._textWidth=u*r,this._textHeight=(n.y+t.lineHeight)*r,0!==this.anchor.x||0!==this.anchor.y)for(var O=0;O<x;O++)this._glyphs[O].x-=this._textWidth*this.anchor.x,this._glyphs[O].y-=this._textHeight*this.anchor.y;this._maxLineHeight=p*r},e.prototype.updateTransform=function(){this.validate(),this.containerUpdateTransform()},e.prototype.getLocalBounds=function(){return this.validate(),t.prototype.getLocalBounds.call(this)},e.prototype.validate=function(){this.dirty&&(this.updateText(),this.dirty=!1)},e.registerFont=function(t,r){var n={},i=t.getElementsByTagName(\"info\")[0],o=t.getElementsByTagName(\"common\")[0],s=t.getElementsByTagName(\"page\")[0].getAttribute(\"file\"),a=(0,d.getResolutionOfUrl)(s,p.default.RESOLUTION);n.font=i.getAttribute(\"face\"),n.size=parseInt(i.getAttribute(\"size\"),10),n.lineHeight=parseInt(o.getAttribute(\"lineHeight\"),10)/a,n.chars={};for(var u=t.getElementsByTagName(\"char\"),l=0;l<u.length;l++){var c=u[l],f=parseInt(c.getAttribute(\"id\"),10),v=new h.Rectangle(parseInt(c.getAttribute(\"x\"),10)/a+r.frame.x/a,parseInt(c.getAttribute(\"y\"),10)/a+r.frame.y/a,parseInt(c.getAttribute(\"width\"),10)/a,parseInt(c.getAttribute(\"height\"),10)/a);n.chars[f]={xOffset:parseInt(c.getAttribute(\"xoffset\"),10)/a,yOffset:parseInt(c.getAttribute(\"yoffset\"),10)/a,xAdvance:parseInt(c.getAttribute(\"xadvance\"),10)/a,kerning:{},texture:new h.Texture(r.baseTexture,v)}}for(var y=t.getElementsByTagName(\"kerning\"),g=0;g<y.length;g++){var m=y[g],_=parseInt(m.getAttribute(\"first\"),10)/a,b=parseInt(m.getAttribute(\"second\"),10)/a,x=parseInt(m.getAttribute(\"amount\"),10)/a;n.chars[b]&&(n.chars[b].kerning[_]=x)}return e.fonts[n.font]=n,n},a(e,[{key:\"tint\",get:function(){return this._font.tint},set:function(t){this._font.tint=\"number\"==typeof t&&t>=0?t:16777215,this.dirty=!0}},{key:\"align\",get:function(){return this._font.align},set:function(t){this._font.align=t||\"left\",this.dirty=!0}},{key:\"anchor\",get:function(){return this._anchor},set:function(t){\"number\"==typeof t?this._anchor.set(t):this._anchor.copy(t)}},{key:\"font\",get:function(){return this._font},set:function(t){t&&(\"string\"==typeof t?(t=t.split(\" \"),this._font.name=1===t.length?t[0]:t.slice(1).join(\" \"),this._font.size=t.length>=2?parseInt(t[0],10):e.fonts[this._font.name].size):(this._font.name=t.name,this._font.size=\"number\"==typeof t.size?t.size:parseInt(t.size,10)),this.dirty=!0)}},{key:\"text\",get:function(){return this._text},set:function(t){t=t.toString()||\" \",this._text!==t&&(this._text=t,this.dirty=!0)}},{key:\"maxWidth\",get:function(){return this._maxWidth},set:function(t){this._maxWidth!==t&&(this._maxWidth=t,this.dirty=!0)}},{key:\"maxLineHeight\",get:function(){return this.validate(),this._maxLineHeight}},{key:\"textWidth\",get:function(){return this.validate(),this._textWidth}},{key:\"textHeight\",get:function(){return this.validate(),this._textHeight}}]),e}(h.Container);r.default=v,v.fonts={}},{\"../core\":65,\"../core/math/ObservablePoint\":68,\"../core/settings\":101,\"../core/utils\":125}],137:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"../core\"),u=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(a),h=t(\"../core/sprites/canvas/CanvasTinter\"),l=function(t){return t&&t.__esModule?t:{default:t}}(h),c=new u.Point,d=function(t){function e(r){var o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:100,s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:100;n(this,e);var a=i(this,t.call(this,r));return a.tileTransform=new u.TransformStatic,a._width=o,a._height=s,a._canvasPattern=null,a.uvTransform=r.transform||new u.TextureMatrix(r),a.pluginName=\"tilingSprite\",a.uvRespectAnchor=!1,a}return o(e,t),e.prototype._onTextureUpdate=function(){this.uvTransform&&(this.uvTransform.texture=this._texture),this.cachedTint=16777215},e.prototype._renderWebGL=function(t){var e=this._texture;e&&e.valid&&(this.tileTransform.updateLocalTransform(),this.uvTransform.update(),t.setObjectRenderer(t.plugins[this.pluginName]),t.plugins[this.pluginName].render(this))},e.prototype._renderCanvas=function(t){var e=this._texture;if(e.baseTexture.hasLoaded){var r=t.context,n=this.worldTransform,i=t.resolution,o=e.baseTexture,s=o.resolution,a=this.tilePosition.x/this.tileScale.x%e._frame.width*s,h=this.tilePosition.y/this.tileScale.y%e._frame.height*s;if(this._textureID!==this._texture._updateID||this.cachedTint!==this.tint){this._textureID=this._texture._updateID;var c=new u.CanvasRenderTarget(e._frame.width,e._frame.height,s);16777215!==this.tint?(this.tintedTexture=l.default.getTintedTexture(this,this.tint),c.context.drawImage(this.tintedTexture,0,0)):c.context.drawImage(o.source,-e._frame.x*s,-e._frame.y*s),this.cachedTint=this.tint,this._canvasPattern=c.context.createPattern(c.canvas,\"repeat\")}r.globalAlpha=this.worldAlpha,r.setTransform(n.a*i,n.b*i,n.c*i,n.d*i,n.tx*i,n.ty*i),t.setBlendMode(this.blendMode),r.fillStyle=this._canvasPattern,r.scale(this.tileScale.x/s,this.tileScale.y/s);var d=this.anchor.x*-this._width,f=this.anchor.y*-this._height;this.uvRespectAnchor?(r.translate(a,h),r.fillRect(-a+d,-h+f,this._width/this.tileScale.x*s,this._height/this.tileScale.y*s)):(r.translate(a+d,h+f),r.fillRect(-a,-h,this._width/this.tileScale.x*s,this._height/this.tileScale.y*s))}},e.prototype._calculateBounds=function(){var t=this._width*-this._anchor._x,e=this._height*-this._anchor._y,r=this._width*(1-this._anchor._x),n=this._height*(1-this._anchor._y);this._bounds.addFrame(this.transform,t,e,r,n)},e.prototype.getLocalBounds=function(e){return 0===this.children.length?(this._bounds.minX=this._width*-this._anchor._x,this._bounds.minY=this._height*-this._anchor._y,this._bounds.maxX=this._width*(1-this._anchor._x),this._bounds.maxY=this._height*(1-this._anchor._x),e||(this._localBoundsRect||(this._localBoundsRect=new u.Rectangle),e=this._localBoundsRect),this._bounds.getRectangle(e)):t.prototype.getLocalBounds.call(this,e)},e.prototype.containsPoint=function(t){this.worldTransform.applyInverse(t,c);var e=this._width,r=this._height,n=-e*this.anchor._x;if(c.x>=n&&c.x<n+e){var i=-r*this.anchor._y;if(c.y>=i&&c.y<i+r)return!0}return!1},e.prototype.destroy=function(e){t.prototype.destroy.call(this,e),this.tileTransform=null,this.uvTransform=null},e.from=function(t,r,n){return new e(u.Texture.from(t),r,n)},e.fromFrame=function(t,r,n){var i=u.utils.TextureCache[t];if(!i)throw new Error('The frameId \"'+t+'\" does not exist in the texture cache '+this);return new e(i,r,n)},e.fromImage=function(t,r,n,i,o){return new e(u.Texture.fromImage(t,i,o),r,n)},s(e,[{key:\"clampMargin\",get:function(){return this.uvTransform.clampMargin},set:function(t){this.uvTransform.clampMargin=t,this.uvTransform.update(!0)}},{key:\"tileScale\",get:function(){return this.tileTransform.scale},set:function(t){this.tileTransform.scale.copy(t)}},{key:\"tilePosition\",get:function(){return this.tileTransform.position},set:function(t){this.tileTransform.position.copy(t)}},{key:\"width\",get:function(){return this._width},set:function(t){this._width=t}},{key:\"height\",get:function(){return this._height},set:function(t){this._height=t}}]),e}(u.Sprite);r.default=d},{\"../core\":65,\"../core/sprites/canvas/CanvasTinter\":104}],138:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}var o=t(\"../core\"),s=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(o),a=t(\"../core/textures/Texture\"),u=n(a),h=t(\"../core/textures/BaseTexture\"),l=n(h),c=t(\"../core/utils\"),d=s.DisplayObject,f=new s.Matrix;d.prototype._cacheAsBitmap=!1,d.prototype._cacheData=!1;var p=function t(){i(this,t),this.textureCacheId=null,this.originalRenderWebGL=null,this.originalRenderCanvas=null,this.originalCalculateBounds=null,this.originalGetLocalBounds=null,this.originalUpdateTransform=null,this.originalHitTest=null,this.originalDestroy=null,this.originalMask=null,this.originalFilterArea=null,this.sprite=null};Object.defineProperties(d.prototype,{cacheAsBitmap:{get:function(){return this._cacheAsBitmap},set:function(t){if(this._cacheAsBitmap!==t){this._cacheAsBitmap=t;var e=void 0;t?(this._cacheData||(this._cacheData=new p),e=this._cacheData,e.originalRenderWebGL=this.renderWebGL,e.originalRenderCanvas=this.renderCanvas,e.originalUpdateTransform=this.updateTransform,e.originalCalculateBounds=this._calculateBounds,e.originalGetLocalBounds=this.getLocalBounds,e.originalDestroy=this.destroy,e.originalContainsPoint=this.containsPoint,e.originalMask=this._mask,e.originalFilterArea=this.filterArea,this.renderWebGL=this._renderCachedWebGL,this.renderCanvas=this._renderCachedCanvas,this.destroy=this._cacheAsBitmapDestroy):(e=this._cacheData,e.sprite&&this._destroyCachedDisplayObject(),this.renderWebGL=e.originalRenderWebGL,this.renderCanvas=e.originalRenderCanvas,this._calculateBounds=e.originalCalculateBounds,this.getLocalBounds=e.originalGetLocalBounds,this.destroy=e.originalDestroy,this.updateTransform=e.originalUpdateTransform,this.containsPoint=e.originalContainsPoint,this._mask=e.originalMask,this.filterArea=e.originalFilterArea)}}}}),d.prototype._renderCachedWebGL=function(t){!this.visible||this.worldAlpha<=0||!this.renderable||(this._initCachedDisplayObject(t),this._cacheData.sprite._transformID=-1,this._cacheData.sprite.worldAlpha=this.worldAlpha,this._cacheData.sprite._renderWebGL(t))},d.prototype._initCachedDisplayObject=function(t){if(!this._cacheData||!this._cacheData.sprite){var e=this.alpha;this.alpha=1,t.currentRenderer.flush();var r=this.getLocalBounds().clone();if(this._filters){var n=this._filters[0].padding;r.pad(n)}var i=t._activeRenderTarget,o=t.filterManager.filterStack,a=s.RenderTexture.create(0|r.width,0|r.height),h=\"cacheAsBitmap_\"+(0,c.uid)();this._cacheData.textureCacheId=h,l.default.addToCache(a.baseTexture,h),u.default.addToCache(a,h);var d=f;d.tx=-r.x,d.ty=-r.y,this.transform.worldTransform.identity(),this.renderWebGL=this._cacheData.originalRenderWebGL,t.render(this,a,!0,d,!0),t.bindRenderTarget(i),t.filterManager.filterStack=o,this.renderWebGL=this._renderCachedWebGL,this.updateTransform=this.displayObjectUpdateTransform,this._mask=null,this.filterArea=null;var p=new s.Sprite(a);p.transform.worldTransform=this.transform.worldTransform,p.anchor.x=-r.x/r.width,p.anchor.y=-r.y/r.height,p.alpha=e,p._bounds=this._bounds,this._calculateBounds=this._calculateCachedBounds,this.getLocalBounds=this._getCachedLocalBounds,this._cacheData.sprite=p,this.transform._parentID=-1,this.parent?this.updateTransform():(this.parent=t._tempDisplayObjectParent,this.updateTransform(),this.parent=null),this.containsPoint=p.containsPoint.bind(p)}},d.prototype._renderCachedCanvas=function(t){!this.visible||this.worldAlpha<=0||!this.renderable||(this._initCachedDisplayObjectCanvas(t),this._cacheData.sprite.worldAlpha=this.worldAlpha,this._cacheData.sprite.renderCanvas(t))},d.prototype._initCachedDisplayObjectCanvas=function(t){if(!this._cacheData||!this._cacheData.sprite){var e=this.getLocalBounds(),r=this.alpha;this.alpha=1;var n=t.context,i=s.RenderTexture.create(0|e.width,0|e.height),o=\"cacheAsBitmap_\"+(0,c.uid)();this._cacheData.textureCacheId=o,l.default.addToCache(i.baseTexture,o),u.default.addToCache(i,o);var a=f;this.transform.localTransform.copy(a),a.invert(),a.tx-=e.x,a.ty-=e.y,this.renderCanvas=this._cacheData.originalRenderCanvas,t.render(this,i,!0,a,!1),t.context=n,this.renderCanvas=this._renderCachedCanvas,this._calculateBounds=this._calculateCachedBounds,this._mask=null,this.filterArea=null;var h=new s.Sprite(i);h.transform.worldTransform=this.transform.worldTransform,h.anchor.x=-e.x/e.width,h.anchor.y=-e.y/e.height,h._bounds=this._bounds,h.alpha=r,this.parent?this.updateTransform():(this.parent=t._tempDisplayObjectParent,this.updateTransform(),this.parent=null),this.updateTransform=this.displayObjectUpdateTransform,this._cacheData.sprite=h,this.containsPoint=h.containsPoint.bind(h)}},d.prototype._calculateCachedBounds=function(){this._cacheData.sprite._calculateBounds()},d.prototype._getCachedLocalBounds=function(){return this._cacheData.sprite.getLocalBounds()},d.prototype._destroyCachedDisplayObject=function(){this._cacheData.sprite._texture.destroy(!0),this._cacheData.sprite=null,l.default.removeFromCache(this._cacheData.textureCacheId),u.default.removeFromCache(this._cacheData.textureCacheId),this._cacheData.textureCacheId=null},d.prototype._cacheAsBitmapDestroy=function(t){this.cacheAsBitmap=!1,this.destroy(t)}},{\"../core\":65,\"../core/textures/BaseTexture\":112,\"../core/textures/Texture\":115,\"../core/utils\":125}],139:[function(t,e,r){\"use strict\";var n=t(\"../core\"),i=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(n);i.DisplayObject.prototype.name=null,i.Container.prototype.getChildByName=function(t){for(var e=0;e<this.children.length;e++)if(this.children[e].name===t)return this.children[e];return null}},{\"../core\":65}],140:[function(t,e,r){\"use strict\";var n=t(\"../core\"),i=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(n);i.DisplayObject.prototype.getGlobalPosition=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:new i.Point,e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return this.parent?this.parent.toGlobal(this.position,t,e):(t.x=this.position.x,t.y=this.position.y),t}},{\"../core\":65}],141:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0,r.BitmapText=r.TilingSpriteRenderer=r.TilingSprite=r.AnimatedSprite=void 0;var i=t(\"./AnimatedSprite\");Object.defineProperty(r,\"AnimatedSprite\",{enumerable:!0,get:function(){return n(i).default}});var o=t(\"./TilingSprite\");Object.defineProperty(r,\"TilingSprite\",{enumerable:!0,get:function(){return n(o).default}});var s=t(\"./webgl/TilingSpriteRenderer\");Object.defineProperty(r,\"TilingSpriteRenderer\",{enumerable:!0,get:function(){return n(s).default}});var a=t(\"./BitmapText\");Object.defineProperty(r,\"BitmapText\",{enumerable:!0,get:function(){return n(a).default}}),t(\"./cacheAsBitmap\"),t(\"./getChildByName\"),t(\"./getGlobalPosition\")},{\"./AnimatedSprite\":135,\"./BitmapText\":136,\"./TilingSprite\":137,\"./cacheAsBitmap\":138,\"./getChildByName\":139,\"./getGlobalPosition\":140,\"./webgl/TilingSpriteRenderer\":142}],142:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=t(\"../../core\"),a=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(s),u=t(\"../../core/const\"),h=(t(\"path\"),new a.Matrix),l=function(t){function e(r){n(this,e);var o=i(this,t.call(this,r));return o.shader=null,o.simpleShader=null,o.quad=null,o}return o(e,t),e.prototype.onContextChange=function(){var t=this.renderer.gl;this.shader=new a.Shader(t,\"attribute vec2 aVertexPosition;\\nattribute vec2 aTextureCoord;\\n\\nuniform mat3 projectionMatrix;\\nuniform mat3 translationMatrix;\\nuniform mat3 uTransform;\\n\\nvarying vec2 vTextureCoord;\\n\\nvoid main(void)\\n{\\n    gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\\n\\n    vTextureCoord = (uTransform * vec3(aTextureCoord, 1.0)).xy;\\n}\\n\",\"varying vec2 vTextureCoord;\\n\\nuniform sampler2D uSampler;\\nuniform vec4 uColor;\\nuniform mat3 uMapCoord;\\nuniform vec4 uClampFrame;\\nuniform vec2 uClampOffset;\\n\\nvoid main(void)\\n{\\n    vec2 coord = mod(vTextureCoord - uClampOffset, vec2(1.0, 1.0)) + uClampOffset;\\n    coord = (uMapCoord * vec3(coord, 1.0)).xy;\\n    coord = clamp(coord, uClampFrame.xy, uClampFrame.zw);\\n\\n    vec4 sample = texture2D(uSampler, coord);\\n    gl_FragColor = sample * uColor;\\n}\\n\"),\nthis.simpleShader=new a.Shader(t,\"attribute vec2 aVertexPosition;\\nattribute vec2 aTextureCoord;\\n\\nuniform mat3 projectionMatrix;\\nuniform mat3 translationMatrix;\\nuniform mat3 uTransform;\\n\\nvarying vec2 vTextureCoord;\\n\\nvoid main(void)\\n{\\n    gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\\n\\n    vTextureCoord = (uTransform * vec3(aTextureCoord, 1.0)).xy;\\n}\\n\",\"varying vec2 vTextureCoord;\\n\\nuniform sampler2D uSampler;\\nuniform vec4 uColor;\\n\\nvoid main(void)\\n{\\n    vec4 sample = texture2D(uSampler, vTextureCoord);\\n    gl_FragColor = sample * uColor;\\n}\\n\"),this.renderer.bindVao(null),this.quad=new a.Quad(t,this.renderer.state.attribState),this.quad.initVao(this.shader)},e.prototype.render=function(t){var e=this.renderer,r=this.quad;e.bindVao(r.vao);var n=r.vertices;n[0]=n[6]=t._width*-t.anchor.x,n[1]=n[3]=t._height*-t.anchor.y,n[2]=n[4]=t._width*(1-t.anchor.x),n[5]=n[7]=t._height*(1-t.anchor.y),t.uvRespectAnchor&&(n=r.uvs,n[0]=n[6]=-t.anchor.x,n[1]=n[3]=-t.anchor.y,n[2]=n[4]=1-t.anchor.x,n[5]=n[7]=1-t.anchor.y),r.upload();var i=t._texture,o=i.baseTexture,s=t.tileTransform.localTransform,l=t.uvTransform,c=o.isPowerOfTwo&&i.frame.width===o.width&&i.frame.height===o.height;c&&(o._glTextures[e.CONTEXT_UID]?c=o.wrapMode!==u.WRAP_MODES.CLAMP:o.wrapMode===u.WRAP_MODES.CLAMP&&(o.wrapMode=u.WRAP_MODES.REPEAT));var d=c?this.simpleShader:this.shader;e.bindShader(d);var f=i.width,p=i.height,v=t._width,y=t._height;h.set(s.a*f/v,s.b*f/y,s.c*p/v,s.d*p/y,s.tx/v,s.ty/y),h.invert(),c?h.prepend(l.mapCoord):(d.uniforms.uMapCoord=l.mapCoord.toArray(!0),d.uniforms.uClampFrame=l.uClampFrame,d.uniforms.uClampOffset=l.uClampOffset),d.uniforms.uTransform=h.toArray(!0),d.uniforms.uColor=a.utils.premultiplyTintToRgba(t.tint,t.worldAlpha,d.uniforms.uColor,o.premultipliedAlpha),d.uniforms.translationMatrix=t.transform.worldTransform.toArray(!0),d.uniforms.uSampler=e.bindTexture(i),e.setBlendMode(a.utils.correctBlendMode(t.blendMode,o.premultipliedAlpha)),r.vao.draw(this.renderer.gl.TRIANGLES,6,0)},e}(a.ObjectRenderer);r.default=l,a.WebGLRenderer.registerPlugin(\"tilingSprite\",l)},{\"../../core\":65,\"../../core/const\":46,path:23}],143:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"../../core\"),u=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(a),h=(t(\"path\"),function(t){function e(){var r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1;n(this,e);var o=i(this,t.call(this,\"attribute vec2 aVertexPosition;\\nattribute vec2 aTextureCoord;\\n\\nuniform mat3 projectionMatrix;\\n\\nvarying vec2 vTextureCoord;\\n\\nvoid main(void)\\n{\\n    gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\\n    vTextureCoord = aTextureCoord;\\n}\",\"varying vec2 vTextureCoord;\\n\\nuniform sampler2D uSampler;\\nuniform float uAlpha;\\n\\nvoid main(void)\\n{\\n   gl_FragColor = texture2D(uSampler, vTextureCoord) * uAlpha;\\n}\\n\"));return o.alpha=r,o.glShaderKey=\"alpha\",o}return o(e,t),s(e,[{key:\"alpha\",get:function(){return this.uniforms.uAlpha},set:function(t){this.uniforms.uAlpha=t}}]),e}(u.Filter));r.default=h},{\"../../core\":65,path:23}],144:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),u=t(\"../../core\"),h=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(u),l=t(\"./BlurXFilter\"),c=n(l),d=t(\"./BlurYFilter\"),f=n(d),p=function(t){function e(r,n,s,a){i(this,e);var u=o(this,t.call(this));return u.blurXFilter=new c.default(r,n,s,a),u.blurYFilter=new f.default(r,n,s,a),u.padding=0,u.resolution=s||h.settings.RESOLUTION,u.quality=n||4,u.blur=r||8,u}return s(e,t),e.prototype.apply=function(t,e,r){var n=t.getRenderTarget(!0);this.blurXFilter.apply(t,e,n,!0),this.blurYFilter.apply(t,n,r,!1),t.returnRenderTarget(n)},a(e,[{key:\"blur\",get:function(){return this.blurXFilter.blur},set:function(t){this.blurXFilter.blur=this.blurYFilter.blur=t,this.padding=2*Math.max(Math.abs(this.blurXFilter.strength),Math.abs(this.blurYFilter.strength))}},{key:\"quality\",get:function(){return this.blurXFilter.quality},set:function(t){this.blurXFilter.quality=this.blurYFilter.quality=t}},{key:\"blurX\",get:function(){return this.blurXFilter.blur},set:function(t){this.blurXFilter.blur=t,this.padding=2*Math.max(Math.abs(this.blurXFilter.strength),Math.abs(this.blurYFilter.strength))}},{key:\"blurY\",get:function(){return this.blurYFilter.blur},set:function(t){this.blurYFilter.blur=t,this.padding=2*Math.max(Math.abs(this.blurXFilter.strength),Math.abs(this.blurYFilter.strength))}},{key:\"blendMode\",get:function(){return this.blurYFilter._blendMode},set:function(t){this.blurYFilter._blendMode=t}}]),e}(h.Filter);r.default=p},{\"../../core\":65,\"./BlurXFilter\":145,\"./BlurYFilter\":146}],145:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),u=t(\"../../core\"),h=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(u),l=t(\"./generateBlurVertSource\"),c=n(l),d=t(\"./generateBlurFragSource\"),f=n(d),p=t(\"./getMaxBlurKernelSize\"),v=n(p),y=function(t){function e(r,n,s,a){i(this,e),a=a||5;var u=(0,c.default)(a,!0),l=(0,f.default)(a),d=o(this,t.call(this,u,l));return d.resolution=s||h.settings.RESOLUTION,d._quality=0,d.quality=n||4,d.strength=r||8,d.firstRun=!0,d}return s(e,t),e.prototype.apply=function(t,e,r,n){if(this.firstRun){var i=t.renderer.gl,o=(0,v.default)(i);this.vertexSrc=(0,c.default)(o,!0),this.fragmentSrc=(0,f.default)(o),this.firstRun=!1}if(this.uniforms.strength=1/r.size.width*(r.size.width/e.size.width),this.uniforms.strength*=this.strength,this.uniforms.strength/=this.passes,1===this.passes)t.applyFilter(this,e,r,n);else{for(var s=t.getRenderTarget(!0),a=e,u=s,h=0;h<this.passes-1;h++){t.applyFilter(this,a,u,!0);var l=u;u=a,a=l}t.applyFilter(this,a,r,n),t.returnRenderTarget(s)}},a(e,[{key:\"blur\",get:function(){return this.strength},set:function(t){this.padding=2*Math.abs(t),this.strength=t}},{key:\"quality\",get:function(){return this._quality},set:function(t){this._quality=t,this.passes=t}}]),e}(h.Filter);r.default=y},{\"../../core\":65,\"./generateBlurFragSource\":147,\"./generateBlurVertSource\":148,\"./getMaxBlurKernelSize\":149}],146:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),u=t(\"../../core\"),h=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(u),l=t(\"./generateBlurVertSource\"),c=n(l),d=t(\"./generateBlurFragSource\"),f=n(d),p=t(\"./getMaxBlurKernelSize\"),v=n(p),y=function(t){function e(r,n,s,a){i(this,e),a=a||5;var u=(0,c.default)(a,!1),l=(0,f.default)(a),d=o(this,t.call(this,u,l));return d.resolution=s||h.settings.RESOLUTION,d._quality=0,d.quality=n||4,d.strength=r||8,d.firstRun=!0,d}return s(e,t),e.prototype.apply=function(t,e,r,n){if(this.firstRun){var i=t.renderer.gl,o=(0,v.default)(i);this.vertexSrc=(0,c.default)(o,!1),this.fragmentSrc=(0,f.default)(o),this.firstRun=!1}if(this.uniforms.strength=1/r.size.height*(r.size.height/e.size.height),this.uniforms.strength*=this.strength,this.uniforms.strength/=this.passes,1===this.passes)t.applyFilter(this,e,r,n);else{for(var s=t.getRenderTarget(!0),a=e,u=s,h=0;h<this.passes-1;h++){t.applyFilter(this,a,u,!0);var l=u;u=a,a=l}t.applyFilter(this,a,r,n),t.returnRenderTarget(s)}},a(e,[{key:\"blur\",get:function(){return this.strength},set:function(t){this.padding=2*Math.abs(t),this.strength=t}},{key:\"quality\",get:function(){return this._quality},set:function(t){this._quality=t,this.passes=t}}]),e}(h.Filter);r.default=y},{\"../../core\":65,\"./generateBlurFragSource\":147,\"./generateBlurVertSource\":148,\"./getMaxBlurKernelSize\":149}],147:[function(t,e,r){\"use strict\";function n(t){for(var e=i[t],r=e.length,n=o,s=\"\",a=\"gl_FragColor += texture2D(uSampler, vBlurTexCoords[%index%]) * %value%;\",u=void 0,h=0;h<t;h++){var l=a.replace(\"%index%\",h);u=h,h>=r&&(u=t-h-1),l=l.replace(\"%value%\",e[u]),s+=l,s+=\"\\n\"}return n=n.replace(\"%blur%\",s),n=n.replace(\"%size%\",t)}r.__esModule=!0,r.default=n;var i={5:[.153388,.221461,.250301],7:[.071303,.131514,.189879,.214607],9:[.028532,.067234,.124009,.179044,.20236],11:[.0093,.028002,.065984,.121703,.175713,.198596],13:[.002406,.009255,.027867,.065666,.121117,.174868,.197641],15:[489e-6,.002403,.009246,.02784,.065602,.120999,.174697,.197448]},o=[\"varying vec2 vBlurTexCoords[%size%];\",\"uniform sampler2D uSampler;\",\"void main(void)\",\"{\",\"    gl_FragColor = vec4(0.0);\",\"    %blur%\",\"}\"].join(\"\\n\")},{}],148:[function(t,e,r){\"use strict\";function n(t,e){var r=Math.ceil(t/2),n=i,o=\"\",s=void 0;s=e?\"vBlurTexCoords[%index%] = aTextureCoord + vec2(%sampleIndex% * strength, 0.0);\":\"vBlurTexCoords[%index%] = aTextureCoord + vec2(0.0, %sampleIndex% * strength);\";for(var a=0;a<t;a++){var u=s.replace(\"%index%\",a);u=u.replace(\"%sampleIndex%\",a-(r-1)+\".0\"),o+=u,o+=\"\\n\"}return n=n.replace(\"%blur%\",o),n=n.replace(\"%size%\",t)}r.__esModule=!0,r.default=n;var i=[\"attribute vec2 aVertexPosition;\",\"attribute vec2 aTextureCoord;\",\"uniform float strength;\",\"uniform mat3 projectionMatrix;\",\"varying vec2 vBlurTexCoords[%size%];\",\"void main(void)\",\"{\",\"gl_Position = vec4((projectionMatrix * vec3((aVertexPosition), 1.0)).xy, 0.0, 1.0);\",\"%blur%\",\"}\"].join(\"\\n\")},{}],149:[function(t,e,r){\"use strict\";function n(t){for(var e=t.getParameter(t.MAX_VARYING_VECTORS),r=15;r>e;)r-=2;return r}r.__esModule=!0,r.default=n},{}],150:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"../../core\"),u=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(a),h=(t(\"path\"),function(t){function e(){n(this,e);var r=i(this,t.call(this,\"attribute vec2 aVertexPosition;\\nattribute vec2 aTextureCoord;\\n\\nuniform mat3 projectionMatrix;\\n\\nvarying vec2 vTextureCoord;\\n\\nvoid main(void)\\n{\\n    gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\\n    vTextureCoord = aTextureCoord;\\n}\",\"varying vec2 vTextureCoord;\\nuniform sampler2D uSampler;\\nuniform float m[20];\\nuniform float uAlpha;\\n\\nvoid main(void)\\n{\\n    vec4 c = texture2D(uSampler, vTextureCoord);\\n\\n    if (uAlpha == 0.0) {\\n        gl_FragColor = c;\\n        return;\\n    }\\n\\n    // Un-premultiply alpha before applying the color matrix. See issue #3539.\\n    if (c.a > 0.0) {\\n      c.rgb /= c.a;\\n    }\\n\\n    vec4 result;\\n\\n    result.r = (m[0] * c.r);\\n        result.r += (m[1] * c.g);\\n        result.r += (m[2] * c.b);\\n        result.r += (m[3] * c.a);\\n        result.r += m[4];\\n\\n    result.g = (m[5] * c.r);\\n        result.g += (m[6] * c.g);\\n        result.g += (m[7] * c.b);\\n        result.g += (m[8] * c.a);\\n        result.g += m[9];\\n\\n    result.b = (m[10] * c.r);\\n       result.b += (m[11] * c.g);\\n       result.b += (m[12] * c.b);\\n       result.b += (m[13] * c.a);\\n       result.b += m[14];\\n\\n    result.a = (m[15] * c.r);\\n       result.a += (m[16] * c.g);\\n       result.a += (m[17] * c.b);\\n       result.a += (m[18] * c.a);\\n       result.a += m[19];\\n\\n    vec3 rgb = mix(c.rgb, result.rgb, uAlpha);\\n\\n    // Premultiply alpha again.\\n    rgb *= result.a;\\n\\n    gl_FragColor = vec4(rgb, result.a);\\n}\\n\"));return r.uniforms.m=[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0],r.alpha=1,r}return o(e,t),e.prototype._loadMatrix=function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=t;e&&(this._multiply(r,this.uniforms.m,t),r=this._colorMatrix(r)),this.uniforms.m=r},e.prototype._multiply=function(t,e,r){return t[0]=e[0]*r[0]+e[1]*r[5]+e[2]*r[10]+e[3]*r[15],t[1]=e[0]*r[1]+e[1]*r[6]+e[2]*r[11]+e[3]*r[16],t[2]=e[0]*r[2]+e[1]*r[7]+e[2]*r[12]+e[3]*r[17],t[3]=e[0]*r[3]+e[1]*r[8]+e[2]*r[13]+e[3]*r[18],t[4]=e[0]*r[4]+e[1]*r[9]+e[2]*r[14]+e[3]*r[19]+e[4],t[5]=e[5]*r[0]+e[6]*r[5]+e[7]*r[10]+e[8]*r[15],t[6]=e[5]*r[1]+e[6]*r[6]+e[7]*r[11]+e[8]*r[16],t[7]=e[5]*r[2]+e[6]*r[7]+e[7]*r[12]+e[8]*r[17],t[8]=e[5]*r[3]+e[6]*r[8]+e[7]*r[13]+e[8]*r[18],t[9]=e[5]*r[4]+e[6]*r[9]+e[7]*r[14]+e[8]*r[19]+e[9],t[10]=e[10]*r[0]+e[11]*r[5]+e[12]*r[10]+e[13]*r[15],t[11]=e[10]*r[1]+e[11]*r[6]+e[12]*r[11]+e[13]*r[16],t[12]=e[10]*r[2]+e[11]*r[7]+e[12]*r[12]+e[13]*r[17],t[13]=e[10]*r[3]+e[11]*r[8]+e[12]*r[13]+e[13]*r[18],t[14]=e[10]*r[4]+e[11]*r[9]+e[12]*r[14]+e[13]*r[19]+e[14],t[15]=e[15]*r[0]+e[16]*r[5]+e[17]*r[10]+e[18]*r[15],t[16]=e[15]*r[1]+e[16]*r[6]+e[17]*r[11]+e[18]*r[16],t[17]=e[15]*r[2]+e[16]*r[7]+e[17]*r[12]+e[18]*r[17],t[18]=e[15]*r[3]+e[16]*r[8]+e[17]*r[13]+e[18]*r[18],t[19]=e[15]*r[4]+e[16]*r[9]+e[17]*r[14]+e[18]*r[19]+e[19],t},e.prototype._colorMatrix=function(t){var e=new Float32Array(t);return e[4]/=255,e[9]/=255,e[14]/=255,e[19]/=255,e},e.prototype.brightness=function(t,e){var r=[t,0,0,0,0,0,t,0,0,0,0,0,t,0,0,0,0,0,1,0];this._loadMatrix(r,e)},e.prototype.greyscale=function(t,e){var r=[t,t,t,0,0,t,t,t,0,0,t,t,t,0,0,0,0,0,1,0];this._loadMatrix(r,e)},e.prototype.blackAndWhite=function(t){var e=[.3,.6,.1,0,0,.3,.6,.1,0,0,.3,.6,.1,0,0,0,0,0,1,0];this._loadMatrix(e,t)},e.prototype.hue=function(t,e){t=(t||0)/180*Math.PI;var r=Math.cos(t),n=Math.sin(t),i=Math.sqrt,o=1/3,s=i(o),a=r+(1-r)*o,u=o*(1-r)-s*n,h=o*(1-r)+s*n,l=o*(1-r)+s*n,c=r+o*(1-r),d=o*(1-r)-s*n,f=o*(1-r)-s*n,p=o*(1-r)+s*n,v=r+o*(1-r),y=[a,u,h,0,0,l,c,d,0,0,f,p,v,0,0,0,0,0,1,0];this._loadMatrix(y,e)},e.prototype.contrast=function(t,e){var r=(t||0)+1,n=-.5*(r-1),i=[r,0,0,0,n,0,r,0,0,n,0,0,r,0,n,0,0,0,1,0];this._loadMatrix(i,e)},e.prototype.saturate=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments[1],r=2*t/3+1,n=-.5*(r-1),i=[r,n,n,0,0,n,r,n,0,0,n,n,r,0,0,0,0,0,1,0];this._loadMatrix(i,e)},e.prototype.desaturate=function(){this.saturate(-1)},e.prototype.negative=function(t){var e=[0,1,1,0,0,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0];this._loadMatrix(e,t)},e.prototype.sepia=function(t){var e=[.393,.7689999,.18899999,0,0,.349,.6859999,.16799999,0,0,.272,.5339999,.13099999,0,0,0,0,0,1,0];this._loadMatrix(e,t)},e.prototype.technicolor=function(t){var e=[1.9125277891456083,-.8545344976951645,-.09155508482755585,0,11.793603434377337,-.3087833385928097,1.7658908555458428,-.10601743074722245,0,-70.35205161461398,-.231103377548616,-.7501899197440212,1.847597816108189,0,30.950940869491138,0,0,0,1,0];this._loadMatrix(e,t)},e.prototype.polaroid=function(t){var e=[1.438,-.062,-.062,0,0,-.122,1.378,-.122,0,0,-.016,-.016,1.483,0,0,0,0,0,1,0];this._loadMatrix(e,t)},e.prototype.toBGR=function(t){var e=[0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0];this._loadMatrix(e,t)},e.prototype.kodachrome=function(t){var e=[1.1285582396593525,-.3967382283601348,-.03992559172921793,0,63.72958762196502,-.16404339962244616,1.0835251566291304,-.05498805115633132,0,24.732407896706203,-.16786010706155763,-.5603416277695248,1.6014850761964943,0,35.62982807460946,0,0,0,1,0];this._loadMatrix(e,t)},e.prototype.browni=function(t){var e=[.5997023498159715,.34553243048391263,-.2708298674538042,0,47.43192855600873,-.037703249837783157,.8609577587992641,.15059552388459913,0,-36.96841498319127,.24113635128153335,-.07441037908422492,.44972182064877153,0,-7.562075277591283,0,0,0,1,0];this._loadMatrix(e,t)},e.prototype.vintage=function(t){var e=[.6279345635605994,.3202183420819367,-.03965408211312453,0,9.651285835294123,.02578397704808868,.6441188644374771,.03259127616149294,0,7.462829176470591,.0466055556782719,-.0851232987247891,.5241648018700465,0,5.159190588235296,0,0,0,1,0];this._loadMatrix(e,t)},e.prototype.colorTone=function(t,e,r,n,i){t=t||.2,e=e||.15,r=r||16770432,n=n||3375104;var o=(r>>16&255)/255,s=(r>>8&255)/255,a=(255&r)/255,u=(n>>16&255)/255,h=(n>>8&255)/255,l=(255&n)/255,c=[.3,.59,.11,0,0,o,s,a,t,0,u,h,l,e,0,o-u,s-h,a-l,0,0];this._loadMatrix(c,i)},e.prototype.night=function(t,e){t=t||.1;var r=[-2*t,-t,0,0,0,-t,0,t,0,0,0,t,2*t,0,0,0,0,0,1,0];this._loadMatrix(r,e)},e.prototype.predator=function(t,e){var r=[11.224130630493164*t,-4.794486999511719*t,-2.8746118545532227*t,0*t,.40342438220977783*t,-3.6330697536468506*t,9.193157196044922*t,-2.951810836791992*t,0*t,-1.316135048866272*t,-3.2184197902679443*t,-4.2375030517578125*t,7.476448059082031*t,0*t,.8044459223747253*t,0,0,0,1,0];this._loadMatrix(r,e)},e.prototype.lsd=function(t){var e=[2,-.4,.5,0,0,-.5,2,-.4,0,0,-.4,-.5,3,0,0,0,0,0,1,0];this._loadMatrix(e,t)},e.prototype.reset=function(){var t=[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0];this._loadMatrix(t,!1)},s(e,[{key:\"matrix\",get:function(){return this.uniforms.m},set:function(t){this.uniforms.m=t}},{key:\"alpha\",get:function(){return this.uniforms.uAlpha},set:function(t){this.uniforms.uAlpha=t}}]),e}(u.Filter));r.default=h,h.prototype.grayscale=h.prototype.greyscale},{\"../../core\":65,path:23}],151:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"../../core\"),u=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(a),h=(t(\"path\"),function(t){function e(r,o){n(this,e);var s=new u.Matrix;r.renderable=!1;var a=i(this,t.call(this,\"attribute vec2 aVertexPosition;\\nattribute vec2 aTextureCoord;\\n\\nuniform mat3 projectionMatrix;\\nuniform mat3 filterMatrix;\\n\\nvarying vec2 vTextureCoord;\\nvarying vec2 vFilterCoord;\\n\\nvoid main(void)\\n{\\n   gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\\n   vFilterCoord = ( filterMatrix * vec3( aTextureCoord, 1.0)  ).xy;\\n   vTextureCoord = aTextureCoord;\\n}\",\"varying vec2 vFilterCoord;\\nvarying vec2 vTextureCoord;\\n\\nuniform vec2 scale;\\n\\nuniform sampler2D uSampler;\\nuniform sampler2D mapSampler;\\n\\nuniform vec4 filterClamp;\\n\\nvoid main(void)\\n{\\n   vec4 map =  texture2D(mapSampler, vFilterCoord);\\n\\n   map -= 0.5;\\n   map.xy *= scale;\\n\\n   gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw));\\n}\\n\"));return a.maskSprite=r,a.maskMatrix=s,a.uniforms.mapSampler=r._texture,a.uniforms.filterMatrix=s,a.uniforms.scale={x:1,y:1},null!==o&&void 0!==o||(o=20),a.scale=new u.Point(o,o),a}return o(e,t),e.prototype.apply=function(t,e,r){var n=1/r.destinationFrame.width*(r.size.width/e.size.width);this.uniforms.filterMatrix=t.calculateSpriteMatrix(this.maskMatrix,this.maskSprite),this.uniforms.scale.x=this.scale.x*n,this.uniforms.scale.y=this.scale.y*n,t.applyFilter(this,e,r)},s(e,[{key:\"map\",get:function(){return this.uniforms.mapSampler},set:function(t){this.uniforms.mapSampler=t}}]),e}(u.Filter));r.default=h},{\"../../core\":65,path:23}],152:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=t(\"../../core\"),a=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(s),u=(t(\"path\"),function(t){function e(){return n(this,e),i(this,t.call(this,\"\\nattribute vec2 aVertexPosition;\\nattribute vec2 aTextureCoord;\\n\\nuniform mat3 projectionMatrix;\\n\\nvarying vec2 v_rgbNW;\\nvarying vec2 v_rgbNE;\\nvarying vec2 v_rgbSW;\\nvarying vec2 v_rgbSE;\\nvarying vec2 v_rgbM;\\n\\nuniform vec4 filterArea;\\n\\nvarying vec2 vTextureCoord;\\n\\nvec2 mapCoord( vec2 coord )\\n{\\n    coord *= filterArea.xy;\\n    coord += filterArea.zw;\\n\\n    return coord;\\n}\\n\\nvec2 unmapCoord( vec2 coord )\\n{\\n    coord -= filterArea.zw;\\n    coord /= filterArea.xy;\\n\\n    return coord;\\n}\\n\\nvoid texcoords(vec2 fragCoord, vec2 resolution,\\n               out vec2 v_rgbNW, out vec2 v_rgbNE,\\n               out vec2 v_rgbSW, out vec2 v_rgbSE,\\n               out vec2 v_rgbM) {\\n    vec2 inverseVP = 1.0 / resolution.xy;\\n    v_rgbNW = (fragCoord + vec2(-1.0, -1.0)) * inverseVP;\\n    v_rgbNE = (fragCoord + vec2(1.0, -1.0)) * inverseVP;\\n    v_rgbSW = (fragCoord + vec2(-1.0, 1.0)) * inverseVP;\\n    v_rgbSE = (fragCoord + vec2(1.0, 1.0)) * inverseVP;\\n    v_rgbM = vec2(fragCoord * inverseVP);\\n}\\n\\nvoid main(void) {\\n\\n   gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\\n\\n   vTextureCoord = aTextureCoord;\\n\\n   vec2 fragCoord = vTextureCoord * filterArea.xy;\\n\\n   texcoords(fragCoord, filterArea.xy, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM);\\n}\",'varying vec2 v_rgbNW;\\nvarying vec2 v_rgbNE;\\nvarying vec2 v_rgbSW;\\nvarying vec2 v_rgbSE;\\nvarying vec2 v_rgbM;\\n\\nvarying vec2 vTextureCoord;\\nuniform sampler2D uSampler;\\nuniform vec4 filterArea;\\n\\n/**\\n Basic FXAA implementation based on the code on geeks3d.com with the\\n modification that the texture2DLod stuff was removed since it\\'s\\n unsupported by WebGL.\\n \\n --\\n \\n From:\\n https://github.com/mitsuhiko/webgl-meincraft\\n \\n Copyright (c) 2011 by Armin Ronacher.\\n \\n Some rights reserved.\\n \\n Redistribution and use in source and binary forms, with or without\\n modification, are permitted provided that the following conditions are\\n met:\\n \\n * Redistributions of source code must retain the above copyright\\n notice, this list of conditions and the following disclaimer.\\n \\n * Redistributions in binary form must reproduce the above\\n copyright notice, this list of conditions and the following\\n disclaimer in the documentation and/or other materials provided\\n with the distribution.\\n \\n * The names of the contributors may not be used to endorse or\\n promote products derived from this software without specific\\n prior written permission.\\n \\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\\n \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\\n LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\\n A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\\n OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\\n SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n\\n#ifndef FXAA_REDUCE_MIN\\n#define FXAA_REDUCE_MIN   (1.0/ 128.0)\\n#endif\\n#ifndef FXAA_REDUCE_MUL\\n#define FXAA_REDUCE_MUL   (1.0 / 8.0)\\n#endif\\n#ifndef FXAA_SPAN_MAX\\n#define FXAA_SPAN_MAX     8.0\\n#endif\\n\\n//optimized version for mobile, where dependent\\n//texture reads can be a bottleneck\\nvec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 resolution,\\n          vec2 v_rgbNW, vec2 v_rgbNE,\\n          vec2 v_rgbSW, vec2 v_rgbSE,\\n          vec2 v_rgbM) {\\n    vec4 color;\\n    mediump vec2 inverseVP = vec2(1.0 / resolution.x, 1.0 / resolution.y);\\n    vec3 rgbNW = texture2D(tex, v_rgbNW).xyz;\\n    vec3 rgbNE = texture2D(tex, v_rgbNE).xyz;\\n    vec3 rgbSW = texture2D(tex, v_rgbSW).xyz;\\n    vec3 rgbSE = texture2D(tex, v_rgbSE).xyz;\\n    vec4 texColor = texture2D(tex, v_rgbM);\\n    vec3 rgbM  = texColor.xyz;\\n    vec3 luma = vec3(0.299, 0.587, 0.114);\\n    float lumaNW = dot(rgbNW, luma);\\n    float lumaNE = dot(rgbNE, luma);\\n    float lumaSW = dot(rgbSW, luma);\\n    float lumaSE = dot(rgbSE, luma);\\n    float lumaM  = dot(rgbM,  luma);\\n    float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));\\n    float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));\\n    \\n    mediump vec2 dir;\\n    dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\\n    dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));\\n    \\n    float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *\\n                          (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);\\n    \\n    float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);\\n    dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),\\n              max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),\\n                  dir * rcpDirMin)) * inverseVP;\\n    \\n    vec3 rgbA = 0.5 * (\\n                       texture2D(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz +\\n                       texture2D(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz);\\n    vec3 rgbB = rgbA * 0.5 + 0.25 * (\\n                                     texture2D(tex, fragCoord * inverseVP + dir * -0.5).xyz +\\n                                     texture2D(tex, fragCoord * inverseVP + dir * 0.5).xyz);\\n    \\n    float lumaB = dot(rgbB, luma);\\n    if ((lumaB < lumaMin) || (lumaB > lumaMax))\\n        color = vec4(rgbA, texColor.a);\\n    else\\n        color = vec4(rgbB, texColor.a);\\n    return color;\\n}\\n\\nvoid main() {\\n\\n      vec2 fragCoord = vTextureCoord * filterArea.xy;\\n\\n      vec4 color;\\n\\n    color = fxaa(uSampler, fragCoord, filterArea.xy, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM);\\n\\n      gl_FragColor = color;\\n}\\n'))}return o(e,t),e}(a.Filter));r.default=u},{\"../../core\":65,path:23}],153:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0;var i=t(\"./fxaa/FXAAFilter\");Object.defineProperty(r,\"FXAAFilter\",{enumerable:!0,get:function(){return n(i).default}});var o=t(\"./noise/NoiseFilter\");Object.defineProperty(r,\"NoiseFilter\",{enumerable:!0,get:function(){return n(o).default}});var s=t(\"./displacement/DisplacementFilter\");Object.defineProperty(r,\"DisplacementFilter\",{enumerable:!0,get:function(){return n(s).default}});var a=t(\"./blur/BlurFilter\");Object.defineProperty(r,\"BlurFilter\",{enumerable:!0,get:function(){return n(a).default}});var u=t(\"./blur/BlurXFilter\");Object.defineProperty(r,\"BlurXFilter\",{enumerable:!0,get:function(){return n(u).default}});var h=t(\"./blur/BlurYFilter\");Object.defineProperty(r,\"BlurYFilter\",{enumerable:!0,get:function(){return n(h).default}});var l=t(\"./colormatrix/ColorMatrixFilter\");Object.defineProperty(r,\"ColorMatrixFilter\",{enumerable:!0,get:function(){return n(l).default}});var c=t(\"./alpha/AlphaFilter\");Object.defineProperty(r,\"AlphaFilter\",{enumerable:!0,get:function(){return n(c).default}})},{\"./alpha/AlphaFilter\":143,\"./blur/BlurFilter\":144,\"./blur/BlurXFilter\":145,\"./blur/BlurYFilter\":146,\"./colormatrix/ColorMatrixFilter\":150,\"./displacement/DisplacementFilter\":151,\"./fxaa/FXAAFilter\":152,\"./noise/NoiseFilter\":154}],154:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\")\n;return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"../../core\"),u=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(a),h=(t(\"path\"),function(t){function e(){var r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:.5,o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:Math.random();n(this,e);var s=i(this,t.call(this,\"attribute vec2 aVertexPosition;\\nattribute vec2 aTextureCoord;\\n\\nuniform mat3 projectionMatrix;\\n\\nvarying vec2 vTextureCoord;\\n\\nvoid main(void)\\n{\\n    gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\\n    vTextureCoord = aTextureCoord;\\n}\",\"precision highp float;\\n\\nvarying vec2 vTextureCoord;\\nvarying vec4 vColor;\\n\\nuniform float uNoise;\\nuniform float uSeed;\\nuniform sampler2D uSampler;\\n\\nfloat rand(vec2 co)\\n{\\n    return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);\\n}\\n\\nvoid main()\\n{\\n    vec4 color = texture2D(uSampler, vTextureCoord);\\n    float randomValue = rand(gl_FragCoord.xy * uSeed);\\n    float diff = (randomValue - 0.5) * uNoise;\\n\\n    // Un-premultiply alpha before applying the color matrix. See issue #3539.\\n    if (color.a > 0.0) {\\n        color.rgb /= color.a;\\n    }\\n\\n    color.r += diff;\\n    color.g += diff;\\n    color.b += diff;\\n\\n    // Premultiply alpha again.\\n    color.rgb *= color.a;\\n\\n    gl_FragColor = color;\\n}\\n\"));return s.noise=r,s.seed=o,s}return o(e,t),s(e,[{key:\"noise\",get:function(){return this.uniforms.uNoise},set:function(t){this.uniforms.uNoise=t}},{key:\"seed\",get:function(){return this.uniforms.uSeed},set:function(t){this.uniforms.uSeed=t}}]),e}(u.Filter));r.default=h},{\"../../core\":65,path:23}],155:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),o=t(\"../core\"),s=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(o),a=function(){function t(){n(this,t),this.global=new s.Point,this.target=null,this.originalEvent=null,this.identifier=null,this.isPrimary=!1,this.button=0,this.buttons=0,this.width=0,this.height=0,this.tiltX=0,this.tiltY=0,this.pointerType=null,this.pressure=0,this.rotationAngle=0,this.twist=0,this.tangentialPressure=0}return t.prototype.getLocalPosition=function(t,e,r){return t.worldTransform.applyInverse(r||this.global,e)},t.prototype._copyEvent=function(t){t.isPrimary&&(this.isPrimary=!0),this.button=t.button,this.buttons=t.buttons,this.width=t.width,this.height=t.height,this.tiltX=t.tiltX,this.tiltY=t.tiltY,this.pointerType=t.pointerType,this.pressure=t.pressure,this.rotationAngle=t.rotationAngle,this.twist=t.twist||0,this.tangentialPressure=t.tangentialPressure||0},t.prototype._reset=function(){this.isPrimary=!1},i(t,[{key:\"pointerId\",get:function(){return this.identifier}}]),t}();r.default=a},{\"../core\":65}],156:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(){n(this,t),this.stopped=!1,this.target=null,this.currentTarget=null,this.type=null,this.data=null}return t.prototype.stopPropagation=function(){this.stopped=!0},t.prototype._reset=function(){this.stopped=!1,this.currentTarget=null,this.target=null},t}();r.default=i},{}],157:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&\"function\"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?\"symbol\":typeof t},u=t(\"../core\"),h=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(u),l=t(\"./InteractionData\"),c=n(l),d=t(\"./InteractionEvent\"),f=n(d),p=t(\"./InteractionTrackingData\"),v=n(p),y=t(\"eventemitter3\"),g=n(y),m=t(\"./interactiveTarget\"),_=n(m);h.utils.mixins.delayMixin(h.DisplayObject.prototype,_.default);var b=\"MOUSE\",x={target:null,data:{global:null}},T=function(t){function e(r,n){i(this,e);var s=o(this,t.call(this));return n=n||{},s.renderer=r,s.autoPreventDefault=void 0===n.autoPreventDefault||n.autoPreventDefault,s.interactionFrequency=n.interactionFrequency||10,s.mouse=new c.default,s.mouse.identifier=b,s.mouse.global.set(-999999),s.activeInteractionData={},s.activeInteractionData[b]=s.mouse,s.interactionDataPool=[],s.eventData=new f.default,s.interactionDOMElement=null,s.moveWhenInside=!1,s.eventsAdded=!1,s.mouseOverRenderer=!1,s.supportsTouchEvents=\"ontouchstart\"in window,s.supportsPointerEvents=!!window.PointerEvent,s.onPointerUp=s.onPointerUp.bind(s),s.processPointerUp=s.processPointerUp.bind(s),s.onPointerCancel=s.onPointerCancel.bind(s),s.processPointerCancel=s.processPointerCancel.bind(s),s.onPointerDown=s.onPointerDown.bind(s),s.processPointerDown=s.processPointerDown.bind(s),s.onPointerMove=s.onPointerMove.bind(s),s.processPointerMove=s.processPointerMove.bind(s),s.onPointerOut=s.onPointerOut.bind(s),s.processPointerOverOut=s.processPointerOverOut.bind(s),s.onPointerOver=s.onPointerOver.bind(s),s.cursorStyles={default:\"inherit\",pointer:\"pointer\"},s.currentCursorMode=null,s.cursor=null,s._tempPoint=new h.Point,s.resolution=1,s.setTargetElement(s.renderer.view,s.renderer.resolution),s}return s(e,t),e.prototype.hitTest=function(t,e){return x.target=null,x.data.global=t,e||(e=this.renderer._lastObjectRendered),this.processInteractive(x,e,null,!0),x.target},e.prototype.setTargetElement=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;this.removeEvents(),this.interactionDOMElement=t,this.resolution=e,this.addEvents()},e.prototype.addEvents=function(){this.interactionDOMElement&&(h.ticker.shared.add(this.update,this,h.UPDATE_PRIORITY.INTERACTION),window.navigator.msPointerEnabled?(this.interactionDOMElement.style[\"-ms-content-zooming\"]=\"none\",this.interactionDOMElement.style[\"-ms-touch-action\"]=\"none\"):this.supportsPointerEvents&&(this.interactionDOMElement.style[\"touch-action\"]=\"none\"),this.supportsPointerEvents?(window.document.addEventListener(\"pointermove\",this.onPointerMove,!0),this.interactionDOMElement.addEventListener(\"pointerdown\",this.onPointerDown,!0),this.interactionDOMElement.addEventListener(\"pointerleave\",this.onPointerOut,!0),this.interactionDOMElement.addEventListener(\"pointerover\",this.onPointerOver,!0),window.addEventListener(\"pointercancel\",this.onPointerCancel,!0),window.addEventListener(\"pointerup\",this.onPointerUp,!0)):(window.document.addEventListener(\"mousemove\",this.onPointerMove,!0),this.interactionDOMElement.addEventListener(\"mousedown\",this.onPointerDown,!0),this.interactionDOMElement.addEventListener(\"mouseout\",this.onPointerOut,!0),this.interactionDOMElement.addEventListener(\"mouseover\",this.onPointerOver,!0),window.addEventListener(\"mouseup\",this.onPointerUp,!0)),this.supportsTouchEvents&&(this.interactionDOMElement.addEventListener(\"touchstart\",this.onPointerDown,!0),this.interactionDOMElement.addEventListener(\"touchcancel\",this.onPointerCancel,!0),this.interactionDOMElement.addEventListener(\"touchend\",this.onPointerUp,!0),this.interactionDOMElement.addEventListener(\"touchmove\",this.onPointerMove,!0)),this.eventsAdded=!0)},e.prototype.removeEvents=function(){this.interactionDOMElement&&(h.ticker.shared.remove(this.update,this),window.navigator.msPointerEnabled?(this.interactionDOMElement.style[\"-ms-content-zooming\"]=\"\",this.interactionDOMElement.style[\"-ms-touch-action\"]=\"\"):this.supportsPointerEvents&&(this.interactionDOMElement.style[\"touch-action\"]=\"\"),this.supportsPointerEvents?(window.document.removeEventListener(\"pointermove\",this.onPointerMove,!0),this.interactionDOMElement.removeEventListener(\"pointerdown\",this.onPointerDown,!0),this.interactionDOMElement.removeEventListener(\"pointerleave\",this.onPointerOut,!0),this.interactionDOMElement.removeEventListener(\"pointerover\",this.onPointerOver,!0),window.removeEventListener(\"pointercancel\",this.onPointerCancel,!0),window.removeEventListener(\"pointerup\",this.onPointerUp,!0)):(window.document.removeEventListener(\"mousemove\",this.onPointerMove,!0),this.interactionDOMElement.removeEventListener(\"mousedown\",this.onPointerDown,!0),this.interactionDOMElement.removeEventListener(\"mouseout\",this.onPointerOut,!0),this.interactionDOMElement.removeEventListener(\"mouseover\",this.onPointerOver,!0),window.removeEventListener(\"mouseup\",this.onPointerUp,!0)),this.supportsTouchEvents&&(this.interactionDOMElement.removeEventListener(\"touchstart\",this.onPointerDown,!0),this.interactionDOMElement.removeEventListener(\"touchcancel\",this.onPointerCancel,!0),this.interactionDOMElement.removeEventListener(\"touchend\",this.onPointerUp,!0),this.interactionDOMElement.removeEventListener(\"touchmove\",this.onPointerMove,!0)),this.interactionDOMElement=null,this.eventsAdded=!1)},e.prototype.update=function(t){if(this._deltaTime+=t,!(this._deltaTime<this.interactionFrequency)&&(this._deltaTime=0,this.interactionDOMElement)){if(this.didMove)return void(this.didMove=!1);this.cursor=null;for(var e in this.activeInteractionData)if(this.activeInteractionData.hasOwnProperty(e)){var r=this.activeInteractionData[e];if(r.originalEvent&&\"touch\"!==r.pointerType){var n=this.configureInteractionEventForDOMEvent(this.eventData,r.originalEvent,r);this.processInteractive(n,this.renderer._lastObjectRendered,this.processPointerOverOut,!0)}}this.setCursorMode(this.cursor)}},e.prototype.setCursorMode=function(t){if(t=t||\"default\",this.currentCursorMode!==t){this.currentCursorMode=t;var e=this.cursorStyles[t];if(e)switch(void 0===e?\"undefined\":a(e)){case\"string\":this.interactionDOMElement.style.cursor=e;break;case\"function\":e(t);break;case\"object\":Object.assign(this.interactionDOMElement.style,e)}else\"string\"!=typeof t||Object.prototype.hasOwnProperty.call(this.cursorStyles,t)||(this.interactionDOMElement.style.cursor=t)}},e.prototype.dispatchEvent=function(t,e,r){r.stopped||(r.currentTarget=t,r.type=e,t.emit(e,r),t[e]&&t[e](r))},e.prototype.mapPositionToPoint=function(t,e,r){var n=void 0;n=this.interactionDOMElement.parentElement?this.interactionDOMElement.getBoundingClientRect():{x:0,y:0,width:0,height:0};var i=navigator.isCocoonJS?this.resolution:1/this.resolution;t.x=(e-n.left)*(this.interactionDOMElement.width/n.width)*i,t.y=(r-n.top)*(this.interactionDOMElement.height/n.height)*i},e.prototype.processInteractive=function(t,e,r,n,i){if(!e||!e.visible)return!1;var o=t.data.global;i=e.interactive||i;var s=!1,a=i;if(e.hitArea?a=!1:n&&e._mask&&(e._mask.containsPoint(o)||(n=!1)),e.interactiveChildren&&e.children)for(var u=e.children,h=u.length-1;h>=0;h--){var l=u[h],c=this.processInteractive(t,l,r,n,a);if(c){if(!l.parent)continue;a=!1,c&&(t.target&&(n=!1),s=!0)}}return i&&(n&&!t.target&&(e.hitArea?(e.worldTransform.applyInverse(o,this._tempPoint),e.hitArea.contains(this._tempPoint.x,this._tempPoint.y)&&(s=!0)):e.containsPoint&&e.containsPoint(o)&&(s=!0)),e.interactive&&(s&&!t.target&&(t.target=e),r&&r(t,e,!!s))),s},e.prototype.onPointerDown=function(t){if(!this.supportsTouchEvents||\"touch\"!==t.pointerType){var e=this.normalizeToPointerData(t);this.autoPreventDefault&&e[0].isNormalized&&t.preventDefault();for(var r=e.length,n=0;n<r;n++){var i=e[n],o=this.getInteractionDataForPointerId(i),s=this.configureInteractionEventForDOMEvent(this.eventData,i,o);if(s.data.originalEvent=t,this.processInteractive(s,this.renderer._lastObjectRendered,this.processPointerDown,!0),this.emit(\"pointerdown\",s),\"touch\"===i.pointerType)this.emit(\"touchstart\",s);else if(\"mouse\"===i.pointerType||\"pen\"===i.pointerType){var a=2===i.button;this.emit(a?\"rightdown\":\"mousedown\",this.eventData)}}}},e.prototype.processPointerDown=function(t,e,r){var n=t.data,i=t.data.identifier;if(r)if(e.trackedPointers[i]||(e.trackedPointers[i]=new v.default(i)),this.dispatchEvent(e,\"pointerdown\",t),\"touch\"===n.pointerType)this.dispatchEvent(e,\"touchstart\",t);else if(\"mouse\"===n.pointerType||\"pen\"===n.pointerType){var o=2===n.button;o?e.trackedPointers[i].rightDown=!0:e.trackedPointers[i].leftDown=!0,this.dispatchEvent(e,o?\"rightdown\":\"mousedown\",t)}},e.prototype.onPointerComplete=function(t,e,r){for(var n=this.normalizeToPointerData(t),i=n.length,o=t.target!==this.interactionDOMElement?\"outside\":\"\",s=0;s<i;s++){var a=n[s],u=this.getInteractionDataForPointerId(a),h=this.configureInteractionEventForDOMEvent(this.eventData,a,u);if(h.data.originalEvent=t,this.processInteractive(h,this.renderer._lastObjectRendered,r,e||!o),this.emit(e?\"pointercancel\":\"pointerup\"+o,h),\"mouse\"===a.pointerType||\"pen\"===a.pointerType){var l=2===a.button;this.emit(l?\"rightup\"+o:\"mouseup\"+o,h)}else\"touch\"===a.pointerType&&(this.emit(e?\"touchcancel\":\"touchend\"+o,h),this.releaseInteractionDataForPointerId(a.pointerId,u))}},e.prototype.onPointerCancel=function(t){this.supportsTouchEvents&&\"touch\"===t.pointerType||this.onPointerComplete(t,!0,this.processPointerCancel)},e.prototype.processPointerCancel=function(t,e){var r=t.data,n=t.data.identifier;void 0!==e.trackedPointers[n]&&(delete e.trackedPointers[n],this.dispatchEvent(e,\"pointercancel\",t),\"touch\"===r.pointerType&&this.dispatchEvent(e,\"touchcancel\",t))},e.prototype.onPointerUp=function(t){this.supportsTouchEvents&&\"touch\"===t.pointerType||this.onPointerComplete(t,!1,this.processPointerUp)},e.prototype.processPointerUp=function(t,e,r){var n=t.data,i=t.data.identifier,o=e.trackedPointers[i],s=\"touch\"===n.pointerType;if(\"mouse\"===n.pointerType||\"pen\"===n.pointerType){var a=2===n.button,u=v.default.FLAGS,h=a?u.RIGHT_DOWN:u.LEFT_DOWN,l=void 0!==o&&o.flags&h;r?(this.dispatchEvent(e,a?\"rightup\":\"mouseup\",t),l&&this.dispatchEvent(e,a?\"rightclick\":\"click\",t)):l&&this.dispatchEvent(e,a?\"rightupoutside\":\"mouseupoutside\",t),o&&(a?o.rightDown=!1:o.leftDown=!1)}r?(this.dispatchEvent(e,\"pointerup\",t),s&&this.dispatchEvent(e,\"touchend\",t),o&&(this.dispatchEvent(e,\"pointertap\",t),s&&(this.dispatchEvent(e,\"tap\",t),o.over=!1))):o&&(this.dispatchEvent(e,\"pointerupoutside\",t),s&&this.dispatchEvent(e,\"touchendoutside\",t)),o&&o.none&&delete e.trackedPointers[i]},e.prototype.onPointerMove=function(t){if(!this.supportsTouchEvents||\"touch\"!==t.pointerType){var e=this.normalizeToPointerData(t);\"mouse\"===e[0].pointerType&&(this.didMove=!0,this.cursor=null);for(var r=e.length,n=0;n<r;n++){var i=e[n],o=this.getInteractionDataForPointerId(i),s=this.configureInteractionEventForDOMEvent(this.eventData,i,o);s.data.originalEvent=t;var a=\"touch\"!==i.pointerType||this.moveWhenInside;this.processInteractive(s,this.renderer._lastObjectRendered,this.processPointerMove,a),this.emit(\"pointermove\",s),\"touch\"===i.pointerType&&this.emit(\"touchmove\",s),\"mouse\"!==i.pointerType&&\"pen\"!==i.pointerType||this.emit(\"mousemove\",s)}\"mouse\"===e[0].pointerType&&this.setCursorMode(this.cursor)}},e.prototype.processPointerMove=function(t,e,r){var n=t.data,i=\"touch\"===n.pointerType,o=\"mouse\"===n.pointerType||\"pen\"===n.pointerType;o&&this.processPointerOverOut(t,e,r),this.moveWhenInside&&!r||(this.dispatchEvent(e,\"pointermove\",t),i&&this.dispatchEvent(e,\"touchmove\",t),o&&this.dispatchEvent(e,\"mousemove\",t))},e.prototype.onPointerOut=function(t){if(!this.supportsTouchEvents||\"touch\"!==t.pointerType){var e=this.normalizeToPointerData(t),r=e[0];\"mouse\"===r.pointerType&&(this.mouseOverRenderer=!1,this.setCursorMode(null));var n=this.getInteractionDataForPointerId(r),i=this.configureInteractionEventForDOMEvent(this.eventData,r,n);i.data.originalEvent=r,this.processInteractive(i,this.renderer._lastObjectRendered,this.processPointerOverOut,!1),this.emit(\"pointerout\",i),\"mouse\"===r.pointerType||\"pen\"===r.pointerType?this.emit(\"mouseout\",i):this.releaseInteractionDataForPointerId(n.identifier)}},e.prototype.processPointerOverOut=function(t,e,r){var n=t.data,i=t.data.identifier,o=\"mouse\"===n.pointerType||\"pen\"===n.pointerType,s=e.trackedPointers[i];r&&!s&&(s=e.trackedPointers[i]=new v.default(i)),void 0!==s&&(r&&this.mouseOverRenderer?(s.over||(s.over=!0,this.dispatchEvent(e,\"pointerover\",t),o&&this.dispatchEvent(e,\"mouseover\",t)),o&&null===this.cursor&&(this.cursor=e.cursor)):s.over&&(s.over=!1,this.dispatchEvent(e,\"pointerout\",this.eventData),o&&this.dispatchEvent(e,\"mouseout\",t),s.none&&delete e.trackedPointers[i]))},e.prototype.onPointerOver=function(t){var e=this.normalizeToPointerData(t),r=e[0],n=this.getInteractionDataForPointerId(r),i=this.configureInteractionEventForDOMEvent(this.eventData,r,n);i.data.originalEvent=r,\"mouse\"===r.pointerType&&(this.mouseOverRenderer=!0),this.emit(\"pointerover\",i),\"mouse\"!==r.pointerType&&\"pen\"!==r.pointerType||this.emit(\"mouseover\",i)},e.prototype.getInteractionDataForPointerId=function(t){var e=t.pointerId,r=void 0;return e===b||\"mouse\"===t.pointerType?r=this.mouse:this.activeInteractionData[e]?r=this.activeInteractionData[e]:(r=this.interactionDataPool.pop()||new c.default,r.identifier=e,this.activeInteractionData[e]=r),r._copyEvent(t),r},e.prototype.releaseInteractionDataForPointerId=function(t){var e=this.activeInteractionData[t];e&&(delete this.activeInteractionData[t],e._reset(),this.interactionDataPool.push(e))},e.prototype.configureInteractionEventForDOMEvent=function(t,e,r){return t.data=r,this.mapPositionToPoint(r.global,e.clientX,e.clientY),navigator.isCocoonJS&&\"touch\"===e.pointerType&&(r.global.x=r.global.x/this.resolution,r.global.y=r.global.y/this.resolution),\"touch\"===e.pointerType&&(e.globalX=r.global.x,e.globalY=r.global.y),r.originalEvent=e,t._reset(),t},e.prototype.normalizeToPointerData=function(t){var e=[];if(this.supportsTouchEvents&&t instanceof TouchEvent)for(var r=0,n=t.changedTouches.length;r<n;r++){var i=t.changedTouches[r];void 0===i.button&&(i.button=t.touches.length?1:0),void 0===i.buttons&&(i.buttons=t.touches.length?1:0),void 0===i.isPrimary&&(i.isPrimary=1===t.touches.length&&\"touchstart\"===t.type),void 0===i.width&&(i.width=i.radiusX||1),void 0===i.height&&(i.height=i.radiusY||1),void 0===i.tiltX&&(i.tiltX=0),void 0===i.tiltY&&(i.tiltY=0),void 0===i.pointerType&&(i.pointerType=\"touch\"),void 0===i.pointerId&&(i.pointerId=i.identifier||0),void 0===i.pressure&&(i.pressure=i.force||.5),i.twist=0,i.tangentialPressure=0,void 0===i.layerX&&(i.layerX=i.offsetX=i.clientX),void 0===i.layerY&&(i.layerY=i.offsetY=i.clientY),i.isNormalized=!0,e.push(i)}else!(t instanceof MouseEvent)||this.supportsPointerEvents&&t instanceof window.PointerEvent?e.push(t):(void 0===t.isPrimary&&(t.isPrimary=!0),void 0===t.width&&(t.width=1),void 0===t.height&&(t.height=1),void 0===t.tiltX&&(t.tiltX=0),void 0===t.tiltY&&(t.tiltY=0),void 0===t.pointerType&&(t.pointerType=\"mouse\"),void 0===t.pointerId&&(t.pointerId=b),void 0===t.pressure&&(t.pressure=.5),t.twist=0,t.tangentialPressure=0,t.isNormalized=!0,e.push(t));return e},e.prototype.destroy=function(){this.removeEvents(),this.removeAllListeners(),this.renderer=null,this.mouse=null,this.eventData=null,this.interactionDOMElement=null,this.onPointerDown=null,this.processPointerDown=null,this.onPointerUp=null,this.processPointerUp=null,this.onPointerCancel=null,this.processPointerCancel=null,this.onPointerMove=null,this.processPointerMove=null,this.onPointerOut=null,this.processPointerOverOut=null,this.onPointerOver=null,this._tempPoint=null},e}(g.default);r.default=T,h.WebGLRenderer.registerPlugin(\"interaction\",T),h.CanvasRenderer.registerPlugin(\"interaction\",T)},{\"../core\":65,\"./InteractionData\":155,\"./InteractionEvent\":156,\"./InteractionTrackingData\":158,\"./interactiveTarget\":160,eventemitter3:3}],158:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),o=function(){function t(e){n(this,t),this._pointerId=e,this._flags=t.FLAGS.NONE}return t.prototype._doSet=function(t,e){this._flags=e?this._flags|t:this._flags&~t},i(t,[{key:\"pointerId\",get:function(){return this._pointerId}},{key:\"flags\",get:function(){return this._flags},set:function(t){this._flags=t}},{key:\"none\",get:function(){return this._flags===this.constructor.FLAGS.NONE}},{key:\"over\",get:function(){return 0!=(this._flags&this.constructor.FLAGS.OVER)},set:function(t){this._doSet(this.constructor.FLAGS.OVER,t)}},{key:\"rightDown\",get:function(){return 0!=(this._flags&this.constructor.FLAGS.RIGHT_DOWN)},set:function(t){this._doSet(this.constructor.FLAGS.RIGHT_DOWN,t)}},{key:\"leftDown\",get:function(){return 0!=(this._flags&this.constructor.FLAGS.LEFT_DOWN)},set:function(t){this._doSet(this.constructor.FLAGS.LEFT_DOWN,t)}}]),t}();r.default=o,o.FLAGS=Object.freeze({NONE:0,OVER:1,LEFT_DOWN:2,RIGHT_DOWN:4})},{}],159:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0;var i=t(\"./InteractionData\");Object.defineProperty(r,\"InteractionData\",{enumerable:!0,get:function(){return n(i).default}});var o=t(\"./InteractionManager\");Object.defineProperty(r,\"InteractionManager\",{enumerable:!0,get:function(){return n(o).default}});var s=t(\"./interactiveTarget\");Object.defineProperty(r,\"interactiveTarget\",{enumerable:!0,get:function(){return n(s).default}});var a=t(\"./InteractionTrackingData\");Object.defineProperty(r,\"InteractionTrackingData\",{enumerable:!0,get:function(){return n(a).default}});var u=t(\"./InteractionEvent\");Object.defineProperty(r,\"InteractionEvent\",{enumerable:!0,get:function(){return n(u).default}})},{\"./InteractionData\":155,\"./InteractionEvent\":156,\"./InteractionManager\":157,\"./InteractionTrackingData\":158,\"./interactiveTarget\":160}],160:[function(t,e,r){\"use strict\";r.__esModule=!0,r.default={interactive:!1,interactiveChildren:!0,hitArea:null,get buttonMode(){return\"pointer\"===this.cursor},set buttonMode(t){t?this.cursor=\"pointer\":\"pointer\"===this.cursor&&(this.cursor=null)},cursor:null,get trackedPointers(){return void 0===this._trackedPointers&&(this._trackedPointers={}),this._trackedPointers},_trackedPointers:void 0}},{}],161:[function(t,e,r){\"use strict\";function n(t,e){t.bitmapFont=u.BitmapText.registerFont(t.data,e)}r.__esModule=!0,r.parse=n,r.default=function(){return function(t,e){if(!t.data||t.type!==a.Resource.TYPE.XML)return void e();if(0===t.data.getElementsByTagName(\"page\").length||0===t.data.getElementsByTagName(\"info\").length||null===t.data.getElementsByTagName(\"info\")[0].getAttribute(\"face\"))return void e();var r=t.isDataUrl?\"\":o.dirname(t.url);t.isDataUrl&&(\".\"===r&&(r=\"\"),this.baseUrl&&r&&\"/\"===this.baseUrl.charAt(this.baseUrl.length-1)&&(r+=\"/\")),(r=r.replace(this.baseUrl,\"\"))&&\"/\"!==r.charAt(r.length-1)&&(r+=\"/\");var i=r+t.data.getElementsByTagName(\"page\")[0].getAttribute(\"file\");if(s.utils.TextureCache[i])n(t,s.utils.TextureCache[i]),e();else{var u={crossOrigin:t.crossOrigin,loadType:a.Resource.LOAD_TYPE.IMAGE,metadata:t.metadata.imageMetadata,parentResource:t};this.add(t.name+\"_image\",i,u,function(r){n(t,r.texture),e()})}}};var i=t(\"path\"),o=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(i),s=t(\"../core\"),a=t(\"resource-loader\"),u=t(\"../extras\")},{\"../core\":65,\"../extras\":141,path:23,\"resource-loader\":36}],162:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0,r.shared=r.Resource=r.textureParser=r.getResourcePath=r.spritesheetParser=r.parseBitmapFontData=r.bitmapFontParser=r.Loader=void 0;var i=t(\"./bitmapFontParser\");Object.defineProperty(r,\"bitmapFontParser\",{enumerable:!0,get:function(){return n(i).default}}),Object.defineProperty(r,\"parseBitmapFontData\",{enumerable:!0,get:function(){return i.parse}});var o=t(\"./spritesheetParser\");Object.defineProperty(r,\"spritesheetParser\",{enumerable:!0,get:function(){return n(o).default}}),Object.defineProperty(r,\"getResourcePath\",{enumerable:!0,get:function(){return o.getResourcePath}});var s=t(\"./textureParser\");Object.defineProperty(r,\"textureParser\",{enumerable:!0,get:function(){return n(s).default}});var a=t(\"resource-loader\");Object.defineProperty(r,\"Resource\",{enumerable:!0,get:function(){return a.Resource}});var u=t(\"../core/Application\"),h=n(u),l=t(\"./loader\"),c=n(l);r.Loader=c.default;var d=new c.default;d.destroy=function(){},r.shared=d;var f=h.default.prototype;f._loader=null,Object.defineProperty(f,\"loader\",{get:function(){if(!this._loader){var t=this._options.sharedLoader;this._loader=t?d:new c.default}return this._loader}}),f._parentDestroy=f.destroy,f.destroy=function(t){this._loader&&(this._loader.destroy(),this._loader=null),this._parentDestroy(t)}},{\"../core/Application\":43,\"./bitmapFontParser\":161,\"./loader\":163,\"./spritesheetParser\":164,\"./textureParser\":165,\"resource-loader\":36}],163:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"resource-loader\"),u=n(a),h=t(\"resource-loader/lib/middlewares/parsing/blob\"),l=t(\"eventemitter3\"),c=n(l),d=t(\"./textureParser\"),f=n(d),p=t(\"./spritesheetParser\"),v=n(p),y=t(\"./bitmapFontParser\"),g=n(y),m=function(t){function e(r,n){i(this,e);var s=o(this,t.call(this,r,n));c.default.call(s);for(var a=0;a<e._pixiMiddleware.length;++a)s.use(e._pixiMiddleware[a]());return s.onStart.add(function(t){return s.emit(\"start\",t)}),s.onProgress.add(function(t,e){return s.emit(\"progress\",t,e)}),s.onError.add(function(t,e,r){return s.emit(\"error\",t,e,r)}),s.onLoad.add(function(t,e){return s.emit(\"load\",t,e)}),s.onComplete.add(function(t,e){return s.emit(\"complete\",t,e)}),s}return s(e,t),e.addPixiMiddleware=function(t){e._pixiMiddleware.push(t)},e.prototype.destroy=function(){this.removeAllListeners(),this.reset()},e}(u.default);r.default=m;for(var _ in c.default.prototype)m.prototype[_]=c.default.prototype[_];m._pixiMiddleware=[h.blobMiddlewareFactory,f.default,v.default,g.default];var b=u.default.Resource;b.setExtensionXhrType(\"fnt\",b.XHR_RESPONSE_TYPE.DOCUMENT)},{\"./bitmapFontParser\":161,\"./spritesheetParser\":164,\"./textureParser\":165,eventemitter3:3,\"resource-loader\":36,\"resource-loader/lib/middlewares/parsing/blob\":37}],164:[function(t,e,r){\"use strict\";function n(t,e){return t.isDataUrl?t.data.meta.image:s.default.resolve(t.url.replace(e,\"\"),t.data.meta.image)}r.__esModule=!0,r.default=function(){return function(t,e){var r=t.name+\"_image\";if(!t.data||t.type!==i.Resource.TYPE.JSON||!t.data.frames||this.resources[r])return void e();var o={crossOrigin:t.crossOrigin,loadType:i.Resource.LOAD_TYPE.IMAGE,metadata:t.metadata.imageMetadata,parentResource:t},s=n(t,this.baseUrl);this.add(r,s,o,function(r){var n=new a.Spritesheet(r.texture.baseTexture,t.data,t.url);n.parse(function(){t.spritesheet=n,t.textures=n.textures,e()})})}},r.getResourcePath=n;var i=t(\"resource-loader\"),o=t(\"url\"),s=function(t){return t&&t.__esModule?t:{default:t}}(o),a=t(\"../core\")},{\"../core\":65,\"resource-loader\":36,url:29}],165:[function(t,e,r){\"use strict\";r.__esModule=!0,r.default=function(){return function(t,e){t.data&&t.type===n.Resource.TYPE.IMAGE&&(t.texture=o.default.fromLoader(t.data,t.url,t.name)),e()}};var n=t(\"resource-loader\"),i=t(\"../core/textures/Texture\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i)},{\"../core/textures/Texture\":115,\"resource-loader\":36}],166:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"../core\"),u=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(a),h=t(\"../core/textures/Texture\"),l=function(t){return t&&t.__esModule?t:{default:t}}(h),c=new u.Point,d=new u.Polygon,f=function(t){function e(r,o,s,a,h){n(this,e);var c=i(this,t.call(this));return c._texture=r||l.default.EMPTY,c.uvs=s||new Float32Array([0,0,1,0,1,1,0,1]),c.vertices=o||new Float32Array([0,0,100,0,100,100,0,100]),c.indices=a||new Uint16Array([0,1,3,2]),c.dirty=0,c.indexDirty=0,c.blendMode=u.BLEND_MODES.NORMAL,c.canvasPadding=0,c.drawMode=h||e.DRAW_MODES.TRIANGLE_MESH,c.shader=null,c.tintRgb=new Float32Array([1,1,1]),c._glDatas={},c._uvTransform=new u.TextureMatrix(c._texture),c.uploadUvTransform=!1,c.pluginName=\"mesh\",c}return o(e,t),e.prototype._renderWebGL=function(t){this.refresh(),t.setObjectRenderer(t.plugins[this.pluginName]),t.plugins[this.pluginName].render(this)},e.prototype._renderCanvas=function(t){this.refresh(),t.plugins[this.pluginName].render(this)},e.prototype._onTextureUpdate=function(){this._uvTransform.texture=this._texture,this.refresh()},e.prototype.multiplyUvs=function(){this.uploadUvTransform||this._uvTransform.multiplyUvs(this.uvs)},e.prototype.refresh=function(t){this._uvTransform.update(t)&&this._refresh()},e.prototype._refresh=function(){},e.prototype._calculateBounds=function(){this._bounds.addVertices(this.transform,this.vertices,0,this.vertices.length)},e.prototype.containsPoint=function(t){if(!this.getBounds().contains(t.x,t.y))return!1;this.worldTransform.applyInverse(t,c)\n;for(var r=this.vertices,n=d.points,i=this.indices,o=this.indices.length,s=this.drawMode===e.DRAW_MODES.TRIANGLES?3:1,a=0;a+2<o;a+=s){var u=2*i[a],h=2*i[a+1],l=2*i[a+2];if(n[0]=r[u],n[1]=r[u+1],n[2]=r[h],n[3]=r[h+1],n[4]=r[l],n[5]=r[l+1],d.contains(c.x,c.y))return!0}return!1},s(e,[{key:\"texture\",get:function(){return this._texture},set:function(t){this._texture!==t&&(this._texture=t,t&&(t.baseTexture.hasLoaded?this._onTextureUpdate():t.once(\"update\",this._onTextureUpdate,this)))}},{key:\"tint\",get:function(){return u.utils.rgb2hex(this.tintRgb)},set:function(t){this.tintRgb=u.utils.hex2rgb(t,this.tintRgb)}}]),e}(u.Container);r.default=f,f.DRAW_MODES={TRIANGLE_MESH:0,TRIANGLES:1}},{\"../core\":65,\"../core/textures/Texture\":115}],167:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"./Plane\"),u=function(t){return t&&t.__esModule?t:{default:t}}(a),h=10,l=function(t){function e(r,o,s,a,u){n(this,e);var l=i(this,t.call(this,r,4,4));return l._origWidth=r.orig.width,l._origHeight=r.orig.height,l._width=l._origWidth,l._height=l._origHeight,l.leftWidth=void 0!==o?o:h,l.rightWidth=void 0!==a?a:h,l.topHeight=void 0!==s?s:h,l.bottomHeight=void 0!==u?u:h,l.refresh(!0),l}return o(e,t),e.prototype.updateHorizontalVertices=function(){var t=this.vertices;t[9]=t[11]=t[13]=t[15]=this._topHeight,t[17]=t[19]=t[21]=t[23]=this._height-this._bottomHeight,t[25]=t[27]=t[29]=t[31]=this._height},e.prototype.updateVerticalVertices=function(){var t=this.vertices;t[2]=t[10]=t[18]=t[26]=this._leftWidth,t[4]=t[12]=t[20]=t[28]=this._width-this._rightWidth,t[6]=t[14]=t[22]=t[30]=this._width},e.prototype._renderCanvas=function(t){var e=t.context;e.globalAlpha=this.worldAlpha;var r=this.worldTransform,n=t.resolution;t.roundPixels?e.setTransform(r.a*n,r.b*n,r.c*n,r.d*n,r.tx*n|0,r.ty*n|0):e.setTransform(r.a*n,r.b*n,r.c*n,r.d*n,r.tx*n,r.ty*n);var i=this._texture.baseTexture,o=i.source,s=i.width*i.resolution,a=i.height*i.resolution;this.drawSegment(e,o,s,a,0,1,10,11),this.drawSegment(e,o,s,a,2,3,12,13),this.drawSegment(e,o,s,a,4,5,14,15),this.drawSegment(e,o,s,a,8,9,18,19),this.drawSegment(e,o,s,a,10,11,20,21),this.drawSegment(e,o,s,a,12,13,22,23),this.drawSegment(e,o,s,a,16,17,26,27),this.drawSegment(e,o,s,a,18,19,28,29),this.drawSegment(e,o,s,a,20,21,30,31)},e.prototype.drawSegment=function(t,e,r,n,i,o,s,a){var u=this.uvs,h=this.vertices,l=(u[s]-u[i])*r,c=(u[a]-u[o])*n,d=h[s]-h[i],f=h[a]-h[o];l<1&&(l=1),c<1&&(c=1),d<1&&(d=1),f<1&&(f=1),t.drawImage(e,u[i]*r,u[o]*n,l,c,h[i],h[o],d,f)},e.prototype._refresh=function(){t.prototype._refresh.call(this);var e=this.uvs,r=this._texture;this._origWidth=r.orig.width,this._origHeight=r.orig.height;var n=1/this._origWidth,i=1/this._origHeight;e[0]=e[8]=e[16]=e[24]=0,e[1]=e[3]=e[5]=e[7]=0,e[6]=e[14]=e[22]=e[30]=1,e[25]=e[27]=e[29]=e[31]=1,e[2]=e[10]=e[18]=e[26]=n*this._leftWidth,e[4]=e[12]=e[20]=e[28]=1-n*this._rightWidth,e[9]=e[11]=e[13]=e[15]=i*this._topHeight,e[17]=e[19]=e[21]=e[23]=1-i*this._bottomHeight,this.updateHorizontalVertices(),this.updateVerticalVertices(),this.dirty++,this.multiplyUvs()},s(e,[{key:\"width\",get:function(){return this._width},set:function(t){this._width=t,this._refresh()}},{key:\"height\",get:function(){return this._height},set:function(t){this._height=t,this._refresh()}},{key:\"leftWidth\",get:function(){return this._leftWidth},set:function(t){this._leftWidth=t,this._refresh()}},{key:\"rightWidth\",get:function(){return this._rightWidth},set:function(t){this._rightWidth=t,this._refresh()}},{key:\"topHeight\",get:function(){return this._topHeight},set:function(t){this._topHeight=t,this._refresh()}},{key:\"bottomHeight\",get:function(){return this._bottomHeight},set:function(t){this._bottomHeight=t,this._refresh()}}]),e}(u.default);r.default=l},{\"./Plane\":168}],168:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=t(\"./Mesh\"),a=function(t){return t&&t.__esModule?t:{default:t}}(s),u=function(t){function e(r,o,s){n(this,e);var u=i(this,t.call(this,r));return u._ready=!0,u.verticesX=o||10,u.verticesY=s||10,u.drawMode=a.default.DRAW_MODES.TRIANGLES,u.refresh(),u}return o(e,t),e.prototype._refresh=function(){for(var t=this._texture,e=this.verticesX*this.verticesY,r=[],n=[],i=[],o=[],s=this.verticesX-1,a=this.verticesY-1,u=t.width/s,h=t.height/a,l=0;l<e;l++){var c=l%this.verticesX,d=l/this.verticesX|0;r.push(c*u,d*h),i.push(c/s,d/a)}for(var f=s*a,p=0;p<f;p++){var v=p%s,y=p/s|0,g=y*this.verticesX+v,m=y*this.verticesX+v+1,_=(y+1)*this.verticesX+v,b=(y+1)*this.verticesX+v+1;o.push(g,m,_),o.push(m,b,_)}this.vertices=new Float32Array(r),this.uvs=new Float32Array(i),this.colors=new Float32Array(n),this.indices=new Uint16Array(o),this.dirty++,this.indexDirty++,this.multiplyUvs()},e.prototype._onTextureUpdate=function(){a.default.prototype._onTextureUpdate.call(this),this._ready&&this.refresh()},e}(a.default);r.default=u},{\"./Mesh\":166}],169:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=t(\"./Mesh\"),a=function(t){return t&&t.__esModule?t:{default:t}}(s),u=function(t){function e(r,o){n(this,e);var s=i(this,t.call(this,r));return s.points=o,s.vertices=new Float32Array(4*o.length),s.uvs=new Float32Array(4*o.length),s.colors=new Float32Array(2*o.length),s.indices=new Uint16Array(2*o.length),s.autoUpdate=!0,s.refresh(),s}return o(e,t),e.prototype._refresh=function(){var t=this.points;if(!(t.length<1)&&this._texture._uvs){this.vertices.length/4!==t.length&&(this.vertices=new Float32Array(4*t.length),this.uvs=new Float32Array(4*t.length),this.colors=new Float32Array(2*t.length),this.indices=new Uint16Array(2*t.length));var e=this.uvs,r=this.indices,n=this.colors;e[0]=0,e[1]=0,e[2]=0,e[3]=1,n[0]=1,n[1]=1,r[0]=0,r[1]=1;for(var i=t.length,o=1;o<i;o++){var s=4*o,a=o/(i-1);e[s]=a,e[s+1]=0,e[s+2]=a,e[s+3]=1,s=2*o,n[s]=1,n[s+1]=1,s=2*o,r[s]=s,r[s+1]=s+1}this.dirty++,this.indexDirty++,this.multiplyUvs(),this.refreshVertices()}},e.prototype.refreshVertices=function(){var t=this.points;if(!(t.length<1))for(var e=t[0],r=void 0,n=0,i=0,o=this.vertices,s=t.length,a=0;a<s;a++){var u=t[a],h=4*a;r=a<t.length-1?t[a+1]:u,i=-(r.x-e.x),n=r.y-e.y;var l=10*(1-a/(s-1));l>1&&(l=1);var c=Math.sqrt(n*n+i*i),d=this._texture.height/2;n/=c,i/=c,n*=d,i*=d,o[h]=u.x+n,o[h+1]=u.y+i,o[h+2]=u.x-n,o[h+3]=u.y-i,e=u}},e.prototype.updateTransform=function(){this.autoUpdate&&this.refreshVertices(),this.containerUpdateTransform()},e}(a.default);r.default=u},{\"./Mesh\":166}],170:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../../core\"),o=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(i),s=t(\"../Mesh\"),a=function(t){return t&&t.__esModule?t:{default:t}}(s),u=function(){function t(e){n(this,t),this.renderer=e}return t.prototype.render=function(t){var e=this.renderer,r=e.context,n=t.worldTransform,i=e.resolution;e.roundPixels?r.setTransform(n.a*i,n.b*i,n.c*i,n.d*i,n.tx*i|0,n.ty*i|0):r.setTransform(n.a*i,n.b*i,n.c*i,n.d*i,n.tx*i,n.ty*i),e.setBlendMode(t.blendMode),t.drawMode===a.default.DRAW_MODES.TRIANGLE_MESH?this._renderTriangleMesh(t):this._renderTriangles(t)},t.prototype._renderTriangleMesh=function(t){for(var e=t.vertices.length/2,r=0;r<e-2;r++){var n=2*r;this._renderDrawTriangle(t,n,n+2,n+4)}},t.prototype._renderTriangles=function(t){for(var e=t.indices,r=e.length,n=0;n<r;n+=3){var i=2*e[n],o=2*e[n+1],s=2*e[n+2];this._renderDrawTriangle(t,i,o,s)}},t.prototype._renderDrawTriangle=function(t,e,r,n){var i=this.renderer.context,o=t.uvs,s=t.vertices,a=t._texture;if(a.valid){var u=a.baseTexture,h=u.source,l=u.width,c=u.height,d=void 0,f=void 0,p=void 0,v=void 0,y=void 0,g=void 0;if(t.uploadUvTransform){var m=t._uvTransform.mapCoord;d=(o[e]*m.a+o[e+1]*m.c+m.tx)*u.width,f=(o[r]*m.a+o[r+1]*m.c+m.tx)*u.width,p=(o[n]*m.a+o[n+1]*m.c+m.tx)*u.width,v=(o[e]*m.b+o[e+1]*m.d+m.ty)*u.height,y=(o[r]*m.b+o[r+1]*m.d+m.ty)*u.height,g=(o[n]*m.b+o[n+1]*m.d+m.ty)*u.height}else d=o[e]*u.width,f=o[r]*u.width,p=o[n]*u.width,v=o[e+1]*u.height,y=o[r+1]*u.height,g=o[n+1]*u.height;var _=s[e],b=s[r],x=s[n],T=s[e+1],w=s[r+1],E=s[n+1];if(t.canvasPadding>0){var S=t.canvasPadding/t.worldTransform.a,O=t.canvasPadding/t.worldTransform.d,M=(_+b+x)/3,P=(T+w+E)/3,C=_-M,R=T-P,A=Math.sqrt(C*C+R*R);_=M+C/A*(A+S),T=P+R/A*(A+O),C=b-M,R=w-P,A=Math.sqrt(C*C+R*R),b=M+C/A*(A+S),w=P+R/A*(A+O),C=x-M,R=E-P,A=Math.sqrt(C*C+R*R),x=M+C/A*(A+S),E=P+R/A*(A+O)}i.save(),i.beginPath(),i.moveTo(_,T),i.lineTo(b,w),i.lineTo(x,E),i.closePath(),i.clip();var I=d*y+v*p+f*g-y*p-v*f-d*g,D=_*y+v*x+b*g-y*x-v*b-_*g,L=d*b+_*p+f*x-b*p-_*f-d*x,N=d*y*x+v*b*p+_*f*g-_*y*p-v*f*x-d*b*g,F=T*y+v*E+w*g-y*E-v*w-T*g,B=d*w+T*p+f*E-w*p-T*f-d*E,k=d*y*E+v*w*p+T*f*g-T*y*p-v*f*E-d*w*g;i.transform(D/I,F/I,L/I,B/I,N/I,k/I),i.drawImage(h,0,0,l*u.resolution,c*u.resolution,0,0,l,c),i.restore(),this.renderer.invalidateBlendMode()}},t.prototype.renderMeshFlat=function(t){var e=this.renderer.context,r=t.vertices,n=r.length/2;e.beginPath();for(var i=1;i<n-2;++i){var o=2*i,s=r[o],a=r[o+1],u=r[o+2],h=r[o+3],l=r[o+4],c=r[o+5];e.moveTo(s,a),e.lineTo(u,h),e.lineTo(l,c)}e.fillStyle=\"#FF0000\",e.fill(),e.closePath()},t.prototype.destroy=function(){this.renderer=null},t}();r.default=u,o.CanvasRenderer.registerPlugin(\"mesh\",u)},{\"../../core\":65,\"../Mesh\":166}],171:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0;var i=t(\"./Mesh\");Object.defineProperty(r,\"Mesh\",{enumerable:!0,get:function(){return n(i).default}});var o=t(\"./webgl/MeshRenderer\");Object.defineProperty(r,\"MeshRenderer\",{enumerable:!0,get:function(){return n(o).default}});var s=t(\"./canvas/CanvasMeshRenderer\");Object.defineProperty(r,\"CanvasMeshRenderer\",{enumerable:!0,get:function(){return n(s).default}});var a=t(\"./Plane\");Object.defineProperty(r,\"Plane\",{enumerable:!0,get:function(){return n(a).default}});var u=t(\"./NineSlicePlane\");Object.defineProperty(r,\"NineSlicePlane\",{enumerable:!0,get:function(){return n(u).default}});var h=t(\"./Rope\");Object.defineProperty(r,\"Rope\",{enumerable:!0,get:function(){return n(h).default}})},{\"./Mesh\":166,\"./NineSlicePlane\":167,\"./Plane\":168,\"./Rope\":169,\"./canvas/CanvasMeshRenderer\":170,\"./webgl/MeshRenderer\":172}],172:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"../../core\"),u=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(a),h=t(\"pixi-gl-core\"),l=n(h),c=t(\"../Mesh\"),d=n(c),f=(t(\"path\"),u.Matrix.IDENTITY),p=function(t){function e(r){i(this,e);var n=o(this,t.call(this,r));return n.shader=null,n}return s(e,t),e.prototype.onContextChange=function(){var t=this.renderer.gl;this.shader=new u.Shader(t,\"attribute vec2 aVertexPosition;\\nattribute vec2 aTextureCoord;\\n\\nuniform mat3 projectionMatrix;\\nuniform mat3 translationMatrix;\\nuniform mat3 uTransform;\\n\\nvarying vec2 vTextureCoord;\\n\\nvoid main(void)\\n{\\n    gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\\n\\n    vTextureCoord = (uTransform * vec3(aTextureCoord, 1.0)).xy;\\n}\\n\",\"varying vec2 vTextureCoord;\\nuniform vec4 uColor;\\n\\nuniform sampler2D uSampler;\\n\\nvoid main(void)\\n{\\n    gl_FragColor = texture2D(uSampler, vTextureCoord) * uColor;\\n}\\n\")},e.prototype.render=function(t){var e=this.renderer,r=e.gl,n=t._texture;if(n.valid){var i=t._glDatas[e.CONTEXT_UID];i||(e.bindVao(null),i={shader:this.shader,vertexBuffer:l.default.GLBuffer.createVertexBuffer(r,t.vertices,r.STREAM_DRAW),uvBuffer:l.default.GLBuffer.createVertexBuffer(r,t.uvs,r.STREAM_DRAW),indexBuffer:l.default.GLBuffer.createIndexBuffer(r,t.indices,r.STATIC_DRAW),vao:null,dirty:t.dirty,indexDirty:t.indexDirty},i.vao=new l.default.VertexArrayObject(r).addIndex(i.indexBuffer).addAttribute(i.vertexBuffer,i.shader.attributes.aVertexPosition,r.FLOAT,!1,8,0).addAttribute(i.uvBuffer,i.shader.attributes.aTextureCoord,r.FLOAT,!1,8,0),t._glDatas[e.CONTEXT_UID]=i),e.bindVao(i.vao),t.dirty!==i.dirty&&(i.dirty=t.dirty,i.uvBuffer.upload(t.uvs)),t.indexDirty!==i.indexDirty&&(i.indexDirty=t.indexDirty,i.indexBuffer.upload(t.indices)),i.vertexBuffer.upload(t.vertices),e.bindShader(i.shader),i.shader.uniforms.uSampler=e.bindTexture(n),e.state.setBlendMode(u.utils.correctBlendMode(t.blendMode,n.baseTexture.premultipliedAlpha)),i.shader.uniforms.uTransform&&(t.uploadUvTransform?i.shader.uniforms.uTransform=t._uvTransform.mapCoord.toArray(!0):i.shader.uniforms.uTransform=f.toArray(!0)),i.shader.uniforms.translationMatrix=t.worldTransform.toArray(!0),i.shader.uniforms.uColor=u.utils.premultiplyRgba(t.tintRgb,t.worldAlpha,i.shader.uniforms.uColor,n.baseTexture.premultipliedAlpha);var o=t.drawMode===d.default.DRAW_MODES.TRIANGLE_MESH?r.TRIANGLE_STRIP:r.TRIANGLES;i.vao.draw(o,t.indices.length,0)}},e}(u.ObjectRenderer);r.default=p,u.WebGLRenderer.registerPlugin(\"mesh\",p)},{\"../../core\":65,\"../Mesh\":166,path:23,\"pixi-gl-core\":12}],173:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"../core\"),u=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(a),h=t(\"../core/utils\"),l=function(t){function e(){var r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1500,o=arguments[1],s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:16384,a=arguments.length>3&&void 0!==arguments[3]&&arguments[3];n(this,e);var h=i(this,t.call(this));return s>16384&&(s=16384),s>r&&(s=r),h._properties=[!1,!0,!1,!1,!1],h._maxSize=r,h._batchSize=s,h._glBuffers={},h._bufferToUpdate=0,h.interactiveChildren=!1,h.blendMode=u.BLEND_MODES.NORMAL,h.autoResize=a,h.roundPixels=!0,h.baseTexture=null,h.setProperties(o),h._tint=0,h.tintRgb=new Float32Array(4),h.tint=16777215,h}return o(e,t),e.prototype.setProperties=function(t){t&&(this._properties[0]=\"scale\"in t?!!t.scale:this._properties[0],this._properties[1]=\"position\"in t?!!t.position:this._properties[1],this._properties[2]=\"rotation\"in t?!!t.rotation:this._properties[2],this._properties[3]=\"uvs\"in t?!!t.uvs:this._properties[3],this._properties[4]=\"alpha\"in t||\"tint\"in t?!!t.alpha||!!t.tint:this._properties[4])},e.prototype.updateTransform=function(){this.displayObjectUpdateTransform()},e.prototype.renderWebGL=function(t){var e=this;this.visible&&!(this.worldAlpha<=0)&&this.children.length&&this.renderable&&(this.baseTexture||(this.baseTexture=this.children[0]._texture.baseTexture,this.baseTexture.hasLoaded||this.baseTexture.once(\"update\",function(){return e.onChildrenChange(0)})),t.setObjectRenderer(t.plugins.particle),t.plugins.particle.render(this))},e.prototype.onChildrenChange=function(t){var e=Math.floor(t/this._batchSize);e<this._bufferToUpdate&&(this._bufferToUpdate=e)},e.prototype.renderCanvas=function(t){if(this.visible&&!(this.worldAlpha<=0)&&this.children.length&&this.renderable){var e=t.context,r=this.worldTransform,n=!0,i=0,o=0,s=0,a=0;t.setBlendMode(this.blendMode),e.globalAlpha=this.worldAlpha,this.displayObjectUpdateTransform();for(var u=0;u<this.children.length;++u){var h=this.children[u];if(h.visible){var l=h._texture.frame;if(e.globalAlpha=this.worldAlpha*h.alpha,h.rotation%(2*Math.PI)==0)n&&(e.setTransform(r.a,r.b,r.c,r.d,r.tx*t.resolution,r.ty*t.resolution),n=!1),i=h.anchor.x*(-l.width*h.scale.x)+h.position.x+.5,o=h.anchor.y*(-l.height*h.scale.y)+h.position.y+.5,s=l.width*h.scale.x,a=l.height*h.scale.y;else{n||(n=!0),h.displayObjectUpdateTransform();var c=h.worldTransform;t.roundPixels?e.setTransform(c.a,c.b,c.c,c.d,c.tx*t.resolution|0,c.ty*t.resolution|0):e.setTransform(c.a,c.b,c.c,c.d,c.tx*t.resolution,c.ty*t.resolution),i=h.anchor.x*-l.width+.5,o=h.anchor.y*-l.height+.5,s=l.width,a=l.height}var d=h._texture.baseTexture.resolution;e.drawImage(h._texture.baseTexture.source,l.x*d,l.y*d,l.width*d,l.height*d,i*t.resolution,o*t.resolution,s*t.resolution,a*t.resolution)}}}},e.prototype.destroy=function(e){if(t.prototype.destroy.call(this,e),this._buffers)for(var r=0;r<this._buffers.length;++r)this._buffers[r].destroy();this._properties=null,this._buffers=null},s(e,[{key:\"tint\",get:function(){return this._tint},set:function(t){this._tint=t,(0,h.hex2rgb)(t,this.tintRgb)}}]),e}(u.Container);r.default=l},{\"../core\":65,\"../core/utils\":125}],174:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0;var i=t(\"./ParticleContainer\");Object.defineProperty(r,\"ParticleContainer\",{enumerable:!0,get:function(){return n(i).default}});var o=t(\"./webgl/ParticleRenderer\");Object.defineProperty(r,\"ParticleRenderer\",{enumerable:!0,get:function(){return n(o).default}})},{\"./ParticleContainer\":173,\"./webgl/ParticleRenderer\":176}],175:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var o=t(\"pixi-gl-core\"),s=n(o),a=t(\"../../core/utils/createIndicesForQuads\"),u=n(a),h=function(){function t(e,r,n,o){i(this,t),this.gl=e,this.size=o,this.dynamicProperties=[],this.staticProperties=[];for(var s=0;s<r.length;++s){var a=r[s];a={attribute:a.attribute,size:a.size,uploadFunction:a.uploadFunction,unsignedByte:a.unsignedByte,offset:a.offset},n[s]?this.dynamicProperties.push(a):this.staticProperties.push(a)}this.staticStride=0,this.staticBuffer=null,this.staticData=null,this.staticDataUint32=null,this.dynamicStride=0,this.dynamicBuffer=null,this.dynamicData=null,this.dynamicDataUint32=null,this.initBuffers()}return t.prototype.initBuffers=function(){var t=this.gl,e=0;this.indices=(0,u.default)(this.size),this.indexBuffer=s.default.GLBuffer.createIndexBuffer(t,this.indices,t.STATIC_DRAW),this.dynamicStride=0;for(var r=0;r<this.dynamicProperties.length;++r){var n=this.dynamicProperties[r];n.offset=e,e+=n.size,this.dynamicStride+=n.size}var i=new ArrayBuffer(this.size*this.dynamicStride*4*4);this.dynamicData=new Float32Array(i),this.dynamicDataUint32=new Uint32Array(i),this.dynamicBuffer=s.default.GLBuffer.createVertexBuffer(t,i,t.STREAM_DRAW);var o=0;this.staticStride=0;for(var a=0;a<this.staticProperties.length;++a){var h=this.staticProperties[a];h.offset=o,o+=h.size,this.staticStride+=h.size}var l=new ArrayBuffer(this.size*this.staticStride*4*4);this.staticData=new Float32Array(l),this.staticDataUint32=new Uint32Array(l),this.staticBuffer=s.default.GLBuffer.createVertexBuffer(t,l,t.STATIC_DRAW),this.vao=new s.default.VertexArrayObject(t).addIndex(this.indexBuffer);for(var c=0;c<this.dynamicProperties.length;++c){var d=this.dynamicProperties[c];d.unsignedByte?this.vao.addAttribute(this.dynamicBuffer,d.attribute,t.UNSIGNED_BYTE,!0,4*this.dynamicStride,4*d.offset):this.vao.addAttribute(this.dynamicBuffer,d.attribute,t.FLOAT,!1,4*this.dynamicStride,4*d.offset)}for(var f=0;f<this.staticProperties.length;++f){var p=this.staticProperties[f];p.unsignedByte?this.vao.addAttribute(this.staticBuffer,p.attribute,t.UNSIGNED_BYTE,!0,4*this.staticStride,4*p.offset):this.vao.addAttribute(this.staticBuffer,p.attribute,t.FLOAT,!1,4*this.staticStride,4*p.offset)}},t.prototype.uploadDynamic=function(t,e,r){for(var n=0;n<this.dynamicProperties.length;n++){var i=this.dynamicProperties[n];i.uploadFunction(t,e,r,i.unsignedByte?this.dynamicDataUint32:this.dynamicData,this.dynamicStride,i.offset)}this.dynamicBuffer.upload()},t.prototype.uploadStatic=function(t,e,r){for(var n=0;n<this.staticProperties.length;n++){var i=this.staticProperties[n];i.uploadFunction(t,e,r,i.unsignedByte?this.staticDataUint32:this.staticData,this.staticStride,i.offset)}this.staticBuffer.upload()},t.prototype.destroy=function(){this.dynamicProperties=null,this.dynamicBuffer.destroy(),this.dynamicBuffer=null,this.dynamicData=null,this.dynamicDataUint32=null,this.staticProperties=null,this.staticBuffer.destroy(),this.staticBuffer=null,this.staticData=null,this.staticDataUint32=null},t}();r.default=h},{\"../../core/utils/createIndicesForQuads\":123,\"pixi-gl-core\":12}],176:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"../../core\"),u=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(a),h=t(\"./ParticleShader\"),l=n(h),c=t(\"./ParticleBuffer\"),d=n(c),f=t(\"../../core/utils\"),p=function(t){function e(r){i(this,e);var n=o(this,t.call(this,r));return n.shader=null,n.indexBuffer=null,n.properties=null,n.tempMatrix=new u.Matrix,n.CONTEXT_UID=0,n}return s(e,t),e.prototype.onContextChange=function(){var t=this.renderer.gl;this.CONTEXT_UID=this.renderer.CONTEXT_UID,this.shader=new l.default(t),this.properties=[{attribute:this.shader.attributes.aVertexPosition,size:2,uploadFunction:this.uploadVertices,offset:0},{attribute:this.shader.attributes.aPositionCoord,size:2,uploadFunction:this.uploadPosition,offset:0},{attribute:this.shader.attributes.aRotation,size:1,uploadFunction:this.uploadRotation,offset:0},{attribute:this.shader.attributes.aTextureCoord,size:2,uploadFunction:this.uploadUvs,offset:0},{attribute:this.shader.attributes.aColor,size:1,unsignedByte:!0,uploadFunction:this.uploadTint,offset:0}]},e.prototype.start=function(){this.renderer.bindShader(this.shader)},e.prototype.render=function(t){var e=t.children,r=t._maxSize,n=t._batchSize,i=this.renderer,o=e.length;if(0!==o){o>r&&(o=r);var s=t._glBuffers[i.CONTEXT_UID];s||(s=t._glBuffers[i.CONTEXT_UID]=this.generateBuffers(t));var a=e[0]._texture.baseTexture;this.renderer.setBlendMode(u.utils.correctBlendMode(t.blendMode,a.premultipliedAlpha));var h=i.gl,l=t.worldTransform.copy(this.tempMatrix);l.prepend(i._activeRenderTarget.projectionMatrix),this.shader.uniforms.projectionMatrix=l.toArray(!0),this.shader.uniforms.uColor=u.utils.premultiplyRgba(t.tintRgb,t.worldAlpha,this.shader.uniforms.uColor,a.premultipliedAlpha),this.shader.uniforms.uSampler=i.bindTexture(a);for(var c=0,d=0;c<o;c+=n,d+=1){var f=o-c;if(f>n&&(f=n),d>=s.length){if(!t.autoResize)break;s.push(this._generateOneMoreBuffer(t))}var p=s[d];p.uploadDynamic(e,c,f),t._bufferToUpdate===d&&(p.uploadStatic(e,c,f),t._bufferToUpdate=d+1),i.bindVao(p.vao),p.vao.draw(h.TRIANGLES,6*f)}}},e.prototype.generateBuffers=function(t){for(var e=this.renderer.gl,r=[],n=t._maxSize,i=t._batchSize,o=t._properties,s=0;s<n;s+=i)r.push(new d.default(e,this.properties,o,i));return r},e.prototype._generateOneMoreBuffer=function(t){var e=this.renderer.gl,r=t._batchSize,n=t._properties;return new d.default(e,this.properties,n,r)},e.prototype.uploadVertices=function(t,e,r,n,i,o){for(var s=0,a=0,u=0,h=0,l=0;l<r;++l){var c=t[e+l],d=c._texture,f=c.scale.x,p=c.scale.y,v=d.trim,y=d.orig;v?(a=v.x-c.anchor.x*y.width,s=a+v.width,h=v.y-c.anchor.y*y.height,u=h+v.height):(s=y.width*(1-c.anchor.x),a=y.width*-c.anchor.x,u=y.height*(1-c.anchor.y),h=y.height*-c.anchor.y),n[o]=a*f,n[o+1]=h*p,n[o+i]=s*f,n[o+i+1]=h*p,n[o+2*i]=s*f,n[o+2*i+1]=u*p,n[o+3*i]=a*f,n[o+3*i+1]=u*p,o+=4*i}},e.prototype.uploadPosition=function(t,e,r,n,i,o){for(var s=0;s<r;s++){var a=t[e+s].position;n[o]=a.x,n[o+1]=a.y,n[o+i]=a.x,n[o+i+1]=a.y,n[o+2*i]=a.x,n[o+2*i+1]=a.y,n[o+3*i]=a.x,n[o+3*i+1]=a.y,o+=4*i}},e.prototype.uploadRotation=function(t,e,r,n,i,o){for(var s=0;s<r;s++){var a=t[e+s].rotation;n[o]=a,n[o+i]=a,n[o+2*i]=a,n[o+3*i]=a,o+=4*i}},e.prototype.uploadUvs=function(t,e,r,n,i,o){for(var s=0;s<r;++s){var a=t[e+s]._texture._uvs;a?(n[o]=a.x0,n[o+1]=a.y0,n[o+i]=a.x1,n[o+i+1]=a.y1,n[o+2*i]=a.x2,n[o+2*i+1]=a.y2,n[o+3*i]=a.x3,n[o+3*i+1]=a.y3,o+=4*i):(n[o]=0,n[o+1]=0,n[o+i]=0,n[o+i+1]=0,n[o+2*i]=0,n[o+2*i+1]=0,n[o+3*i]=0,n[o+3*i+1]=0,o+=4*i)}},e.prototype.uploadTint=function(t,e,r,n,i,o){for(var s=0;s<r;++s){var a=t[e+s],u=a._texture.baseTexture.premultipliedAlpha,h=a.alpha,l=h<1&&u?(0,f.premultiplyTint)(a._tintRGB,h):a._tintRGB+(255*h<<24);n[o]=l,n[o+i]=l,n[o+2*i]=l,n[o+3*i]=l,o+=4*i}},e.prototype.destroy=function(){this.renderer.gl&&this.renderer.gl.deleteBuffer(this.indexBuffer),t.prototype.destroy.call(this),this.shader.destroy(),this.indices=null,this.tempMatrix=null},e}(u.ObjectRenderer);r.default=p,u.WebGLRenderer.registerPlugin(\"particle\",p)},{\"../../core\":65,\"../../core/utils\":125,\"./ParticleBuffer\":175,\"./ParticleShader\":177}],177:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=t(\"../../core/Shader\"),a=function(t){return t&&t.__esModule?t:{default:t}}(s),u=function(t){function e(r){return n(this,e),i(this,t.call(this,r,[\"attribute vec2 aVertexPosition;\",\"attribute vec2 aTextureCoord;\",\"attribute vec4 aColor;\",\"attribute vec2 aPositionCoord;\",\"attribute vec2 aScale;\",\"attribute float aRotation;\",\"uniform mat3 projectionMatrix;\",\"uniform vec4 uColor;\",\"varying vec2 vTextureCoord;\",\"varying vec4 vColor;\",\"void main(void){\",\"   float x = (aVertexPosition.x) * cos(aRotation) - (aVertexPosition.y) * sin(aRotation);\",\"   float y = (aVertexPosition.x) * sin(aRotation) + (aVertexPosition.y) * cos(aRotation);\",\"   vec2 v = vec2(x, y);\",\"   v = v + aPositionCoord;\",\"   gl_Position = vec4((projectionMatrix * vec3(v, 1.0)).xy, 0.0, 1.0);\",\"   vTextureCoord = aTextureCoord;\",\"   vColor = aColor * uColor;\",\"}\"].join(\"\\n\"),[\"varying vec2 vTextureCoord;\",\"varying vec4 vColor;\",\"uniform sampler2D uSampler;\",\"void main(void){\",\"  vec4 color = texture2D(uSampler, vTextureCoord) * vColor;\",\"  gl_FragColor = color;\",\"}\"].join(\"\\n\")))}return o(e,t),e}(a.default);r.default=u},{\"../../core/Shader\":44}],178:[function(t,e,r){\"use strict\";Math.sign||(Math.sign=function(t){return t=Number(t),0===t||isNaN(t)?t:t>0?1:-1})},{}],179:[function(t,e,r){\"use strict\";var n=t(\"object-assign\"),i=function(t){return t&&t.__esModule?t:{default:t}}(n);Object.assign||(Object.assign=i.default)},{\"object-assign\":5}],180:[function(t,e,r){\"use strict\";t(\"./Object.assign\"),t(\"./requestAnimationFrame\"),t(\"./Math.sign\"),window.ArrayBuffer||(window.ArrayBuffer=Array),window.Float32Array||(window.Float32Array=Array),window.Uint32Array||(window.Uint32Array=Array),window.Uint16Array||(window.Uint16Array=Array)},{\"./Math.sign\":178,\"./Object.assign\":179,\"./requestAnimationFrame\":181}],181:[function(t,e,r){(function(t){\"use strict\";if(Date.now&&Date.prototype.getTime||(Date.now=function(){return(new Date).getTime()}),!t.performance||!t.performance.now){var e=Date.now();t.performance||(t.performance={}),t.performance.now=function(){return Date.now()-e}}for(var r=Date.now(),n=[\"ms\",\"moz\",\"webkit\",\"o\"],i=0;i<n.length&&!t.requestAnimationFrame;++i){var o=n[i];t.requestAnimationFrame=t[o+\"RequestAnimationFrame\"],t.cancelAnimationFrame=t[o+\"CancelAnimationFrame\"]||t[o+\"CancelRequestAnimationFrame\"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(t){if(\"function\"!=typeof t)throw new TypeError(t+\"is not a function\");var e=Date.now(),n=16+r-e;return n<0&&(n=0),r=e,setTimeout(function(){r=Date.now(),t(performance.now())},n)}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(t){return clearTimeout(t)})}).call(this,\"undefined\"!=typeof global?global:\"undefined\"!=typeof self?self:\"undefined\"!=typeof window?window:{})},{}],182:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){var r=!1;if(t&&t._textures&&t._textures.length)for(var n=0;n<t._textures.length;n++)if(t._textures[n]instanceof d.Texture){var i=t._textures[n].baseTexture;-1===e.indexOf(i)&&(e.push(i),r=!0)}return r}function o(t,e){return t instanceof d.BaseTexture&&(-1===e.indexOf(t)&&e.push(t),!0)}function s(t,e){\nif(t._texture&&t._texture instanceof d.Texture){var r=t._texture.baseTexture;return-1===e.indexOf(r)&&e.push(r),!0}return!1}function a(t,e){return e instanceof d.Text&&(e.updateText(!0),!0)}function u(t,e){if(e instanceof d.TextStyle){var r=e.toFontString();return d.TextMetrics.measureFont(r),!0}return!1}function h(t,e){if(t instanceof d.Text){-1===e.indexOf(t.style)&&e.push(t.style),-1===e.indexOf(t)&&e.push(t);var r=t._texture.baseTexture;return-1===e.indexOf(r)&&e.push(r),!0}return!1}function l(t,e){return t instanceof d.TextStyle&&(-1===e.indexOf(t)&&e.push(t),!0)}r.__esModule=!0;var c=t(\"../core\"),d=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(c),f=t(\"./limiters/CountLimiter\"),p=function(t){return t&&t.__esModule?t:{default:t}}(f),v=d.ticker.shared;d.settings.UPLOADS_PER_FRAME=4;var y=function(){function t(e){var r=this;n(this,t),this.limiter=new p.default(d.settings.UPLOADS_PER_FRAME),this.renderer=e,this.uploadHookHelper=null,this.queue=[],this.addHooks=[],this.uploadHooks=[],this.completes=[],this.ticking=!1,this.delayedTick=function(){r.queue&&r.prepareItems()},this.registerFindHook(h),this.registerFindHook(l),this.registerFindHook(i),this.registerFindHook(o),this.registerFindHook(s),this.registerUploadHook(a),this.registerUploadHook(u)}return t.prototype.upload=function(t,e){\"function\"==typeof t&&(e=t,t=null),t&&this.add(t),this.queue.length?(e&&this.completes.push(e),this.ticking||(this.ticking=!0,v.addOnce(this.tick,this,d.UPDATE_PRIORITY.UTILITY))):e&&e()},t.prototype.tick=function(){setTimeout(this.delayedTick,0)},t.prototype.prepareItems=function(){for(this.limiter.beginFrame();this.queue.length&&this.limiter.allowedToUpload();){var t=this.queue[0],e=!1;if(t&&!t._destroyed)for(var r=0,n=this.uploadHooks.length;r<n;r++)if(this.uploadHooks[r](this.uploadHookHelper,t)){this.queue.shift(),e=!0;break}e||this.queue.shift()}if(this.queue.length)v.addOnce(this.tick,this,d.UPDATE_PRIORITY.UTILITY);else{this.ticking=!1;var i=this.completes.slice(0);this.completes.length=0;for(var o=0,s=i.length;o<s;o++)i[o]()}},t.prototype.registerFindHook=function(t){return t&&this.addHooks.push(t),this},t.prototype.registerUploadHook=function(t){return t&&this.uploadHooks.push(t),this},t.prototype.add=function(t){for(var e=0,r=this.addHooks.length;e<r&&!this.addHooks[e](t,this.queue);e++);if(t instanceof d.Container)for(var n=t.children.length-1;n>=0;n--)this.add(t.children[n]);return this},t.prototype.destroy=function(){this.ticking&&v.remove(this.tick,this),this.ticking=!1,this.addHooks=null,this.uploadHooks=null,this.renderer=null,this.completes=null,this.queue=null,this.limiter=null,this.uploadHookHelper=null},t}();r.default=y},{\"../core\":65,\"./limiters/CountLimiter\":185}],183:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function s(t,e){if(e instanceof u.BaseTexture){var r=e.source,n=0===r.width?t.canvas.width:Math.min(t.canvas.width,r.width),i=0===r.height?t.canvas.height:Math.min(t.canvas.height,r.height);return t.ctx.drawImage(r,0,0,n,i,0,0,t.canvas.width,t.canvas.height),!0}return!1}r.__esModule=!0;var a=t(\"../../core\"),u=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(a),h=t(\"../BasePrepare\"),l=function(t){return t&&t.__esModule?t:{default:t}}(h),c=16,d=function(t){function e(r){n(this,e);var o=i(this,t.call(this,r));return o.uploadHookHelper=o,o.canvas=document.createElement(\"canvas\"),o.canvas.width=c,o.canvas.height=c,o.ctx=o.canvas.getContext(\"2d\"),o.registerUploadHook(s),o}return o(e,t),e.prototype.destroy=function(){t.prototype.destroy.call(this),this.ctx=null,this.canvas=null},e}(l.default);r.default=d,u.CanvasRenderer.registerPlugin(\"prepare\",d)},{\"../../core\":65,\"../BasePrepare\":182}],184:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0;var i=t(\"./webgl/WebGLPrepare\");Object.defineProperty(r,\"webgl\",{enumerable:!0,get:function(){return n(i).default}});var o=t(\"./canvas/CanvasPrepare\");Object.defineProperty(r,\"canvas\",{enumerable:!0,get:function(){return n(o).default}});var s=t(\"./BasePrepare\");Object.defineProperty(r,\"BasePrepare\",{enumerable:!0,get:function(){return n(s).default}});var a=t(\"./limiters/CountLimiter\");Object.defineProperty(r,\"CountLimiter\",{enumerable:!0,get:function(){return n(a).default}});var u=t(\"./limiters/TimeLimiter\");Object.defineProperty(r,\"TimeLimiter\",{enumerable:!0,get:function(){return n(u).default}})},{\"./BasePrepare\":182,\"./canvas/CanvasPrepare\":183,\"./limiters/CountLimiter\":185,\"./limiters/TimeLimiter\":186,\"./webgl/WebGLPrepare\":187}],185:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(e){n(this,t),this.maxItemsPerFrame=e,this.itemsLeft=0}return t.prototype.beginFrame=function(){this.itemsLeft=this.maxItemsPerFrame},t.prototype.allowedToUpload=function(){return this.itemsLeft-- >0},t}();r.default=i},{}],186:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(e){n(this,t),this.maxMilliseconds=e,this.frameStart=0}return t.prototype.beginFrame=function(){this.frameStart=Date.now()},t.prototype.allowedToUpload=function(){return Date.now()-this.frameStart<this.maxMilliseconds},t}();r.default=i},{}],187:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function s(t,e){return e instanceof l.BaseTexture&&(e._glTextures[t.CONTEXT_UID]||t.textureManager.updateTexture(e),!0)}function a(t,e){return e instanceof l.Graphics&&((e.dirty||e.clearDirty||!e._webGL[t.plugins.graphics.CONTEXT_UID])&&t.plugins.graphics.updateGraphics(e),!0)}function u(t,e){return t instanceof l.Graphics&&(e.push(t),!0)}r.__esModule=!0;var h=t(\"../../core\"),l=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(h),c=t(\"../BasePrepare\"),d=function(t){return t&&t.__esModule?t:{default:t}}(c),f=function(t){function e(r){n(this,e);var o=i(this,t.call(this,r));return o.uploadHookHelper=o.renderer,o.registerFindHook(u),o.registerUploadHook(s),o.registerUploadHook(a),o}return o(e,t),e}(d.default);r.default=f,l.WebGLRenderer.registerPlugin(\"prepare\",f)},{\"../../core\":65,\"../BasePrepare\":182}],188:[function(t,e,r){(function(e){\"use strict\";function n(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}r.__esModule=!0,r.loader=r.prepare=r.particles=r.mesh=r.loaders=r.interaction=r.filters=r.extras=r.extract=r.accessibility=void 0;var i=t(\"./polyfill\");Object.keys(i).forEach(function(t){\"default\"!==t&&\"__esModule\"!==t&&Object.defineProperty(r,t,{enumerable:!0,get:function(){return i[t]}})});var o=t(\"./core\");Object.keys(o).forEach(function(t){\"default\"!==t&&\"__esModule\"!==t&&Object.defineProperty(r,t,{enumerable:!0,get:function(){return o[t]}})});var s=t(\"./deprecation\"),a=function(t){return t&&t.__esModule?t:{default:t}}(s),u=t(\"./accessibility\"),h=n(u),l=t(\"./extract\"),c=n(l),d=t(\"./extras\"),f=n(d),p=t(\"./filters\"),v=n(p),y=t(\"./interaction\"),g=n(y),m=t(\"./loaders\"),_=n(m),b=t(\"./mesh\"),x=n(b),T=t(\"./particles\"),w=n(T),E=t(\"./prepare\"),S=n(E);o.utils.mixins.performMixins();var O=_.shared||null;r.accessibility=h,r.extract=c,r.extras=f,r.filters=v,r.interaction=g,r.loaders=_,r.mesh=x,r.particles=w,r.prepare=S,r.loader=O,\"function\"==typeof a.default&&(0,a.default)(r),e.PIXI=r}).call(this,\"undefined\"!=typeof global?global:\"undefined\"!=typeof self?self:\"undefined\"!=typeof window?window:{})},{\"./accessibility\":42,\"./core\":65,\"./deprecation\":131,\"./extract\":133,\"./extras\":141,\"./filters\":153,\"./interaction\":159,\"./loaders\":162,\"./mesh\":171,\"./particles\":174,\"./polyfill\":180,\"./prepare\":184}]},{},[188])(188)});\n//# sourceMappingURL=pixi.min.js.map\n"
  },
  {
    "path": "lib/polyfills.js",
    "content": "if (!String.prototype.startsWith) {\n    String.prototype.startsWith = function(searchString, position){\n      position = position || 0;\n      return this.substr(position, searchString.length) === searchString;\n  };\n}\n\nif (!Object.keys) {\n    Object.keys = function (obj) {\n        var keys = [],\n            k;\n        for (k in obj) {\n            if (Object.prototype.hasOwnProperty.call(obj, k)) {\n                keys.push(k);\n            }\n        }\n        return keys;\n    };\n}\n\n// http://stackoverflow.com/questions/872310/javascript-swap-array-elements\nArray.prototype.swap = function (x,y) {\n  var b = this[x];\n  this[x] = this[y];\n  this[y] = b;\n  return this;\n}\n\nif (!String.prototype.splice) {\n    /**\n     * {JSDoc}\n     *\n     * The splice() method changes the content of a string by removing a range of\n     * characters and/or adding new characters.\n     *\n     * @this {String}\n     * @param {number} start Index at which to start changing the string.\n     * @param {number} delCount An integer indicating the number of old chars to remove.\n     * @param {string} newSubStr The String that is spliced in.\n     * @return {string} A new string with the spliced substring.\n     */\n    String.prototype.splice = function(start, delCount, newSubStr) {\n        return this.slice(0, start) + newSubStr + this.slice(start + Math.abs(delCount));\n    };\n}\n\n// Production steps of ECMA-262, Edition 5, 15.4.4.18\n// Reference: http://es5.github.io/#x15.4.4.18\nif (!Array.prototype.forEachBackwards) {\n\n  Array.prototype.forEachBackwards = function(callback, thisArg) {\n\n    var T, k;\n\n    if (this === null) {\n      throw new TypeError('this is null or not defined');\n    }\n\n    // 1. Let O be the result of calling toObject() passing the\n    // |this| value as the argument.\n    var O = Object(this);\n\n    // 2. Let lenValue be the result of calling the Get() internal\n    // method of O with the argument \"length\".\n    // 3. Let len be toUint32(lenValue).\n    var len = O.length >>> 0;\n\n    // 4. If isCallable(callback) is false, throw a TypeError exception. \n    // See: http://es5.github.com/#x9.11\n    if (typeof callback !== 'function') {\n      throw new TypeError(callback + ' is not a function');\n    }\n\n    // 5. If thisArg was supplied, let T be thisArg; else let\n    // T be undefined.\n    if (arguments.length > 1) {\n      T = thisArg;\n    }\n\n    // 6. Let k be 0\n    k = len-1;\n\n    // 7. Repeat, while k < len\n    while (k >= 0) {\n\n      var kValue;\n\n      // a. Let Pk be ToString(k).\n      //    This is implicit for LHS operands of the in operator\n      // b. Let kPresent be the result of calling the HasProperty\n      //    internal method of O with argument Pk.\n      //    This step can be combined with c\n      // c. If kPresent is true, then\n      if (k in O) {\n\n        // i. Let kValue be the result of calling the Get internal\n        // method of O with argument Pk.\n        kValue = O[k];\n\n        // ii. Call the Call internal method of callback with T as\n        // the this value and argument list containing kValue, k, and O.\n        callback.call(T, kValue, k, O);\n      }\n      // d. Increase k by 1.\n      k--;\n    }\n    // 8. return undefined\n  };\n}\n\n//http://stackoverflow.com/questions/7837456/how-to-compare-arrays-in-javascript\n// Warn if overriding existing method\nif(Array.prototype.equals)\n    console.warn(\"Overriding existing Array.prototype.equals. Possible causes: New API defines the method, there's a framework conflict or you've got double inclusions in your code.\");\n// attach the .equals method to Array's prototype to call it on any array\nArray.prototype.equals = function (array) {\n    // if the other array is a falsy value, return\n    if (!array)\n        return false;\n\n    // compare lengths - can save a lot of time \n    if (this.length != array.length)\n        return false;\n\n    for (var i = 0, l=this.length; i < l; i++) {\n        // Check if we have nested arrays\n        if (this[i] instanceof Array && array[i] instanceof Array) {\n            // recurse into the nested arrays\n            if (!this[i].equals(array[i]))\n                return false;       \n        }           \n        else if (this[i] != array[i]) { \n            // Warning - two different object instances will never be equal: {x:20} != {x:20}\n            return false;   \n        }           \n    }       \n    return true;\n}\n// Hide method from for-in loops\nObject.defineProperty(Array.prototype, \"equals\", {enumerable: false});\n\n//if(!BrowserDetectionUtils.isChrome || !BrowserDetectionUtils.isFirefox) {\n    window.polyfillClipboardData = (function () {\n        var pcd = {};\n\n        var data = {};\n        \n        pcd.types = [];\n\n        pcd.setData = function (type,newdata) {\n            data[type] = {type:type,data:newdata};\n            if(pcd.types.indexOf(type) === -1) pcd.types.push(type);\n        }\n\n        pcd.getData = function (type) {\n            return data[type].data;\n        }\n\n        return pcd;\n    })();\n//}\n\n//http://stackoverflow.com/questions/5306680/move-an-array-element-from-one-array-position-to-another\nArray.prototype.move = function (old_index, new_index) {\n    if (new_index >= this.length) {\n        var k = new_index - this.length;\n        while ((k--) + 1) {\n            this.push(undefined);\n        }\n    }\n    this.splice(new_index, 0, this.splice(old_index, 1)[0]);\n    return this; // for testing purposes\n};\n\n// https://tc39.github.io/ecma262/#sec-array.prototype.includes\nif (!Array.prototype.includes) {\n  Object.defineProperty(Array.prototype, 'includes', {\n    value: function(searchElement, fromIndex) {\n\n      // 1. Let O be ? ToObject(this value).\n      if (this == null) {\n        throw new TypeError('\"this\" is null or not defined');\n      }\n\n      var o = Object(this);\n\n      // 2. Let len be ? ToLength(? Get(O, \"length\")).\n      var len = o.length >>> 0;\n\n      // 3. If len is 0, return false.\n      if (len === 0) {\n        return false;\n      }\n\n      // 4. Let n be ? ToInteger(fromIndex).\n      //    (If fromIndex is undefined, this step produces the value 0.)\n      var n = fromIndex | 0;\n\n      // 5. If n ≥ 0, then\n      //  a. Let k be n.\n      // 6. Else n < 0,\n      //  a. Let k be len + n.\n      //  b. If k < 0, let k be 0.\n      var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);\n\n      // 7. Repeat, while k < len\n      while (k < len) {\n        // a. Let elementK be the result of ? Get(O, ! ToString(k)).\n        // b. If SameValueZero(searchElement, elementK) is true, return true.\n        // c. Increase k by 1.\n        // NOTE: === provides the correct \"SameValueZero\" comparison needed here.\n        if (o[k] === searchElement) {\n          return true;\n        }\n        k++;\n      }\n\n      // 8. Return false\n      return false;\n    }\n  });\n}\n\nElement.prototype.remove = function() {\n    this.parentElement.removeChild(this);\n}\nNodeList.prototype.remove = HTMLCollection.prototype.remove = function() {\n    for(var i = this.length - 1; i >= 0; i--) {\n        if(this[i] && this[i].parentElement) {\n            this[i].parentElement.removeChild(this[i]);\n        }\n    }\n}\n\n//////////////////////////////////////////////////\n// BELOW ARE NOT POLYFILLS PLEASE MOVE ELSEWHERE//\n//////////////////////////////////////////////////\n\nvar BrowserDetect = (function () {\n\n    var browserDetectionUtils = { };\n\n    browserDetectionUtils.isFirefox = \n        navigator.userAgent.search(\"Firefox\");\n\n    browserDetectionUtils.isSafari = \n        navigator.appVersion.search('Safari') != -1 \n     && navigator.appVersion.search('Chrome') == -1 \n     && navigator.appVersion.search('CrMo') == -1 \n     && navigator.appVersion.search('CriOS') == -1;\n\n    browserDetectionUtils.isIe = (\n        navigator.userAgent.toLowerCase().indexOf(\"msie\") != -1 \n     || navigator.userAgent.toLowerCase().indexOf(\"trident\") != -1 );\n\n    browserDetectionUtils.isChrome = \n        /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);\n\n    browserDetectionUtils.inMobileMode =\n        /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);\n\n    return browserDetectionUtils;\n    \n})();\n\nvar isSafari = navigator.appVersion.search('Safari') != -1 && navigator.appVersion.search('Chrome') == -1 && navigator.appVersion.search('CrMo') == -1 && navigator.appVersion.search('CriOS') == -1;\nvar isIe = (navigator.userAgent.toLowerCase().indexOf(\"msie\") != -1 || navigator.userAgent.toLowerCase().indexOf(\"trident\") != -1);\nvar isChrome = /chrome/.test( navigator.userAgent.toLowerCase() );\n\nvar roundToNearestN = function (val, n, d) {\n  if(d === undefined) d = 20;\n  return parseFloat((Math.round(val/n)*n).toFixed(d));\n}\n\nvar roundToHundredths = function (val) {\n  return roundToNearestN(val, 0.01, 2);\n}\n\nvar buildDiv = function(className, parentElem) {\n  var div = document.createElement('div');\n  div.className = className;\n  if(parentElem) {\n    parentElem.appendChild(div);\n  }\n  return div;\n}\n\nvar buildSpan = function(className, parentElem) {\n  var div = document.createElement('span');\n  div.className = className;\n  if(parentElem) {\n    parentElem.appendChild(div);\n  }\n  return div;\n}\n\n//http://stackoverflow.com/questions/11076975/insert-text-into-textarea-at-cursor-position-javascript\nfunction insertAtCursor(myField, myValue) {\n    //IE support\n    if (document.selection) {\n        myField.focus();\n        sel = document.selection.createRange();\n        sel.text = myValue;\n    }\n    //MOZILLA and others\n    else if (myField.selectionStart || myField.selectionStart == '0') {\n        var startPos = myField.selectionStart;\n        var endPos = myField.selectionEnd;\n        myField.value = myField.value.substring(0, startPos)\n            + myValue\n            + myField.value.substring(endPos, myField.value.length);\n    } else {\n        myField.value += myValue;\n    }\n}\n\nvar startMillis;\nfunction resetElapsedTime () {\n  startMillis = new Date().getTime()\n}\nresetElapsedTime();\nfunction elapsedSeconds () {\n  return Math.floor(elapsedMilliseconds()/1000);\n}\n\nfunction elapsedMilliseconds () {\n  var d = new Date();\n  var n = d.getTime();\n  return n - startMillis;\n}\n\nfunction rotate_point(pointX, pointY, originX, originY, angle) {\n  angle = angle * Math.PI / 180.0;\n  return {\n    x: Math.cos(angle) * (pointX-originX) - Math.sin(angle) * (pointY-originY) + originX,\n    y: Math.sin(angle) * (pointX-originX) + Math.cos(angle) * (pointY-originY) + originY\n  };\n}\n\n// http://stackoverflow.com/questions/9705123/how-can-i-get-sin-cos-and-tan-to-use-degrees-instead-of-radians\nfunction toRadians (angle) {\n  return angle * (Math.PI / 180);\n}\n\nfunction clamp (val, min, max) {\n  return Math.min(Math.max(val, min), max);\n}\n\n\n// \nfunction hexToRgbA(hex, a){\n    var c;\n\n    if(hex === 'none') return 'rgba(0,0,0,0)';\n\n    if(/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)){\n        c= hex.substring(1).split('');\n        if(c.length== 3){\n            c= [c[0], c[0], c[1], c[1], c[2], c[2]];\n        }\n        c= '0x'+c.join('');\n        return 'rgba('+[(c>>16)&255, (c>>8)&255, c&255].join(',')+','+a+')';\n    }\n    console.log(hex);\n    throw new Error('Bad Hex');\n}\n\nfunction dataURItoBlob(dataURI) {\n  // convert base64 to raw binary data held in a string\n  // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this\n  var byteString = atob(dataURI.split(',')[1]);\n\n  // separate out the mime component\n  var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]\n\n  // write the bytes of the string to an ArrayBuffer\n  var ab = new ArrayBuffer(byteString.length);\n  var ia = new Uint8Array(ab);\n  for (var i = 0; i < byteString.length; i++) {\n      ia[i] = byteString.charCodeAt(i);\n  }\n\n  // write the ArrayBuffer to a blob, and you're done\n  var blob = new Blob([ab], {type: mimeString});\n  return blob;\n\n  // Old code\n  // var bb = new BlobBuilder();\n  // bb.append(ab);\n  // return bb.getBlob(mimeString);\n}\n\nfunction deepCopy (val) {\n  if(typeof val === 'object') {\n    return JSON.parse(JSON.stringify(val));\n  } else {\n    return val;\n  }\n}\n\nfunction getAvailableFonts () {\n  var availableFonts = [\n    'Arial', \n    'Times New Roman', \n    'Comic Sans MS', \n    'Georgia', \n    'Palatino Linotype', \n    'Book Antiqua', \n    'Helvetica', \n    'Arial Black', \n    'Impact', \n    'Lucida Sans Unicode', \n    'Tahoma', \n    'Geneva', \n    'Trebuchet MS', \n    'Verdana', \n    'Courier New', \n    'Lucida Console'\n  ];\n  availableFonts.sort();\n  return availableFonts;\n}\n\nfunction elementInsideElement (target, parent) {\n  if(target === parent) return true;\n\n  if(target.parentElement) {\n    if(target.parentElement === target) {\n      return true;\n    } else {\n      return elementInsideElement(target.parentElement, parent)\n    }\n  } else {\n    return false;\n  }\n}\n\nfunction getBrowserAndOSInfo () {\n  var nVer = navigator.appVersion;\n  var nAgt = navigator.userAgent;\n  var browserName  = navigator.appName;\n  var fullVersion  = ''+parseFloat(navigator.appVersion); \n  var majorVersion = parseInt(navigator.appVersion,10);\n  var nameOffset,verOffset,ix;\n\n  // In Opera, the true version is after \"Opera\" or after \"Version\"\n  if ((verOffset=nAgt.indexOf(\"Opera\"))!=-1) {\n   browserName = \"Opera\";\n   fullVersion = nAgt.substring(verOffset+6);\n   if ((verOffset=nAgt.indexOf(\"Version\"))!=-1) \n     fullVersion = nAgt.substring(verOffset+8);\n  }\n  // In MSIE, the true version is after \"MSIE\" in userAgent\n  else if ((verOffset=nAgt.indexOf(\"MSIE\"))!=-1) {\n   browserName = \"Microsoft Internet Explorer\";\n   fullVersion = nAgt.substring(verOffset+5);\n  }\n  // In Chrome, the true version is after \"Chrome\" \n  else if ((verOffset=nAgt.indexOf(\"Chrome\"))!=-1) {\n   browserName = \"Chrome\";\n   fullVersion = nAgt.substring(verOffset+7);\n  }\n  // In Safari, the true version is after \"Safari\" or after \"Version\" \n  else if ((verOffset=nAgt.indexOf(\"Safari\"))!=-1) {\n   browserName = \"Safari\";\n   fullVersion = nAgt.substring(verOffset+7);\n   if ((verOffset=nAgt.indexOf(\"Version\"))!=-1) \n     fullVersion = nAgt.substring(verOffset+8);\n  }\n  // In Firefox, the true version is after \"Firefox\" \n  else if ((verOffset=nAgt.indexOf(\"Firefox\"))!=-1) {\n   browserName = \"Firefox\";\n   fullVersion = nAgt.substring(verOffset+8);\n  }\n  // In most other browsers, \"name/version\" is at the end of userAgent \n  else if ( (nameOffset=nAgt.lastIndexOf(' ')+1) < \n            (verOffset=nAgt.lastIndexOf('/')) ) \n  {\n   browserName = nAgt.substring(nameOffset,verOffset);\n   fullVersion = nAgt.substring(verOffset+1);\n   if (browserName.toLowerCase()==browserName.toUpperCase()) {\n    browserName = navigator.appName;\n   }\n  }\n  // trim the fullVersion string at semicolon/space if present\n  if ((ix=fullVersion.indexOf(\";\"))!=-1)\n     fullVersion=fullVersion.substring(0,ix);\n  if ((ix=fullVersion.indexOf(\" \"))!=-1)\n     fullVersion=fullVersion.substring(0,ix);\n\n  majorVersion = parseInt(''+fullVersion,10);\n  if (isNaN(majorVersion)) {\n   fullVersion  = ''+parseFloat(navigator.appVersion); \n   majorVersion = parseInt(navigator.appVersion,10);\n  }\n\n  /*return''\n   +'Browser name  = '+browserName+'<br>'\n   +'Full version  = '+fullVersion+'<br>'\n   +'Major version = '+majorVersion+'<br>'\n   +'navigator.appName = '+navigator.appName+'<br>'\n   +'navigator.userAgent = '+navigator.userAgent+'<br>';*/\n   return {\n    browser: browserName,\n    browserVersion: fullVersion,\n    navigatorAppName: navigator.appName,\n    navigatorUserAgent: navigator.userAgent,\n    devicePixelRatio: window.devicePixelRatio,\n   }\n\n}\n\n// https://gist.github.com/hurjas/2660489\n\n/**\n * Return a timestamp with the format \"m/d/yy h:MM:ss TT\"\n * @type {Date}\n */\n\nfunction timeStamp() {\n// Create a date object with the current time\n  var now = new Date();\n\n  var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']\n\n// Create an array with the current month, day and time\n  var date = [ months[now.getMonth()], now.getDate() + '-', now.getFullYear() ];\n\n// Create an array with the current hour, minute and second\n  var time = [ now.getHours(), now.getMinutes() ];\n\n// Determine AM or PM suffix based on the hour\n  var suffix = ( time[0] < 12 ) ? \"AM\" : \"PM\";\n\n// Convert hour from military time\n  time[0] = ( time[0] < 12 ) ? time[0] : time[0] - 12;\n\n// If hour is 0, set it to 12\n  time[0] = time[0] || 12;\n\n// If seconds and minutes are less than 10, add a zero\n  for ( var i = 1; i < 3; i++ ) {\n    if ( time[i] < 10 ) {\n      time[i] = \"0\" + time[i];\n    }\n  }\n\n// Return the formatted string\n  return date.join(\"\") + \"-\" + time.join(\".\") + \"\" + suffix;\n}\n\nfunction invertColor(hexTripletColor) {\n    var color = hexTripletColor;\n    color = color.substring(1); // remove #\n    color = parseInt(color, 16); // convert to integer\n    color = 0xFFFFFF ^ color; // invert three bytes\n    color = color.toString(16); // convert to hex\n    color = (\"000000\" + color).slice(-6); // pad with leading zeros\n    color = \"#\" + color; // prepend #\n    return color;\n}\n\nvar start;\n\nvar startTiming = function () {\n  start = performance.now();\n}\n\nvar stopTiming = function (name, min) {\n  if(min === undefined) min = 0;\n  var t = performance.now();\n  var roundedT = t - start;\n  if(roundedT > min) {\n    console.log(\"SLOW: \" + roundedT + \"ms: \" + name);\n  }\n  start = t\n}\n\nfunction previewImage (image) {\n  var win = window.open('', 'Title', 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, width='+image.width+', height='+image.height+', top=100, left=100');\n  win.document.body.innerHTML = '<div><img src= '+image.src+'></div>';\n}\n\nfunction intersectRect(r1, r2) {\n  return !(r2.left > r1.right || \n           r2.right < r1.left || \n           r2.top > r1.bottom ||\n           r2.bottom < r1.top);\n}\n\nvar GOOGLE_FONTS = [\n\"ABeeZee\",\"Abel\",\"Abhaya Libre\",\"Abril Fatface\",\"Aclonica\",\"Acme\",\"Actor\",\"Adamina\",\"Advent Pro\",\"Aguafina Script\",\"Akronim\",\"Aladin\",\"Aldrich\",\"Alef\",\"Alegreya\",\"Alegreya SC\",\"Alegreya Sans\",\"Alegreya Sans SC\",\"Alex Brush\",\"Alfa Slab One\",\"Alice\",\"Alike\",\"Alike Angular\",\"Allan\",\"Allerta\",\"Allerta Stencil\",\"Allura\",\"Almendra\",\"Almendra Display\",\"Almendra SC\",\"Amarante\",\"Amaranth\",\"Amatic SC\",\"Amatica SC\",\"Amethysta\",\"Amiko\",\"Amiri\",\"Amita\",\"Anaheim\",\"Andada\",\"Andika\",\"Angkor\",\"Annie Use Your Telescope\",\"Anonymous Pro\",\"Antic\",\"Antic Didone\",\"Antic Slab\",\"Anton\",\"Arapey\",\"Arbutus\",\"Arbutus Slab\",\"Architects Daughter\",\"Archivo\",\"Archivo Black\",\"Archivo Narrow\",\"Aref Ruqaa\",\"Arima Madurai\",\"Arimo\",\"Arizonia\",\"Armata\",\"Arsenal\",\"Artifika\",\"Arvo\",\"Arya\",\"Asap\",\"Asap Condensed\",\"Asar\",\"Asset\",\"Assistant\",\"Astloch\",\"Asul\",\"Athiti\",\"Atma\",\"Atomic Age\",\"Aubrey\",\"Audiowide\",\"Autour One\",\"Average\",\"Average Sans\",\"Averia Gruesa Libre\",\"Averia Libre\",\"Averia Sans Libre\",\"Averia Serif Libre\",\"Bad Script\",\"Bahiana\",\"Baloo\",\"Baloo Bhai\",\"Baloo Bhaijaan\",\"Baloo Bhaina\",\"Baloo Chettan\",\"Baloo Da\",\"Baloo Paaji\",\"Baloo Tamma\",\"Baloo Tammudu\",\"Baloo Thambi\",\"Balthazar\",\"Bangers\",\"Barrio\",\"Basic\",\"Battambang\",\"Baumans\",\"Bayon\",\"Belgrano\",\"Bellefair\",\"Belleza\",\"BenchNine\",\"Bentham\",\"Berkshire Swash\",\"Bevan\",\"Bigelow Rules\",\"Bigshot One\",\"Bilbo\",\"Bilbo Swash Caps\",\"BioRhyme\",\"BioRhyme Expanded\",\"Biryani\",\"Bitter\",\"Black Ops One\",\"Bokor\",\"Bonbon\",\"Boogaloo\",\"Bowlby One\",\"Bowlby One SC\",\"Brawler\",\"Bree Serif\",\"Bubblegum Sans\",\"Bubbler One\",\"Buda\",\"Buenard\",\"Bungee\",\"Bungee Hairline\",\"Bungee Inline\",\"Bungee Outline\",\"Bungee Shade\",\"Butcherman\",\"Butterfly Kids\",\"Cabin\",\"Cabin Condensed\",\"Cabin Sketch\",\"Caesar Dressing\",\"Cagliostro\",\"Cairo\",\"Calligraffitti\",\"Cambay\",\"Cambo\",\"Candal\",\"Cantarell\",\"Cantata One\",\"Cantora One\",\"Capriola\",\"Cardo\",\"Carme\",\"Carrois Gothic\",\"Carrois Gothic SC\",\"Carter One\",\"Catamaran\",\"Caudex\",\"Caveat\",\"Caveat Brush\",\"Cedarville Cursive\",\"Ceviche One\",\"Changa\",\"Changa One\",\"Chango\",\"Chathura\",\"Chau Philomene One\",\"Chela One\",\"Chelsea Market\",\"Chenla\",\"Cherry Cream Soda\",\"Cherry Swash\",\"Chewy\",\"Chicle\",\"Chivo\",\"Chonburi\",\"Cinzel\",\"Cinzel Decorative\",\"Clicker Script\",\"Coda\",\"Coda Caption\",\"Codystar\",\"Coiny\",\"Combo\",\"Comfortaa\",\"Coming Soon\",\"Concert One\",\"Condiment\",\"Content\",\"Contrail One\",\"Convergence\",\"Cookie\",\"Copse\",\"Corben\",\"Cormorant\",\"Cormorant Garamond\",\"Cormorant Infant\",\"Cormorant SC\",\"Cormorant Unicase\",\"Cormorant Upright\",\"Courgette\",\"Cousine\",\"Coustard\",\"Covered By Your Grace\",\"Crafty Girls\",\"Creepster\",\"Crete Round\",\"Crimson Text\",\"Croissant One\",\"Crushed\",\"Cuprum\",\"Cutive\",\"Cutive Mono\",\"Damion\",\"Dancing Script\",\"Dangrek\",\"David Libre\",\"Dawning of a New Day\",\"Days One\",\"Dekko\",\"Delius\",\"Delius Swash Caps\",\"Delius Unicase\",\"Della Respira\",\"Denk One\",\"Devonshire\",\"Dhurjati\",\"Didact Gothic\",\"Diplomata\",\"Diplomata SC\",\"Domine\",\"Donegal One\",\"Doppio One\",\"Dorsa\",\"Dosis\",\"Dr Sugiyama\",\"Droid Sans\",\"Droid Sans Mono\",\"Droid Serif\",\"Duru Sans\",\"Dynalight\",\"EB Garamond\",\"Eagle Lake\",\"Eater\",\"Economica\",\"Eczar\",\"El Messiri\",\"Electrolize\",\"Elsie\",\"Elsie Swash Caps\",\"Emblema One\",\"Emilys Candy\",\"Encode Sans\",\"Encode Sans Condensed\",\"Encode Sans Expanded\",\"Encode Sans Semi Condensed\",\"Encode Sans Semi Expanded\",\"Engagement\",\"Englebert\",\"Enriqueta\",\"Erica One\",\"Esteban\",\"Euphoria Script\",\"Ewert\",\"Exo\",\"Exo 2\",\"Expletus Sans\",\"Fanwood Text\",\"Farsan\",\"Fascinate\",\"Fascinate Inline\",\"Faster One\",\"Fasthand\",\"Fauna One\",\"Faustina\",\"Federant\",\"Federo\",\"Felipa\",\"Fenix\",\"Finger Paint\",\"Fira Mono\",\"Fira Sans\",\"Fira Sans Condensed\",\"Fira Sans Extra Condensed\",\"Fjalla One\",\"Fjord One\",\"Flamenco\",\"Flavors\",\"Fondamento\",\"Fontdiner Swanky\",\"Forum\",\"Francois One\",\"Frank Ruhl Libre\",\"Freckle Face\",\"Fredericka the Great\",\"Fredoka One\",\"Freehand\",\"Fresca\",\"Frijole\",\"Fruktur\",\"Fugaz One\",\"GFS Didot\",\"GFS Neohellenic\",\"Gabriela\",\"Gafata\",\"Galada\",\"Galdeano\",\"Galindo\",\"Gentium Basic\",\"Gentium Book Basic\",\"Geo\",\"Geostar\",\"Geostar Fill\",\"Germania One\",\"Gidugu\",\"Gilda Display\",\"Give You Glory\",\"Glass Antiqua\",\"Glegoo\",\"Gloria Hallelujah\",\"Goblin One\",\"Gochi Hand\",\"Gorditas\",\"Goudy Bookletter 1911\",\"Graduate\",\"Grand Hotel\",\"Gravitas One\",\"Great Vibes\",\"Griffy\",\"Gruppo\",\"Gudea\",\"Gurajada\",\"Habibi\",\"Halant\",\"Hammersmith One\",\"Hanalei\",\"Hanalei Fill\",\"Handlee\",\"Hanuman\",\"Happy Monkey\",\"Harmattan\",\"Headland One\",\"Heebo\",\"Henny Penny\",\"Herr Von Muellerhoff\",\"Hind\",\"Hind Guntur\",\"Hind Madurai\",\"Hind Siliguri\",\"Hind Vadodara\",\"Holtwood One SC\",\"Homemade Apple\",\"Homenaje\",\"IM Fell DW Pica\",\"IM Fell DW Pica SC\",\"IM Fell Double Pica\",\"IM Fell Double Pica SC\",\"IM Fell English\",\"IM Fell English SC\",\"IM Fell French Canon\",\"IM Fell French Canon SC\",\"IM Fell Great Primer\",\"IM Fell Great Primer SC\",\"Iceberg\",\"Iceland\",\"Imprima\",\"Inconsolata\",\"Inder\",\"Indie Flower\",\"Inika\",\"Inknut Antiqua\",\"Irish Grover\",\"Istok Web\",\"Italiana\",\"Italianno\",\"Itim\",\"Jacques Francois\",\"Jacques Francois Shadow\",\"Jaldi\",\"Jim Nightshade\",\"Jockey One\",\"Jolly Lodger\",\"Jomhuria\",\"Josefin Sans\",\"Josefin Slab\",\"Joti One\",\"Judson\",\"Julee\",\"Julius Sans One\",\"Junge\",\"Jura\",\"Just Another Hand\",\"Just Me Again Down Here\",\"Kadwa\",\"Kalam\",\"Kameron\",\"Kanit\",\"Kantumruy\",\"Karla\",\"Karma\",\"Katibeh\",\"Kaushan Script\",\"Kavivanar\",\"Kavoon\",\"Kdam Thmor\",\"Keania One\",\"Kelly Slab\",\"Kenia\",\"Khand\",\"Khmer\",\"Khula\",\"Kite One\",\"Knewave\",\"Kotta One\",\"Koulen\",\"Kranky\",\"Kreon\",\"Kristi\",\"Krona One\",\"Kumar One\",\"Kumar One Outline\",\"Kurale\",\"La Belle Aurore\",\"Laila\",\"Lakki Reddy\",\"Lalezar\",\"Lancelot\",\"Lateef\",\"Lato\",\"League Script\",\"Leckerli One\",\"Ledger\",\"Lekton\",\"Lemon\",\"Lemonada\",\"Libre Barcode 128\",\"Libre Barcode 128 Text\",\"Libre Barcode 39\",\"Libre Barcode 39 Extended\",\"Libre Barcode 39 Extended Text\",\"Libre Barcode 39 Text\",\"Libre Baskerville\",\"Libre Franklin\",\"Life Savers\",\"Lilita One\",\"Lily Script One\",\"Limelight\",\"Linden Hill\",\"Lobster\",\"Lobster Two\",\"Londrina Outline\",\"Londrina Shadow\",\"Londrina Sketch\",\"Londrina Solid\",\"Lora\",\"Love Ya Like A Sister\",\"Loved by the King\",\"Lovers Quarrel\",\"Luckiest Guy\",\"Lusitana\",\"Lustria\",\"Macondo\",\"Macondo Swash Caps\",\"Mada\",\"Magra\",\"Maiden Orange\",\"Maitree\",\"Mako\",\"Mallanna\",\"Mandali\",\"Manuale\",\"Marcellus\",\"Marcellus SC\",\"Marck Script\",\"Margarine\",\"Marko One\",\"Marmelad\",\"Martel\",\"Martel Sans\",\"Marvel\",\"Mate\",\"Mate SC\",\"Maven Pro\",\"McLaren\",\"Meddon\",\"MedievalSharp\",\"Medula One\",\"Meera Inimai\",\"Megrim\",\"Meie Script\",\"Merienda\",\"Merienda One\",\"Merriweather\",\"Merriweather Sans\",\"Metal\",\"Metal Mania\",\"Metamorphous\",\"Metrophobic\",\"Michroma\",\"Milonga\",\"Miltonian\",\"Miltonian Tattoo\",\"Miniver\",\"Miriam Libre\",\"Mirza\",\"Miss Fajardose\",\"Mitr\",\"Modak\",\"Modern Antiqua\",\"Mogra\",\"Molengo\",\"Molle\",\"Monda\",\"Monofett\",\"Monoton\",\"Monsieur La Doulaise\",\"Montaga\",\"Montez\",\"Montserrat\",\"Montserrat Alternates\",\"Montserrat Subrayada\",\"Moul\",\"Moulpali\",\"Mountains of Christmas\",\"Mouse Memoirs\",\"Mr Bedfort\",\"Mr Dafoe\",\"Mr De Haviland\",\"Mrs Saint Delafield\",\"Mrs Sheppards\",\"Mukta\",\"Mukta Mahee\",\"Mukta Malar\",\"Mukta Vaani\",\"Muli\",\"Mystery Quest\",\"NTR\",\"Neucha\",\"Neuton\",\"New Rocker\",\"News Cycle\",\"Niconne\",\"Nixie One\",\"Nobile\",\"Nokora\",\"Norican\",\"Nosifer\",\"Nothing You Could Do\",\"Noticia Text\",\"Noto Sans\",\"Noto Serif\",\"Nova Cut\",\"Nova Flat\",\"Nova Mono\",\"Nova Oval\",\"Nova Round\",\"Nova Script\",\"Nova Slim\",\"Nova Square\",\"Numans\",\"Nunito\",\"Nunito Sans\",\"Odor Mean Chey\",\"Offside\",\"Old Standard TT\",\"Oldenburg\",\"Oleo Script\",\"Oleo Script Swash Caps\",\"Open Sans\",\"Open Sans Condensed\",\"Oranienbaum\",\"Orbitron\",\"Oregano\",\"Orienta\",\"Original Surfer\",\"Oswald\",\"Over the Rainbow\",\"Overlock\",\"Overlock SC\",\"Overpass\",\"Overpass Mono\",\"Ovo\",\"Oxygen\",\"Oxygen Mono\",\"PT Mono\",\"PT Sans\",\"PT Sans Caption\",\"PT Sans Narrow\",\"PT Serif\",\"PT Serif Caption\",\"Pacifico\",\"Padauk\",\"Palanquin\",\"Palanquin Dark\",\"Pangolin\",\"Paprika\",\"Parisienne\",\"Passero One\",\"Passion One\",\"Pathway Gothic One\",\"Patrick Hand\",\"Patrick Hand SC\",\"Pattaya\",\"Patua One\",\"Pavanam\",\"Paytone One\",\"Peddana\",\"Peralta\",\"Permanent Marker\",\"Petit Formal Script\",\"Petrona\",\"Philosopher\",\"Piedra\",\"Pinyon Script\",\"Pirata One\",\"Plaster\",\"Play\",\"Playball\",\"Playfair Display\",\"Playfair Display SC\",\"Podkova\",\"Poiret One\",\"Poller One\",\"Poly\",\"Pompiere\",\"Pontano Sans\",\"Poppins\",\"Port Lligat Sans\",\"Port Lligat Slab\",\"Pragati Narrow\",\"Prata\",\"Preahvihear\",\"Press Start 2P\",\"Pridi\",\"Princess Sofia\",\"Prociono\",\"Prompt\",\"Prosto One\",\"Proza Libre\",\"Puritan\",\"Purple Purse\",\"Quando\",\"Quantico\",\"Quattrocento\",\"Quattrocento Sans\",\"Questrial\",\"Quicksand\",\"Quintessential\",\"Qwigley\",\"Racing Sans One\",\"Radley\",\"Rajdhani\",\"Rakkas\",\"Raleway\",\"Raleway Dots\",\"Ramabhadra\",\"Ramaraja\",\"Rambla\",\"Rammetto One\",\"Ranchers\",\"Rancho\",\"Ranga\",\"Rasa\",\"Rationale\",\"Ravi Prakash\",\"Redressed\",\"Reem Kufi\",\"Reenie Beanie\",\"Revalia\",\"Rhodium Libre\",\"Ribeye\",\"Ribeye Marrow\",\"Righteous\",\"Risque\",\"Roboto\",\"Roboto Condensed\",\"Roboto Mono\",\"Roboto Slab\",\"Rochester\",\"Rock Salt\",\"Rokkitt\",\"Romanesco\",\"Ropa Sans\",\"Rosario\",\"Rosarivo\",\"Rouge Script\",\"Rozha One\",\"Rubik\",\"Rubik Mono One\",\"Ruda\",\"Rufina\",\"Ruge Boogie\",\"Ruluko\",\"Rum Raisin\",\"Ruslan Display\",\"Russo One\",\"Ruthie\",\"Rye\",\"Sacramento\",\"Sahitya\",\"Sail\",\"Saira\",\"Saira Condensed\",\"Saira Extra Condensed\",\"Saira Semi Condensed\",\"Salsa\",\"Sanchez\",\"Sancreek\",\"Sansita\",\"Sarala\",\"Sarina\",\"Sarpanch\",\"Satisfy\",\"Scada\",\"Scheherazade\",\"Schoolbell\",\"Scope One\",\"Seaweed Script\",\"Secular One\",\"Sedgwick Ave\",\"Sedgwick Ave Display\",\"Sevillana\",\"Seymour One\",\"Shadows Into Light\",\"Shadows Into Light Two\",\"Shanti\",\"Share\",\"Share Tech\",\"Share Tech Mono\",\"Shojumaru\",\"Short Stack\",\"Shrikhand\",\"Siemreap\",\"Sigmar One\",\"Signika\",\"Signika Negative\",\"Simonetta\",\"Sintony\",\"Sirin Stencil\",\"Six Caps\",\"Skranji\",\"Slabo 13px\",\"Slabo 27px\",\"Slackey\",\"Smokum\",\"Smythe\",\"Sniglet\",\"Snippet\",\"Snowburst One\",\"Sofadi One\",\"Sofia\",\"Sonsie One\",\"Sorts Mill Goudy\",\"Source Code Pro\",\"Source Sans Pro\",\"Source Serif Pro\",\"Space Mono\",\"Special Elite\",\"Spectral\",\"Spicy Rice\",\"Spinnaker\",\"Spirax\",\"Squada One\",\"Sree Krushnadevaraya\",\"Sriracha\",\"Stalemate\",\"Stalinist One\",\"Stardos Stencil\",\"Stint Ultra Condensed\",\"Stint Ultra Expanded\",\"Stoke\",\"Strait\",\"Sue Ellen Francisco\",\"Suez One\",\"Sumana\",\"Sunshiney\",\"Supermercado One\",\"Sura\",\"Suranna\",\"Suravaram\",\"Suwannaphum\",\"Swanky and Moo Moo\",\"Syncopate\",\"Tangerine\",\"Taprom\",\"Tauri\",\"Taviraj\",\"Teko\",\"Telex\",\"Tenali Ramakrishna\",\"Tenor Sans\",\"Text Me One\",\"The Girl Next Door\",\"Tienne\",\"Tillana\",\"Timmana\",\"Tinos\",\"Titan One\",\"Titillium Web\",\"Trade Winds\",\"Trirong\",\"Trocchi\",\"Trochut\",\"Trykker\",\"Tulpen One\",\"Ubuntu\",\"Ubuntu Condensed\",\"Ubuntu Mono\",\"Ultra\",\"Uncial Antiqua\",\"Underdog\",\"Unica One\",\"UnifrakturCook\",\"UnifrakturMaguntia\",\"Unkempt\",\"Unlock\",\"Unna\",\"VT323\",\"Vampiro One\",\"Varela\",\"Varela Round\",\"Vast Shadow\",\"Vesper Libre\",\"Vibur\",\"Vidaloka\",\"Viga\",\"Voces\",\"Volkhov\",\"Vollkorn\",\"Voltaire\",\"Waiting for the Sunrise\",\"Wallpoet\",\"Walter Turncoat\",\"Warnes\",\"Wellfleet\",\"Wendy One\",\"Wire One\",\"Work Sans\",\"Yanone Kaffeesatz\",\"Yantramanav\",\"Yatra One\",\"Yellowtail\",\"Yeseva One\",\"Yesteryear\",\"Yrsa\",\"Zeyada\",\"Zilla Slab\",\"Zilla Slab Highlight\"]\nfunction getAllGoogleFonts () {\n  return GOOGLE_FONTS;\n}\n\nfunction loadGoogleFonts (fontFamilyArray, callback) {\n  if(fontFamilyArray.length === 0) return;\n  WebFont.load({\n    google: {\n      families: fontFamilyArray,\n    },\n    active: callback,\n  });\n}\n\n// https://stackoverflow.com/questions/20958078/resize-a-base-64-image-in-javascript-without-using-canvas\n// Takes a data URI and returns the Data URI corresponding to the resized image at the wanted size.\nfunction resizedataURL(datas, wantedWidth, wantedHeight, callback, jpeg)\n    {\n        // We create an image to receive the Data URI\n        var img = document.createElement('img');\n\n        // When the event \"onload\" is triggered we can resize the image.\n        img.onload = function()\n            {        \n                // We create a canvas and get its context.\n                var canvas = document.createElement('canvas');\n                var ctx = canvas.getContext('2d');\n\n                // We set the dimensions at the wanted size.\n                canvas.width = wantedWidth;\n                canvas.height = wantedHeight;\n\n                // We resize the image with the canvas method drawImage();\n                ctx.drawImage(this, 0, 0, wantedWidth, wantedHeight);\n\n                var dataURI\n                if(jpeg) {\n                   dataURI = canvas.toDataURL('image/jpeg', 1.0);\n                } else {\n                    dataURI = canvas.toDataURL();\n                }\n\n                callback(dataURI);\n            };\n\n        // We put the Data URI in the image's src attribute\n        img.src = datas;\n    }\n// Use it like that : resizedataURL('yourDataURIHere', 50, 50);\n\n//https://gist.github.com/borismus/1032746\nvar BASE64_MARKER = ';base64,';\n\nfunction convertDataURIToBinary(dataURI) {\n  var base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;\n  var base64 = dataURI.substring(base64Index);\n  var raw = window.atob(base64);\n  var rawLength = raw.length;\n  var array = new Uint8Array(new ArrayBuffer(rawLength));\n\n  for(i = 0; i < rawLength; i++) {\n    array[i] = raw.charCodeAt(i);\n  }\n  return array;\n}\n\nfunction zeroFill( number, width )\n{\n  width -= number.toString().length;\n  if ( width > 0 )\n  {\n    return new Array( width + (/\\./.test( number ) ? 2 : 1) ).join( '0' ) + number;\n  }\n  return number + \"\"; // always return a string\n}\n"
  },
  {
    "path": "lib/potrace.js",
    "content": "/* \n * A javascript port of Potrace (http://potrace.sourceforge.net).\n *  \n * This is a fork of potrace.js with some modifications (see comments with zrispo). \n * \n * Licensed under the GPL\n * \n * Usage\n *   loadImageFromFile(file) : load image from File API\n *   loadImageFromUrl(url): load image from URL\n *     because of the same-origin policy, can not load image from another domain.\n *     input color/grayscale image is simply converted to binary image. no pre-\n *     process is performed.\n * \n *   setParameter({para1: value, ...}) : set parameters\n *     parameters:\n *        turnpolicy (\"black\" / \"white\" / \"left\" / \"right\" / \"minority\" / \"majority\")\n *          how to resolve ambiguities in path decomposition. (default: \"minority\")       \n *        turdsize\n *          suppress speckles of up to this size (default: 2)\n *        optcurve (true / false)\n *          turn on/off curve optimization (default: true)\n *        alphamax\n *          corner threshold parameter (default: 1)\n *        opttolerance \n *          curve optimization tolerance (default: 0.2)\n *       \n *   process(callback) : wait for the image be loaded, then run potrace algorithm,\n *                       then call callback function.\n * \n *   getSVG: getSVG(size, opt_type) : return a string of generated SVG image.\n *                                    result_image_size = original_image_size * size\n *                                    optional parameter opt_type can be \"curve\"\n */\n\nvar Potrace = function() {\n\n  function Point(x, y) {\n    this.x = x;\n    this.y = y;\n  }\n  \n  Point.prototype.copy = function(){\n    return new Point(this.x, this.y);\n  };\n\n  function Bitmap(w, h) {\n    this.w = w;\n    this.h = h;\n    this.size = w * h;\n    this.arraybuffer = new ArrayBuffer(this.size);\n    this.data = new Int8Array(this.arraybuffer);\n  }\n\n  Bitmap.prototype.at = function (x, y) {\n    return (x >= 0 && x < this.w && y >=0 && y < this.h) && \n        this.data[this.w * y + x] === 1;\n  };\n\n  Bitmap.prototype.index = function(i) {\n    var point = new Point();\n    point.y = Math.floor(i / this.w);\n    point.x = i - point.y * this.w;\n    return point;\n  };\n\n  Bitmap.prototype.flip = function(x, y) {\n    if (this.at(x, y)) {\n      this.data[this.w * y + x] = 0;\n    } else {\n      this.data[this.w * y + x] = 1;\n    }\n  };\n    \n  Bitmap.prototype.copy = function() {\n    var bm = new Bitmap(this.w, this.h), i;\n    for (i = 0; i < this.size; i++) {\n      bm.data[i] = this.data[i];\n    }\n    return bm;\n  };\n\n  function Path() {\n    this.area = 0;\n    this.len = 0;\n    this.curve = {};\n    this.pt = [];\n    this.minX = 100000;\n    this.minY = 100000;\n    this.maxX= -1;\n    this.maxY = -1;\n  }\n\n  function Curve(n) {\n    this.n = n;\n    this.tag = new Array(n);\n    this.c = new Array(n * 3);\n    this.alphaCurve = 0;\n    this.vertex = new Array(n);\n    this.alpha = new Array(n);\n    this.alpha0 = new Array(n);\n    this.beta = new Array(n);\n  }\n\n  var imgElement = document.createElement(\"img\"),\n      imgCanvas = document.createElement(\"canvas\"),\n      bm = null,\n      pathlist = [],\n      callback,\n      info = {\n        isReady: false,\n        turnpolicy: \"black\", \n        turdsize: 2,\n        optcurve: false,\n        alphamax: 1,\n        opttolerance: 1.0\n      };\n\n  imgElement.onload = function() {\n    loadCanvas();\n    loadBm();\n  };\n\n  // zrispo - \n  // Added this method so we don't have to convert a dataURL to a File to pass it to potrace.js.\n  function loadImageFromDataURL(src) {\n    if (info.isReady) {\n      clear();\n    }\n    imgElement.src = src;\n  }\n\n  function loadImageFromFile(file) {\n    if (info.isReady) {\n      clear();\n    }\n    imgElement.file = file;\n    var reader = new FileReader();\n    reader.onload = (function(aImg) {\n      return function(e) {\n        aImg.src = e.target.result;\n      };\n    })(imgElement);\n    reader.readAsDataURL(file);\n  }\n  \n  function loadImageFromUrl(url) {\n    if (info.isReady) {\n      clear();\n    }\n    imgElement.src = url;\n    \n  }\n  \n  function setParameter(obj) {\n   var key;\n   for (key in obj) {\n     if (obj.hasOwnProperty(key)) {\n       info[key] = obj[key];\n     }\n    }\n  }\n  \n  function loadCanvas() {\n    imgCanvas.width = imgElement.width;\n    imgCanvas.height = imgElement.height;\n    var ctx = imgCanvas.getContext('2d');\n    ctx.drawImage(imgElement, 0, 0);\n  }\n  \n  function loadBm() {\n    var ctx = imgCanvas.getContext('2d');\n    bm = new Bitmap(imgCanvas.width, imgCanvas.height);\n    var imgdataobj = ctx.getImageData(0, 0, bm.w, bm.h);\n    var l = imgdataobj.data.length, i, j, color;\n    for (i = 0, j = 0; i < l; i += 4, j++) {\n      // zrispo - transparency lower that a certain threshold sets color to 0.\n      var alphaThreshold = 100;\n      if(imgdataobj.data[i+3] < alphaThreshold) {\n        bm.data[j] = 0;\n      } else {\n        bm.data[j] = 1;\n      }\n    }\n    info.isReady = true;\n  }\n  \n  \n  function bmToPathlist() {\n  \n    var bm1 = bm.copy(),\n      currentPoint = new Point(0, 0),\n      path;\n    \n    function findNext(point) {\n      var i = bm1.w * point.y + point.x;\n      while (i < bm1.size && bm1.data[i] !== 1) {\n        i++;\n      }\n      return i < bm1.size && bm1.index(i);\n    }\n    \n    function majority(x, y) {\n      var i, a, ct;\n      for (i = 2; i < 5; i++) {\n        ct = 0;\n        for (a = -i + 1; a <= i - 1; a++) {\n          ct += bm1.at(x + a, y + i - 1) ? 1 : -1;\n          ct += bm1.at(x + i - 1, y + a - 1) ? 1 : -1;\n          ct += bm1.at(x + a - 1, y - i) ? 1 : -1;\n          ct += bm1.at(x - i, y + a) ? 1 : -1;\n        }\n        if (ct > 0) {\n          return 1;\n        } else if (ct < 0) {\n          return 0;\n        }\n      }\n      return 0;\n    }\n    \n    function findPath(point) {\n      var path = new Path(),\n        x = point.x, y = point.y,\n        dirx = 0, diry = 1, tmp;\n      \n      path.sign = bm.at(point.x, point.y) ? \"+\" : \"-\";\n      \n      while (1) {\n        path.pt.push(new Point(x, y));\n        if (x > path.maxX)\n          path.maxX = x;\n        if (x < path.minX)\n          path.minX = x;\n        if (y > path.maxY)\n          path.maxY = y;\n        if (y < path.minY)\n          path.minY = y;\n        path.len++;\n        \n        x += dirx;\n        y += diry;\n        path.area -= x * diry;\n        \n        if (x === point.x && y === point.y)\n          break;\n        \n        var l = bm1.at(x + (dirx + diry - 1 ) / 2, y + (diry - dirx - 1) / 2);\n        var r = bm1.at(x + (dirx - diry - 1) / 2, y + (diry + dirx - 1) / 2);\n        \n        if (r && !l) {\n          if (info.turnpolicy === \"right\" ||\n          (info.turnpolicy === \"black\" && path.sign === '+') ||\n          (info.turnpolicy === \"white\" && path.sign === '-') ||\n          (info.turnpolicy === \"majority\" && majority(x, y)) ||\n          (info.turnpolicy === \"minority\" && !majority(x, y))) {\n            tmp = dirx;\n            dirx = -diry;\n            diry = tmp;\n          } else {\n            tmp = dirx;\n            dirx = diry;\n            diry = -tmp;\n          }\n        } else if (r) {\n          tmp = dirx;\n          dirx = -diry;\n          diry = tmp;\n        } else if (!l) {\n          tmp = dirx;\n          dirx = diry;\n          diry = -tmp;\n        }\n      }\n      return path;\n    }\n    \n    function xorPath(path){\n      var y1 = path.pt[0].y,\n        len = path.len,\n        x, y, maxX, minY, i, j;\n      for (i = 1; i < len; i++) {\n        x = path.pt[i].x;\n        y = path.pt[i].y;\n        \n        if (y !== y1) {\n          minY = y1 < y ? y1 : y;\n          maxX = path.maxX;\n          for (j = x; j < maxX; j++) {\n            bm1.flip(j, minY);\n          }\n          y1 = y;\n        }\n      }\n      \n    }\n    \n    while (currentPoint = findNext(currentPoint)) {\n\n      path = findPath(currentPoint);\n      \n      xorPath(path);\n      \n      if (path.area > info.turdsize) {\n        pathlist.push(path);\n      }\n    }\n    \n  }\n  \n\n  function processPath() {\n  \n    function Quad() {\n      this.data = [0,0,0,0,0,0,0,0,0];\n    }\n\n    Quad.prototype.at = function(x, y) {\n      return this.data[x * 3 + y];\n    };\n    \n    function Sum(x, y, xy, x2, y2) {\n      this.x = x;\n      this.y = y;\n      this.xy = xy;\n      this.x2 = x2;\n      this.y2 = y2;\n    }\n    \n    function mod(a, n) {\n        return a >= n ? a % n : a>=0 ? a : n-1-(-1-a) % n;\n    }\n  \n    function xprod(p1, p2) {\n      return p1.x * p2.y - p1.y * p2.x;\n    }\n    \n    function cyclic(a, b, c) {\n      if (a <= c) {\n        return (a <= b && b < c);\n      } else {\n        return (a <= b || b < c);\n      }\n    }\n      \n    function sign(i) {\n      return i > 0 ? 1 : i < 0 ? -1 : 0;\n    }\n    \n    function quadform(Q, w) {\n      var v = new Array(3), i, j, sum;\n    \n      v[0] = w.x;\n      v[1] = w.y;\n      v[2] = 1;\n      sum = 0.0;\n    \n      for (i=0; i<3; i++) {\n        for (j=0; j<3; j++) {\n          sum += v[i] * Q.at(i, j) * v[j];\n        }\n      }\n      return sum;\n    }\n  \n    function interval(lambda, a, b) {\n      var res = new Point();\n    \n      res.x = a.x + lambda * (b.x - a.x);\n      res.y = a.y + lambda * (b.y - a.y);\n      return res;\n    }\n    \n    function dorth_infty(p0, p2) {\n      var r = new Point();\n      \n      r.y = sign(p2.x - p0.x);\n      r.x = -sign(p2.y - p0.y);\n    \n      return r;\n    }\n    \n    function ddenom(p0, p2) {\n      var r = dorth_infty(p0, p2);\n    \n      return r.y * (p2.x - p0.x) - r.x * (p2.y - p0.y);\n    }\n    \n    function dpara(p0, p1, p2) {\n      var x1, y1, x2, y2;\n    \n      x1 = p1.x - p0.x;\n      y1 = p1.y - p0.y;\n      x2 = p2.x - p0.x;\n      y2 = p2.y - p0.y;\n    \n      return x1 * y2 - x2 * y1;\n    }\n    \n    function cprod(p0, p1, p2, p3) {\n      var x1, y1, x2, y2;\n    \n      x1 = p1.x - p0.x;\n      y1 = p1.y - p0.y;\n      x2 = p3.x - p2.x;\n      y2 = p3.y - p2.y;\n    \n      return x1 * y2 - x2 * y1;\n    }\n      \n    function iprod(p0, p1, p2) {\n      var x1, y1, x2, y2;\n    \n      x1 = p1.x - p0.x;\n      y1 = p1.y - p0.y;\n      x2 = p2.x - p0.x;\n      y2 = p2.y - p0.y;\n    \n      return x1*x2 + y1*y2;\n    }\n      \n    function iprod1(p0, p1, p2, p3) {\n      var x1, y1, x2, y2;\n    \n      x1 = p1.x - p0.x;\n      y1 = p1.y - p0.y;\n      x2 = p3.x - p2.x;\n      y2 = p3.y - p2.y;\n    \n      return x1 * x2 + y1 * y2;\n    }\n    \n    function ddist(p, q) {\n      return Math.sqrt((p.x - q.x) * (p.x - q.x) + (p.y - q.y) * (p.y - q.y));\n    }\n    \n    function bezier(t, p0, p1, p2, p3) {\n      var s = 1 - t, res = new Point();\n    \n      res.x = s*s*s*p0.x + 3*(s*s*t)*p1.x + 3*(t*t*s)*p2.x + t*t*t*p3.x;\n      res.y = s*s*s*p0.y + 3*(s*s*t)*p1.y + 3*(t*t*s)*p2.y + t*t*t*p3.y;\n    \n      return res;\n    }\n  \n    function tangent(p0, p1, p2, p3, q0, q1) {\n      var A, B, C, a, b, c, d, s, r1, r2;\n    \n      A = cprod(p0, p1, q0, q1);\n      B = cprod(p1, p2, q0, q1);\n      C = cprod(p2, p3, q0, q1);\n    \n      a = A - 2 * B + C;\n      b = -2 * A + 2 * B;\n      c = A;\n      \n      d = b * b - 4 * a * c;\n    \n      if (a===0 || d<0) {\n        return -1.0;\n      }\n    \n      s = Math.sqrt(d);\n    \n      r1 = (-b + s) / (2 * a);\n      r2 = (-b - s) / (2 * a);\n    \n      if (r1 >= 0 && r1 <= 1) {\n        return r1;\n      } else if (r2 >= 0 && r2 <= 1) {\n        return r2;\n      } else {\n        return -1.0;\n      }\n    }\n    \n    function calcSums(path) {\n      var i, x, y;\n      path.x0 = path.pt[0].x;\n      path.y0 = path.pt[0].y;\n      \n      path.sums = [];\n      var s = path.sums;\n      s.push(new Sum(0, 0, 0, 0, 0));\n      for(i = 0; i < path.len; i++){\n        x = path.pt[i].x - path.x0;\n        y = path.pt[i].y - path.y0;\n        s.push(new Sum(s[i].x + x, s[i].y + y, s[i].xy + x * y,\n            s[i].x2 + x * x, s[i].y2 + y * y));\n      }\n    }\n   \n    function calcLon(path) {\n      \n      var n = path.len, pt = path.pt, dir,\n        pivk = new Array(n),\n        nc = new Array(n),\n        ct = new Array(4);\n      path.lon = new Array(n);\n      \n      var constraint = [new Point(), new Point()],\n          cur = new Point(),\n          off = new Point(),\n          dk = new Point(),\n          foundk;\n      \n      var i, j, k1, a, b, c, d, k = 0;\n      for(i = n - 1; i >= 0; i--){\n        if (pt[i].x != pt[k].x && pt[i].y != pt[k].y) {\n          k = i + 1;\n        }\n        nc[i] = k;\n      }\n      \n      for (i = n - 1; i >= 0; i--) {\n        ct[0] = ct[1] = ct[2] = ct[3] = 0;\n        dir = (3 + 3 * (pt[mod(i + 1, n)].x - pt[i].x) + \n            (pt[mod(i + 1, n)].y - pt[i].y)) / 2;\n        ct[dir]++;\n        \n        constraint[0].x = 0;\n        constraint[0].y = 0;\n        constraint[1].x = 0;\n        constraint[1].y = 0;\n        \n        k = nc[i];\n        k1 = i;\n        while (1) {\n          foundk = 0;\n          dir =  (3 + 3 * sign(pt[k].x - pt[k1].x) + \n              sign(pt[k].y - pt[k1].y)) / 2;\n          ct[dir]++;\n          \n          if (ct[0] && ct[1] && ct[2] && ct[3]) {\n            pivk[i] = k1;\n            foundk = 1;\n            break;\n          }\n          \n          cur.x = pt[k].x - pt[i].x;\n          cur.y = pt[k].y - pt[i].y;\n          \n          if (xprod(constraint[0], cur) < 0 || xprod(constraint[1], cur) > 0) {\n            break;\n          }\n              \n          if (Math.abs(cur.x) <= 1 && Math.abs(cur.y) <= 1) {\n          \n          } else {\n            off.x = cur.x + ((cur.y >= 0 && (cur.y > 0 || cur.x < 0)) ? 1 : -1);\n            off.y = cur.y + ((cur.x <= 0 && (cur.x < 0 || cur.y < 0)) ? 1 : -1);\n            if (xprod(constraint[0], off) >= 0) {\n              constraint[0].x = off.x;\n              constraint[0].y = off.y;\n            }\n            off.x = cur.x + ((cur.y <= 0 && (cur.y < 0 || cur.x < 0)) ? 1 : -1);\n            off.y = cur.y + ((cur.x >= 0 && (cur.x > 0 || cur.y < 0)) ? 1 : -1);\n            if (xprod(constraint[1], off) <= 0) {\n              constraint[1].x = off.x;\n              constraint[1].y = off.y;\n            }\n          }\n          k1 = k;\n          k = nc[k1];\n          if (!cyclic(k, i, k1)) {\n            break;\n          }\n        }\n        if (foundk === 0) {\n          dk.x = sign(pt[k].x-pt[k1].x);\n          dk.y = sign(pt[k].y-pt[k1].y);\n          cur.x = pt[k1].x - pt[i].x;\n          cur.y = pt[k1].y - pt[i].y;\n  \n          a = xprod(constraint[0], cur);\n          b = xprod(constraint[0], dk);\n          c = xprod(constraint[1], cur);\n          d = xprod(constraint[1], dk);\n  \n          j = 10000000;\n          if (b < 0) {\n            j = Math.floor(a / -b);\n          }\n          if (d > 0) {\n            j = Math.min(j, Math.floor(-c / d));\n          }\n          pivk[i] = mod(k1+j,n);\n        }\n      }\n      \n      j=pivk[n-1];\n      path.lon[n-1]=j;\n      for (i=n-2; i>=0; i--) {\n        if (cyclic(i+1,pivk[i],j)) {\n          j=pivk[i];\n        }\n        path.lon[i]=j;\n      }\n  \n      for (i=n-1; cyclic(mod(i+1,n),j,path.lon[i]); i--) {\n        path.lon[i] = j;\n      }\n    }\n    \n    function bestPolygon(path) {\n      \n      function penalty3(path, i, j) {\n        \n        var n = path.len, pt = path.pt, sums = path.sums;\n        var x, y, xy, x2, y2,\n          k, a, b, c, s,\n          px, py, ex, ey,\n          r = 0;\n        if (j>=n) {\n          j -= n;\n          r = 1;\n        }\n        \n        if (r === 0) {\n          x = sums[j+1].x - sums[i].x;\n          y = sums[j+1].y - sums[i].y;\n          x2 = sums[j+1].x2 - sums[i].x2;\n          xy = sums[j+1].xy - sums[i].xy;\n          y2 = sums[j+1].y2 - sums[i].y2;\n          k = j+1 - i;\n        } else {\n          x = sums[j+1].x - sums[i].x + sums[n].x;\n          y = sums[j+1].y - sums[i].y + sums[n].y;\n          x2 = sums[j+1].x2 - sums[i].x2 + sums[n].x2;\n          xy = sums[j+1].xy - sums[i].xy + sums[n].xy;\n          y2 = sums[j+1].y2 - sums[i].y2 + sums[n].y2;\n          k = j+1 - i + n;\n        } \n      \n        px = (pt[i].x + pt[j].x) / 2.0 - pt[0].x;\n        py = (pt[i].y + pt[j].y) / 2.0 - pt[0].y;\n        ey = (pt[j].x - pt[i].x);\n        ex = -(pt[j].y - pt[i].y);\n      \n        a = ((x2 - 2*x*px) / k + px*px);\n        b = ((xy - x*py - y*px) / k + px*py);\n        c = ((y2 - 2*y*py) / k + py*py);\n        \n        s = ex*ex*a + 2*ex*ey*b + ey*ey*c;\n      \n        return Math.sqrt(s);\n      }\n      \n      var i, j, m, k,    \n      n = path.len,\n      pen = new Array(n + 1),\n      prev = new Array(n + 1),\n      clip0 = new Array(n),\n      clip1 = new Array(n + 1),\n      seg0 = new Array (n + 1),\n      seg1 = new Array(n + 1),\n      thispen, best, c;\n      \n      for (i=0; i<n; i++) {\n        c = mod(path.lon[mod(i-1,n)]-1,n);\n        if (c == i) {\n          c = mod(i+1,n);\n        }\n        if (c < i) {\n          clip0[i] = n;\n        } else {\n          clip0[i] = c;\n        }\n      }\n      \n      j = 1;\n      for (i=0; i<n; i++) {\n        while (j <= clip0[i]) {\n          clip1[j] = i;\n          j++;\n        }\n      }\n      \n      i = 0;\n      for (j=0; i<n; j++) {\n        seg0[j] = i;\n        i = clip0[i];\n      }\n      seg0[j] = n;\n      m = j;\n    \n      i = n;\n      for (j=m; j>0; j--) {\n        seg1[j] = i;\n        i = clip1[i];\n      }\n      seg1[0] = 0;\n      \n      pen[0]=0;\n      for (j=1; j<=m; j++) {\n        for (i=seg1[j]; i<=seg0[j]; i++) {\n          best = -1;\n          for (k=seg0[j-1]; k>=clip1[i]; k--) {\n            thispen = penalty3(path, k, i) + pen[k];\n            if (best < 0 || thispen < best) {\n              prev[i] = k;\n              best = thispen;\n            }\n          }\n          pen[i] = best;\n        }\n      }\n      path.m = m;\n      path.po = new Array(m);\n    \n      for (i=n, j=m-1; i>0; j--) {\n        i = prev[i];\n        path.po[j] = i;\n      }\n    }\n    \n    function adjustVertices(path) {\n      \n      function pointslope(path, i, j, ctr, dir) {\n    \n        var n = path.len, sums = path.sums,\n          x, y, x2, xy, y2,\n          k, a, b, c, lambda2, l, r=0;\n      \n        while (j>=n) {\n          j-=n;\n          r+=1;\n        }\n        while (i>=n) {\n          i-=n;\n          r-=1;\n        }\n        while (j<0) {\n          j+=n;\n          r-=1;\n        }\n        while (i<0) {\n          i+=n;\n          r+=1;\n        }\n        \n        x = sums[j+1].x-sums[i].x+r*sums[n].x;\n        y = sums[j+1].y-sums[i].y+r*sums[n].y;\n        x2 = sums[j+1].x2-sums[i].x2+r*sums[n].x2;\n        xy = sums[j+1].xy-sums[i].xy+r*sums[n].xy;\n        y2 = sums[j+1].y2-sums[i].y2+r*sums[n].y2;\n        k = j+1-i+r*n;\n        \n        ctr.x = x/k;\n        ctr.y = y/k;\n      \n        a = (x2-x*x/k)/k;\n        b = (xy-x*y/k)/k;\n        c = (y2-y*y/k)/k;\n        \n        lambda2 = (a+c+Math.sqrt((a-c)*(a-c)+4*b*b))/2;\n      \n        a -= lambda2;\n        c -= lambda2;\n      \n        if (Math.abs(a) >= Math.abs(c)) {\n          l = Math.sqrt(a*a+b*b);\n          if (l!==0) {\n            dir.x = -b/l;\n            dir.y = a/l;\n          }\n        } else {\n          l = Math.sqrt(c*c+b*b);\n          if (l!==0) {\n            dir.x = -c/l;\n            dir.y = b/l;\n          }\n        }\n        if (l===0) {\n          dir.x = dir.y = 0; \n        }\n      }\n      \n      var m = path.m, po = path.po, n = path.len, pt = path.pt,\n        x0 = path.x0, y0 = path.y0,\n        ctr = new Array(m), dir = new Array(m),\n        q = new Array(m),\n        v = new Array(3), d, i, j, k, l,\n        s = new Point();\n      \n      path.curve = new Curve(m);\n  \n      for (i=0; i<m; i++) {\n        j = po[mod(i+1,m)];\n        j = mod(j-po[i],n)+po[i];\n        ctr[i] = new Point();\n        dir[i] = new Point();\n        pointslope(path, po[i], j, ctr[i], dir[i]);\n      }\n    \n      for (i=0; i<m; i++) {\n        q[i] = new Quad();\n        d = dir[i].x * dir[i].x + dir[i].y * dir[i].y;\n        if (d === 0.0) {\n          for (j=0; j<3; j++) {\n            for (k=0; k<3; k++) {\n              q[i].data[j * 3 + k] = 0;\n            }\n          }\n        } else {\n          v[0] = dir[i].y;\n          v[1] = -dir[i].x;\n          v[2] = - v[1] * ctr[i].y - v[0] * ctr[i].x;\n          for (l=0; l<3; l++) {\n            for (k=0; k<3; k++) {\n              q[i].data[l * 3 + k] = v[l] * v[k] / d;\n            }\n          }\n        }\n      }\n     \n      var Q, w, dx, dy, det, min, cand, xmin, ymin, z;\n      for (i=0; i<m; i++) {\n        Q = new Quad();\n        w = new Point();\n    \n        s.x = pt[po[i]].x-x0;\n        s.y = pt[po[i]].y-y0;\n    \n        j = mod(i-1,m);\n        \n        for (l=0; l<3; l++) {\n          for (k=0; k<3; k++) {\n            Q.data[l * 3 + k] = q[j].at(l, k) + q[i].at(l, k);\n          }\n        }\n        \n        while(1) {\n          \n          det = Q.at(0, 0)*Q.at(1, 1) - Q.at(0, 1)*Q.at(1, 0);\n          if (det !== 0.0) {\n            w.x = (-Q.at(0, 2)*Q.at(1, 1) + Q.at(1, 2)*Q.at(0, 1)) / det;\n            w.y = ( Q.at(0, 2)*Q.at(1, 0) - Q.at(1, 2)*Q.at(0, 0)) / det;\n            break;\n          }\n    \n          if (Q.at(0, 0)>Q.at(1, 1)) {\n            v[0] = -Q.at(0, 1);\n            v[1] = Q.at(0, 0);\n          } else if (Q.at(1, 1)) {\n            v[0] = -Q.at(1, 1);\n            v[1] = Q.at(1, 0);\n          } else {\n            v[0] = 1;\n            v[1] = 0;\n          }\n          d = v[0] * v[0] + v[1] * v[1];\n          v[2] = - v[1] * s.y - v[0] * s.x;\n          for (l=0; l<3; l++) {\n            for (k=0; k<3; k++) {\n              Q.data[l * 3 + k] += v[l] * v[k] / d;\n            }\n          }\n        }\n        dx = Math.abs(w.x-s.x);\n        dy = Math.abs(w.y-s.y);\n        if (dx <= 0.5 && dy <= 0.5) {\n          path.curve.vertex[i] = new Point(w.x+x0, w.y+y0);\n          continue;\n        }\n    \n        min = quadform(Q, s);\n        xmin = s.x;\n        ymin = s.y;\n    \n        if (Q.at(0, 0) !== 0.0) {\n          for (z=0; z<2; z++) {\n            w.y = s.y-0.5+z;\n            w.x = - (Q.at(0, 1) * w.y + Q.at(0, 2)) / Q.at(0, 0);\n            dx = Math.abs(w.x-s.x);\n            cand = quadform(Q, w);\n            if (dx <= 0.5 && cand < min) {\n              min = cand;\n              xmin = w.x;\n              ymin = w.y;\n            }\n          }\n        }\n  \n        if (Q.at(1, 1) !== 0.0) {\n          for (z=0; z<2; z++) {\n            w.x = s.x-0.5+z;\n            w.y = - (Q.at(1, 0) * w.x + Q.at(1, 2)) / Q.at(1, 1);\n            dy = Math.abs(w.y-s.y);\n            cand = quadform(Q, w);\n            if (dy <= 0.5 && cand < min) {\n              min = cand;\n              xmin = w.x;\n              ymin = w.y;\n            }\n          }\n        }\n  \n        for (l=0; l<2; l++) {\n          for (k=0; k<2; k++) {\n            w.x = s.x-0.5+l;\n            w.y = s.y-0.5+k;\n            cand = quadform(Q, w);\n            if (cand < min) {\n              min = cand;\n              xmin = w.x;\n              ymin = w.y;\n            }\n          }\n        }\n    \n        path.curve.vertex[i] = new Point(xmin + x0, ymin + y0);\n      }\n    }\n    \n    function reverse(path) {\n      var curve = path.curve, m = curve.n, v = curve.vertex, i, j, tmp;\n    \n      for (i=0, j=m-1; i<j; i++, j--) {\n        tmp = v[i];\n        v[i] = v[j];\n        v[j] = tmp;\n      }\n    }\n    \n    function smooth(path) {\n      var m = path.curve.n, curve = path.curve;\n\n      var i, j, k, dd, denom, alpha,\n        p2, p3, p4;\n    \n      for (i=0; i<m; i++) {\n        j = mod(i+1, m);\n        k = mod(i+2, m);\n        p4 = interval(1/2.0, curve.vertex[k], curve.vertex[j]);\n    \n        denom = ddenom(curve.vertex[i], curve.vertex[k]);\n        if (denom !== 0.0) {\n          dd = dpara(curve.vertex[i], curve.vertex[j], curve.vertex[k]) / denom;\n          dd = Math.abs(dd);\n          alpha = dd>1 ? (1 - 1.0/dd) : 0;\n          alpha = alpha / 0.75;\n        } else {\n          alpha = 4/3.0;\n        }\n        curve.alpha0[j] = alpha;\n    \n        if (alpha >= info.alphamax) { \n          curve.tag[j] = \"CORNER\";\n          curve.c[3 * j + 1] = curve.vertex[j];\n          curve.c[3 * j + 2] = p4;\n        } else {\n          if (alpha < 0.55) {\n            alpha = 0.55;\n          } else if (alpha > 1) {\n            alpha = 1;\n          }\n          p2 = interval(0.5+0.5*alpha, curve.vertex[i], curve.vertex[j]);\n          p3 = interval(0.5+0.5*alpha, curve.vertex[k], curve.vertex[j]);\n          curve.tag[j] = \"CURVE\";\n          curve.c[3 * j + 0] = p2;\n          curve.c[3 * j + 1] = p3;\n          curve.c[3 * j + 2] = p4;\n        }\n        curve.alpha[j] = alpha;  \n        curve.beta[j] = 0.5;\n      }\n      curve.alphacurve = 1;\n    }\n    \n    function optiCurve(path) {\n      function Opti(){\n        this.pen = 0;\n        this.c = [new Point(), new Point()];\n        this.t = 0;\n        this.s = 0;\n        this.alpha = 0;\n      }\n      \n      function opti_penalty(path, i, j, res, opttolerance, convc, areac) {\n        var m = path.curve.n, curve = path.curve, vertex = curve.vertex, \n          k, k1, k2, conv, i1,\n          area, alpha, d, d1, d2,\n          p0, p1, p2, p3, pt,\n          A, R, A1, A2, A3, A4,\n          s, t;\n      \n        if (i==j) {\n          return 1;\n        }\n      \n        k = i;\n        i1 = mod(i+1, m);\n        k1 = mod(k+1, m);\n        conv = convc[k1];\n        if (conv === 0) {\n          return 1;\n        }\n        d = ddist(vertex[i], vertex[i1]);\n        for (k=k1; k!=j; k=k1) {\n          k1 = mod(k+1, m);\n          k2 = mod(k+2, m);\n          if (convc[k1] != conv) {\n            return 1;\n          }\n          if (sign(cprod(vertex[i], vertex[i1], vertex[k1], vertex[k2])) !=\n              conv) {\n            return 1;\n          }\n          if (iprod1(vertex[i], vertex[i1], vertex[k1], vertex[k2]) <\n              d * ddist(vertex[k1], vertex[k2]) * -0.999847695156) {\n            return 1;\n          }\n        }\n    \n        p0 = curve.c[mod(i,m) * 3 + 2].copy();\n        p1 = vertex[mod(i+1,m)].copy();\n        p2 = vertex[mod(j,m)].copy();\n        p3 = curve.c[mod(j,m) * 3 + 2].copy();\n      \n        area = areac[j] - areac[i];\n        area -= dpara(vertex[0], curve.c[i * 3 + 2], curve.c[j * 3 + 2])/2;\n        if (i>=j) {\n          area += areac[m];\n        }\n      \n        A1 = dpara(p0, p1, p2);\n        A2 = dpara(p0, p1, p3);\n        A3 = dpara(p0, p2, p3);\n  \n        A4 = A1+A3-A2;    \n        \n        if (A2 == A1) {\n          return 1;\n        }\n      \n        t = A3/(A3-A4);\n        s = A2/(A2-A1);\n        A = A2 * t / 2.0;\n        \n        if (A === 0.0) {\n          return 1;\n        }\n      \n        R = area / A;\n        alpha = 2 - Math.sqrt(4 - R / 0.3);\n      \n        res.c[0] = interval(t * alpha, p0, p1);\n        res.c[1] = interval(s * alpha, p3, p2);\n        res.alpha = alpha;\n        res.t = t;\n        res.s = s;\n      \n        p1 = res.c[0].copy();\n        p2 = res.c[1].copy(); \n      \n        res.pen = 0;\n      \n        for (k=mod(i+1,m); k!=j; k=k1) {\n          k1 = mod(k+1,m);\n          t = tangent(p0, p1, p2, p3, vertex[k], vertex[k1]);\n          if (t<-0.5) {\n            return 1;\n          }\n          pt = bezier(t, p0, p1, p2, p3);\n          d = ddist(vertex[k], vertex[k1]);\n          if (d === 0.0) {\n            return 1;\n          }\n          d1 = dpara(vertex[k], vertex[k1], pt) / d;\n          if (Math.abs(d1) > opttolerance) {\n            return 1;\n          }\n          if (iprod(vertex[k], vertex[k1], pt) < 0 ||\n              iprod(vertex[k1], vertex[k], pt) < 0) {\n            return 1;\n          }\n          res.pen += d1 * d1;\n        }\n      \n        for (k=i; k!=j; k=k1) {\n          k1 = mod(k+1,m);\n          t = tangent(p0, p1, p2, p3, curve.c[k * 3 + 2], curve.c[k1 * 3 + 2]);\n          if (t<-0.5) {\n            return 1;\n          }\n          pt = bezier(t, p0, p1, p2, p3);\n          d = ddist(curve.c[k * 3 + 2], curve.c[k1 * 3 + 2]);\n          if (d === 0.0) {\n            return 1;\n          }\n          d1 = dpara(curve.c[k * 3 + 2], curve.c[k1 * 3 + 2], pt) / d;\n          d2 = dpara(curve.c[k * 3 + 2], curve.c[k1 * 3 + 2], vertex[k1]) / d;\n          d2 *= 0.75 * curve.alpha[k1];\n          if (d2 < 0) {\n            d1 = -d1;\n            d2 = -d2;\n          }\n          if (d1 < d2 - opttolerance) {\n            return 1;\n          }\n          if (d1 < d2) {\n            res.pen += (d1 - d2) * (d1 - d2);\n          }\n        }\n      \n        return 0;\n      }\n    \n      var curve = path.curve, m = curve.n, vert = curve.vertex, \n        pt = new Array(m + 1),\n        pen = new Array(m + 1),\n        len = new Array(m + 1),\n        opt = new Array(m + 1),\n        om, i,j,r,\n        o = new Opti(), p0,\n        i1, area, alpha, ocurve,\n        s, t;\n      \n      var convc = new Array(m), areac = new Array(m + 1);\n      \n      for (i=0; i<m; i++) {\n        if (curve.tag[i] == \"CURVE\") {\n          convc[i] = sign(dpara(vert[mod(i-1,m)], vert[i], vert[mod(i+1,m)]));\n        } else {\n          convc[i] = 0;\n        }\n      }\n    \n      area = 0.0;\n      areac[0] = 0.0;\n      p0 = curve.vertex[0];\n      for (i=0; i<m; i++) {\n        i1 = mod(i+1, m);\n        if (curve.tag[i1] == \"CURVE\") {\n          alpha = curve.alpha[i1];\n          area += 0.3 * alpha * (4-alpha) *\n              dpara(curve.c[i * 3 + 2], vert[i1], curve.c[i1 * 3 + 2])/2;\n          area += dpara(p0, curve.c[i * 3 + 2], curve.c[i1 * 3 + 2])/2;\n        }\n        areac[i+1] = area;\n      }\n    \n      pt[0] = -1;\n      pen[0] = 0;\n      len[0] = 0;\n    \n    \n      for (j=1; j<=m; j++) {\n        pt[j] = j-1;\n        pen[j] = pen[j-1];\n        len[j] = len[j-1]+1;\n    \n        for (i=j-2; i>=0; i--) {\n          r = opti_penalty(path, i, mod(j,m), o, info.opttolerance, convc, \n              areac);\n          if (r) {\n            break;\n          }\n            if (len[j] > len[i]+1 ||\n                (len[j] == len[i]+1 && pen[j] > pen[i] + o.pen)) {\n              pt[j] = i;\n              pen[j] = pen[i] + o.pen;\n              len[j] = len[i] + 1;\n              opt[j] = o;\n              o = new Opti();\n            }\n        }\n      }\n      om = len[m];\n      ocurve = new Curve(om);\n      s = new Array(om);\n      t = new Array(om);\n    \n      j = m;\n      for (i=om-1; i>=0; i--) {\n        if (pt[j]==j-1) {\n          ocurve.tag[i]     = curve.tag[mod(j,m)];\n          ocurve.c[i * 3 + 0]    = curve.c[mod(j,m) * 3 + 0];\n          ocurve.c[i * 3 + 1]    = curve.c[mod(j,m) * 3 + 1];\n          ocurve.c[i * 3 + 2]    = curve.c[mod(j,m) * 3 + 2];\n          ocurve.vertex[i]  = curve.vertex[mod(j,m)];\n          ocurve.alpha[i]   = curve.alpha[mod(j,m)];\n          ocurve.alpha0[i]  = curve.alpha0[mod(j,m)];\n          ocurve.beta[i]    = curve.beta[mod(j,m)];\n          s[i] = t[i] = 1.0;\n        } else {\n          ocurve.tag[i] = \"CURVE\";\n          ocurve.c[i * 3 + 0] = opt[j].c[0];\n          ocurve.c[i * 3 + 1] = opt[j].c[1];\n          ocurve.c[i * 3 + 2] = curve.c[mod(j,m) * 3 + 2];\n          ocurve.vertex[i] = interval(opt[j].s, curve.c[mod(j,m) * 3 + 2],\n                                       vert[mod(j,m)]);\n          ocurve.alpha[i] = opt[j].alpha;\n          ocurve.alpha0[i] = opt[j].alpha;\n          s[i] = opt[j].s;\n          t[i] = opt[j].t;\n        }\n        j = pt[j];\n      }\n    \n      for (i=0; i<om; i++) {\n        i1 = mod(i+1,om);\n        ocurve.beta[i] = s[i] / (s[i] + t[i1]);\n      }\n      ocurve.alphacurve = 1;\n      path.curve = ocurve;\n    }\n    \n    for (var i = 0; i < pathlist.length; i++) {\n      var path = pathlist[i];\n      calcSums(path);\n      calcLon(path);\n      bestPolygon(path);\n      adjustVertices(path);\n      \n      if (path.sign === \"-\") {\n        reverse(path);\n      }\n      \n      smooth(path);\n      \n      if (info.optcurve) {\n        optiCurve(path);\n      }\n    }\n  \n  }\n\n  function process(c) {\n\n    if (c) {\n      callback = c;\n    }\n    if (!info.isReady) {\n      setTimeout(process, 100);\n      return;\n    }\n    bmToPathlist();\n    processPath();\n    callback();\n    callback = null;\n  }\n\n  function clear() {\n    bm = null;\n    pathlist = [];\n    callback = null;\n    info.isReady = false;\n  }\n  \n  function getSVG(size, opt_type, fillColor) {\n  \n    function path(curve) {\n    \n      function bezier(i) {\n        var b = 'C ' + (curve.c[i * 3 + 0].x * size).toFixed(3) + ' ' +\n            (curve.c[i * 3 + 0].y * size).toFixed(3) + ',';\n        b += (curve.c[i * 3 + 1].x * size).toFixed(3) + ' ' +\n            (curve.c[i * 3 + 1].y * size).toFixed(3) + ',';\n        b += (curve.c[i * 3 + 2].x * size).toFixed(3) + ' ' +\n            (curve.c[i * 3 + 2].y * size).toFixed(3) + ' ';\n        return b;\n      }\n    \n      function segment(i) {\n        var s = 'L ' + (curve.c[i * 3 + 1].x * size).toFixed(3) + ' ' +\n            (curve.c[i * 3 + 1].y * size).toFixed(3) + ' ';\n        s += (curve.c[i * 3 + 2].x * size).toFixed(3) + ' ' +\n            (curve.c[i * 3 + 2].y * size).toFixed(3) + ' ';\n        return s;\n      }\n\n      var n = curve.n, i;\n      var p = 'M' + (curve.c[(n - 1) * 3 + 2].x * size).toFixed(3) +\n          ' ' + (curve.c[(n - 1) * 3 + 2].y * size).toFixed(3) + ' ';\n      for (i = 0; i < n; i++) {\n        if (curve.tag[i] === \"CURVE\") {\n          p += bezier(i);\n        } else if (curve.tag[i] === \"CORNER\") {\n          p += segment(i);\n        }\n      }\n      //p += \n      return p;\n    }\n\n    var w = bm.w * size, h = bm.h * size,\n      len = pathlist.length, c, i, strokec, fillc, fillrule;\n\n    var svg = '<svg id=\"svg\" version=\"1.1\" width=\"' + w + '\" height=\"' + h +\n        '\" xmlns=\"http://www.w3.org/2000/svg\">';\n    svg += '<path d=\"';\n    for (i = 0; i < len; i++) {\n      c = pathlist[i].curve;\n      svg += path(c);\n    }\n    if (opt_type === \"curve\") {\n      strokec = \"black\";\n      fillc = \"none\";\n      fillrule = '';\n    } else {\n      strokec = \"none\";\n      fillc = fillColor;\n      fillrule = ' fill-rule=\"evenodd\"';\n    }\n    svg += '\" stroke=\"' + strokec + '\" fill=\"' + fillc + '\"' + fillrule + '/></svg>';\n    return svg;\n  }\n  \n  return{\n    loadImageFromDataURL: loadImageFromDataURL, // zrispo \n    loadImageFromFile: loadImageFromFile,\n    loadImageFromUrl: loadImageFromUrl,\n    setParameter: setParameter,\n    process: process,\n    getSVG: getSVG,\n    img: imgElement\n  };\n};\n\n\n// Util function to get correct sized SVGs on retina displays (zrispo)\nvar potraceImage = function (img, callback, color) {\n\n    //if(window.devicePixelRatio === 1) {\n        dataURL = img.src;\n    /*} else {\n        // Scale the image before we pass it to potrace (fixes retina display bugs!)\n        var dummyCanvas = document.createElement('canvas');\n        var dummyContext = dummyCanvas.getContext('2d');\n        dummyCanvas.width = img.width/window.devicePixelRatio;\n        dummyCanvas.height = img.height/window.devicePixelRatio;\n        dummyContext.drawImage(img, 0,0, img.width,img.height, 0,0, img.width/window.devicePixelRatio,img.height/window.devicePixelRatio);\n        dataURL = dummyCanvas.toDataURL();\n    }*/\n\n    // Send settings and the image data to potrace to vectorize it!\n    var potrace = new Potrace();\n    potrace.loadImageFromDataURL(dataURL);\n    potrace.setParameter({\n        optcurve: false,\n        alphamax: 1.0,\n        opttolerance: 0,\n    });\n    potrace.process(function(){\n        callback(potrace.getSVG(1, null, color));\n    });\n};\n\nvar isElectronMode = window && window.process && window.process.type === \"renderer\";\n\n"
  },
  {
    "path": "lib/random.js",
    "content": "/*jshint eqnull:true*/\n(function (root) {\n  \"use strict\";\n\n  var GLOBAL_KEY = \"Random\";\n\n  var imul = (typeof Math.imul !== \"function\" || Math.imul(0xffffffff, 5) !== -5 ?\n    function (a, b) {\n      var ah = (a >>> 16) & 0xffff;\n      var al = a & 0xffff;\n      var bh = (b >>> 16) & 0xffff;\n      var bl = b & 0xffff;\n      // the shift by 0 fixes the sign on the high part\n      // the final |0 converts the unsigned value into a signed value\n      return (al * bl) + (((ah * bl + al * bh) << 16) >>> 0) | 0;\n    } :\n    Math.imul);\n\n  var stringRepeat = (typeof String.prototype.repeat === \"function\" && \"x\".repeat(3) === \"xxx\" ?\n    function (x, y) {\n      return x.repeat(y);\n    } : function (pattern, count) {\n      var result = \"\";\n      while (count > 0) {\n        if (count & 1) {\n          result += pattern;\n        }\n        count >>= 1;\n        pattern += pattern;\n      }\n      return result;\n    });\n\n  function Random(engine) {\n    if (!(this instanceof Random)) {\n      return new Random(engine);\n    }\n\n    if (engine == null) {\n      engine = Random.engines.nativeMath;\n    } else if (typeof engine !== \"function\") {\n      throw new TypeError(\"Expected engine to be a function, got \" + typeof engine);\n    }\n    this.engine = engine;\n  }\n  var proto = Random.prototype;\n\n  Random.engines = {\n    nativeMath: function () {\n      return (Math.random() * 0x100000000) | 0;\n    },\n    mt19937: (function (Int32Array) {\n      // http://en.wikipedia.org/wiki/Mersenne_twister\n      function refreshData(data) {\n        var k = 0;\n        var tmp = 0;\n        for (;\n          (k | 0) < 227; k = (k + 1) | 0) {\n          tmp = (data[k] & 0x80000000) | (data[(k + 1) | 0] & 0x7fffffff);\n          data[k] = data[(k + 397) | 0] ^ (tmp >>> 1) ^ ((tmp & 0x1) ? 0x9908b0df : 0);\n        }\n\n        for (;\n          (k | 0) < 623; k = (k + 1) | 0) {\n          tmp = (data[k] & 0x80000000) | (data[(k + 1) | 0] & 0x7fffffff);\n          data[k] = data[(k - 227) | 0] ^ (tmp >>> 1) ^ ((tmp & 0x1) ? 0x9908b0df : 0);\n        }\n\n        tmp = (data[623] & 0x80000000) | (data[0] & 0x7fffffff);\n        data[623] = data[396] ^ (tmp >>> 1) ^ ((tmp & 0x1) ? 0x9908b0df : 0);\n      }\n\n      function temper(value) {\n        value ^= value >>> 11;\n        value ^= (value << 7) & 0x9d2c5680;\n        value ^= (value << 15) & 0xefc60000;\n        return value ^ (value >>> 18);\n      }\n\n      function seedWithArray(data, source) {\n        var i = 1;\n        var j = 0;\n        var sourceLength = source.length;\n        var k = Math.max(sourceLength, 624) | 0;\n        var previous = data[0] | 0;\n        for (;\n          (k | 0) > 0; --k) {\n          data[i] = previous = ((data[i] ^ imul((previous ^ (previous >>> 30)), 0x0019660d)) + (source[j] | 0) + (j | 0)) | 0;\n          i = (i + 1) | 0;\n          ++j;\n          if ((i | 0) > 623) {\n            data[0] = data[623];\n            i = 1;\n          }\n          if (j >= sourceLength) {\n            j = 0;\n          }\n        }\n        for (k = 623;\n          (k | 0) > 0; --k) {\n          data[i] = previous = ((data[i] ^ imul((previous ^ (previous >>> 30)), 0x5d588b65)) - i) | 0;\n          i = (i + 1) | 0;\n          if ((i | 0) > 623) {\n            data[0] = data[623];\n            i = 1;\n          }\n        }\n        data[0] = 0x80000000;\n      }\n\n      function mt19937() {\n        var data = new Int32Array(624);\n        var index = 0;\n        var uses = 0;\n\n        function next() {\n          if ((index | 0) >= 624) {\n            refreshData(data);\n            index = 0;\n          }\n\n          var value = data[index];\n          index = (index + 1) | 0;\n          uses += 1;\n          return temper(value) | 0;\n        }\n        next.getUseCount = function() {\n          return uses;\n        };\n        next.discard = function (count) {\n          uses += count;\n          if ((index | 0) >= 624) {\n            refreshData(data);\n            index = 0;\n          }\n          while ((count - index) > 624) {\n            count -= 624 - index;\n            refreshData(data);\n            index = 0;\n          }\n          index = (index + count) | 0;\n          return next;\n        };\n        next.seed = function (initial) {\n          var previous = 0;\n          data[0] = previous = initial | 0;\n\n          for (var i = 1; i < 624; i = (i + 1) | 0) {\n            data[i] = previous = (imul((previous ^ (previous >>> 30)), 0x6c078965) + i) | 0;\n          }\n          index = 624;\n          uses = 0;\n          return next;\n        };\n        next.seedWithArray = function (source) {\n          next.seed(0x012bd6aa);\n          seedWithArray(data, source);\n          return next;\n        };\n        next.autoSeed = function () {\n          return next.seedWithArray(Random.generateEntropyArray());\n        };\n        return next;\n      }\n\n      return mt19937;\n    }(typeof Int32Array === \"function\" ? Int32Array : Array)),\n    browserCrypto: (typeof crypto !== \"undefined\" && typeof crypto.getRandomValues === \"function\" && typeof Int32Array === \"function\") ? (function () {\n      var data = null;\n      var index = 128;\n\n      return function () {\n        if (index >= 128) {\n          if (data === null) {\n            data = new Int32Array(128);\n          }\n          crypto.getRandomValues(data);\n          index = 0;\n        }\n\n        return data[index++] | 0;\n      };\n    }()) : null\n  };\n\n  Random.generateEntropyArray = function () {\n    var array = [];\n    var engine = Random.engines.nativeMath;\n    for (var i = 0; i < 16; ++i) {\n      array[i] = engine() | 0;\n    }\n    array.push(new Date().getTime() | 0);\n    return array;\n  };\n\n  function returnValue(value) {\n    return function () {\n      return value;\n    };\n  }\n\n  // [-0x80000000, 0x7fffffff]\n  Random.int32 = function (engine) {\n    return engine() | 0;\n  };\n  proto.int32 = function () {\n    return Random.int32(this.engine);\n  };\n\n  // [0, 0xffffffff]\n  Random.uint32 = function (engine) {\n    return engine() >>> 0;\n  };\n  proto.uint32 = function () {\n    return Random.uint32(this.engine);\n  };\n\n  // [0, 0x1fffffffffffff]\n  Random.uint53 = function (engine) {\n    var high = engine() & 0x1fffff;\n    var low = engine() >>> 0;\n    return (high * 0x100000000) + low;\n  };\n  proto.uint53 = function () {\n    return Random.uint53(this.engine);\n  };\n\n  // [0, 0x20000000000000]\n  Random.uint53Full = function (engine) {\n    while (true) {\n      var high = engine() | 0;\n      if (high & 0x200000) {\n        if ((high & 0x3fffff) === 0x200000 && (engine() | 0) === 0) {\n          return 0x20000000000000;\n        }\n      } else {\n        var low = engine() >>> 0;\n        return ((high & 0x1fffff) * 0x100000000) + low;\n      }\n    }\n  };\n  proto.uint53Full = function () {\n    return Random.uint53Full(this.engine);\n  };\n\n  // [-0x20000000000000, 0x1fffffffffffff]\n  Random.int53 = function (engine) {\n    var high = engine() | 0;\n    var low = engine() >>> 0;\n    return ((high & 0x1fffff) * 0x100000000) + low + (high & 0x200000 ? -0x20000000000000 : 0);\n  };\n  proto.int53 = function () {\n    return Random.int53(this.engine);\n  };\n\n  // [-0x20000000000000, 0x20000000000000]\n  Random.int53Full = function (engine) {\n    while (true) {\n      var high = engine() | 0;\n      if (high & 0x400000) {\n        if ((high & 0x7fffff) === 0x400000 && (engine() | 0) === 0) {\n          return 0x20000000000000;\n        }\n      } else {\n        var low = engine() >>> 0;\n        return ((high & 0x1fffff) * 0x100000000) + low + (high & 0x200000 ? -0x20000000000000 : 0);\n      }\n    }\n  };\n  proto.int53Full = function () {\n    return Random.int53Full(this.engine);\n  };\n\n  function add(generate, addend) {\n    if (addend === 0) {\n      return generate;\n    } else {\n      return function (engine) {\n        return generate(engine) + addend;\n      };\n    }\n  }\n\n  Random.integer = (function () {\n    function isPowerOfTwoMinusOne(value) {\n      return ((value + 1) & value) === 0;\n    }\n\n    function bitmask(masking) {\n      return function (engine) {\n        return engine() & masking;\n      };\n    }\n\n    function downscaleToLoopCheckedRange(range) {\n      var extendedRange = range + 1;\n      var maximum = extendedRange * Math.floor(0x100000000 / extendedRange);\n      return function (engine) {\n        var value = 0;\n        do {\n          value = engine() >>> 0;\n        } while (value >= maximum);\n        return value % extendedRange;\n      };\n    }\n\n    function downscaleToRange(range) {\n      if (isPowerOfTwoMinusOne(range)) {\n        return bitmask(range);\n      } else {\n        return downscaleToLoopCheckedRange(range);\n      }\n    }\n\n    function isEvenlyDivisibleByMaxInt32(value) {\n      return (value | 0) === 0;\n    }\n\n    function upscaleWithHighMasking(masking) {\n      return function (engine) {\n        var high = engine() & masking;\n        var low = engine() >>> 0;\n        return (high * 0x100000000) + low;\n      };\n    }\n\n    function upscaleToLoopCheckedRange(extendedRange) {\n      var maximum = extendedRange * Math.floor(0x20000000000000 / extendedRange);\n      return function (engine) {\n        var ret = 0;\n        do {\n          var high = engine() & 0x1fffff;\n          var low = engine() >>> 0;\n          ret = (high * 0x100000000) + low;\n        } while (ret >= maximum);\n        return ret % extendedRange;\n      };\n    }\n\n    function upscaleWithinU53(range) {\n      var extendedRange = range + 1;\n      if (isEvenlyDivisibleByMaxInt32(extendedRange)) {\n        var highRange = ((extendedRange / 0x100000000) | 0) - 1;\n        if (isPowerOfTwoMinusOne(highRange)) {\n          return upscaleWithHighMasking(highRange);\n        }\n      }\n      return upscaleToLoopCheckedRange(extendedRange);\n    }\n\n    function upscaleWithinI53AndLoopCheck(min, max) {\n      return function (engine) {\n        var ret = 0;\n        do {\n          var high = engine() | 0;\n          var low = engine() >>> 0;\n          ret = ((high & 0x1fffff) * 0x100000000) + low + (high & 0x200000 ? -0x20000000000000 : 0);\n        } while (ret < min || ret > max);\n        return ret;\n      };\n    }\n\n    return function (min, max) {\n      min = Math.floor(min);\n      max = Math.floor(max);\n      if (min < -0x20000000000000 || !isFinite(min)) {\n        throw new RangeError(\"Expected min to be at least \" + (-0x20000000000000));\n      } else if (max > 0x20000000000000 || !isFinite(max)) {\n        throw new RangeError(\"Expected max to be at most \" + 0x20000000000000);\n      }\n\n      var range = max - min;\n      if (range <= 0 || !isFinite(range)) {\n        return returnValue(min);\n      } else if (range === 0xffffffff) {\n        if (min === 0) {\n          return Random.uint32;\n        } else {\n          return add(Random.int32, min + 0x80000000);\n        }\n      } else if (range < 0xffffffff) {\n        return add(downscaleToRange(range), min);\n      } else if (range === 0x1fffffffffffff) {\n        return add(Random.uint53, min);\n      } else if (range < 0x1fffffffffffff) {\n        return add(upscaleWithinU53(range), min);\n      } else if (max - 1 - min === 0x1fffffffffffff) {\n        return add(Random.uint53Full, min);\n      } else if (min === -0x20000000000000 && max === 0x20000000000000) {\n        return Random.int53Full;\n      } else if (min === -0x20000000000000 && max === 0x1fffffffffffff) {\n        return Random.int53;\n      } else if (min === -0x1fffffffffffff && max === 0x20000000000000) {\n        return add(Random.int53, 1);\n      } else if (max === 0x20000000000000) {\n        return add(upscaleWithinI53AndLoopCheck(min - 1, max - 1), 1);\n      } else {\n        return upscaleWithinI53AndLoopCheck(min, max);\n      }\n    };\n  }());\n  proto.integer = function (min, max) {\n    return Random.integer(min, max)(this.engine);\n  };\n\n  // [0, 1] (floating point)\n  Random.realZeroToOneInclusive = function (engine) {\n    return Random.uint53Full(engine) / 0x20000000000000;\n  };\n  proto.realZeroToOneInclusive = function () {\n    return Random.realZeroToOneInclusive(this.engine);\n  };\n\n  // [0, 1) (floating point)\n  Random.realZeroToOneExclusive = function (engine) {\n    return Random.uint53(engine) / 0x20000000000000;\n  };\n  proto.realZeroToOneExclusive = function () {\n    return Random.realZeroToOneExclusive(this.engine);\n  };\n\n  Random.real = (function () {\n    function multiply(generate, multiplier) {\n      if (multiplier === 1) {\n        return generate;\n      } else if (multiplier === 0) {\n        return function () {\n          return 0;\n        };\n      } else {\n        return function (engine) {\n          return generate(engine) * multiplier;\n        };\n      }\n    }\n\n    return function (left, right, inclusive) {\n      if (!isFinite(left)) {\n        throw new RangeError(\"Expected left to be a finite number\");\n      } else if (!isFinite(right)) {\n        throw new RangeError(\"Expected right to be a finite number\");\n      }\n      return add(\n        multiply(\n          inclusive ? Random.realZeroToOneInclusive : Random.realZeroToOneExclusive,\n          right - left),\n        left);\n    };\n  }());\n  proto.real = function (min, max, inclusive) {\n    return Random.real(min, max, inclusive)(this.engine);\n  };\n\n  Random.bool = (function () {\n    function isLeastBitTrue(engine) {\n      return (engine() & 1) === 1;\n    }\n\n    function lessThan(generate, value) {\n      return function (engine) {\n        return generate(engine) < value;\n      };\n    }\n\n    function probability(percentage) {\n      if (percentage <= 0) {\n        return returnValue(false);\n      } else if (percentage >= 1) {\n        return returnValue(true);\n      } else {\n        var scaled = percentage * 0x100000000;\n        if (scaled % 1 === 0) {\n          return lessThan(Random.int32, (scaled - 0x80000000) | 0);\n        } else {\n          return lessThan(Random.uint53, Math.round(percentage * 0x20000000000000));\n        }\n      }\n    }\n\n    return function (numerator, denominator) {\n      if (denominator == null) {\n        if (numerator == null) {\n          return isLeastBitTrue;\n        }\n        return probability(numerator);\n      } else {\n        if (numerator <= 0) {\n          return returnValue(false);\n        } else if (numerator >= denominator) {\n          return returnValue(true);\n        }\n        return lessThan(Random.integer(0, denominator - 1), numerator);\n      }\n    };\n  }());\n  proto.bool = function (numerator, denominator) {\n    return Random.bool(numerator, denominator)(this.engine);\n  };\n\n  function toInteger(value) {\n    var number = +value;\n    if (number < 0) {\n      return Math.ceil(number);\n    } else {\n      return Math.floor(number);\n    }\n  }\n\n  function convertSliceArgument(value, length) {\n    if (value < 0) {\n      return Math.max(value + length, 0);\n    } else {\n      return Math.min(value, length);\n    }\n  }\n  Random.pick = function (engine, array, begin, end) {\n    var length = array.length;\n    var start = begin == null ? 0 : convertSliceArgument(toInteger(begin), length);\n    var finish = end === void 0 ? length : convertSliceArgument(toInteger(end), length);\n    if (start >= finish) {\n      return void 0;\n    }\n    var distribution = Random.integer(start, finish - 1);\n    return array[distribution(engine)];\n  };\n  proto.pick = function (array, begin, end) {\n    return Random.pick(this.engine, array, begin, end);\n  };\n\n  function returnUndefined() {\n    return void 0;\n  }\n  var slice = Array.prototype.slice;\n  Random.picker = function (array, begin, end) {\n    var clone = slice.call(array, begin, end);\n    if (!clone.length) {\n      return returnUndefined;\n    }\n    var distribution = Random.integer(0, clone.length - 1);\n    return function (engine) {\n      return clone[distribution(engine)];\n    };\n  };\n\n  Random.shuffle = function (engine, array, downTo) {\n    var length = array.length;\n    if (length) {\n      if (downTo == null) {\n        downTo = 0;\n      }\n      for (var i = (length - 1) >>> 0; i > downTo; --i) {\n        var distribution = Random.integer(0, i);\n        var j = distribution(engine);\n        if (i !== j) {\n          var tmp = array[i];\n          array[i] = array[j];\n          array[j] = tmp;\n        }\n      }\n    }\n    return array;\n  };\n  proto.shuffle = function (array) {\n    return Random.shuffle(this.engine, array);\n  };\n\n  Random.sample = function (engine, population, sampleSize) {\n    if (sampleSize < 0 || sampleSize > population.length || !isFinite(sampleSize)) {\n      throw new RangeError(\"Expected sampleSize to be within 0 and the length of the population\");\n    }\n\n    if (sampleSize === 0) {\n      return [];\n    }\n\n    var clone = slice.call(population);\n    var length = clone.length;\n    if (length === sampleSize) {\n      return Random.shuffle(engine, clone, 0);\n    }\n    var tailLength = length - sampleSize;\n    return Random.shuffle(engine, clone, tailLength - 1).slice(tailLength);\n  };\n  proto.sample = function (population, sampleSize) {\n    return Random.sample(this.engine, population, sampleSize);\n  };\n\n  Random.die = function (sideCount) {\n    return Random.integer(1, sideCount);\n  };\n  proto.die = function (sideCount) {\n    return Random.die(sideCount)(this.engine);\n  };\n\n  Random.dice = function (sideCount, dieCount) {\n    var distribution = Random.die(sideCount);\n    return function (engine) {\n      var result = [];\n      result.length = dieCount;\n      for (var i = 0; i < dieCount; ++i) {\n        result[i] = distribution(engine);\n      }\n      return result;\n    };\n  };\n  proto.dice = function (sideCount, dieCount) {\n    return Random.dice(sideCount, dieCount)(this.engine);\n  };\n\n  // http://en.wikipedia.org/wiki/Universally_unique_identifier\n  Random.uuid4 = (function () {\n    function zeroPad(string, zeroCount) {\n      return stringRepeat(\"0\", zeroCount - string.length) + string;\n    }\n\n    return function (engine) {\n      var a = engine() >>> 0;\n      var b = engine() | 0;\n      var c = engine() | 0;\n      var d = engine() >>> 0;\n\n      return (\n        zeroPad(a.toString(16), 8) +\n        \"-\" +\n        zeroPad((b & 0xffff).toString(16), 4) +\n        \"-\" +\n        zeroPad((((b >> 4) & 0x0fff) | 0x4000).toString(16), 4) +\n        \"-\" +\n        zeroPad(((c & 0x3fff) | 0x8000).toString(16), 4) +\n        \"-\" +\n        zeroPad(((c >> 4) & 0xffff).toString(16), 4) +\n        zeroPad(d.toString(16), 8));\n    };\n  }());\n  proto.uuid4 = function () {\n    return Random.uuid4(this.engine);\n  };\n\n  Random.string = (function () {\n    // has 2**x chars, for faster uniform distribution\n    var DEFAULT_STRING_POOL = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-\";\n\n    return function (pool) {\n      if (pool == null) {\n        pool = DEFAULT_STRING_POOL;\n      }\n\n      var length = pool.length;\n      if (!length) {\n        throw new Error(\"Expected pool not to be an empty string\");\n      }\n\n      var distribution = Random.integer(0, length - 1);\n      return function (engine, length) {\n        var result = \"\";\n        for (var i = 0; i < length; ++i) {\n          var j = distribution(engine);\n          result += pool.charAt(j);\n        }\n        return result;\n      };\n    };\n  }());\n  proto.string = function (length, pool) {\n    return Random.string(pool)(this.engine, length);\n  };\n\n  Random.hex = (function () {\n    var LOWER_HEX_POOL = \"0123456789abcdef\";\n    var lowerHex = Random.string(LOWER_HEX_POOL);\n    var upperHex = Random.string(LOWER_HEX_POOL.toUpperCase());\n\n    return function (upper) {\n      if (upper) {\n        return upperHex;\n      } else {\n        return lowerHex;\n      }\n    };\n  }());\n  proto.hex = function (length, upper) {\n    return Random.hex(upper)(this.engine, length);\n  };\n\n  Random.date = function (start, end) {\n    if (!(start instanceof Date)) {\n      throw new TypeError(\"Expected start to be a Date, got \" + typeof start);\n    } else if (!(end instanceof Date)) {\n      throw new TypeError(\"Expected end to be a Date, got \" + typeof end);\n    }\n    var distribution = Random.integer(start.getTime(), end.getTime());\n    return function (engine) {\n      return new Date(distribution(engine));\n    };\n  };\n  proto.date = function (start, end) {\n    return Random.date(start, end)(this.engine);\n  };\n\n  if (typeof define === \"function\" && define.amd) {\n    define(function () {\n      return Random;\n    });\n  } else if (typeof module !== \"undefined\" && typeof require === \"function\") {\n    module.exports = Random;\n  } else {\n    (function () {\n      var oldGlobal = root[GLOBAL_KEY];\n      Random.noConflict = function () {\n        root[GLOBAL_KEY] = oldGlobal;\n        return this;\n      };\n    }());\n    root[GLOBAL_KEY] = Random;\n  }\n}(this));\n\nwindow.random = new Random();\nwindow.randomInt = function (min,max) { return random.integer(min,max); };\nwindow.randomBool = function () { return random.bool() };\nwindow.randomFloat = function (min,max) { return random.real(min,max); };"
  },
  {
    "path": "lib/rangeslider.css",
    "content": ".rangeslider,\n.rangeslider__fill {\n  display: block;\n  -moz-box-shadow: inset 0px 1px 3px rgba(0, 0, 0, 0.3);\n  -webkit-box-shadow: inset 0px 1px 3px rgba(0, 0, 0, 0.3);\n  box-shadow: inset 0px 1px 3px rgba(0, 0, 0, 0.3);\n  -moz-border-radius: 10px;\n  -webkit-border-radius: 10px;\n  border-radius: 10px;\n}\n\n.rangeslider {\n  background: #e6e6e6;\n  position: relative;\n}\n\n.rangeslider--horizontal {\n  height: 10px;\n  width: 130px;\n  margin-top: 5px;\n  float:right;\n}\n\n.rangeslider--vertical {\n  width: 10px;\n  min-height: 150px;\n  max-height: 100%;\n}\n\n.rangeslider--disabled {\n  filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40);\n  opacity: 0.4;\n}\n\n.rangeslider__fill {\n  background: #666;\n  position: absolute;\n}\n.rangeslider--horizontal .rangeslider__fill {\n  top: 0;\n  height: 100%;\n}\n.rangeslider--vertical .rangeslider__fill {\n  bottom: 0;\n  width: 100%;\n}\n\n.rangeslider__handle {\n  background: white;\n  border: 1px solid #ccc;\n  cursor: pointer;\n  display: inline-block;\n  width: 15px;\n  height: 15px;\n  position: absolute;\n  background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4xIi8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g');\n  background-size: 100%;\n  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(0, 0, 0, 0.1)));\n  background-image: -moz-linear-gradient(rgba(255, 255, 255, 0), rgba(0, 0, 0, 0.1));\n  background-image: -webkit-linear-gradient(rgba(255, 255, 255, 0), rgba(0, 0, 0, 0.1));\n  background-image: linear-gradient(rgba(255, 255, 255, 0), rgba(0, 0, 0, 0.1));\n  /*-moz-box-shadow: 0 0 8px rgba(0, 0, 0, 0.3);\n  -webkit-box-shadow: 0 0 8px rgba(0, 0, 0, 0.3);\n  box-shadow: 0 0 8px rgba(0, 0, 0, 0.3);*/\n  -moz-border-radius: 50%;\n  -webkit-border-radius: 50%;\n  border-radius: 50%;\n}\n.rangeslider__handle:after {\n  content: \"\";\n  display: block;\n  width: 18px;\n  height: 18px;\n  margin: auto;\n  position: absolute;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjEzIi8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjZmZmZmZmIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');\n  background-size: 100%;\n  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(0, 0, 0, 0.13)), color-stop(100%, rgba(255, 255, 255, 0)));\n  background-image: -moz-linear-gradient(rgba(0, 0, 0, 0.13), rgba(255, 255, 255, 0));\n  background-image: -webkit-linear-gradient(rgba(0, 0, 0, 0.13), rgba(255, 255, 255, 0));\n  background-image: linear-gradient(rgba(0, 0, 0, 0.13), rgba(255, 255, 255, 0));\n  -moz-border-radius: 50%;\n  -webkit-border-radius: 50%;\n  border-radius: 50%;\n}\n.rangeslider__handle:active, .rangeslider--active .rangeslider__handle {\n  background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjEiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4xMiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');\n  background-size: 100%;\n  background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(0, 0, 0, 0.1)), color-stop(100%, rgba(0, 0, 0, 0.12)));\n  background-image: -moz-linear-gradient(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.12));\n  background-image: -webkit-linear-gradient(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.12));\n  background-image: linear-gradient(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.12));\n}\n.rangeslider--horizontal .rangeslider__handle {\n  top: -4px;\n  touch-action: pan-y;\n  -ms-touch-action: pan-y;\n}\n.rangeslider--vertical .rangeslider__handle {\n  left: -4px;\n  touch-action: pan-x;\n  -ms-touch-action: pan-x;\n}\n"
  },
  {
    "path": "lib/saveSvgAsPng.js",
    "content": "(function() {\n  var out$ = typeof exports != 'undefined' && exports || typeof define != 'undefined' && {} || this;\n\n  var doctype = '<?xml version=\"1.0\" standalone=\"no\"?><!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\" [<!ENTITY nbsp \"&#160;\">]>';\n\n  function isElement(obj) {\n    return obj instanceof HTMLElement || obj instanceof SVGElement;\n  }\n\n  function requireDomNode(el) {\n    if (!isElement(el)) {\n      throw new Error('an HTMLElement or SVGElement is required; got ' + el);\n    }\n  }\n\n  function isExternal(url) {\n    return url && url.lastIndexOf('http',0) == 0 && url.lastIndexOf(window.location.host) == -1;\n  }\n\n  function inlineImages(el, callback) {\n    requireDomNode(el);\n\n    var images = el.querySelectorAll('image'),\n        left = images.length,\n        checkDone = function() {\n          if (left === 0) {\n            callback();\n          }\n        };\n\n    checkDone();\n    for (var i = 0; i < images.length; i++) {\n      (function(image) {\n        var href = image.getAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\");\n        if (href) {\n          if (isExternal(href.value)) {\n            console.warn(\"Cannot render embedded images linking to external hosts: \"+href.value);\n            return;\n          }\n        }\n        var canvas = document.createElement('canvas');\n        var ctx = canvas.getContext('2d');\n        var img = new Image();\n        img.crossOrigin=\"anonymous\";\n        href = href || image.getAttribute('href');\n        if (href) {\n          img.src = href;\n          img.onload = function() {\n            canvas.width = img.width;\n            canvas.height = img.height;\n            ctx.drawImage(img, 0, 0);\n            image.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", canvas.toDataURL('image/png'));\n            left--;\n            checkDone();\n          }\n          img.onerror = function() {\n            console.log(\"Could not load \"+href);\n            left--;\n            checkDone();\n          }\n        } else {\n          left--;\n          checkDone();\n        }\n      })(images[i]);\n    }\n  }\n\n  function styles(el, options, cssLoadedCallback) {\n    var selectorRemap = options.selectorRemap;\n    var modifyStyle = options.modifyStyle;\n    var css = \"\";\n    // each font that has extranl link is saved into queue, and processed\n    // asynchronously\n    var fontsQueue = [];\n    var sheets = document.styleSheets;\n    for (var i = 0; i < sheets.length; i++) {\n      try {\n        var rules = sheets[i].cssRules;\n      } catch (e) {\n        console.warn(\"Stylesheet could not be loaded: \"+sheets[i].href);\n        continue;\n      }\n\n      if (rules != null) {\n        for (var j = 0, match; j < rules.length; j++, match = null) {\n          var rule = rules[j];\n          if (typeof(rule.style) != \"undefined\") {\n            var selectorText;\n\n            try {\n              selectorText = rule.selectorText;\n            } catch(err) {\n              console.warn('The following CSS rule has an invalid selector: \"' + rule + '\"', err);\n            }\n\n            try {\n              if (selectorText) {\n                match = el.querySelector(selectorText) || el.parentNode.querySelector(selectorText);\n              }\n            } catch(err) {\n              console.warn('Invalid CSS selector \"' + selectorText + '\"', err);\n            }\n\n            if (match) {\n              var selector = selectorRemap ? selectorRemap(rule.selectorText) : rule.selectorText;\n              var cssText = modifyStyle ? modifyStyle(rule.style.cssText) : rule.style.cssText;\n              css += selector + \" { \" + cssText + \" }\\n\";\n            } else if(rule.cssText.match(/^@font-face/)) {\n              // below we are trying to find matches to external link. E.g.\n              // @font-face {\n              //   // ...\n              //   src: local('Abel'), url(https://fonts.gstatic.com/s/abel/v6/UzN-iejR1VoXU2Oc-7LsbvesZW2xOQ-xsNqO47m55DA.woff2);\n              // }\n              //\n              // This regex will save extrnal link into first capture group\n              var fontUrlRegexp = /url\\([\"']?(.+?)[\"']?\\)/;\n              // TODO: This needs to be changed to support multiple url declarations per font.\n              var fontUrlMatch = rule.cssText.match(fontUrlRegexp);\n\n              var externalFontUrl = (fontUrlMatch && fontUrlMatch[1]) || '';\n              var fontUrlIsDataURI = externalFontUrl.match(/^data:/);\n              if (fontUrlIsDataURI) {\n                // We should ignore data uri - they are already embedded\n                externalFontUrl = '';\n              }\n\n              if (externalFontUrl === 'about:blank') {\n                // no point trying to load this\n                externalFontUrl = '';\n              }\n\n              if (externalFontUrl) {\n                // okay, we are lucky. We can fetch this font later\n\n                //handle url if relative\n                if (externalFontUrl.startsWith('../')) {\n                  externalFontUrl = sheets[i].href + '/../' + externalFontUrl\n                } else if (externalFontUrl.startsWith('./')) {\n                  externalFontUrl = sheets[i].href + '/.' + externalFontUrl\n                }\n\n                fontsQueue.push({\n                  text: rule.cssText,\n                  // Pass url regex, so that once font is downladed, we can run `replace()` on it\n                  fontUrlRegexp: fontUrlRegexp,\n                  format: getFontMimeTypeFromUrl(externalFontUrl),\n                  url: externalFontUrl\n                });\n              } else {\n                // otherwise, use previous logic\n                css += rule.cssText + '\\n';\n              }\n            }\n          }\n        }\n      }\n    }\n\n    // Now all css is processed, it's time to handle scheduled fonts\n    processFontQueue(fontsQueue);\n\n    function getFontMimeTypeFromUrl(fontUrl) {\n      var supportedFormats = {\n        'woff2': 'font/woff2',\n        'woff': 'font/woff',\n        'otf': 'application/x-font-opentype',\n        'ttf': 'application/x-font-ttf',\n        'eot': 'application/vnd.ms-fontobject',\n        'sfnt': 'application/font-sfnt',\n        'svg': 'image/svg+xml'\n      };\n      var extensions = Object.keys(supportedFormats);\n      for (var i = 0; i < extensions.length; ++i) {\n        var extension = extensions[i];\n        // TODO: This is not bullet proof, it needs to handle edge cases...\n        if (fontUrl.indexOf('.' + extension) > 0) {\n          return supportedFormats[extension];\n        }\n      }\n\n      // If you see this error message, you probably need to update code above.\n      console.error('Unknown font format for ' + fontUrl+ '; Fonts may not be working correctly');\n      return 'application/octet-stream';\n    }\n\n    function processFontQueue(queue) {\n\n      cssLoadedCallback(css)\n      return;\n\n      if (queue.length > 0) {\n        // load fonts one by one until we have anything in the queue:\n        var font = queue.pop();\n        processNext(font);\n      } else {\n        // no more fonts to load.\n        cssLoadedCallback(css);\n      }\n\n      function processNext(font) {\n        // TODO: This could benefit from caching.\n        var oReq = new XMLHttpRequest();\n        oReq.addEventListener('load', fontLoaded);\n        oReq.addEventListener('error', transferFailed);\n        oReq.addEventListener('abort', transferFailed);\n        oReq.open('GET', font.url);\n        oReq.responseType = 'arraybuffer';\n        oReq.send();\n\n        function fontLoaded() {\n          // TODO: it may be also worth to wait until fonts are fully loaded before\n          // attempting to rasterize them. (e.g. use https://developer.mozilla.org/en-US/docs/Web/API/FontFaceSet )\n          var fontBits = oReq.response;\n          var fontInBase64 = arrayBufferToBase64(fontBits);\n          updateFontStyle(font, fontInBase64);\n        }\n\n        function transferFailed(e) {\n          console.warn('Failed to load font from: ' + font.url);\n          console.warn(e)\n          css += font.text + '\\n';\n          processFontQueue(queue);\n        }\n\n        function updateFontStyle(font, fontInBase64) {\n          var dataUrl = 'url(\"data:' + font.format + ';base64,' + fontInBase64 + '\")';\n          css += font.text.replace(font.fontUrlRegexp, dataUrl) + '\\n';\n\n          // schedule next font download on next tick.\n          setTimeout(function() {\n            processFontQueue(queue)\n          }, 0);\n        }\n\n      }\n    }\n\n    function arrayBufferToBase64(buffer) {\n      var binary = '';\n      var bytes = new Uint8Array(buffer);\n      var len = bytes.byteLength;\n\n      for (var i = 0; i < len; i++) {\n          binary += String.fromCharCode(bytes[i]);\n      }\n\n      return window.btoa(binary);\n    }\n  }\n\n  function getDimension(el, clone, dim) {\n    var v = (el.viewBox && el.viewBox.baseVal && el.viewBox.baseVal[dim]) ||\n      (clone.getAttribute(dim) !== null && !clone.getAttribute(dim).match(/%$/) && parseInt(clone.getAttribute(dim))) ||\n      el.getBoundingClientRect()[dim] ||\n      parseInt(clone.style[dim]) ||\n      parseInt(window.getComputedStyle(el).getPropertyValue(dim));\n    return (typeof v === 'undefined' || v === null || isNaN(parseFloat(v))) ? 0 : v;\n  }\n\n  function reEncode(data) {\n    data = encodeURIComponent(data);\n    data = data.replace(/%([0-9A-F]{2})/g, function(match, p1) {\n      var c = String.fromCharCode('0x'+p1);\n      return c === '%' ? '%25' : c;\n    });\n    return decodeURIComponent(data);\n  }\n\n  out$.prepareSvg = function(el, options, cb) {\n    requireDomNode(el);\n\n    options = options || {};\n    options.scale = options.scale || 1;\n    options.responsive = options.responsive || false;\n    var xmlns = \"http://www.w3.org/2000/xmlns/\";\n\n    inlineImages(el, function() {\n      var outer = document.createElement(\"div\");\n      var clone = el.cloneNode(true);\n      var width, height;\n      if(el.tagName == 'svg') {\n        width = options.width || getDimension(el, clone, 'width');\n        height = options.height || getDimension(el, clone, 'height');\n      } else if(el.getBBox) {\n        var box = el.getBBox();\n        width = box.x + box.width;\n        height = box.y + box.height;\n        clone.setAttribute('transform', clone.getAttribute('transform').replace(/translate\\(.*?\\)/, ''));\n\n        var svg = document.createElementNS('http://www.w3.org/2000/svg','svg')\n        svg.appendChild(clone)\n        clone = svg;\n      } else {\n        console.error('Attempted to render non-SVG element', el);\n        return;\n      }\n\n      clone.setAttribute(\"version\", \"1.1\");\n      if (!clone.getAttribute('xmlns')) {\n        clone.setAttributeNS(xmlns, \"xmlns\", \"http://www.w3.org/2000/svg\");\n      }\n      if (!clone.getAttribute('xmlns:xlink')) {\n        clone.setAttributeNS(xmlns, \"xmlns:xlink\", \"http://www.w3.org/1999/xlink\");\n      }\n\n      if (options.responsive) {\n        clone.removeAttribute('width');\n        clone.removeAttribute('height');\n        clone.setAttribute('preserveAspectRatio', 'xMinYMin meet');\n      } else {\n        clone.setAttribute(\"width\", width * options.scale);\n        clone.setAttribute(\"height\", height * options.scale);\n      }\n\n      clone.setAttribute(\"viewBox\", [\n        options.left || 0,\n        options.top || 0,\n        width,\n        height\n      ].join(\" \"));\n\n      var fos = clone.querySelectorAll('foreignObject > *');\n      for (var i = 0; i < fos.length; i++) {\n        if (!fos[i].getAttribute('xmlns')) {\n          fos[i].setAttributeNS(xmlns, \"xmlns\", \"http://www.w3.org/1999/xhtml\");\n        }\n      }\n\n      outer.appendChild(clone);\n\n      // In case of custom fonts we need to fetch font first, and then inline\n      // its url into data-uri format (encode as base64). That's why style\n      // processing is done asynchonously. Once all inlining is finshed\n      // cssLoadedCallback() is called.\n      styles(el, options, cssLoadedCallback);\n\n      function cssLoadedCallback(css) {\n        // here all fonts are inlined, so that we can render them properly.\n        var s = document.createElement('style');\n        s.setAttribute('type', 'text/css');\n        s.innerHTML = \"<![CDATA[\\n\" + css + \"\\n]]>\";\n        var defs = document.createElement('defs');\n        defs.appendChild(s);\n        clone.insertBefore(defs, clone.firstChild);\n\n        if (cb) {\n          var outHtml = outer.innerHTML;\n          outHtml = outHtml.replace(/NS\\d+:href/gi, 'xmlns:xlink=\"http://www.w3.org/1999/xlink\" xlink:href');\n          cb(outHtml, width, height);\n        }\n      }\n    });\n  }\n\n  out$.svgAsDataUri = function(el, options, cb) {\n    out$.prepareSvg(el, options, function(svg) {\n      var uri = 'data:image/svg+xml;base64,' + window.btoa(reEncode(doctype + svg));\n      if (cb) {\n        cb(uri);\n      }\n    });\n  }\n\n  out$.svgAsPngUri = function(el, options, cb) {\n    requireDomNode(el);\n\n    options = options || {};\n    options.encoderType = options.encoderType || 'image/png';\n    options.encoderOptions = options.encoderOptions || 0.8;\n\n    var convertToPng = function(src, w, h) {\n      var canvas = document.createElement('canvas');\n      var context = canvas.getContext('2d');\n      canvas.width = w;\n      canvas.height = h;\n\n      if(options.canvg) {\n        options.canvg(canvas, src);\n      } else {\n        context.drawImage(src, 0, 0);\n      }\n\n      if(options.backgroundColor){\n        context.globalCompositeOperation = 'destination-over';\n        context.fillStyle = options.backgroundColor;\n        context.fillRect(0, 0, canvas.width, canvas.height);\n      }\n\n      var png;\n      try {\n        png = canvas.toDataURL(options.encoderType, options.encoderOptions);\n      } catch (e) {\n        if ((typeof SecurityError !== 'undefined' && e instanceof SecurityError) || e.name == \"SecurityError\") {\n          console.error(\"Rendered SVG images cannot be downloaded in this browser.\");\n          return;\n        } else {\n          throw e;\n        }\n      }\n      cb(png);\n    }\n\n    if(options.canvg) {\n      out$.prepareSvg(el, options, convertToPng);\n    } else {\n      out$.svgAsDataUri(el, options, function(uri) {\n        var image = new Image();\n\n        image.onload = function() {\n          convertToPng(image, image.width, image.height);\n        }\n\n        image.onerror = function() {\n          console.error(\n            'There was an error loading the data URI as an image on the following SVG\\n',\n            window.atob(uri.slice(26)), '\\n',\n            \"Open the following link to see browser's diagnosis\\n\",\n            uri);\n        }\n\n        image.src = uri;\n      });\n    }\n  }\n\n  out$.download = function(name, uri) {\n    if (navigator.msSaveOrOpenBlob) {\n      navigator.msSaveOrOpenBlob(uriToBlob(uri), name);\n    } else {\n      var saveLink = document.createElement('a');\n      var downloadSupported = 'download' in saveLink;\n      if (downloadSupported) {\n        saveLink.download = name;\n        saveLink.style.display = 'none';\n        document.body.appendChild(saveLink);\n        try {\n          var blob = uriToBlob(uri);\n          var url = URL.createObjectURL(blob);\n          saveLink.href = url;\n          saveLink.onclick = function() {\n            requestAnimationFrame(function() {\n              URL.revokeObjectURL(url);\n            })\n          };\n        } catch (e) {\n          console.warn('This browser does not support object URLs. Falling back to string URL.');\n          saveLink.href = uri;\n        }\n        saveLink.click();\n        document.body.removeChild(saveLink);\n      }\n      else {\n        window.open(uri, '_temp', 'menubar=no,toolbar=no,status=no');\n      }\n    }\n  }\n\n  function uriToBlob(uri) {\n    var byteString = window.atob(uri.split(',')[1]);\n    var mimeString = uri.split(',')[0].split(':')[1].split(';')[0]\n    var buffer = new ArrayBuffer(byteString.length);\n    var intArray = new Uint8Array(buffer);\n    for (var i = 0; i < byteString.length; i++) {\n      intArray[i] = byteString.charCodeAt(i);\n    }\n    return new Blob([buffer], {type: mimeString});\n  }\n\n  out$.saveSvg = function(el, name, options) {\n    requireDomNode(el);\n\n    options = options || {};\n    out$.svgAsDataUri(el, options, function(uri) {\n      out$.download(name, uri);\n    });\n  }\n\n  out$.saveSvgAsPng = function(el, name, options) {\n    requireDomNode(el);\n\n    options = options || {};\n    out$.svgAsPngUri(el, options, function(uri) {\n      out$.download(name, uri);\n    });\n  }\n\n  // if define is defined create as an AMD module\n  if (typeof define !== 'undefined') {\n    define(function() {\n      return out$;\n    });\n  }\n\n})();\n"
  },
  {
    "path": "lib/screenfull.js",
    "content": "/*!\n* screenfull\n* v3.0.0 - 2015-11-24\n* (c) Sindre Sorhus; MIT License\n*/\n(function () {\n\t'use strict';\n\n\tvar isCommonjs = typeof module !== 'undefined' && module.exports;\n\tvar keyboardAllowed = typeof Element !== 'undefined' && 'ALLOW_KEYBOARD_INPUT' in Element;\n\n\tvar fn = (function () {\n\t\tvar val;\n\t\tvar valLength;\n\n\t\tvar fnMap = [\n\t\t\t[\n\t\t\t\t'requestFullscreen',\n\t\t\t\t'exitFullscreen',\n\t\t\t\t'fullscreenElement',\n\t\t\t\t'fullscreenEnabled',\n\t\t\t\t'fullscreenchange',\n\t\t\t\t'fullscreenerror'\n\t\t\t],\n\t\t\t// new WebKit\n\t\t\t[\n\t\t\t\t'webkitRequestFullscreen',\n\t\t\t\t'webkitExitFullscreen',\n\t\t\t\t'webkitFullscreenElement',\n\t\t\t\t'webkitFullscreenEnabled',\n\t\t\t\t'webkitfullscreenchange',\n\t\t\t\t'webkitfullscreenerror'\n\n\t\t\t],\n\t\t\t// old WebKit (Safari 5.1)\n\t\t\t[\n\t\t\t\t'webkitRequestFullScreen',\n\t\t\t\t'webkitCancelFullScreen',\n\t\t\t\t'webkitCurrentFullScreenElement',\n\t\t\t\t'webkitCancelFullScreen',\n\t\t\t\t'webkitfullscreenchange',\n\t\t\t\t'webkitfullscreenerror'\n\n\t\t\t],\n\t\t\t[\n\t\t\t\t'mozRequestFullScreen',\n\t\t\t\t'mozCancelFullScreen',\n\t\t\t\t'mozFullScreenElement',\n\t\t\t\t'mozFullScreenEnabled',\n\t\t\t\t'mozfullscreenchange',\n\t\t\t\t'mozfullscreenerror'\n\t\t\t],\n\t\t\t[\n\t\t\t\t'msRequestFullscreen',\n\t\t\t\t'msExitFullscreen',\n\t\t\t\t'msFullscreenElement',\n\t\t\t\t'msFullscreenEnabled',\n\t\t\t\t'MSFullscreenChange',\n\t\t\t\t'MSFullscreenError'\n\t\t\t]\n\t\t];\n\n\t\tvar i = 0;\n\t\tvar l = fnMap.length;\n\t\tvar ret = {};\n\n\t\tfor (; i < l; i++) {\n\t\t\tval = fnMap[i];\n\t\t\tif (val && val[1] in document) {\n\t\t\t\tfor (i = 0, valLength = val.length; i < valLength; i++) {\n\t\t\t\t\tret[fnMap[0][i]] = val[i];\n\t\t\t\t}\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t})();\n\n\tvar screenfull = {\n\t\trequest: function (elem) {\n\t\t\tvar request = fn.requestFullscreen;\n\n\t\t\telem = elem || document.documentElement;\n\n\t\t\t// Work around Safari 5.1 bug: reports support for\n\t\t\t// keyboard in fullscreen even though it doesn't.\n\t\t\t// Browser sniffing, since the alternative with\n\t\t\t// setTimeout is even worse.\n\t\t\tif (/5\\.1[\\.\\d]* Safari/.test(navigator.userAgent)) {\n\t\t\t\telem[request]();\n\t\t\t} else {\n\t\t\t\telem[request](keyboardAllowed && Element.ALLOW_KEYBOARD_INPUT);\n\t\t\t}\n\t\t},\n\t\texit: function () {\n\t\t\tdocument[fn.exitFullscreen]();\n\t\t},\n\t\ttoggle: function (elem) {\n\t\t\tif (this.isFullscreen) {\n\t\t\t\tthis.exit();\n\t\t\t} else {\n\t\t\t\tthis.request(elem);\n\t\t\t}\n\t\t},\n\t\traw: fn\n\t};\n\n\tif (!fn) {\n\t\tif (isCommonjs) {\n\t\t\tmodule.exports = false;\n\t\t} else {\n\t\t\twindow.screenfull = false;\n\t\t}\n\n\t\treturn;\n\t}\n\n\tObject.defineProperties(screenfull, {\n\t\tisFullscreen: {\n\t\t\tget: function () {\n\t\t\t\treturn Boolean(document[fn.fullscreenElement]);\n\t\t\t}\n\t\t},\n\t\telement: {\n\t\t\tenumerable: true,\n\t\t\tget: function () {\n\t\t\t\treturn document[fn.fullscreenElement];\n\t\t\t}\n\t\t},\n\t\tenabled: {\n\t\t\tenumerable: true,\n\t\t\tget: function () {\n\t\t\t\t// Coerce to boolean in case of old WebKit\n\t\t\t\treturn Boolean(document[fn.fullscreenEnabled]);\n\t\t\t}\n\t\t}\n\t});\n\n\tif (isCommonjs) {\n\t\tmodule.exports = screenfull;\n\t} else {\n\t\twindow.screenfull = screenfull;\n\t}\n})();\n"
  },
  {
    "path": "lib/scrollbar.js",
    "content": "/*    scrollbar code      */\n/*     just for fun       */\n/* for late night sadness */\n\nvar Scrollbar = function (viewboxSize, contentSize, scrollbarContainerSize) {\n\n\tthis.viewboxSize = viewboxSize;\n\tthis.viewboxPosition - undefined;\n\n\tthis.barSize = undefined;\n\tthis.barPosition = 0;\n\n\tthis.contentSize = contentSize;\n\n\tthis.scrollbarContainerSize = scrollbarContainerSize;\n\n\tthis._recalcBarSize();\n\tthis._recalcViewboxPosition();\n\n};\n\nScrollbar.prototype._recalcBarSize = function () {\n\tthis.barSize = this.viewboxSize * (this.viewboxSize / this.contentSize);\n\tthis.barSize = Math.max(this.barSize, 14);\n};\n\nScrollbar.prototype._recalcBarPosition = function () {\n\tthis.barPosition = this.viewboxSize * (this.viewboxPosition / this.contentSize);\n\tthis._constrainBarPosition();\n};\n\nScrollbar.prototype._recalcViewboxPosition = function (val) {\n\tthis.viewboxPosition = (this.barPosition / this.viewboxSize) * this.contentSize;\n};\n\nScrollbar.prototype._constrainBarPosition = function () {\n\tthis.barPosition = Math.max(this.barPosition, 0);\n\tthis.barPosition = Math.min(this.barPosition, this.scrollbarContainerSize-this.barSize);\n}\n\nScrollbar.prototype.setViewboxSize = function (val) {\n\tthis.viewboxSize = val;\n\tthis._recalcBarSize();\n\tthis._recalcBarPosition();\n\tthis._recalcViewboxPosition();\n};\n\nScrollbar.prototype.setContentSize = function (val) {\n\tthis.contentSize = val;\n\tthis._recalcBarSize();\n\tthis._recalcBarPosition();\n\tthis._recalcViewboxPosition();\n};\n\nScrollbar.prototype.setBarPosition = function (val) {\n\tthis.barPosition = val;\n\tthis._constrainBarPosition();\n\tthis._recalcViewboxPosition();\n\tthis._recalcBarPosition();\n};\n\nScrollbar.prototype.setViewboxPosition = function (val) {\n\tthis.viewboxPosition = val;\n\tthis._recalcBarPosition();\n};\n\nScrollbar.prototype.setScrollbarContainerSize = function (val) {\n\tthis.scrollbarContainerSize = val;\n};"
  },
  {
    "path": "lib/skin-win8/ui.fancytree.css",
    "content": "/*!\n * Fancytree \"Win8\" skin.\n *\n * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from\n * the LESS templates.\n */\n/*******************************************************************************\n * Common Styles for Fancytree Skins.\n *\n * This section is automatically generated from the `skin-common.less` template.\n ******************************************************************************/\n/*------------------------------------------------------------------------------\n * Helpers\n *----------------------------------------------------------------------------*/\n.ui-helper-hidden {\n  display: none;\n}\n/*------------------------------------------------------------------------------\n * Container and UL / LI\n *----------------------------------------------------------------------------*/\nul.fancytree-container {\n  font-family: tahoma, arial, helvetica;\n  font-size: 10pt;\n  white-space: nowrap;\n  padding: 3px;\n  margin: 0;\n  background-color: rgba(0,0,0,0);\n  /*border: 1px dotted gray;*/\n  min-height: 0%;\n  position: relative;\n}\nul.fancytree-container ul {\n  padding: 0 0 0 16px;\n  margin: 0;\n}\nul.fancytree-container ul > li:before {\n  content: none;\n}\nul.fancytree-container li {\n  list-style-image: none;\n  list-style-position: outside;\n  list-style-type: none;\n  -moz-background-clip: border;\n  -moz-background-inline-policy: continuous;\n  -moz-background-origin: padding;\n  background-attachment: scroll;\n  background-color: transparent;\n  background-position: 0px 0px;\n  background-repeat: repeat-y;\n  background-image: none;\n  margin: 0;\n}\nul.fancytree-container li.fancytree-lastsib {\n  background-image: none;\n}\n.ui-fancytree-disabled ul.fancytree-container {\n  opacity: 0.5;\n  background-color: silver;\n}\nul.fancytree-connectors.fancytree-container li {\n  background-image: url(\"data:image/gif;base64,R0lGODlhEAAQAPcAAAAAANPT0wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAQABAAAAgxAP8JHPgvAMGDCA0iXFiQ4UKFDglCjChwIkWLETE61MiQ40OKEkEO9JhQZEWTDRcGBAA7\");\n  background-position: 0 0;\n}\nul.fancytree-container li.fancytree-lastsib,\nul.fancytree-no-connector > li {\n  background-image: none;\n}\n/*------------------------------------------------------------------------------\n * Common icon definitions\n *----------------------------------------------------------------------------*/\nspan.fancytree-empty,\nspan.fancytree-vline,\nspan.fancytree-expander,\nspan.fancytree-icon,\nspan.fancytree-checkbox,\nspan.fancytree-radio,\nspan.fancytree-drag-helper-img,\n#fancytree-drop-marker {\n  width: 16px;\n  height: 16px;\n  display: inline-block;\n  vertical-align: top;\n  background-repeat: no-repeat;\n  background-position: left;\n  background-image: url(\"icons.gif\");\n  background-position: 0px 0px;\n}\nspan.fancytree-icon,\nspan.fancytree-checkbox,\nspan.fancytree-expander,\nspan.fancytree-radio,\nspan.fancytree-custom-icon {\n  margin-top: 2px;\n}\n/* Used by icon option: */\nspan.fancytree-custom-icon {\n  width: 16px;\n  height: 16px;\n  display: inline-block;\n  margin-left: 3px;\n  background-position: 0px 0px;\n}\n/* Used by 'icon' node option: */\nimg.fancytree-icon {\n  width: 16px;\n  height: 16px;\n  margin-left: 3px;\n  margin-top: 2px;\n  vertical-align: top;\n  border-style: none;\n}\n/*------------------------------------------------------------------------------\n * Expander icon\n *\n * Note: IE6 doesn't correctly evaluate multiples class names,\n *\t\t so we create combined class names that can be used in the CSS.\n *\n * Prefix: fancytree-exp-\n * 1st character: 'e': expanded, 'c': collapsed, 'n': no children\n * 2nd character (optional): 'd': lazy (Delayed)\n * 3rd character (optional): 'l': Last sibling\n *----------------------------------------------------------------------------*/\nspan.fancytree-expander {\n  cursor: pointer;\n}\n.fancytree-exp-n span.fancytree-expander,\n.fancytree-exp-nl span.fancytree-expander {\n  background-image: none;\n  cursor: default;\n}\n.fancytree-connectors .fancytree-exp-n span.fancytree-expander,\n.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {\n  background-image: url(\"icons.gif\");\n  margin-top: 0;\n}\n.fancytree-connectors .fancytree-exp-n span.fancytree-expander,\n.fancytree-connectors .fancytree-exp-n span.fancytree-expander:hover {\n  background-position: 0px -64px;\n}\n.fancytree-connectors .fancytree-exp-nl span.fancytree-expander,\n.fancytree-connectors .fancytree-exp-nl span.fancytree-expander:hover {\n  background-position: -16px -64px;\n}\n.fancytree-exp-c span.fancytree-expander {\n  background-position: 0px -80px;\n}\n.fancytree-exp-c span.fancytree-expander:hover {\n  background-position: -16px -80px;\n}\n.fancytree-exp-cl span.fancytree-expander {\n  background-position: 0px -96px;\n}\n.fancytree-exp-cl span.fancytree-expander:hover {\n  background-position: -16px -96px;\n}\n.fancytree-exp-cd span.fancytree-expander {\n  background-position: -64px -80px;\n}\n.fancytree-exp-cd span.fancytree-expander:hover {\n  background-position: -80px -80px;\n}\n.fancytree-exp-cdl span.fancytree-expander {\n  background-position: -64px -96px;\n}\n.fancytree-exp-cdl span.fancytree-expander:hover {\n  background-position: -80px -96px;\n}\n.fancytree-exp-e span.fancytree-expander,\n.fancytree-exp-ed span.fancytree-expander {\n  background-position: -32px -80px;\n}\n.fancytree-exp-e span.fancytree-expander:hover,\n.fancytree-exp-ed span.fancytree-expander:hover {\n  background-position: -48px -80px;\n}\n.fancytree-exp-el span.fancytree-expander,\n.fancytree-exp-edl span.fancytree-expander {\n  background-position: -32px -96px;\n}\n.fancytree-exp-el span.fancytree-expander:hover,\n.fancytree-exp-edl span.fancytree-expander:hover {\n  background-position: -48px -96px;\n}\n/* Fade out expanders, when container is not hovered or active */\n.fancytree-fade-expander span.fancytree-expander {\n  transition: opacity 1.5s;\n  opacity: 0;\n}\n.fancytree-fade-expander:hover span.fancytree-expander,\n.fancytree-fade-expander.fancytree-treefocus span.fancytree-expander,\n.fancytree-fade-expander .fancytree-treefocus span.fancytree-expander,\n.fancytree-fade-expander [class*='fancytree-statusnode-'] span.fancytree-expander {\n  transition: opacity 0.6s;\n  opacity: 1;\n}\n/*------------------------------------------------------------------------------\n * Checkbox icon\n *----------------------------------------------------------------------------*/\nspan.fancytree-checkbox {\n  margin-left: 3px;\n  background-position: 0px -32px;\n}\nspan.fancytree-checkbox:hover {\n  background-position: -16px -32px;\n}\n.fancytree-partsel span.fancytree-checkbox {\n  background-position: -64px -32px;\n}\n.fancytree-partsel span.fancytree-checkbox:hover {\n  background-position: -80px -32px;\n}\n.fancytree-selected span.fancytree-checkbox {\n  background-position: -32px -32px;\n}\n.fancytree-selected span.fancytree-checkbox:hover {\n  background-position: -48px -32px;\n}\n.fancytree-unselectable span.fancytree-checkbox {\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\n.fancytree-unselectable span.fancytree-checkbox:hover {\n  background-position: 0px -32px;\n}\n.fancytree-unselectable.fancytree-partsel span.fancytree-checkbox:hover {\n  background-position: -64px -32px;\n}\n.fancytree-unselectable.fancytree-selected span.fancytree-checkbox:hover {\n  background-position: -32px -32px;\n}\n/*------------------------------------------------------------------------------\n * Radiobutton icon\n * This is a customization, that may be activated by overriding the 'checkbox'\n * class name as 'fancytree-radio' in the tree options.\n *----------------------------------------------------------------------------*/\n.fancytree-radio span.fancytree-checkbox {\n  background-position: 0px -48px;\n}\n.fancytree-radio span.fancytree-checkbox:hover {\n  background-position: -16px -48px;\n}\n.fancytree-radio .fancytree-partsel span.fancytree-checkbox {\n  background-position: -64px -48px;\n}\n.fancytree-radio .fancytree-partsel span.fancytree-checkbox:hover {\n  background-position: -80px -48px;\n}\n.fancytree-radio .fancytree-selected span.fancytree-checkbox {\n  background-position: -32px -48px;\n}\n.fancytree-radio .fancytree-selected span.fancytree-checkbox:hover {\n  background-position: -48px -48px;\n}\n.fancytree-radio .fancytree-unselectable span.fancytree-checkbox,\n.fancytree-radio .fancytree-unselectable span.fancytree-checkbox:hover {\n  background-position: 0px -48px;\n}\n/*------------------------------------------------------------------------------\n * Node type icon\n * Note: IE6 doesn't correctly evaluate multiples class names,\n *\t\t so we create combined class names that can be used in the CSS.\n *\n * Prefix: fancytree-ico-\n * 1st character: 'e': expanded, 'c': collapsed\n * 2nd character (optional): 'f': folder\n *----------------------------------------------------------------------------*/\nspan.fancytree-icon {\n  margin-left: 3px;\n  background-position: 0px 0px;\n}\n/* Documents */\n.fancytree-ico-c span.fancytree-icon:hover {\n  background-position: -16px 0px;\n}\n.fancytree-has-children.fancytree-ico-c span.fancytree-icon {\n  background-position: -32px 0px;\n}\n.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover {\n  background-position: -48px 0px;\n}\n.fancytree-ico-e span.fancytree-icon {\n  background-position: -64px 0px;\n}\n.fancytree-ico-e span.fancytree-icon:hover {\n  background-position: -80px 0px;\n}\n/* Folders */\n.fancytree-ico-cf span.fancytree-icon {\n  background-position: 0px -16px;\n}\n.fancytree-ico-cf span.fancytree-icon:hover {\n  background-position: -16px -16px;\n}\n.fancytree-has-children.fancytree-ico-cf span.fancytree-icon {\n  background-position: -32px -16px;\n}\n.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover {\n  background-position: -48px -16px;\n}\n.fancytree-ico-ef span.fancytree-icon {\n  background-position: -64px -16px;\n}\n.fancytree-ico-ef span.fancytree-icon:hover {\n  background-position: -80px -16px;\n}\n.fancytree-loading span.fancytree-expander,\n.fancytree-loading span.fancytree-expander:hover,\n.fancytree-statusnode-loading span.fancytree-icon,\n.fancytree-statusnode-loading span.fancytree-icon:hover {\n  background-image: url(\"data:image/gif;base64,R0lGODlhEAAQAPcAAEai/0+m/1is/12u/2Oy/2u1/3C3/3G4/3W6/3q8/3+//4HA/4XC/4nE/4/H/5LI/5XK/5vN/57O/6DP/6HQ/6TS/6/X/7DX/7HY/7bb/7rd/7ze/8Hg/8fj/8rl/83m/9Dn/9Lp/9bq/9jr/9rt/9/v/+Dv/+Hw/+Xy/+v1/+32//D3//L5//f7//j7//v9/0qk/06m/1Ko/1er/2Cw/2m0/2y2/3u9/32+/4jD/5bK/5jL/5/P/6HP/6PS/6fS/6nU/67X/7Ta/7nc/7zd/8Ph/8bj/8jk/8vl/9Pp/9fr/9rs/9zu/+j0/+72//T6/0ij/1Op/1uu/1yu/2Wy/2q0/2+3/3C4/3m8/3y9/4PB/4vE/4/G/6XS/6jU/67W/7HZ/7Xa/7vd/73e/8Lh/8nk/87m/9Hn/9Ho/9vt/97u/+Lx/+bz/+n0//H4//X6/1Gn/1Go/2Gx/36+/5PJ/5TJ/5nL/57P/7PZ/7TZ/8Xi/9Tq/9zt/+by/+r0/+73//P5//n8/0uk/1Wq/3K4/3e7/4bC/4vF/47G/5fK/77f/9Do/9ns/+Tx/+/3//L4//b6//r9/2Wx/2q1/4bD/6DQ/6fT/9Tp/+Lw/+jz//D4//j8/1qt/2mz/5rM/6bS/8Lg/8jj/97v/+r1/1Cn/1ar/2Cv/3O5/3++/53O/8Th/9Lo/9Xq/+z2/2Kw/2Sx/8Ti/4rF/7DY/1+v/4TB/7fb/+Ty/1+u/2Ox/4zG/6vU/7/f//r8/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/i1NYWRlIGJ5IEtyYXNpbWlyYSBOZWpjaGV2YSAod3d3LmxvYWRpbmZvLm5ldCkAIfkEAQoAMAAsAAAAABAAEAAABptAmFCI6mAsnNNwCUthGomDoYCQoJinyELRgDwUhAFCNFRJGg8P6/VSaQyCgxK2cURMTJioEIA0Jw8geUIZAQMkIhEVLIMwKgMAFx4SGS+NLwwCFR8UGo1CKSgsJBUYLZ9sMCsZF3iDLy2nMCEXGyp5bSqyLBwaHSguQi8sKigqlkIqHb4hJc4lJsdMLSQeHyEhIyXSgy2hxsFLQQAh+QQBCgAAACwAAAAAEAAQAAAHp4AAgoIoH0NCSCiDiwBORDo5Czg3C0BNjCg/Dw46PjwOBwcLS4MrQTs9ICwvL05FODU4igBGPECzi0s4NDyNQT5KjINDAzZMTEBCLMKCTQczQ0lBRcyDODI8SojVAC84MTxMQkVP1SgDMEJPRkS4jB8xM6RKRR/Lwi9HQYJPIB9KTV4MeuHiicBSSkAoYYKiiRMnKw4ucnFiyRKGKJyUq/aChUaDjAIBACH5BAEKAAAALAAAAAAQABAAAAeogACCgm1KZGRmbYOLAG5GXjoPXFsPYIqLbWE7XV1fXjtaWQ9qg25iXmBKby8AKmVcWFyXaBdil4tqWldejWNhpIyCZFZZa2tjZG/BgipYVWRpY2bLg1s0XWpGaNQAL1pTXW1maMrLbVZSYm9oZyrUYVFUpGxoaeWLZzQBOoJvamkm3OCSAsWKiUH+1rBp48bFCxVWaGxb9LBNGxVvVqUBFuzFizculgUCACH5BAEKAAEALAAAAAAQABAAAAi4AAMIFPiHxJEjJPwMXBgAEIg8XijcsUNhzB+GfzjkwYNnSB4KdRzcWTPwzZEhY/i8EfgmhJ0GdhQGIDFGz0WGJuoswBPgzQc9fRgOPDKnQR8/H0K4EErQQQKgIPgwFRioTgE8ffZInRqIztWCfAJN/TOnAAcXJvgAmjpEDgKSf9b4Ectwz5UBd6j68fNnaYBAfvIUEIAgKNU/gN4E+sNgAJw4BvYIfeMiUB8BAAbUMTz1TYU8YRcGBAAh+QQBCgAAACwAAAAAEAAQAAAItAABCBT4qJGIRY0cDVwIAJIIMnnyWABiwYjChY8WGVFExgjELjwsNBroQgSSD40gCXQIJFGXi41AiHjEEECjLg8UNWS06GLND4gSNXrEqESkmgQTGfrgqMRIpAAidVkwpKDPmpF44MgDqVGTo0gdHbqBJJIjR2BrkiG0YCSkRyprMsJBCMhASJEioczbZEihGoaeCtQrgwYOujRoLGBU08IgQYJkzKjBQ/DCSIzy8OgypATDgAAh+QQBCgAAACwAAAAAEAAQAAAIswABCBQIKRMfPmw0DVwIYBObEEiKjBEzJoTChZD4XArB0UyRMBfGtBm4CdOSJW02EeQjxkuYi38wYYLEEEAmDJWMNGyTsKbAS5Us/YHU5o9PgZos7QixSdPFo18eFNkESeXRTV+4FGlo1aemHVvM7ORzFMmCByOXHJgSoiafLTgwCOQjCYqkMCk3/SlCCQvagSEmBRh0gBLcAwe4kF2IaYekKVNoTMLiZWTNTSwtWRqDiWFAACH5BAEKAAIALAAAAAAQABAAAAi5AAUIFOhCBRs2o94MXCjghQpRI/YkQYJkj8KFL0atEcVRVJIOY0KtWKhi1Cg3LwS+YdNhCCg3Kt2oSMlQxZg8IGLSZChA1IU8Khru5PkmjxdRbtgE5TlwCAUknzgxGIoxDw8kQgAMGMVUgJtPnvaQGBAgT1cQDyhwhRCnUxKeazw5GCNwTQFOBsbMfLECyYMGPJYK2INgAAEFDyA0ULDA0xqGbHggKFDgQIIGF7jyfLGmw4ULHdgwDAgAIfkEAQoAAAAsAAAAABAAEAAACLcAAQgcqElTK00uBioUuKlVEzYnlixhk3BhC4MO2SxhtIrVCoWbNrnYNLAhKzMgWggMgqTiwhVIiiwBsKQUKTMLB7IhoqpVHhimmuQU2KJInhOpYtxwmdNMHlapZKAiORRAkSCshpQ61arqijxAJNoYMKTqEh95uvagUWjmQjZAUqkSyAZVDVRFWoXUBKLHjiAfBS5hcOqUg1Q+djh44IPNwiZAFtxAtSCHDiJdh55AkmeIGaEKAwIAIfkEAQoAAAAsAAAAABAAEAAACLcAAQgcGMgFJEiBBioEUEIJAINuRo36k1AhGldXVhSMyAaTCUgDMVWBMiWNQjeY0pRwIVBHAFdoFgKAxOgMG4avooSRKfCPmTOQNEi5MornwzNIRnWZQqkiTyVFSnRxtYWlUTMa0hSpkuWPUUgcNGDClMVKEaMmwohxA6CLFUolZI7ScCEmgFFcsnBB4nVmCTBeNLAVWCKvlh1dvnjRUSlMUYWjwDzYwuWBji6wBss1U6QImscDAwIAIfkEAQoAAQAsAAAAABAAEAAACLMAAwgUyEfWJxYDEw5sBGEAAAGNXkCCpDAAKwNw4AxgoEIii44LCwnolMfPC4EvVPgxKfDOgCusKr7ws0ZFABOF5IipKJAFHz4vOBSYY5NnAD4jVMgqAOGkUT5J/CxtajRAmiRr9CSIVbQiJFZI/DRyMAeJ0awfKMqaQ2dNRRV6xqQR6MdOLDusEAaAtGbMGCR6A6y54wDCpzxiZCnm0FWgijF3INyhcDhJYIV+wH5I0zhAQAAh+QQBCgAAACwAAAAAEAAQAAAItAABCBRYYkiqVLUYuRjIkE2qGjNkxBA0IwhDgYwU0JhVg1YCGjLMLBzYxFCNBEM0uXDBxkyLlQOBEFLA6CKAlZpaAGBjiBAZmwP//HFhJMGhP0AF/mHjopaCVCOBsmGjqZahLlFtsinxx4yhHZqSurDFaGkiREmS/rnESOeQB6nY2NR0CYRcAH+67AByaWSLlkj6DmQTJFWXWmSMkCFCBkRYhn+MBAESpBbitmpLJLlU4vHAgAAh+QQBCgAAACwAAAAAEAAQAAAIvQABCBS4ZpclS0PWDFwIoI0uHFVu3ZIiiY7ChWpyHTiAowGDK4MCVEEzsA0dLAw4OOHFq00YXFBwqREIBkeumQzN3DqQBkCmOgvKMByYpg0vAGZy7XAydCCvFgA45NLVdGCLFrw40PlytCoLJy0u7bAEtSkvJ21aOLF055JXNkYBwKoEJtPQFmvWMAWwIoyuIWrKunCSJo2Jrg2HXAjDwcwlNCDQpCk7kAWIXUN2wTKDZo2Lqk7YpFGTibLAgAA7\");\n  background-position: 0px 0px;\n}\n/* Status node icons */\n.fancytree-statusnode-error span.fancytree-icon,\n.fancytree-statusnode-error span.fancytree-icon:hover {\n  background-position: 0px -112px;\n}\n/*------------------------------------------------------------------------------\n * Node titles and highlighting\n *----------------------------------------------------------------------------*/\nspan.fancytree-node {\n  /* See #117 */\n  display: inherit;\n  width: 100%;\n  margin-top: 0px;\n  min-height: 20px;\n}\nspan.fancytree-title {\n  color: black;\n  cursor: pointer;\n  display: inline-block;\n  vertical-align: top;\n  min-height: 20px;\n  padding: 0 3px 0 3px;\n  margin: 0px 0 0 3px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 0px;\n  -moz-border-radius: 0px;\n  -ms-border-radius: 0px;\n  -o-border-radius: 0px;\n  border-radius: 0px;\n}\nspan.fancytree-node.fancytree-error span.fancytree-title {\n  color: red;\n}\n/*------------------------------------------------------------------------------\n * Drag'n'drop support\n *----------------------------------------------------------------------------*/\ndiv.fancytree-drag-helper span.fancytree-childcounter,\ndiv.fancytree-drag-helper span.fancytree-dnd-modifier {\n  display: inline-block;\n  color: #fff;\n  background: #337ab7;\n  border: 1px solid gray;\n  min-width: 10px;\n  height: 10px;\n  line-height: 1;\n  vertical-align: baseline;\n  border-radius: 10px;\n  padding: 2px;\n  text-align: center;\n  font-size: 9px;\n}\ndiv.fancytree-drag-helper span.fancytree-childcounter {\n  position: absolute;\n  top: -6px;\n  right: -6px;\n}\ndiv.fancytree-drag-helper span.fancytree-dnd-modifier {\n  background: #5cb85c;\n  border: none;\n  font-weight: bolder;\n}\ndiv.fancytree-drag-helper.fancytree-drop-accept span.fancytree-drag-helper-img {\n  background-position: -32px -112px;\n}\ndiv.fancytree-drag-helper.fancytree-drop-reject span.fancytree-drag-helper-img {\n  background-position: -16px -112px;\n}\n/*** Drop marker icon *********************************************************/\n#fancytree-drop-marker {\n  width: 32px;\n  position: absolute;\n  background-position: 0px -128px;\n  margin: 0;\n}\n#fancytree-drop-marker.fancytree-drop-after,\n#fancytree-drop-marker.fancytree-drop-before {\n  width: 64px;\n  background-position: 0px -144px;\n}\n#fancytree-drop-marker.fancytree-drop-copy {\n  background-position: -64px -128px;\n}\n#fancytree-drop-marker.fancytree-drop-move {\n  background-position: -32px -128px;\n}\n/*** Source node while dragging ***********************************************/\nspan.fancytree-drag-source.fancytree-drag-remove {\n  opacity: 0.15;\n}\n/*** Target node while dragging cursor is over it *****************************/\n/*------------------------------------------------------------------------------\n * 'rtl' option\n *----------------------------------------------------------------------------*/\n.fancytree-container.fancytree-rtl .fancytree-title {\n  /*unicode-bidi: bidi-override;*/\n  /* optional: reverse title letters */\n}\n.fancytree-container.fancytree-rtl span.fancytree-connector,\n.fancytree-container.fancytree-rtl span.fancytree-expander,\n.fancytree-container.fancytree-rtl span.fancytree-icon,\n.fancytree-container.fancytree-rtl span.fancytree-drag-helper-img,\n.fancytree-container.fancytree-rtl #fancytree-drop-marker {\n  background-image: url(\"icons-rtl.gif\");\n}\n.fancytree-container.fancytree-rtl .fancytree-exp-n span.fancytree-expander,\n.fancytree-container.fancytree-rtl .fancytree-exp-nl span.fancytree-expander {\n  background-image: none;\n}\n.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-n span.fancytree-expander,\n.fancytree-container.fancytree-rtl.fancytree-connectors .fancytree-exp-nl span.fancytree-expander {\n  background-image: url(\"icons-rtl.gif\");\n}\nul.fancytree-container.fancytree-rtl ul {\n  padding: 0 16px 0 0;\n}\nul.fancytree-container.fancytree-rtl.fancytree-connectors li {\n  background-position: right 0;\n  background-image: url(\"vline-rtl.gif\");\n}\nul.fancytree-container.fancytree-rtl li.fancytree-lastsib,\nul.fancytree-container.fancytree-rtl.fancytree-no-connector > li {\n  background-image: none;\n}\n/*------------------------------------------------------------------------------\n * 'table' extension\n *----------------------------------------------------------------------------*/\ntable.fancytree-ext-table {\n  border-collapse: collapse;\n}\ntable.fancytree-ext-table span.fancytree-node {\n  display: inline-block;\n  box-sizing: border-box;\n}\n/*------------------------------------------------------------------------------\n * 'columnview' extension\n *----------------------------------------------------------------------------*/\ntable.fancytree-ext-columnview tbody tr td {\n  position: relative;\n  border: 1px solid gray;\n  vertical-align: top;\n  overflow: auto;\n}\ntable.fancytree-ext-columnview tbody tr td > ul {\n  padding: 0;\n}\ntable.fancytree-ext-columnview tbody tr td > ul li {\n  list-style-image: none;\n  list-style-position: outside;\n  list-style-type: none;\n  -moz-background-clip: border;\n  -moz-background-inline-policy: continuous;\n  -moz-background-origin: padding;\n  background-attachment: scroll;\n  background-color: transparent;\n  background-position: 0px 0px;\n  background-repeat: repeat-y;\n  background-image: none;\n  /* no v-lines */\n  margin: 0;\n}\ntable.fancytree-ext-columnview span.fancytree-node {\n  position: relative;\n  /* allow positioning of embedded spans */\n  display: inline-block;\n}\ntable.fancytree-ext-columnview span.fancytree-node.fancytree-expanded {\n  background-color: #CBE8F6;\n}\ntable.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right {\n  position: absolute;\n  right: 3px;\n  background-position: 0px -80px;\n}\ntable.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover {\n  background-position: -16px -80px;\n}\n/*------------------------------------------------------------------------------\n * 'filter' extension\n *----------------------------------------------------------------------------*/\n.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title {\n  color: silver;\n  font-weight: lighter;\n}\n.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title,\n.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title {\n  color: black;\n  font-weight: normal;\n}\n.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title,\n.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title {\n  color: black;\n  font-weight: bold;\n}\n.fancytree-ext-filter-hide tr.fancytree-hide,\n.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide {\n  display: none;\n}\n.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title,\n.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title {\n  color: silver;\n  font-weight: lighter;\n}\n.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title,\n.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title {\n  color: black;\n  font-weight: normal;\n}\n/* Hide expanders if all child nodes are hidden by filter */\n.fancytree-ext-filter-hide-expanders tr.fancytree-match span.fancytree-expander,\n.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-match span.fancytree-expander {\n  visibility: hidden;\n}\n.fancytree-ext-filter-hide-expanders tr.fancytree-submatch span.fancytree-expander,\n.fancytree-ext-filter-hide-expanders span.fancytree-node.fancytree-submatch span.fancytree-expander {\n  visibility: visible;\n}\n.fancytree-ext-childcounter span.fancytree-icon,\n.fancytree-ext-filter span.fancytree-icon {\n  position: relative;\n}\n.fancytree-ext-childcounter span.fancytree-childcounter,\n.fancytree-ext-filter span.fancytree-childcounter {\n  color: #fff;\n  background: #777;\n  border: 1px solid gray;\n  position: absolute;\n  top: -6px;\n  right: -6px;\n  min-width: 10px;\n  height: 10px;\n  line-height: 1;\n  vertical-align: baseline;\n  border-radius: 10px;\n  padding: 2px;\n  text-align: center;\n  font-size: 9px;\n}\n/*------------------------------------------------------------------------------\n * 'wide' extension\n *----------------------------------------------------------------------------*/\nul.fancytree-ext-wide {\n  position: relative;\n  min-width: 100%;\n  z-index: 2;\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\nul.fancytree-ext-wide span.fancytree-node > span {\n  position: relative;\n  z-index: 2;\n}\nul.fancytree-ext-wide span.fancytree-node span.fancytree-title {\n  position: absolute;\n  z-index: 1;\n  left: 0px;\n  min-width: 100%;\n  margin-left: 0;\n  margin-right: 0;\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\n/*------------------------------------------------------------------------------\n * 'fixed' extension\n *----------------------------------------------------------------------------*/\n.fancytree-ext-fixed-wrapper .fancytree-fixed-hidden {\n  display: none;\n}\n.fancytree-ext-fixed-wrapper div.scrollBorderBottom {\n  border-bottom: 3px solid rgba(0, 0, 0, 0.75);\n}\n.fancytree-ext-fixed-wrapper div.scrollBorderRight {\n  border-right: 3px solid rgba(0, 0, 0, 0.75);\n}\n.fancytree-ext-fixed-wrapper div.fancytree-fixed-wrapper-tl {\n  position: absolute;\n  overflow: hidden;\n  z-index: 3;\n  top: 0px;\n  left: 0px;\n}\n.fancytree-ext-fixed-wrapper div.fancytree-fixed-wrapper-tr {\n  position: absolute;\n  overflow: hidden;\n  z-index: 2;\n  top: 0px;\n}\n.fancytree-ext-fixed-wrapper div.fancytree-fixed-wrapper-bl {\n  position: absolute;\n  overflow: hidden;\n  z-index: 2;\n  left: 0px;\n}\n.fancytree-ext-fixed-wrapper div.fancytree-fixed-wrapper-br {\n  position: absolute;\n  overflow: scroll;\n  z-index: 1;\n}\n/*******************************************************************************\n * Styles specific to this skin.\n *\n * This section is automatically generated from the `ui-fancytree.less` template.\n ******************************************************************************/\n/*******************************************************************************\n * Node titles\n */\n.fancytree-plain span.fancytree-title {\n  border: 1px solid transparent;\n}\n.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-focused span.fancytree-title {\n  border-color: #3399ff;\n}\n.fancytree-plain span.fancytree-active span.fancytree-title,\n.fancytree-plain span.fancytree-selected span.fancytree-title {\n  background-color: #f7f7f7;\n  border-color: #dedede;\n}\n.fancytree-plain span.fancytree-node span.fancytree-selected span.fancytree-title {\n  font-style: italic;\n}\n.fancytree-plain span.fancytree-node:hover span.fancytree-title {\n  background-color: #eff9fe;\n  border-color: #70c0e7;\n}\n.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-active span.fancytree-title,\n.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-selected span.fancytree-title {\n  background-color: #cbe8f6;\n  border-color: #26a0da;\n}\n/*******************************************************************************\n * 'table' extension\n */\ntable.fancytree-ext-table tbody tr td {\n  border: 1px solid #EDEDED;\n}\ntable.fancytree-ext-table tbody span.fancytree-node,\ntable.fancytree-ext-table tbody span.fancytree-node:hover {\n  border: none;\n  background: none;\n}\ntable.fancytree-ext-table tbody tr:hover {\n  background-color: #E5F3FB;\n  outline: 1px solid #70C0E7;\n}\ntable.fancytree-ext-table tbody tr.fancytree-focused span.fancytree-title {\n  outline: 1px dotted black;\n}\ntable.fancytree-ext-table tbody tr.fancytree-active:hover,\ntable.fancytree-ext-table tbody tr.fancytree-selected:hover {\n  background-color: #CBE8F6;\n  outline: 1px solid #26A0DA;\n}\ntable.fancytree-ext-table tbody tr.fancytree-active {\n  background-color: #F7F7F7;\n  outline: 1px solid #DEDEDE;\n}\ntable.fancytree-ext-table tbody tr.fancytree-selected {\n  background-color: #F7F7F7;\n}\ntable.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-active {\n  background-color: #CBE8F6;\n  outline: 1px solid #26A0DA;\n}\ntable.fancytree-ext-table.fancytree-treefocus tbody tr.fancytree-selected {\n  background-color: #CBE8F6;\n}\n"
  },
  {
    "path": "lib/skin-win8/ui.fancytree.less",
    "content": "/*!\n * Fancytree \"Win8\" skin.\n *\n * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from\n * the LESS templates.\n */\n\n// Import common styles\n@import \"../skin-common.less\";\n\n\n/*******************************************************************************\n * Styles specific to this skin.\n *\n * This section is automatically generated from the `ui-fancytree.less` template.\n ******************************************************************************/\n\n// Borders have NO radius and NO gradients are used!\n\n// both:\n//    unselected background: white\n//    hover bar (unselected, inactive): #E5F3FB (border: #70C0E7) 'very light blue'\n//    active node: #CBE8F6 (border: #26A0DA)  'light blue'\n//    active node with hover: wie active node\n\n// Tree view:\n//    active node, tree inactive: #F7F7F7 (border: #DEDEDE) 'light gray, selected, but tree not active'\n\n// List view: \n//    selected bar: --> active bar\n//    focus  bar: transparent(white) + border 1px solid #3399FF  ()\n\n//    table left/right border: #EDEDED 'light gray'\n\n// Override the variable after the import. \n// NOTE: Variables are always resolved as the last definition, even if it is \n// after where it is used.\n@fancy-use-sprites: true;      // false: suppress all background images (i.e. icons)\n\n@fancy-line-height: 20px;      // height of a nodes selection bar including borders\n@fancy-node-v-spacing: 0px;    // gap between two node borders\n@fancy-icon-width: 16px;\n@fancy-icon-height: 16px;\n@fancy-icon-spacing: 3px;      // margin between icon/icon or icon/title\n@fancy-icon-ofs-top: 2px;      // extra vertical offset for expander, checkbox and icon\n@fancy-title-ofs-top: 0px;     // extra vertical offset for title\n@fancy-node-border-width: 1px;\n@fancy-node-border-radius: 0px;\n@fancy-node-outline-width: 1px;\n\n\n// @fancy-icon-width: 16px;\n// @fancy-icon-height: 16px;\n// @fancy-line-height: 16px;\n// @fancy-icon-spacing: 3px;\n\n// Use 'data-uri(...)' to embed the image into CSS instead of linking to 'loading.gif':\n@fancy-loading-url: data-uri(\"@{fancy-image-dir}/loading.gif\");\n// Set to `true` to use `data-uri(...)` which will embed icons.gif into CSS \n// instead of linking to that file:\n// @fancy-inline-sprites: true;\n\n/*******************************************************************************\n * Node titles\n */\n.fancytree-plain  {\n\tspan.fancytree-title {\n\t\tborder: @fancy-node-border-width solid transparent;  // avoid jumping, when a border is added on hover\n\t}\n\t&.fancytree-container.fancytree-treefocus span.fancytree-focused span.fancytree-title {\n\t\tborder-color: #3399ff;\n\t}\n\tspan.fancytree-active span.fancytree-title,\n\tspan.fancytree-selected span.fancytree-title { // active/selcted nodes inside inactive tree\n\t\tbackground-color: #f7f7f7;\n\t\tborder-color: #dedede;\n\t}\n\tspan.fancytree-node span.fancytree-selected span.fancytree-title {\n\t\tfont-style: italic;\n\t}\n\tspan.fancytree-node:hover span.fancytree-title {\n\t\tbackground-color: #eff9fe; // hover is always colored, even if tree is unfocused\n\t\tborder-color: #70c0e7;\n\t}\n\t&.fancytree-container.fancytree-treefocus {\n\t\tspan.fancytree-active span.fancytree-title,\n\t\tspan.fancytree-selected span.fancytree-title {\n\t\t\tbackground-color: #cbe8f6;\n\t\t\tborder-color: #26a0da;\n\t\t}\n\t}\n}\n\n/*******************************************************************************\n * 'table' extension\n */\ntable.fancytree-ext-table tbody {\n\ttr td {\n\t  border: 1px solid #EDEDED;\n\t}\n\tspan.fancytree-node,\n\tspan.fancytree-node:hover { // undo standard tree css\n\t\tborder: none;\n\t\tbackground: none;\n\t}\n\t// Title gets a white background, when hovered. Undo standard node formatting\n\t// span.fancytree-title:hover {\n\t//   border: none; //1px solid transparent;\n\t//   background: inherit;\n\t//   background: transparent;\n\t//   background: none;\n\t//   filter: none;\n\t// }\n\ttr:hover  {\n\t\tbackground-color: #E5F3FB;\n\t    outline: 1px solid #70C0E7;\n\t}\n\t// tr:hover td {\n\t//   outline: 1px solid #D8F0FA;\n\t// }\n\t// tr.fancytree-focused {\n\t// \tborder-color: #3399FF;\n //    \toutline: 1px dotted black;\n\t// }\n\ttr.fancytree-focused span.fancytree-title {\n\t  outline: 1px dotted black;\n\t}\n\n\ttr.fancytree-active:hover,\n\ttr.fancytree-selected:hover {\n\t\tbackground-color: #CBE8F6;\n\t    outline: 1px solid #26A0DA;\n\t}\n\ttr.fancytree-active {  // dimmed, if inside inactive tree\n\t\tbackground-color: #F7F7F7;\n\t    outline: 1px solid #DEDEDE;\n\t}\n\ttr.fancytree-selected {  // dimmed, if inside inactive tree\n\t\tbackground-color: #F7F7F7;\n\t}\n}\n\ntable.fancytree-ext-table.fancytree-treefocus tbody {\n\ttr.fancytree-active {\n\t\tbackground-color: #CBE8F6;\n\t    outline: 1px solid #26A0DA;\n\t}\n\ttr.fancytree-selected {\n\t\tbackground-color: #CBE8F6;\n\t}\n}\n"
  },
  {
    "path": "lib/socket.io-1.2.0.js",
    "content": "!function(e){if(\"object\"==typeof exports&&\"undefined\"!=typeof module)module.exports=e();else if(\"function\"==typeof define&&define.amd)define([],e);else{var f;\"undefined\"!=typeof window?f=window:\"undefined\"!=typeof global?f=global:\"undefined\"!=typeof self&&(f=self),f.io=e()}}(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);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.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){module.exports=_dereq_(\"./lib/\")},{\"./lib/\":2}],2:[function(_dereq_,module,exports){var url=_dereq_(\"./url\");var parser=_dereq_(\"socket.io-parser\");var Manager=_dereq_(\"./manager\");var debug=_dereq_(\"debug\")(\"socket.io-client\");module.exports=exports=lookup;var cache=exports.managers={};function lookup(uri,opts){if(typeof uri==\"object\"){opts=uri;uri=undefined}opts=opts||{};var parsed=url(uri);var source=parsed.source;var id=parsed.id;var io;if(opts.forceNew||opts[\"force new connection\"]||false===opts.multiplex){debug(\"ignoring socket cache for %s\",source);io=Manager(source,opts)}else{if(!cache[id]){debug(\"new io instance for %s\",source);cache[id]=Manager(source,opts)}io=cache[id]}return io.socket(parsed.path)}exports.protocol=parser.protocol;exports.connect=lookup;exports.Manager=_dereq_(\"./manager\");exports.Socket=_dereq_(\"./socket\")},{\"./manager\":3,\"./socket\":5,\"./url\":6,debug:9,\"socket.io-parser\":40}],3:[function(_dereq_,module,exports){var url=_dereq_(\"./url\");var eio=_dereq_(\"engine.io-client\");var Socket=_dereq_(\"./socket\");var Emitter=_dereq_(\"component-emitter\");var parser=_dereq_(\"socket.io-parser\");var on=_dereq_(\"./on\");var bind=_dereq_(\"component-bind\");var object=_dereq_(\"object-component\");var debug=_dereq_(\"debug\")(\"socket.io-client:manager\");var indexOf=_dereq_(\"indexof\");module.exports=Manager;function Manager(uri,opts){if(!(this instanceof Manager))return new Manager(uri,opts);if(uri&&\"object\"==typeof uri){opts=uri;uri=undefined}opts=opts||{};opts.path=opts.path||\"/socket.io\";this.nsps={};this.subs=[];this.opts=opts;this.reconnection(opts.reconnection!==false);this.reconnectionAttempts(opts.reconnectionAttempts||Infinity);this.reconnectionDelay(opts.reconnectionDelay||1e3);this.reconnectionDelayMax(opts.reconnectionDelayMax||5e3);this.timeout(null==opts.timeout?2e4:opts.timeout);this.readyState=\"closed\";this.uri=uri;this.connected=[];this.attempts=0;this.encoding=false;this.packetBuffer=[];this.encoder=new parser.Encoder;this.decoder=new parser.Decoder;this.autoConnect=opts.autoConnect!==false;if(this.autoConnect)this.open()}Manager.prototype.emitAll=function(){this.emit.apply(this,arguments);for(var nsp in this.nsps){this.nsps[nsp].emit.apply(this.nsps[nsp],arguments)}};Emitter(Manager.prototype);Manager.prototype.reconnection=function(v){if(!arguments.length)return this._reconnection;this._reconnection=!!v;return this};Manager.prototype.reconnectionAttempts=function(v){if(!arguments.length)return this._reconnectionAttempts;this._reconnectionAttempts=v;return this};Manager.prototype.reconnectionDelay=function(v){if(!arguments.length)return this._reconnectionDelay;this._reconnectionDelay=v;return this};Manager.prototype.reconnectionDelayMax=function(v){if(!arguments.length)return this._reconnectionDelayMax;this._reconnectionDelayMax=v;return this};Manager.prototype.timeout=function(v){if(!arguments.length)return this._timeout;this._timeout=v;return this};Manager.prototype.maybeReconnectOnOpen=function(){if(!this.openReconnect&&!this.reconnecting&&this._reconnection&&this.attempts===0){this.openReconnect=true;this.reconnect()}};Manager.prototype.open=Manager.prototype.connect=function(fn){debug(\"readyState %s\",this.readyState);if(~this.readyState.indexOf(\"open\"))return this;debug(\"opening %s\",this.uri);this.engine=eio(this.uri,this.opts);var socket=this.engine;var self=this;this.readyState=\"opening\";this.skipReconnect=false;var openSub=on(socket,\"open\",function(){self.onopen();fn&&fn()});var errorSub=on(socket,\"error\",function(data){debug(\"connect_error\");self.cleanup();self.readyState=\"closed\";self.emitAll(\"connect_error\",data);if(fn){var err=new Error(\"Connection error\");err.data=data;fn(err)}self.maybeReconnectOnOpen()});if(false!==this._timeout){var timeout=this._timeout;debug(\"connect attempt will timeout after %d\",timeout);var timer=setTimeout(function(){debug(\"connect attempt timed out after %d\",timeout);openSub.destroy();socket.close();socket.emit(\"error\",\"timeout\");self.emitAll(\"connect_timeout\",timeout)},timeout);this.subs.push({destroy:function(){clearTimeout(timer)}})}this.subs.push(openSub);this.subs.push(errorSub);return this};Manager.prototype.onopen=function(){debug(\"open\");this.cleanup();this.readyState=\"open\";this.emit(\"open\");var socket=this.engine;this.subs.push(on(socket,\"data\",bind(this,\"ondata\")));this.subs.push(on(this.decoder,\"decoded\",bind(this,\"ondecoded\")));this.subs.push(on(socket,\"error\",bind(this,\"onerror\")));this.subs.push(on(socket,\"close\",bind(this,\"onclose\")))};Manager.prototype.ondata=function(data){this.decoder.add(data)};Manager.prototype.ondecoded=function(packet){this.emit(\"packet\",packet)};Manager.prototype.onerror=function(err){debug(\"error\",err);this.emitAll(\"error\",err)};Manager.prototype.socket=function(nsp){var socket=this.nsps[nsp];if(!socket){socket=new Socket(this,nsp);this.nsps[nsp]=socket;var self=this;socket.on(\"connect\",function(){if(!~indexOf(self.connected,socket)){self.connected.push(socket)}})}return socket};Manager.prototype.destroy=function(socket){var index=indexOf(this.connected,socket);if(~index)this.connected.splice(index,1);if(this.connected.length)return;this.close()};Manager.prototype.packet=function(packet){debug(\"writing packet %j\",packet);var self=this;if(!self.encoding){self.encoding=true;this.encoder.encode(packet,function(encodedPackets){for(var i=0;i<encodedPackets.length;i++){self.engine.write(encodedPackets[i])}self.encoding=false;self.processPacketQueue()})}else{self.packetBuffer.push(packet)}};Manager.prototype.processPacketQueue=function(){if(this.packetBuffer.length>0&&!this.encoding){var pack=this.packetBuffer.shift();this.packet(pack)}};Manager.prototype.cleanup=function(){var sub;while(sub=this.subs.shift())sub.destroy();this.packetBuffer=[];this.encoding=false;this.decoder.destroy()};Manager.prototype.close=Manager.prototype.disconnect=function(){this.skipReconnect=true;this.readyState=\"closed\";this.engine&&this.engine.close()};Manager.prototype.onclose=function(reason){debug(\"close\");this.cleanup();this.readyState=\"closed\";this.emit(\"close\",reason);if(this._reconnection&&!this.skipReconnect){this.reconnect()}};Manager.prototype.reconnect=function(){if(this.reconnecting||this.skipReconnect)return this;var self=this;this.attempts++;if(this.attempts>this._reconnectionAttempts){debug(\"reconnect failed\");this.emitAll(\"reconnect_failed\");this.reconnecting=false}else{var delay=this.attempts*this.reconnectionDelay();delay=Math.min(delay,this.reconnectionDelayMax());debug(\"will wait %dms before reconnect attempt\",delay);this.reconnecting=true;var timer=setTimeout(function(){if(self.skipReconnect)return;debug(\"attempting reconnect\");self.emitAll(\"reconnect_attempt\",self.attempts);self.emitAll(\"reconnecting\",self.attempts);if(self.skipReconnect)return;self.open(function(err){if(err){debug(\"reconnect attempt error\");self.reconnecting=false;self.reconnect();self.emitAll(\"reconnect_error\",err.data)}else{debug(\"reconnect success\");self.onreconnect()}})},delay);this.subs.push({destroy:function(){clearTimeout(timer)}})}};Manager.prototype.onreconnect=function(){var attempt=this.attempts;this.attempts=0;this.reconnecting=false;this.emitAll(\"reconnect\",attempt)}},{\"./on\":4,\"./socket\":5,\"./url\":6,\"component-bind\":7,\"component-emitter\":8,debug:9,\"engine.io-client\":10,indexof:36,\"object-component\":37,\"socket.io-parser\":40}],4:[function(_dereq_,module,exports){module.exports=on;function on(obj,ev,fn){obj.on(ev,fn);return{destroy:function(){obj.removeListener(ev,fn)}}}},{}],5:[function(_dereq_,module,exports){var parser=_dereq_(\"socket.io-parser\");var Emitter=_dereq_(\"component-emitter\");var toArray=_dereq_(\"to-array\");var on=_dereq_(\"./on\");var bind=_dereq_(\"component-bind\");var debug=_dereq_(\"debug\")(\"socket.io-client:socket\");var hasBin=_dereq_(\"has-binary\");module.exports=exports=Socket;var events={connect:1,connect_error:1,connect_timeout:1,disconnect:1,error:1,reconnect:1,reconnect_attempt:1,reconnect_failed:1,reconnect_error:1,reconnecting:1};var emit=Emitter.prototype.emit;function Socket(io,nsp){this.io=io;this.nsp=nsp;this.json=this;this.ids=0;this.acks={};if(this.io.autoConnect)this.open();this.receiveBuffer=[];this.sendBuffer=[];this.connected=false;this.disconnected=true}Emitter(Socket.prototype);Socket.prototype.subEvents=function(){if(this.subs)return;var io=this.io;this.subs=[on(io,\"open\",bind(this,\"onopen\")),on(io,\"packet\",bind(this,\"onpacket\")),on(io,\"close\",bind(this,\"onclose\"))]};Socket.prototype.open=Socket.prototype.connect=function(){if(this.connected)return this;this.subEvents();this.io.open();if(\"open\"==this.io.readyState)this.onopen();return this};Socket.prototype.send=function(){var args=toArray(arguments);args.unshift(\"message\");this.emit.apply(this,args);return this};Socket.prototype.emit=function(ev){if(events.hasOwnProperty(ev)){emit.apply(this,arguments);return this}var args=toArray(arguments);var parserType=parser.EVENT;if(hasBin(args)){parserType=parser.BINARY_EVENT}var packet={type:parserType,data:args};if(\"function\"==typeof args[args.length-1]){debug(\"emitting packet with ack id %d\",this.ids);this.acks[this.ids]=args.pop();packet.id=this.ids++}if(this.connected){this.packet(packet)}else{this.sendBuffer.push(packet)}return this};Socket.prototype.packet=function(packet){packet.nsp=this.nsp;this.io.packet(packet)};Socket.prototype.onopen=function(){debug(\"transport is open - connecting\");if(\"/\"!=this.nsp){this.packet({type:parser.CONNECT})}};Socket.prototype.onclose=function(reason){debug(\"close (%s)\",reason);this.connected=false;this.disconnected=true;this.emit(\"disconnect\",reason)};Socket.prototype.onpacket=function(packet){if(packet.nsp!=this.nsp)return;switch(packet.type){case parser.CONNECT:this.onconnect();break;case parser.EVENT:this.onevent(packet);break;case parser.BINARY_EVENT:this.onevent(packet);break;case parser.ACK:this.onack(packet);break;case parser.BINARY_ACK:this.onack(packet);break;case parser.DISCONNECT:this.ondisconnect();break;case parser.ERROR:this.emit(\"error\",packet.data);break}};Socket.prototype.onevent=function(packet){var args=packet.data||[];debug(\"emitting event %j\",args);if(null!=packet.id){debug(\"attaching ack callback to event\");args.push(this.ack(packet.id))}if(this.connected){emit.apply(this,args)}else{this.receiveBuffer.push(args)}};Socket.prototype.ack=function(id){var self=this;var sent=false;return function(){if(sent)return;sent=true;var args=toArray(arguments);debug(\"sending ack %j\",args);var type=hasBin(args)?parser.BINARY_ACK:parser.ACK;self.packet({type:type,id:id,data:args})}};Socket.prototype.onack=function(packet){debug(\"calling ack %s with %j\",packet.id,packet.data);var fn=this.acks[packet.id];fn.apply(this,packet.data);delete this.acks[packet.id]};Socket.prototype.onconnect=function(){this.connected=true;this.disconnected=false;this.emit(\"connect\");this.emitBuffered()};Socket.prototype.emitBuffered=function(){var i;for(i=0;i<this.receiveBuffer.length;i++){emit.apply(this,this.receiveBuffer[i])}this.receiveBuffer=[];for(i=0;i<this.sendBuffer.length;i++){this.packet(this.sendBuffer[i])}this.sendBuffer=[]};Socket.prototype.ondisconnect=function(){debug(\"server disconnect (%s)\",this.nsp);this.destroy();this.onclose(\"io server disconnect\")};Socket.prototype.destroy=function(){if(this.subs){for(var i=0;i<this.subs.length;i++){this.subs[i].destroy()}this.subs=null}this.io.destroy(this)};Socket.prototype.close=Socket.prototype.disconnect=function(){if(this.connected){debug(\"performing disconnect (%s)\",this.nsp);this.packet({type:parser.DISCONNECT})}this.destroy();if(this.connected){this.onclose(\"io client disconnect\")}return this}},{\"./on\":4,\"component-bind\":7,\"component-emitter\":8,debug:9,\"has-binary\":32,\"socket.io-parser\":40,\"to-array\":44}],6:[function(_dereq_,module,exports){(function(global){var parseuri=_dereq_(\"parseuri\");var debug=_dereq_(\"debug\")(\"socket.io-client:url\");module.exports=url;function url(uri,loc){var obj=uri;var loc=loc||global.location;if(null==uri)uri=loc.protocol+\"//\"+loc.hostname;if(\"string\"==typeof uri){if(\"/\"==uri.charAt(0)){if(\"/\"==uri.charAt(1)){uri=loc.protocol+uri}else{uri=loc.hostname+uri}}if(!/^(https?|wss?):\\/\\//.test(uri)){debug(\"protocol-less url %s\",uri);if(\"undefined\"!=typeof loc){uri=loc.protocol+\"//\"+uri}else{uri=\"https://\"+uri}}debug(\"parse %s\",uri);obj=parseuri(uri)}if(!obj.port){if(/^(http|ws)$/.test(obj.protocol)){obj.port=\"80\"}else if(/^(http|ws)s$/.test(obj.protocol)){obj.port=\"443\"}}obj.path=obj.path||\"/\";obj.id=obj.protocol+\"://\"+obj.host+\":\"+obj.port;obj.href=obj.protocol+\"://\"+obj.host+(loc&&loc.port==obj.port?\"\":\":\"+obj.port);return obj}}).call(this,typeof self!==\"undefined\"?self:typeof window!==\"undefined\"?window:{})},{debug:9,parseuri:38}],7:[function(_dereq_,module,exports){var slice=[].slice;module.exports=function(obj,fn){if(\"string\"==typeof fn)fn=obj[fn];if(\"function\"!=typeof fn)throw new Error(\"bind() requires a function\");var args=slice.call(arguments,2);return function(){return fn.apply(obj,args.concat(slice.call(arguments)))}}},{}],8:[function(_dereq_,module,exports){module.exports=Emitter;function Emitter(obj){if(obj)return mixin(obj)}function mixin(obj){for(var key in Emitter.prototype){obj[key]=Emitter.prototype[key]}return obj}Emitter.prototype.on=Emitter.prototype.addEventListener=function(event,fn){this._callbacks=this._callbacks||{};(this._callbacks[event]=this._callbacks[event]||[]).push(fn);return this};Emitter.prototype.once=function(event,fn){var self=this;this._callbacks=this._callbacks||{};function on(){self.off(event,on);fn.apply(this,arguments)}on.fn=fn;this.on(event,on);return this};Emitter.prototype.off=Emitter.prototype.removeListener=Emitter.prototype.removeAllListeners=Emitter.prototype.removeEventListener=function(event,fn){this._callbacks=this._callbacks||{};if(0==arguments.length){this._callbacks={};return this}var callbacks=this._callbacks[event];if(!callbacks)return this;if(1==arguments.length){delete this._callbacks[event];return this}var cb;for(var i=0;i<callbacks.length;i++){cb=callbacks[i];if(cb===fn||cb.fn===fn){callbacks.splice(i,1);break}}return this};Emitter.prototype.emit=function(event){this._callbacks=this._callbacks||{};var args=[].slice.call(arguments,1),callbacks=this._callbacks[event];if(callbacks){callbacks=callbacks.slice(0);for(var i=0,len=callbacks.length;i<len;++i){callbacks[i].apply(this,args)}}return this};Emitter.prototype.listeners=function(event){this._callbacks=this._callbacks||{};return this._callbacks[event]||[]};Emitter.prototype.hasListeners=function(event){return!!this.listeners(event).length}},{}],9:[function(_dereq_,module,exports){module.exports=debug;function debug(name){if(!debug.enabled(name))return function(){};return function(fmt){fmt=coerce(fmt);var curr=new Date;var ms=curr-(debug[name]||curr);debug[name]=curr;fmt=name+\" \"+fmt+\" +\"+debug.humanize(ms);window.console&&console.log&&Function.prototype.apply.call(console.log,console,arguments)}}debug.names=[];debug.skips=[];debug.enable=function(name){try{localStorage.debug=name}catch(e){}var split=(name||\"\").split(/[\\s,]+/),len=split.length;for(var i=0;i<len;i++){name=split[i].replace(\"*\",\".*?\");if(name[0]===\"-\"){debug.skips.push(new RegExp(\"^\"+name.substr(1)+\"$\"))}else{debug.names.push(new RegExp(\"^\"+name+\"$\"))}}};debug.disable=function(){debug.enable(\"\")};debug.humanize=function(ms){var sec=1e3,min=60*1e3,hour=60*min;if(ms>=hour)return(ms/hour).toFixed(1)+\"h\";if(ms>=min)return(ms/min).toFixed(1)+\"m\";if(ms>=sec)return(ms/sec|0)+\"s\";return ms+\"ms\"};debug.enabled=function(name){for(var i=0,len=debug.skips.length;i<len;i++){if(debug.skips[i].test(name)){return false}}for(var i=0,len=debug.names.length;i<len;i++){if(debug.names[i].test(name)){return true}}return false};function coerce(val){if(val instanceof Error)return val.stack||val.message;return val}try{if(window.localStorage)debug.enable(localStorage.debug)}catch(e){}},{}],10:[function(_dereq_,module,exports){module.exports=_dereq_(\"./lib/\")},{\"./lib/\":11}],11:[function(_dereq_,module,exports){module.exports=_dereq_(\"./socket\");module.exports.parser=_dereq_(\"engine.io-parser\")},{\"./socket\":12,\"engine.io-parser\":21}],12:[function(_dereq_,module,exports){(function(global){var transports=_dereq_(\"./transports\");var Emitter=_dereq_(\"component-emitter\");var debug=_dereq_(\"debug\")(\"engine.io-client:socket\");var index=_dereq_(\"indexof\");var parser=_dereq_(\"engine.io-parser\");var parseuri=_dereq_(\"parseuri\");var parsejson=_dereq_(\"parsejson\");var parseqs=_dereq_(\"parseqs\");module.exports=Socket;function noop(){}function Socket(uri,opts){if(!(this instanceof Socket))return new Socket(uri,opts);opts=opts||{};if(uri&&\"object\"==typeof uri){opts=uri;uri=null}if(uri){uri=parseuri(uri);opts.host=uri.host;opts.secure=uri.protocol==\"https\"||uri.protocol==\"wss\";opts.port=uri.port;if(uri.query)opts.query=uri.query}this.secure=null!=opts.secure?opts.secure:global.location&&\"https:\"==location.protocol;if(opts.host){var pieces=opts.host.split(\":\");opts.hostname=pieces.shift();if(pieces.length)opts.port=pieces.pop()}this.agent=opts.agent||false;this.hostname=opts.hostname||(global.location?location.hostname:\"localhost\");this.port=opts.port||(global.location&&location.port?location.port:this.secure?443:80);this.query=opts.query||{};if(\"string\"==typeof this.query)this.query=parseqs.decode(this.query);this.upgrade=false!==opts.upgrade;this.path=(opts.path||\"/engine.io\").replace(/\\/$/,\"\")+\"/\";this.forceJSONP=!!opts.forceJSONP;this.jsonp=false!==opts.jsonp;this.forceBase64=!!opts.forceBase64;this.enablesXDR=!!opts.enablesXDR;this.timestampParam=opts.timestampParam||\"t\";this.timestampRequests=opts.timestampRequests;this.transports=opts.transports||[\"polling\",\"websocket\"];this.readyState=\"\";this.writeBuffer=[];this.callbackBuffer=[];this.policyPort=opts.policyPort||843;this.rememberUpgrade=opts.rememberUpgrade||false;this.open();this.binaryType=null;this.onlyBinaryUpgrades=opts.onlyBinaryUpgrades}Socket.priorWebsocketSuccess=false;Emitter(Socket.prototype);Socket.protocol=parser.protocol;Socket.Socket=Socket;Socket.Transport=_dereq_(\"./transport\");Socket.transports=_dereq_(\"./transports\");Socket.parser=_dereq_(\"engine.io-parser\");Socket.prototype.createTransport=function(name){debug('creating transport \"%s\"',name);var query=clone(this.query);query.EIO=parser.protocol;query.transport=name;if(this.id)query.sid=this.id;var transport=new transports[name]({agent:this.agent,hostname:this.hostname,port:this.port,secure:this.secure,path:this.path,query:query,forceJSONP:this.forceJSONP,jsonp:this.jsonp,forceBase64:this.forceBase64,enablesXDR:this.enablesXDR,timestampRequests:this.timestampRequests,timestampParam:this.timestampParam,policyPort:this.policyPort,socket:this});return transport};function clone(obj){var o={};for(var i in obj){if(obj.hasOwnProperty(i)){o[i]=obj[i]}}return o}Socket.prototype.open=function(){var transport;if(this.rememberUpgrade&&Socket.priorWebsocketSuccess&&this.transports.indexOf(\"websocket\")!=-1){transport=\"websocket\"}else if(0==this.transports.length){var self=this;setTimeout(function(){self.emit(\"error\",\"No transports available\")},0);return}else{transport=this.transports[0]}this.readyState=\"opening\";var transport;try{transport=this.createTransport(transport)}catch(e){this.transports.shift();this.open();return}transport.open();this.setTransport(transport)};Socket.prototype.setTransport=function(transport){debug(\"setting transport %s\",transport.name);var self=this;if(this.transport){debug(\"clearing existing transport %s\",this.transport.name);this.transport.removeAllListeners()}this.transport=transport;transport.on(\"drain\",function(){self.onDrain()}).on(\"packet\",function(packet){self.onPacket(packet)}).on(\"error\",function(e){self.onError(e)}).on(\"close\",function(){self.onClose(\"transport close\")})};Socket.prototype.probe=function(name){debug('probing transport \"%s\"',name);var transport=this.createTransport(name,{probe:1}),failed=false,self=this;Socket.priorWebsocketSuccess=false;function onTransportOpen(){if(self.onlyBinaryUpgrades){var upgradeLosesBinary=!this.supportsBinary&&self.transport.supportsBinary;failed=failed||upgradeLosesBinary}if(failed)return;debug('probe transport \"%s\" opened',name);transport.send([{type:\"ping\",data:\"probe\"}]);transport.once(\"packet\",function(msg){if(failed)return;if(\"pong\"==msg.type&&\"probe\"==msg.data){debug('probe transport \"%s\" pong',name);self.upgrading=true;self.emit(\"upgrading\",transport);if(!transport)return;Socket.priorWebsocketSuccess=\"websocket\"==transport.name;debug('pausing current transport \"%s\"',self.transport.name);self.transport.pause(function(){if(failed)return;if(\"closed\"==self.readyState)return;debug(\"changing transport and sending upgrade packet\");cleanup();self.setTransport(transport);transport.send([{type:\"upgrade\"}]);self.emit(\"upgrade\",transport);transport=null;self.upgrading=false;self.flush()})}else{debug('probe transport \"%s\" failed',name);var err=new Error(\"probe error\");err.transport=transport.name;self.emit(\"upgradeError\",err)}})}function freezeTransport(){if(failed)return;failed=true;cleanup();transport.close();transport=null}function onerror(err){var error=new Error(\"probe error: \"+err);error.transport=transport.name;freezeTransport();debug('probe transport \"%s\" failed because of error: %s',name,err);self.emit(\"upgradeError\",error)}function onTransportClose(){onerror(\"transport closed\")}function onclose(){onerror(\"socket closed\")}function onupgrade(to){if(transport&&to.name!=transport.name){debug('\"%s\" works - aborting \"%s\"',to.name,transport.name);freezeTransport()}}function cleanup(){transport.removeListener(\"open\",onTransportOpen);transport.removeListener(\"error\",onerror);transport.removeListener(\"close\",onTransportClose);self.removeListener(\"close\",onclose);self.removeListener(\"upgrading\",onupgrade)}transport.once(\"open\",onTransportOpen);transport.once(\"error\",onerror);transport.once(\"close\",onTransportClose);this.once(\"close\",onclose);this.once(\"upgrading\",onupgrade);transport.open()};Socket.prototype.onOpen=function(){debug(\"socket open\");this.readyState=\"open\";Socket.priorWebsocketSuccess=\"websocket\"==this.transport.name;this.emit(\"open\");this.flush();if(\"open\"==this.readyState&&this.upgrade&&this.transport.pause){debug(\"starting upgrade probes\");for(var i=0,l=this.upgrades.length;i<l;i++){this.probe(this.upgrades[i])}}};Socket.prototype.onPacket=function(packet){if(\"opening\"==this.readyState||\"open\"==this.readyState){debug('socket receive: type \"%s\", data \"%s\"',packet.type,packet.data);this.emit(\"packet\",packet);this.emit(\"heartbeat\");switch(packet.type){case\"open\":this.onHandshake(parsejson(packet.data));break;case\"pong\":this.setPing();break;case\"error\":var err=new Error(\"server error\");err.code=packet.data;this.emit(\"error\",err);break;case\"message\":this.emit(\"data\",packet.data);this.emit(\"message\",packet.data);break}}else{debug('packet received with socket readyState \"%s\"',this.readyState)}};Socket.prototype.onHandshake=function(data){this.emit(\"handshake\",data);this.id=data.sid;this.transport.query.sid=data.sid;this.upgrades=this.filterUpgrades(data.upgrades);this.pingInterval=data.pingInterval;this.pingTimeout=data.pingTimeout;this.onOpen();if(\"closed\"==this.readyState)return;this.setPing();this.removeListener(\"heartbeat\",this.onHeartbeat);this.on(\"heartbeat\",this.onHeartbeat)};Socket.prototype.onHeartbeat=function(timeout){clearTimeout(this.pingTimeoutTimer);var self=this;self.pingTimeoutTimer=setTimeout(function(){if(\"closed\"==self.readyState)return;self.onClose(\"ping timeout\")},timeout||self.pingInterval+self.pingTimeout)};Socket.prototype.setPing=function(){var self=this;clearTimeout(self.pingIntervalTimer);self.pingIntervalTimer=setTimeout(function(){debug(\"writing ping packet - expecting pong within %sms\",self.pingTimeout);self.ping();self.onHeartbeat(self.pingTimeout)},self.pingInterval)};Socket.prototype.ping=function(){this.sendPacket(\"ping\")};Socket.prototype.onDrain=function(){for(var i=0;i<this.prevBufferLen;i++){if(this.callbackBuffer[i]){this.callbackBuffer[i]()}}this.writeBuffer.splice(0,this.prevBufferLen);this.callbackBuffer.splice(0,this.prevBufferLen);this.prevBufferLen=0;if(this.writeBuffer.length==0){this.emit(\"drain\")}else{this.flush()}};Socket.prototype.flush=function(){if(\"closed\"!=this.readyState&&this.transport.writable&&!this.upgrading&&this.writeBuffer.length){debug(\"flushing %d packets in socket\",this.writeBuffer.length);this.transport.send(this.writeBuffer);this.prevBufferLen=this.writeBuffer.length;this.emit(\"flush\")}};Socket.prototype.write=Socket.prototype.send=function(msg,fn){this.sendPacket(\"message\",msg,fn);return this};Socket.prototype.sendPacket=function(type,data,fn){if(\"closing\"==this.readyState||\"closed\"==this.readyState){return}var packet={type:type,data:data};this.emit(\"packetCreate\",packet);this.writeBuffer.push(packet);this.callbackBuffer.push(fn);this.flush()};Socket.prototype.close=function(){if(\"opening\"==this.readyState||\"open\"==this.readyState){this.readyState=\"closing\";var self=this;function close(){self.onClose(\"forced close\");debug(\"socket closing - telling transport to close\");self.transport.close()}function cleanupAndClose(){self.removeListener(\"upgrade\",cleanupAndClose);self.removeListener(\"upgradeError\",cleanupAndClose);close()}function waitForUpgrade(){self.once(\"upgrade\",cleanupAndClose);self.once(\"upgradeError\",cleanupAndClose)}if(this.writeBuffer.length){this.once(\"drain\",function(){if(this.upgrading){waitForUpgrade()}else{close()}})}else if(this.upgrading){waitForUpgrade()}else{close()}}return this};Socket.prototype.onError=function(err){debug(\"socket error %j\",err);Socket.priorWebsocketSuccess=false;this.emit(\"error\",err);this.onClose(\"transport error\",err)};Socket.prototype.onClose=function(reason,desc){if(\"opening\"==this.readyState||\"open\"==this.readyState||\"closing\"==this.readyState){debug('socket close with reason: \"%s\"',reason);var self=this;clearTimeout(this.pingIntervalTimer);clearTimeout(this.pingTimeoutTimer);setTimeout(function(){self.writeBuffer=[];self.callbackBuffer=[];self.prevBufferLen=0},0);this.transport.removeAllListeners(\"close\");this.transport.close();this.transport.removeAllListeners();this.readyState=\"closed\";this.id=null;this.emit(\"close\",reason,desc)}};Socket.prototype.filterUpgrades=function(upgrades){var filteredUpgrades=[];for(var i=0,j=upgrades.length;i<j;i++){if(~index(this.transports,upgrades[i]))filteredUpgrades.push(upgrades[i])}return filteredUpgrades}}).call(this,typeof self!==\"undefined\"?self:typeof window!==\"undefined\"?window:{})},{\"./transport\":13,\"./transports\":14,\"component-emitter\":8,debug:9,\"engine.io-parser\":21,indexof:36,parsejson:28,parseqs:29,parseuri:30}],13:[function(_dereq_,module,exports){var parser=_dereq_(\"engine.io-parser\");var Emitter=_dereq_(\"component-emitter\");module.exports=Transport;function Transport(opts){this.path=opts.path;this.hostname=opts.hostname;this.port=opts.port;this.secure=opts.secure;this.query=opts.query;this.timestampParam=opts.timestampParam;this.timestampRequests=opts.timestampRequests;this.readyState=\"\";this.agent=opts.agent||false;this.socket=opts.socket;this.enablesXDR=opts.enablesXDR}Emitter(Transport.prototype);Transport.timestamps=0;Transport.prototype.onError=function(msg,desc){var err=new Error(msg);err.type=\"TransportError\";err.description=desc;this.emit(\"error\",err);return this};Transport.prototype.open=function(){if(\"closed\"==this.readyState||\"\"==this.readyState){this.readyState=\"opening\";this.doOpen()}return this};Transport.prototype.close=function(){if(\"opening\"==this.readyState||\"open\"==this.readyState){this.doClose();this.onClose()}return this};Transport.prototype.send=function(packets){if(\"open\"==this.readyState){this.write(packets)}else{throw new Error(\"Transport not open\")}};Transport.prototype.onOpen=function(){this.readyState=\"open\";this.writable=true;this.emit(\"open\")};Transport.prototype.onData=function(data){var packet=parser.decodePacket(data,this.socket.binaryType);this.onPacket(packet)};Transport.prototype.onPacket=function(packet){this.emit(\"packet\",packet)};Transport.prototype.onClose=function(){this.readyState=\"closed\";this.emit(\"close\")}},{\"component-emitter\":8,\"engine.io-parser\":21}],14:[function(_dereq_,module,exports){(function(global){var XMLHttpRequest=_dereq_(\"xmlhttprequest\");var XHR=_dereq_(\"./polling-xhr\");var JSONP=_dereq_(\"./polling-jsonp\");var websocket=_dereq_(\"./websocket\");exports.polling=polling;exports.websocket=websocket;function polling(opts){var xhr;var xd=false;var xs=false;var jsonp=false!==opts.jsonp;if(global.location){var isSSL=\"https:\"==location.protocol;var port=location.port;if(!port){port=isSSL?443:80}xd=opts.hostname!=location.hostname||port!=opts.port;xs=opts.secure!=isSSL}opts.xdomain=xd;opts.xscheme=xs;xhr=new XMLHttpRequest(opts);if(\"open\"in xhr&&!opts.forceJSONP){return new XHR(opts)}else{if(!jsonp)throw new Error(\"JSONP disabled\");return new JSONP(opts)}}}).call(this,typeof self!==\"undefined\"?self:typeof window!==\"undefined\"?window:{})},{\"./polling-jsonp\":15,\"./polling-xhr\":16,\"./websocket\":18,xmlhttprequest:19}],15:[function(_dereq_,module,exports){(function(global){var Polling=_dereq_(\"./polling\");var inherit=_dereq_(\"component-inherit\");module.exports=JSONPPolling;var rNewline=/\\n/g;var rEscapedNewline=/\\\\n/g;var callbacks;var index=0;function empty(){}function JSONPPolling(opts){Polling.call(this,opts);this.query=this.query||{};if(!callbacks){if(!global.___eio)global.___eio=[];callbacks=global.___eio}this.index=callbacks.length;var self=this;callbacks.push(function(msg){self.onData(msg)});this.query.j=this.index;if(global.document&&global.addEventListener){global.addEventListener(\"beforeunload\",function(){if(self.script)self.script.onerror=empty})}}inherit(JSONPPolling,Polling);JSONPPolling.prototype.supportsBinary=false;JSONPPolling.prototype.doClose=function(){if(this.script){this.script.parentNode.removeChild(this.script);this.script=null}if(this.form){this.form.parentNode.removeChild(this.form);this.form=null;this.iframe=null}Polling.prototype.doClose.call(this)};JSONPPolling.prototype.doPoll=function(){var self=this;var script=document.createElement(\"script\");if(this.script){this.script.parentNode.removeChild(this.script);this.script=null}script.async=true;script.src=this.uri();script.onerror=function(e){self.onError(\"jsonp poll error\",e)};var insertAt=document.getElementsByTagName(\"script\")[0];insertAt.parentNode.insertBefore(script,insertAt);this.script=script;var isUAgecko=\"undefined\"!=typeof navigator&&/gecko/i.test(navigator.userAgent);if(isUAgecko){setTimeout(function(){var iframe=document.createElement(\"iframe\");document.body.appendChild(iframe);document.body.removeChild(iframe)},100)}};JSONPPolling.prototype.doWrite=function(data,fn){var self=this;if(!this.form){var form=document.createElement(\"form\");var area=document.createElement(\"textarea\");var id=this.iframeId=\"eio_iframe_\"+this.index;var iframe;form.className=\"socketio\";form.style.position=\"absolute\";form.style.top=\"-1000px\";form.style.left=\"-1000px\";form.target=id;form.method=\"POST\";form.setAttribute(\"accept-charset\",\"utf-8\");area.name=\"d\";form.appendChild(area);document.body.appendChild(form);this.form=form;this.area=area}this.form.action=this.uri();function complete(){initIframe();fn()}function initIframe(){if(self.iframe){try{self.form.removeChild(self.iframe)\n}catch(e){self.onError(\"jsonp polling iframe removal error\",e)}}try{var html='<iframe src=\"javascript:0\" name=\"'+self.iframeId+'\">';iframe=document.createElement(html)}catch(e){iframe=document.createElement(\"iframe\");iframe.name=self.iframeId;iframe.src=\"javascript:0\"}iframe.id=self.iframeId;self.form.appendChild(iframe);self.iframe=iframe}initIframe();data=data.replace(rEscapedNewline,\"\\\\\\n\");this.area.value=data.replace(rNewline,\"\\\\n\");try{this.form.submit()}catch(e){}if(this.iframe.attachEvent){this.iframe.onreadystatechange=function(){if(self.iframe.readyState==\"complete\"){complete()}}}else{this.iframe.onload=complete}}}).call(this,typeof self!==\"undefined\"?self:typeof window!==\"undefined\"?window:{})},{\"./polling\":17,\"component-inherit\":20}],16:[function(_dereq_,module,exports){(function(global){var XMLHttpRequest=_dereq_(\"xmlhttprequest\");var Polling=_dereq_(\"./polling\");var Emitter=_dereq_(\"component-emitter\");var inherit=_dereq_(\"component-inherit\");var debug=_dereq_(\"debug\")(\"engine.io-client:polling-xhr\");module.exports=XHR;module.exports.Request=Request;function empty(){}function XHR(opts){Polling.call(this,opts);if(global.location){var isSSL=\"https:\"==location.protocol;var port=location.port;if(!port){port=isSSL?443:80}this.xd=opts.hostname!=global.location.hostname||port!=opts.port;this.xs=opts.secure!=isSSL}}inherit(XHR,Polling);XHR.prototype.supportsBinary=true;XHR.prototype.request=function(opts){opts=opts||{};opts.uri=this.uri();opts.xd=this.xd;opts.xs=this.xs;opts.agent=this.agent||false;opts.supportsBinary=this.supportsBinary;opts.enablesXDR=this.enablesXDR;return new Request(opts)};XHR.prototype.doWrite=function(data,fn){var isBinary=typeof data!==\"string\"&&data!==undefined;var req=this.request({method:\"POST\",data:data,isBinary:isBinary});var self=this;req.on(\"success\",fn);req.on(\"error\",function(err){self.onError(\"xhr post error\",err)});this.sendXhr=req};XHR.prototype.doPoll=function(){debug(\"xhr poll\");var req=this.request();var self=this;req.on(\"data\",function(data){self.onData(data)});req.on(\"error\",function(err){self.onError(\"xhr poll error\",err)});this.pollXhr=req};function Request(opts){this.method=opts.method||\"GET\";this.uri=opts.uri;this.xd=!!opts.xd;this.xs=!!opts.xs;this.async=false!==opts.async;this.data=undefined!=opts.data?opts.data:null;this.agent=opts.agent;this.isBinary=opts.isBinary;this.supportsBinary=opts.supportsBinary;this.enablesXDR=opts.enablesXDR;this.create()}Emitter(Request.prototype);Request.prototype.create=function(){var xhr=this.xhr=new XMLHttpRequest({agent:this.agent,xdomain:this.xd,xscheme:this.xs,enablesXDR:this.enablesXDR});var self=this;try{debug(\"xhr open %s: %s\",this.method,this.uri);xhr.open(this.method,this.uri,this.async);if(this.supportsBinary){xhr.responseType=\"arraybuffer\"}if(\"POST\"==this.method){try{if(this.isBinary){xhr.setRequestHeader(\"Content-type\",\"application/octet-stream\")}else{xhr.setRequestHeader(\"Content-type\",\"text/plain;charset=UTF-8\")}}catch(e){}}if(\"withCredentials\"in xhr){xhr.withCredentials=true}if(this.hasXDR()){xhr.onload=function(){self.onLoad()};xhr.onerror=function(){self.onError(xhr.responseText)}}else{xhr.onreadystatechange=function(){if(4!=xhr.readyState)return;if(200==xhr.status||1223==xhr.status){self.onLoad()}else{setTimeout(function(){self.onError(xhr.status)},0)}}}debug(\"xhr data %s\",this.data);xhr.send(this.data)}catch(e){setTimeout(function(){self.onError(e)},0);return}if(global.document){this.index=Request.requestsCount++;Request.requests[this.index]=this}};Request.prototype.onSuccess=function(){this.emit(\"success\");this.cleanup()};Request.prototype.onData=function(data){this.emit(\"data\",data);this.onSuccess()};Request.prototype.onError=function(err){this.emit(\"error\",err);this.cleanup()};Request.prototype.cleanup=function(){if(\"undefined\"==typeof this.xhr||null===this.xhr){return}if(this.hasXDR()){this.xhr.onload=this.xhr.onerror=empty}else{this.xhr.onreadystatechange=empty}try{this.xhr.abort()}catch(e){}if(global.document){delete Request.requests[this.index]}this.xhr=null};Request.prototype.onLoad=function(){var data;try{var contentType;try{contentType=this.xhr.getResponseHeader(\"Content-Type\").split(\";\")[0]}catch(e){}if(contentType===\"application/octet-stream\"){data=this.xhr.response}else{if(!this.supportsBinary){data=this.xhr.responseText}else{data=\"ok\"}}}catch(e){this.onError(e)}if(null!=data){this.onData(data)}};Request.prototype.hasXDR=function(){return\"undefined\"!==typeof global.XDomainRequest&&!this.xs&&this.enablesXDR};Request.prototype.abort=function(){this.cleanup()};if(global.document){Request.requestsCount=0;Request.requests={};if(global.attachEvent){global.attachEvent(\"onunload\",unloadHandler)}else if(global.addEventListener){global.addEventListener(\"beforeunload\",unloadHandler)}}function unloadHandler(){for(var i in Request.requests){if(Request.requests.hasOwnProperty(i)){Request.requests[i].abort()}}}}).call(this,typeof self!==\"undefined\"?self:typeof window!==\"undefined\"?window:{})},{\"./polling\":17,\"component-emitter\":8,\"component-inherit\":20,debug:9,xmlhttprequest:19}],17:[function(_dereq_,module,exports){var Transport=_dereq_(\"../transport\");var parseqs=_dereq_(\"parseqs\");var parser=_dereq_(\"engine.io-parser\");var inherit=_dereq_(\"component-inherit\");var debug=_dereq_(\"debug\")(\"engine.io-client:polling\");module.exports=Polling;var hasXHR2=function(){var XMLHttpRequest=_dereq_(\"xmlhttprequest\");var xhr=new XMLHttpRequest({xdomain:false});return null!=xhr.responseType}();function Polling(opts){var forceBase64=opts&&opts.forceBase64;if(!hasXHR2||forceBase64){this.supportsBinary=false}Transport.call(this,opts)}inherit(Polling,Transport);Polling.prototype.name=\"polling\";Polling.prototype.doOpen=function(){this.poll()};Polling.prototype.pause=function(onPause){var pending=0;var self=this;this.readyState=\"pausing\";function pause(){debug(\"paused\");self.readyState=\"paused\";onPause()}if(this.polling||!this.writable){var total=0;if(this.polling){debug(\"we are currently polling - waiting to pause\");total++;this.once(\"pollComplete\",function(){debug(\"pre-pause polling complete\");--total||pause()})}if(!this.writable){debug(\"we are currently writing - waiting to pause\");total++;this.once(\"drain\",function(){debug(\"pre-pause writing complete\");--total||pause()})}}else{pause()}};Polling.prototype.poll=function(){debug(\"polling\");this.polling=true;this.doPoll();this.emit(\"poll\")};Polling.prototype.onData=function(data){var self=this;debug(\"polling got data %s\",data);var callback=function(packet,index,total){if(\"opening\"==self.readyState){self.onOpen()}if(\"close\"==packet.type){self.onClose();return false}self.onPacket(packet)};parser.decodePayload(data,this.socket.binaryType,callback);if(\"closed\"!=this.readyState){this.polling=false;this.emit(\"pollComplete\");if(\"open\"==this.readyState){this.poll()}else{debug('ignoring poll - transport state \"%s\"',this.readyState)}}};Polling.prototype.doClose=function(){var self=this;function close(){debug(\"writing close packet\");self.write([{type:\"close\"}])}if(\"open\"==this.readyState){debug(\"transport open - closing\");close()}else{debug(\"transport not open - deferring close\");this.once(\"open\",close)}};Polling.prototype.write=function(packets){var self=this;this.writable=false;var callbackfn=function(){self.writable=true;self.emit(\"drain\")};var self=this;parser.encodePayload(packets,this.supportsBinary,function(data){self.doWrite(data,callbackfn)})};Polling.prototype.uri=function(){var query=this.query||{};var schema=this.secure?\"https\":\"http\";var port=\"\";if(false!==this.timestampRequests){query[this.timestampParam]=+new Date+\"-\"+Transport.timestamps++}if(!this.supportsBinary&&!query.sid){query.b64=1}query=parseqs.encode(query);if(this.port&&(\"https\"==schema&&this.port!=443||\"http\"==schema&&this.port!=80)){port=\":\"+this.port}if(query.length){query=\"?\"+query}return schema+\"://\"+this.hostname+port+this.path+query}},{\"../transport\":13,\"component-inherit\":20,debug:9,\"engine.io-parser\":21,parseqs:29,xmlhttprequest:19}],18:[function(_dereq_,module,exports){var Transport=_dereq_(\"../transport\");var parser=_dereq_(\"engine.io-parser\");var parseqs=_dereq_(\"parseqs\");var inherit=_dereq_(\"component-inherit\");var debug=_dereq_(\"debug\")(\"engine.io-client:websocket\");var WebSocket=_dereq_(\"ws\");module.exports=WS;function WS(opts){var forceBase64=opts&&opts.forceBase64;if(forceBase64){this.supportsBinary=false}Transport.call(this,opts)}inherit(WS,Transport);WS.prototype.name=\"websocket\";WS.prototype.supportsBinary=true;WS.prototype.doOpen=function(){if(!this.check()){return}var self=this;var uri=this.uri();var protocols=void 0;var opts={agent:this.agent};this.ws=new WebSocket(uri,protocols,opts);if(this.ws.binaryType===undefined){this.supportsBinary=false}this.ws.binaryType=\"arraybuffer\";this.addEventListeners()};WS.prototype.addEventListeners=function(){var self=this;this.ws.onopen=function(){self.onOpen()};this.ws.onclose=function(){self.onClose()};this.ws.onmessage=function(ev){self.onData(ev.data)};this.ws.onerror=function(e){self.onError(\"websocket error\",e)}};if(\"undefined\"!=typeof navigator&&/iPad|iPhone|iPod/i.test(navigator.userAgent)){WS.prototype.onData=function(data){var self=this;setTimeout(function(){Transport.prototype.onData.call(self,data)},0)}}WS.prototype.write=function(packets){var self=this;this.writable=false;for(var i=0,l=packets.length;i<l;i++){parser.encodePacket(packets[i],this.supportsBinary,function(data){try{self.ws.send(data)}catch(e){debug(\"websocket closed before onclose event\")}})}function ondrain(){self.writable=true;self.emit(\"drain\")}setTimeout(ondrain,0)};WS.prototype.onClose=function(){Transport.prototype.onClose.call(this)};WS.prototype.doClose=function(){if(typeof this.ws!==\"undefined\"){this.ws.close()}};WS.prototype.uri=function(){var query=this.query||{};var schema=this.secure?\"wss\":\"ws\";var port=\"\";if(this.port&&(\"wss\"==schema&&this.port!=443||\"ws\"==schema&&this.port!=80)){port=\":\"+this.port}if(this.timestampRequests){query[this.timestampParam]=+new Date}if(!this.supportsBinary){query.b64=1}query=parseqs.encode(query);if(query.length){query=\"?\"+query}return schema+\"://\"+this.hostname+port+this.path+query};WS.prototype.check=function(){return!!WebSocket&&!(\"__initialize\"in WebSocket&&this.name===WS.prototype.name)}},{\"../transport\":13,\"component-inherit\":20,debug:9,\"engine.io-parser\":21,parseqs:29,ws:31}],19:[function(_dereq_,module,exports){var hasCORS=_dereq_(\"has-cors\");module.exports=function(opts){var xdomain=opts.xdomain;var xscheme=opts.xscheme;var enablesXDR=opts.enablesXDR;try{if(\"undefined\"!=typeof XMLHttpRequest&&(!xdomain||hasCORS)){return new XMLHttpRequest}}catch(e){}try{if(\"undefined\"!=typeof XDomainRequest&&!xscheme&&enablesXDR){return new XDomainRequest}}catch(e){}if(!xdomain){try{return new ActiveXObject(\"Microsoft.XMLHTTP\")}catch(e){}}}},{\"has-cors\":34}],20:[function(_dereq_,module,exports){module.exports=function(a,b){var fn=function(){};fn.prototype=b.prototype;a.prototype=new fn;a.prototype.constructor=a}},{}],21:[function(_dereq_,module,exports){(function(global){var keys=_dereq_(\"./keys\");var sliceBuffer=_dereq_(\"arraybuffer.slice\");var base64encoder=_dereq_(\"base64-arraybuffer\");var after=_dereq_(\"after\");var utf8=_dereq_(\"utf8\");var isAndroid=navigator.userAgent.match(/Android/i);exports.protocol=3;var packets=exports.packets={open:0,close:1,ping:2,pong:3,message:4,upgrade:5,noop:6};var packetslist=keys(packets);var err={type:\"error\",data:\"parser error\"};var Blob=_dereq_(\"blob\");exports.encodePacket=function(packet,supportsBinary,utf8encode,callback){if(\"function\"==typeof supportsBinary){callback=supportsBinary;supportsBinary=false}if(\"function\"==typeof utf8encode){callback=utf8encode;utf8encode=null}var data=packet.data===undefined?undefined:packet.data.buffer||packet.data;if(global.ArrayBuffer&&data instanceof ArrayBuffer){return encodeArrayBuffer(packet,supportsBinary,callback)}else if(Blob&&data instanceof global.Blob){return encodeBlob(packet,supportsBinary,callback)}var encoded=packets[packet.type];if(undefined!==packet.data){encoded+=utf8encode?utf8.encode(String(packet.data)):String(packet.data)}return callback(\"\"+encoded)};function encodeArrayBuffer(packet,supportsBinary,callback){if(!supportsBinary){return exports.encodeBase64Packet(packet,callback)}var data=packet.data;var contentArray=new Uint8Array(data);var resultBuffer=new Uint8Array(1+data.byteLength);resultBuffer[0]=packets[packet.type];for(var i=0;i<contentArray.length;i++){resultBuffer[i+1]=contentArray[i]}return callback(resultBuffer.buffer)}function encodeBlobAsArrayBuffer(packet,supportsBinary,callback){if(!supportsBinary){return exports.encodeBase64Packet(packet,callback)}var fr=new FileReader;fr.onload=function(){packet.data=fr.result;exports.encodePacket(packet,supportsBinary,true,callback)};return fr.readAsArrayBuffer(packet.data)}function encodeBlob(packet,supportsBinary,callback){if(!supportsBinary){return exports.encodeBase64Packet(packet,callback)}if(isAndroid){return encodeBlobAsArrayBuffer(packet,supportsBinary,callback)}var length=new Uint8Array(1);length[0]=packets[packet.type];var blob=new Blob([length.buffer,packet.data]);return callback(blob)}exports.encodeBase64Packet=function(packet,callback){var message=\"b\"+exports.packets[packet.type];if(Blob&&packet.data instanceof Blob){var fr=new FileReader;fr.onload=function(){var b64=fr.result.split(\",\")[1];callback(message+b64)};return fr.readAsDataURL(packet.data)}var b64data;try{b64data=String.fromCharCode.apply(null,new Uint8Array(packet.data))}catch(e){var typed=new Uint8Array(packet.data);var basic=new Array(typed.length);for(var i=0;i<typed.length;i++){basic[i]=typed[i]}b64data=String.fromCharCode.apply(null,basic)}message+=global.btoa(b64data);return callback(message)};exports.decodePacket=function(data,binaryType,utf8decode){if(typeof data==\"string\"||data===undefined){if(data.charAt(0)==\"b\"){return exports.decodeBase64Packet(data.substr(1),binaryType)}if(utf8decode){try{data=utf8.decode(data)}catch(e){return err}}var type=data.charAt(0);if(Number(type)!=type||!packetslist[type]){return err}if(data.length>1){return{type:packetslist[type],data:data.substring(1)}}else{return{type:packetslist[type]}}}var asArray=new Uint8Array(data);var type=asArray[0];var rest=sliceBuffer(data,1);if(Blob&&binaryType===\"blob\"){rest=new Blob([rest])}return{type:packetslist[type],data:rest}};exports.decodeBase64Packet=function(msg,binaryType){var type=packetslist[msg.charAt(0)];if(!global.ArrayBuffer){return{type:type,data:{base64:true,data:msg.substr(1)}}}var data=base64encoder.decode(msg.substr(1));if(binaryType===\"blob\"&&Blob){data=new Blob([data])}return{type:type,data:data}};exports.encodePayload=function(packets,supportsBinary,callback){if(typeof supportsBinary==\"function\"){callback=supportsBinary;supportsBinary=null}if(supportsBinary){if(Blob&&!isAndroid){return exports.encodePayloadAsBlob(packets,callback)}return exports.encodePayloadAsArrayBuffer(packets,callback)}if(!packets.length){return callback(\"0:\")}function setLengthHeader(message){return message.length+\":\"+message}function encodeOne(packet,doneCallback){exports.encodePacket(packet,supportsBinary,true,function(message){doneCallback(null,setLengthHeader(message))})}map(packets,encodeOne,function(err,results){return callback(results.join(\"\"))})};function map(ary,each,done){var result=new Array(ary.length);var next=after(ary.length,done);var eachWithIndex=function(i,el,cb){each(el,function(error,msg){result[i]=msg;cb(error,result)})};for(var i=0;i<ary.length;i++){eachWithIndex(i,ary[i],next)}}exports.decodePayload=function(data,binaryType,callback){if(typeof data!=\"string\"){return exports.decodePayloadAsBinary(data,binaryType,callback)}if(typeof binaryType===\"function\"){callback=binaryType;binaryType=null}var packet;if(data==\"\"){return callback(err,0,1)}var length=\"\",n,msg;for(var i=0,l=data.length;i<l;i++){var chr=data.charAt(i);if(\":\"!=chr){length+=chr}else{if(\"\"==length||length!=(n=Number(length))){return callback(err,0,1)}msg=data.substr(i+1,n);if(length!=msg.length){return callback(err,0,1)}if(msg.length){packet=exports.decodePacket(msg,binaryType,true);if(err.type==packet.type&&err.data==packet.data){return callback(err,0,1)}var ret=callback(packet,i+n,l);if(false===ret)return}i+=n;length=\"\"}}if(length!=\"\"){return callback(err,0,1)}};exports.encodePayloadAsArrayBuffer=function(packets,callback){if(!packets.length){return callback(new ArrayBuffer(0))}function encodeOne(packet,doneCallback){exports.encodePacket(packet,true,true,function(data){return doneCallback(null,data)})}map(packets,encodeOne,function(err,encodedPackets){var totalLength=encodedPackets.reduce(function(acc,p){var len;if(typeof p===\"string\"){len=p.length}else{len=p.byteLength}return acc+len.toString().length+len+2},0);var resultArray=new Uint8Array(totalLength);var bufferIndex=0;encodedPackets.forEach(function(p){var isString=typeof p===\"string\";var ab=p;if(isString){var view=new Uint8Array(p.length);for(var i=0;i<p.length;i++){view[i]=p.charCodeAt(i)}ab=view.buffer}if(isString){resultArray[bufferIndex++]=0}else{resultArray[bufferIndex++]=1}var lenStr=ab.byteLength.toString();for(var i=0;i<lenStr.length;i++){resultArray[bufferIndex++]=parseInt(lenStr[i])}resultArray[bufferIndex++]=255;var view=new Uint8Array(ab);for(var i=0;i<view.length;i++){resultArray[bufferIndex++]=view[i]}});return callback(resultArray.buffer)})};exports.encodePayloadAsBlob=function(packets,callback){function encodeOne(packet,doneCallback){exports.encodePacket(packet,true,true,function(encoded){var binaryIdentifier=new Uint8Array(1);binaryIdentifier[0]=1;if(typeof encoded===\"string\"){var view=new Uint8Array(encoded.length);for(var i=0;i<encoded.length;i++){view[i]=encoded.charCodeAt(i)}encoded=view.buffer;binaryIdentifier[0]=0}var len=encoded instanceof ArrayBuffer?encoded.byteLength:encoded.size;var lenStr=len.toString();var lengthAry=new Uint8Array(lenStr.length+1);for(var i=0;i<lenStr.length;i++){lengthAry[i]=parseInt(lenStr[i])}lengthAry[lenStr.length]=255;if(Blob){var blob=new Blob([binaryIdentifier.buffer,lengthAry.buffer,encoded]);doneCallback(null,blob)}})}map(packets,encodeOne,function(err,results){return callback(new Blob(results))})};exports.decodePayloadAsBinary=function(data,binaryType,callback){if(typeof binaryType===\"function\"){callback=binaryType;binaryType=null}var bufferTail=data;var buffers=[];var numberTooLong=false;while(bufferTail.byteLength>0){var tailArray=new Uint8Array(bufferTail);var isString=tailArray[0]===0;var msgLength=\"\";for(var i=1;;i++){if(tailArray[i]==255)break;if(msgLength.length>310){numberTooLong=true;break}msgLength+=tailArray[i]}if(numberTooLong)return callback(err,0,1);bufferTail=sliceBuffer(bufferTail,2+msgLength.length);msgLength=parseInt(msgLength);var msg=sliceBuffer(bufferTail,0,msgLength);if(isString){try{msg=String.fromCharCode.apply(null,new Uint8Array(msg))}catch(e){var typed=new Uint8Array(msg);msg=\"\";for(var i=0;i<typed.length;i++){msg+=String.fromCharCode(typed[i])}}}buffers.push(msg);bufferTail=sliceBuffer(bufferTail,msgLength)}var total=buffers.length;buffers.forEach(function(buffer,i){callback(exports.decodePacket(buffer,binaryType,true),i,total)})}}).call(this,typeof self!==\"undefined\"?self:typeof window!==\"undefined\"?window:{})},{\"./keys\":22,after:23,\"arraybuffer.slice\":24,\"base64-arraybuffer\":25,blob:26,utf8:27}],22:[function(_dereq_,module,exports){module.exports=Object.keys||function keys(obj){var arr=[];var has=Object.prototype.hasOwnProperty;for(var i in obj){if(has.call(obj,i)){arr.push(i)}}return arr}},{}],23:[function(_dereq_,module,exports){module.exports=after;function after(count,callback,err_cb){var bail=false;err_cb=err_cb||noop;proxy.count=count;return count===0?callback():proxy;function proxy(err,result){if(proxy.count<=0){throw new Error(\"after called too many times\")}--proxy.count;if(err){bail=true;callback(err);callback=err_cb}else if(proxy.count===0&&!bail){callback(null,result)}}}function noop(){}},{}],24:[function(_dereq_,module,exports){module.exports=function(arraybuffer,start,end){var bytes=arraybuffer.byteLength;start=start||0;end=end||bytes;if(arraybuffer.slice){return arraybuffer.slice(start,end)}if(start<0){start+=bytes}if(end<0){end+=bytes}if(end>bytes){end=bytes}if(start>=bytes||start>=end||bytes===0){return new ArrayBuffer(0)}var abv=new Uint8Array(arraybuffer);var result=new Uint8Array(end-start);for(var i=start,ii=0;i<end;i++,ii++){result[ii]=abv[i]}return result.buffer}},{}],25:[function(_dereq_,module,exports){(function(chars){\"use strict\";exports.encode=function(arraybuffer){var bytes=new Uint8Array(arraybuffer),i,len=bytes.length,base64=\"\";for(i=0;i<len;i+=3){base64+=chars[bytes[i]>>2];base64+=chars[(bytes[i]&3)<<4|bytes[i+1]>>4];base64+=chars[(bytes[i+1]&15)<<2|bytes[i+2]>>6];base64+=chars[bytes[i+2]&63]}if(len%3===2){base64=base64.substring(0,base64.length-1)+\"=\"}else if(len%3===1){base64=base64.substring(0,base64.length-2)+\"==\"}return base64};exports.decode=function(base64){var bufferLength=base64.length*.75,len=base64.length,i,p=0,encoded1,encoded2,encoded3,encoded4;if(base64[base64.length-1]===\"=\"){bufferLength--;if(base64[base64.length-2]===\"=\"){bufferLength--}}var arraybuffer=new ArrayBuffer(bufferLength),bytes=new Uint8Array(arraybuffer);for(i=0;i<len;i+=4){encoded1=chars.indexOf(base64[i]);encoded2=chars.indexOf(base64[i+1]);encoded3=chars.indexOf(base64[i+2]);encoded4=chars.indexOf(base64[i+3]);bytes[p++]=encoded1<<2|encoded2>>4;bytes[p++]=(encoded2&15)<<4|encoded3>>2;bytes[p++]=(encoded3&3)<<6|encoded4&63}return arraybuffer}})(\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\")},{}],26:[function(_dereq_,module,exports){(function(global){var BlobBuilder=global.BlobBuilder||global.WebKitBlobBuilder||global.MSBlobBuilder||global.MozBlobBuilder;var blobSupported=function(){try{var b=new Blob([\"hi\"]);return b.size==2}catch(e){return false}}();var blobBuilderSupported=BlobBuilder&&BlobBuilder.prototype.append&&BlobBuilder.prototype.getBlob;function BlobBuilderConstructor(ary,options){options=options||{};var bb=new BlobBuilder;for(var i=0;i<ary.length;i++){bb.append(ary[i])}return options.type?bb.getBlob(options.type):bb.getBlob()}module.exports=function(){if(blobSupported){return global.Blob}else if(blobBuilderSupported){return BlobBuilderConstructor}else{return undefined}}()}).call(this,typeof self!==\"undefined\"?self:typeof window!==\"undefined\"?window:{})},{}],27:[function(_dereq_,module,exports){(function(global){(function(root){var freeExports=typeof exports==\"object\"&&exports;var freeModule=typeof module==\"object\"&&module&&module.exports==freeExports&&module;var freeGlobal=typeof global==\"object\"&&global;if(freeGlobal.global===freeGlobal||freeGlobal.window===freeGlobal){root=freeGlobal}var stringFromCharCode=String.fromCharCode;function ucs2decode(string){var output=[];var counter=0;var length=string.length;var value;var extra;while(counter<length){value=string.charCodeAt(counter++);if(value>=55296&&value<=56319&&counter<length){extra=string.charCodeAt(counter++);if((extra&64512)==56320){output.push(((value&1023)<<10)+(extra&1023)+65536)}else{output.push(value);counter--}}else{output.push(value)}}return output}function ucs2encode(array){var length=array.length;var index=-1;var value;var output=\"\";while(++index<length){value=array[index];if(value>65535){value-=65536;output+=stringFromCharCode(value>>>10&1023|55296);value=56320|value&1023}output+=stringFromCharCode(value)}return output}function createByte(codePoint,shift){return stringFromCharCode(codePoint>>shift&63|128)}function encodeCodePoint(codePoint){if((codePoint&4294967168)==0){return stringFromCharCode(codePoint)}var symbol=\"\";if((codePoint&4294965248)==0){symbol=stringFromCharCode(codePoint>>6&31|192)}else if((codePoint&4294901760)==0){symbol=stringFromCharCode(codePoint>>12&15|224);symbol+=createByte(codePoint,6)}else if((codePoint&4292870144)==0){symbol=stringFromCharCode(codePoint>>18&7|240);symbol+=createByte(codePoint,12);symbol+=createByte(codePoint,6)}symbol+=stringFromCharCode(codePoint&63|128);return symbol}function utf8encode(string){var codePoints=ucs2decode(string);var length=codePoints.length;var index=-1;var codePoint;var byteString=\"\";while(++index<length){codePoint=codePoints[index];byteString+=encodeCodePoint(codePoint)}return byteString}function readContinuationByte(){if(byteIndex>=byteCount){throw Error(\"Invalid byte index\")}var continuationByte=byteArray[byteIndex]&255;byteIndex++;if((continuationByte&192)==128){return continuationByte&63}throw Error(\"Invalid continuation byte\")}function decodeSymbol(){var byte1;var byte2;var byte3;var byte4;var codePoint;if(byteIndex>byteCount){throw Error(\"Invalid byte index\")}if(byteIndex==byteCount){return false}byte1=byteArray[byteIndex]&255;byteIndex++;if((byte1&128)==0){return byte1}if((byte1&224)==192){var byte2=readContinuationByte();codePoint=(byte1&31)<<6|byte2;if(codePoint>=128){return codePoint}else{throw Error(\"Invalid continuation byte\")}}if((byte1&240)==224){byte2=readContinuationByte();byte3=readContinuationByte();codePoint=(byte1&15)<<12|byte2<<6|byte3;if(codePoint>=2048){return codePoint}else{throw Error(\"Invalid continuation byte\")}}if((byte1&248)==240){byte2=readContinuationByte();byte3=readContinuationByte();byte4=readContinuationByte();codePoint=(byte1&15)<<18|byte2<<12|byte3<<6|byte4;if(codePoint>=65536&&codePoint<=1114111){return codePoint}}throw Error(\"Invalid UTF-8 detected\")}var byteArray;var byteCount;var byteIndex;function utf8decode(byteString){byteArray=ucs2decode(byteString);byteCount=byteArray.length;byteIndex=0;var codePoints=[];var tmp;while((tmp=decodeSymbol())!==false){codePoints.push(tmp)}return ucs2encode(codePoints)}var utf8={version:\"2.0.0\",encode:utf8encode,decode:utf8decode};if(typeof define==\"function\"&&typeof define.amd==\"object\"&&define.amd){define(function(){return utf8})}else if(freeExports&&!freeExports.nodeType){if(freeModule){freeModule.exports=utf8}else{var object={};var hasOwnProperty=object.hasOwnProperty;for(var key in utf8){hasOwnProperty.call(utf8,key)&&(freeExports[key]=utf8[key])}}}else{root.utf8=utf8}})(this)}).call(this,typeof self!==\"undefined\"?self:typeof window!==\"undefined\"?window:{})},{}],28:[function(_dereq_,module,exports){(function(global){var rvalidchars=/^[\\],:{}\\s]*$/;var rvalidescape=/\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g;var rvalidtokens=/\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g;var rvalidbraces=/(?:^|:|,)(?:\\s*\\[)+/g;var rtrimLeft=/^\\s+/;var rtrimRight=/\\s+$/;module.exports=function parsejson(data){if(\"string\"!=typeof data||!data){return null}data=data.replace(rtrimLeft,\"\").replace(rtrimRight,\"\");if(global.JSON&&JSON.parse){return JSON.parse(data)}if(rvalidchars.test(data.replace(rvalidescape,\"@\").replace(rvalidtokens,\"]\").replace(rvalidbraces,\"\"))){return new Function(\"return \"+data)()}}}).call(this,typeof self!==\"undefined\"?self:typeof window!==\"undefined\"?window:{})},{}],29:[function(_dereq_,module,exports){exports.encode=function(obj){var str=\"\";for(var i in obj){if(obj.hasOwnProperty(i)){if(str.length)str+=\"&\";str+=encodeURIComponent(i)+\"=\"+encodeURIComponent(obj[i])}}return str};exports.decode=function(qs){var qry={};var pairs=qs.split(\"&\");for(var i=0,l=pairs.length;i<l;i++){var pair=pairs[i].split(\"=\");qry[decodeURIComponent(pair[0])]=decodeURIComponent(pair[1])}return qry}},{}],30:[function(_dereq_,module,exports){var re=/^(?:(?![^:@]+:[^:@\\/]*@)(http|https|ws|wss):\\/\\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\\/?#]*)(?::(\\d*))?)(((\\/(?:[^?#](?![^?#\\/]*\\.[^?#\\/.]+(?:[?#]|$)))*\\/?)?([^?#\\/]*))(?:\\?([^#]*))?(?:#(.*))?)/;var parts=[\"source\",\"protocol\",\"authority\",\"userInfo\",\"user\",\"password\",\"host\",\"port\",\"relative\",\"path\",\"directory\",\"file\",\"query\",\"anchor\"];module.exports=function parseuri(str){var src=str,b=str.indexOf(\"[\"),e=str.indexOf(\"]\");if(b!=-1&&e!=-1){str=str.substring(0,b)+str.substring(b,e).replace(/:/g,\";\")+str.substring(e,str.length)}var m=re.exec(str||\"\"),uri={},i=14;while(i--){uri[parts[i]]=m[i]||\"\"}if(b!=-1&&e!=-1){uri.source=src;uri.host=uri.host.substring(1,uri.host.length-1).replace(/;/g,\":\");uri.authority=uri.authority.replace(\"[\",\"\").replace(\"]\",\"\").replace(/;/g,\":\");uri.ipv6uri=true}return uri}},{}],31:[function(_dereq_,module,exports){var global=function(){return this}();var WebSocket=global.WebSocket||global.MozWebSocket;module.exports=WebSocket?ws:null;function ws(uri,protocols,opts){var instance;if(protocols){instance=new WebSocket(uri,protocols)}else{instance=new WebSocket(uri)}return instance}if(WebSocket)ws.prototype=WebSocket.prototype},{}],32:[function(_dereq_,module,exports){(function(global){var isArray=_dereq_(\"isarray\");module.exports=hasBinary;function hasBinary(data){function _hasBinary(obj){if(!obj)return false;if(global.Buffer&&global.Buffer.isBuffer(obj)||global.ArrayBuffer&&obj instanceof ArrayBuffer||global.Blob&&obj instanceof Blob||global.File&&obj instanceof File){return true}if(isArray(obj)){for(var i=0;i<obj.length;i++){if(_hasBinary(obj[i])){return true}}}else if(obj&&\"object\"==typeof obj){if(obj.toJSON){obj=obj.toJSON()}for(var key in obj){if(obj.hasOwnProperty(key)&&_hasBinary(obj[key])){return true}}}return false}return _hasBinary(data)}}).call(this,typeof self!==\"undefined\"?self:typeof window!==\"undefined\"?window:{})},{isarray:33}],33:[function(_dereq_,module,exports){module.exports=Array.isArray||function(arr){return Object.prototype.toString.call(arr)==\"[object Array]\"}},{}],34:[function(_dereq_,module,exports){var global=_dereq_(\"global\");try{module.exports=\"XMLHttpRequest\"in global&&\"withCredentials\"in new global.XMLHttpRequest}catch(err){module.exports=false}},{global:35}],35:[function(_dereq_,module,exports){module.exports=function(){return this}()},{}],36:[function(_dereq_,module,exports){var indexOf=[].indexOf;module.exports=function(arr,obj){if(indexOf)return arr.indexOf(obj);for(var i=0;i<arr.length;++i){if(arr[i]===obj)return i}return-1}},{}],37:[function(_dereq_,module,exports){var has=Object.prototype.hasOwnProperty;exports.keys=Object.keys||function(obj){var keys=[];for(var key in obj){if(has.call(obj,key)){keys.push(key)}}return keys};exports.values=function(obj){var vals=[];for(var key in obj){if(has.call(obj,key)){vals.push(obj[key])}}return vals};exports.merge=function(a,b){for(var key in b){if(has.call(b,key)){a[key]=b[key]}}return a};exports.length=function(obj){return exports.keys(obj).length};exports.isEmpty=function(obj){return 0==exports.length(obj)}},{}],38:[function(_dereq_,module,exports){var re=/^(?:(?![^:@]+:[^:@\\/]*@)(http|https|ws|wss):\\/\\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\\/?#]*)(?::(\\d*))?)(((\\/(?:[^?#](?![^?#\\/]*\\.[^?#\\/.]+(?:[?#]|$)))*\\/?)?([^?#\\/]*))(?:\\?([^#]*))?(?:#(.*))?)/;var parts=[\"source\",\"protocol\",\"authority\",\"userInfo\",\"user\",\"password\",\"host\",\"port\",\"relative\",\"path\",\"directory\",\"file\",\"query\",\"anchor\"];module.exports=function parseuri(str){var m=re.exec(str||\"\"),uri={},i=14;while(i--){uri[parts[i]]=m[i]||\"\"}return uri}},{}],39:[function(_dereq_,module,exports){(function(global){var isArray=_dereq_(\"isarray\");var isBuf=_dereq_(\"./is-buffer\");exports.deconstructPacket=function(packet){var buffers=[];var packetData=packet.data;function _deconstructPacket(data){if(!data)return data;if(isBuf(data)){var placeholder={_placeholder:true,num:buffers.length};buffers.push(data);return placeholder}else if(isArray(data)){var newData=new Array(data.length);for(var i=0;i<data.length;i++){newData[i]=_deconstructPacket(data[i])}return newData}else if(\"object\"==typeof data&&!(data instanceof Date)){var newData={};for(var key in data){newData[key]=_deconstructPacket(data[key])}return newData}return data}var pack=packet;pack.data=_deconstructPacket(packetData);pack.attachments=buffers.length;return{packet:pack,buffers:buffers}};exports.reconstructPacket=function(packet,buffers){var curPlaceHolder=0;function _reconstructPacket(data){if(data&&data._placeholder){var buf=buffers[data.num];return buf\n}else if(isArray(data)){for(var i=0;i<data.length;i++){data[i]=_reconstructPacket(data[i])}return data}else if(data&&\"object\"==typeof data){for(var key in data){data[key]=_reconstructPacket(data[key])}return data}return data}packet.data=_reconstructPacket(packet.data);packet.attachments=undefined;return packet};exports.removeBlobs=function(data,callback){function _removeBlobs(obj,curKey,containingObject){if(!obj)return obj;if(global.Blob&&obj instanceof Blob||global.File&&obj instanceof File){pendingBlobs++;var fileReader=new FileReader;fileReader.onload=function(){if(containingObject){containingObject[curKey]=this.result}else{bloblessData=this.result}if(!--pendingBlobs){callback(bloblessData)}};fileReader.readAsArrayBuffer(obj)}else if(isArray(obj)){for(var i=0;i<obj.length;i++){_removeBlobs(obj[i],i,obj)}}else if(obj&&\"object\"==typeof obj&&!isBuf(obj)){for(var key in obj){_removeBlobs(obj[key],key,obj)}}}var pendingBlobs=0;var bloblessData=data;_removeBlobs(bloblessData);if(!pendingBlobs){callback(bloblessData)}}}).call(this,typeof self!==\"undefined\"?self:typeof window!==\"undefined\"?window:{})},{\"./is-buffer\":41,isarray:42}],40:[function(_dereq_,module,exports){var debug=_dereq_(\"debug\")(\"socket.io-parser\");var json=_dereq_(\"json3\");var isArray=_dereq_(\"isarray\");var Emitter=_dereq_(\"component-emitter\");var binary=_dereq_(\"./binary\");var isBuf=_dereq_(\"./is-buffer\");exports.protocol=4;exports.types=[\"CONNECT\",\"DISCONNECT\",\"EVENT\",\"BINARY_EVENT\",\"ACK\",\"BINARY_ACK\",\"ERROR\"];exports.CONNECT=0;exports.DISCONNECT=1;exports.EVENT=2;exports.ACK=3;exports.ERROR=4;exports.BINARY_EVENT=5;exports.BINARY_ACK=6;exports.Encoder=Encoder;exports.Decoder=Decoder;function Encoder(){}Encoder.prototype.encode=function(obj,callback){debug(\"encoding packet %j\",obj);if(exports.BINARY_EVENT==obj.type||exports.BINARY_ACK==obj.type){encodeAsBinary(obj,callback)}else{var encoding=encodeAsString(obj);callback([encoding])}};function encodeAsString(obj){var str=\"\";var nsp=false;str+=obj.type;if(exports.BINARY_EVENT==obj.type||exports.BINARY_ACK==obj.type){str+=obj.attachments;str+=\"-\"}if(obj.nsp&&\"/\"!=obj.nsp){nsp=true;str+=obj.nsp}if(null!=obj.id){if(nsp){str+=\",\";nsp=false}str+=obj.id}if(null!=obj.data){if(nsp)str+=\",\";str+=json.stringify(obj.data)}debug(\"encoded %j as %s\",obj,str);return str}function encodeAsBinary(obj,callback){function writeEncoding(bloblessData){var deconstruction=binary.deconstructPacket(bloblessData);var pack=encodeAsString(deconstruction.packet);var buffers=deconstruction.buffers;buffers.unshift(pack);callback(buffers)}binary.removeBlobs(obj,writeEncoding)}function Decoder(){this.reconstructor=null}Emitter(Decoder.prototype);Decoder.prototype.add=function(obj){var packet;if(\"string\"==typeof obj){packet=decodeString(obj);if(exports.BINARY_EVENT==packet.type||exports.BINARY_ACK==packet.type){this.reconstructor=new BinaryReconstructor(packet);if(this.reconstructor.reconPack.attachments==0){this.emit(\"decoded\",packet)}}else{this.emit(\"decoded\",packet)}}else if(isBuf(obj)||obj.base64){if(!this.reconstructor){throw new Error(\"got binary data when not reconstructing a packet\")}else{packet=this.reconstructor.takeBinaryData(obj);if(packet){this.reconstructor=null;this.emit(\"decoded\",packet)}}}else{throw new Error(\"Unknown type: \"+obj)}};function decodeString(str){var p={};var i=0;p.type=Number(str.charAt(0));if(null==exports.types[p.type])return error();if(exports.BINARY_EVENT==p.type||exports.BINARY_ACK==p.type){p.attachments=\"\";while(str.charAt(++i)!=\"-\"){p.attachments+=str.charAt(i)}p.attachments=Number(p.attachments)}if(\"/\"==str.charAt(i+1)){p.nsp=\"\";while(++i){var c=str.charAt(i);if(\",\"==c)break;p.nsp+=c;if(i+1==str.length)break}}else{p.nsp=\"/\"}var next=str.charAt(i+1);if(\"\"!=next&&Number(next)==next){p.id=\"\";while(++i){var c=str.charAt(i);if(null==c||Number(c)!=c){--i;break}p.id+=str.charAt(i);if(i+1==str.length)break}p.id=Number(p.id)}if(str.charAt(++i)){try{p.data=json.parse(str.substr(i))}catch(e){return error()}}debug(\"decoded %s as %j\",str,p);return p}Decoder.prototype.destroy=function(){if(this.reconstructor){this.reconstructor.finishedReconstruction()}};function BinaryReconstructor(packet){this.reconPack=packet;this.buffers=[]}BinaryReconstructor.prototype.takeBinaryData=function(binData){this.buffers.push(binData);if(this.buffers.length==this.reconPack.attachments){var packet=binary.reconstructPacket(this.reconPack,this.buffers);this.finishedReconstruction();return packet}return null};BinaryReconstructor.prototype.finishedReconstruction=function(){this.reconPack=null;this.buffers=[]};function error(data){return{type:exports.ERROR,data:\"parser error\"}}},{\"./binary\":39,\"./is-buffer\":41,\"component-emitter\":8,debug:9,isarray:42,json3:43}],41:[function(_dereq_,module,exports){(function(global){module.exports=isBuf;function isBuf(obj){return global.Buffer&&global.Buffer.isBuffer(obj)||global.ArrayBuffer&&obj instanceof ArrayBuffer}}).call(this,typeof self!==\"undefined\"?self:typeof window!==\"undefined\"?window:{})},{}],42:[function(_dereq_,module,exports){module.exports=_dereq_(33)},{}],43:[function(_dereq_,module,exports){(function(window){var getClass={}.toString,isProperty,forEach,undef;var isLoader=typeof define===\"function\"&&define.amd;var nativeJSON=typeof JSON==\"object\"&&JSON;var JSON3=typeof exports==\"object\"&&exports&&!exports.nodeType&&exports;if(JSON3&&nativeJSON){JSON3.stringify=nativeJSON.stringify;JSON3.parse=nativeJSON.parse}else{JSON3=window.JSON=nativeJSON||{}}var isExtended=new Date(-0xc782b5b800cec);try{isExtended=isExtended.getUTCFullYear()==-109252&&isExtended.getUTCMonth()===0&&isExtended.getUTCDate()===1&&isExtended.getUTCHours()==10&&isExtended.getUTCMinutes()==37&&isExtended.getUTCSeconds()==6&&isExtended.getUTCMilliseconds()==708}catch(exception){}function has(name){if(has[name]!==undef){return has[name]}var isSupported;if(name==\"bug-string-char-index\"){isSupported=\"a\"[0]!=\"a\"}else if(name==\"json\"){isSupported=has(\"json-stringify\")&&has(\"json-parse\")}else{var value,serialized='{\"a\":[1,true,false,null,\"\\\\u0000\\\\b\\\\n\\\\f\\\\r\\\\t\"]}';if(name==\"json-stringify\"){var stringify=JSON3.stringify,stringifySupported=typeof stringify==\"function\"&&isExtended;if(stringifySupported){(value=function(){return 1}).toJSON=value;try{stringifySupported=stringify(0)===\"0\"&&stringify(new Number)===\"0\"&&stringify(new String)=='\"\"'&&stringify(getClass)===undef&&stringify(undef)===undef&&stringify()===undef&&stringify(value)===\"1\"&&stringify([value])==\"[1]\"&&stringify([undef])==\"[null]\"&&stringify(null)==\"null\"&&stringify([undef,getClass,null])==\"[null,null,null]\"&&stringify({a:[value,true,false,null,\"\\x00\\b\\n\\f\\r\t\"]})==serialized&&stringify(null,value)===\"1\"&&stringify([1,2],null,1)==\"[\\n 1,\\n 2\\n]\"&&stringify(new Date(-864e13))=='\"-271821-04-20T00:00:00.000Z\"'&&stringify(new Date(864e13))=='\"+275760-09-13T00:00:00.000Z\"'&&stringify(new Date(-621987552e5))=='\"-000001-01-01T00:00:00.000Z\"'&&stringify(new Date(-1))=='\"1969-12-31T23:59:59.999Z\"'}catch(exception){stringifySupported=false}}isSupported=stringifySupported}if(name==\"json-parse\"){var parse=JSON3.parse;if(typeof parse==\"function\"){try{if(parse(\"0\")===0&&!parse(false)){value=parse(serialized);var parseSupported=value[\"a\"].length==5&&value[\"a\"][0]===1;if(parseSupported){try{parseSupported=!parse('\"\t\"')}catch(exception){}if(parseSupported){try{parseSupported=parse(\"01\")!==1}catch(exception){}}if(parseSupported){try{parseSupported=parse(\"1.\")!==1}catch(exception){}}}}}catch(exception){parseSupported=false}}isSupported=parseSupported}}return has[name]=!!isSupported}if(!has(\"json\")){var functionClass=\"[object Function]\";var dateClass=\"[object Date]\";var numberClass=\"[object Number]\";var stringClass=\"[object String]\";var arrayClass=\"[object Array]\";var booleanClass=\"[object Boolean]\";var charIndexBuggy=has(\"bug-string-char-index\");if(!isExtended){var floor=Math.floor;var Months=[0,31,59,90,120,151,181,212,243,273,304,334];var getDay=function(year,month){return Months[month]+365*(year-1970)+floor((year-1969+(month=+(month>1)))/4)-floor((year-1901+month)/100)+floor((year-1601+month)/400)}}if(!(isProperty={}.hasOwnProperty)){isProperty=function(property){var members={},constructor;if((members.__proto__=null,members.__proto__={toString:1},members).toString!=getClass){isProperty=function(property){var original=this.__proto__,result=property in(this.__proto__=null,this);this.__proto__=original;return result}}else{constructor=members.constructor;isProperty=function(property){var parent=(this.constructor||constructor).prototype;return property in this&&!(property in parent&&this[property]===parent[property])}}members=null;return isProperty.call(this,property)}}var PrimitiveTypes={\"boolean\":1,number:1,string:1,undefined:1};var isHostType=function(object,property){var type=typeof object[property];return type==\"object\"?!!object[property]:!PrimitiveTypes[type]};forEach=function(object,callback){var size=0,Properties,members,property;(Properties=function(){this.valueOf=0}).prototype.valueOf=0;members=new Properties;for(property in members){if(isProperty.call(members,property)){size++}}Properties=members=null;if(!size){members=[\"valueOf\",\"toString\",\"toLocaleString\",\"propertyIsEnumerable\",\"isPrototypeOf\",\"hasOwnProperty\",\"constructor\"];forEach=function(object,callback){var isFunction=getClass.call(object)==functionClass,property,length;var hasProperty=!isFunction&&typeof object.constructor!=\"function\"&&isHostType(object,\"hasOwnProperty\")?object.hasOwnProperty:isProperty;for(property in object){if(!(isFunction&&property==\"prototype\")&&hasProperty.call(object,property)){callback(property)}}for(length=members.length;property=members[--length];hasProperty.call(object,property)&&callback(property));}}else if(size==2){forEach=function(object,callback){var members={},isFunction=getClass.call(object)==functionClass,property;for(property in object){if(!(isFunction&&property==\"prototype\")&&!isProperty.call(members,property)&&(members[property]=1)&&isProperty.call(object,property)){callback(property)}}}}else{forEach=function(object,callback){var isFunction=getClass.call(object)==functionClass,property,isConstructor;for(property in object){if(!(isFunction&&property==\"prototype\")&&isProperty.call(object,property)&&!(isConstructor=property===\"constructor\")){callback(property)}}if(isConstructor||isProperty.call(object,property=\"constructor\")){callback(property)}}}return forEach(object,callback)};if(!has(\"json-stringify\")){var Escapes={92:\"\\\\\\\\\",34:'\\\\\"',8:\"\\\\b\",12:\"\\\\f\",10:\"\\\\n\",13:\"\\\\r\",9:\"\\\\t\"};var leadingZeroes=\"000000\";var toPaddedString=function(width,value){return(leadingZeroes+(value||0)).slice(-width)};var unicodePrefix=\"\\\\u00\";var quote=function(value){var result='\"',index=0,length=value.length,isLarge=length>10&&charIndexBuggy,symbols;if(isLarge){symbols=value.split(\"\")}for(;index<length;index++){var charCode=value.charCodeAt(index);switch(charCode){case 8:case 9:case 10:case 12:case 13:case 34:case 92:result+=Escapes[charCode];break;default:if(charCode<32){result+=unicodePrefix+toPaddedString(2,charCode.toString(16));break}result+=isLarge?symbols[index]:charIndexBuggy?value.charAt(index):value[index]}}return result+'\"'};var serialize=function(property,object,callback,properties,whitespace,indentation,stack){var value,className,year,month,date,time,hours,minutes,seconds,milliseconds,results,element,index,length,prefix,result;try{value=object[property]}catch(exception){}if(typeof value==\"object\"&&value){className=getClass.call(value);if(className==dateClass&&!isProperty.call(value,\"toJSON\")){if(value>-1/0&&value<1/0){if(getDay){date=floor(value/864e5);for(year=floor(date/365.2425)+1970-1;getDay(year+1,0)<=date;year++);for(month=floor((date-getDay(year,0))/30.42);getDay(year,month+1)<=date;month++);date=1+date-getDay(year,month);time=(value%864e5+864e5)%864e5;hours=floor(time/36e5)%24;minutes=floor(time/6e4)%60;seconds=floor(time/1e3)%60;milliseconds=time%1e3}else{year=value.getUTCFullYear();month=value.getUTCMonth();date=value.getUTCDate();hours=value.getUTCHours();minutes=value.getUTCMinutes();seconds=value.getUTCSeconds();milliseconds=value.getUTCMilliseconds()}value=(year<=0||year>=1e4?(year<0?\"-\":\"+\")+toPaddedString(6,year<0?-year:year):toPaddedString(4,year))+\"-\"+toPaddedString(2,month+1)+\"-\"+toPaddedString(2,date)+\"T\"+toPaddedString(2,hours)+\":\"+toPaddedString(2,minutes)+\":\"+toPaddedString(2,seconds)+\".\"+toPaddedString(3,milliseconds)+\"Z\"}else{value=null}}else if(typeof value.toJSON==\"function\"&&(className!=numberClass&&className!=stringClass&&className!=arrayClass||isProperty.call(value,\"toJSON\"))){value=value.toJSON(property)}}if(callback){value=callback.call(object,property,value)}if(value===null){return\"null\"}className=getClass.call(value);if(className==booleanClass){return\"\"+value}else if(className==numberClass){return value>-1/0&&value<1/0?\"\"+value:\"null\"}else if(className==stringClass){return quote(\"\"+value)}if(typeof value==\"object\"){for(length=stack.length;length--;){if(stack[length]===value){throw TypeError()}}stack.push(value);results=[];prefix=indentation;indentation+=whitespace;if(className==arrayClass){for(index=0,length=value.length;index<length;index++){element=serialize(index,value,callback,properties,whitespace,indentation,stack);results.push(element===undef?\"null\":element)}result=results.length?whitespace?\"[\\n\"+indentation+results.join(\",\\n\"+indentation)+\"\\n\"+prefix+\"]\":\"[\"+results.join(\",\")+\"]\":\"[]\"}else{forEach(properties||value,function(property){var element=serialize(property,value,callback,properties,whitespace,indentation,stack);if(element!==undef){results.push(quote(property)+\":\"+(whitespace?\" \":\"\")+element)}});result=results.length?whitespace?\"{\\n\"+indentation+results.join(\",\\n\"+indentation)+\"\\n\"+prefix+\"}\":\"{\"+results.join(\",\")+\"}\":\"{}\"}stack.pop();return result}};JSON3.stringify=function(source,filter,width){var whitespace,callback,properties,className;if(typeof filter==\"function\"||typeof filter==\"object\"&&filter){if((className=getClass.call(filter))==functionClass){callback=filter}else if(className==arrayClass){properties={};for(var index=0,length=filter.length,value;index<length;value=filter[index++],(className=getClass.call(value),className==stringClass||className==numberClass)&&(properties[value]=1));}}if(width){if((className=getClass.call(width))==numberClass){if((width-=width%1)>0){for(whitespace=\"\",width>10&&(width=10);whitespace.length<width;whitespace+=\" \");}}else if(className==stringClass){whitespace=width.length<=10?width:width.slice(0,10)}}return serialize(\"\",(value={},value[\"\"]=source,value),callback,properties,whitespace,\"\",[])}}if(!has(\"json-parse\")){var fromCharCode=String.fromCharCode;var Unescapes={92:\"\\\\\",34:'\"',47:\"/\",98:\"\\b\",116:\"\t\",110:\"\\n\",102:\"\\f\",114:\"\\r\"};var Index,Source;var abort=function(){Index=Source=null;throw SyntaxError()};var lex=function(){var source=Source,length=source.length,value,begin,position,isSigned,charCode;while(Index<length){charCode=source.charCodeAt(Index);switch(charCode){case 9:case 10:case 13:case 32:Index++;break;case 123:case 125:case 91:case 93:case 58:case 44:value=charIndexBuggy?source.charAt(Index):source[Index];Index++;return value;case 34:for(value=\"@\",Index++;Index<length;){charCode=source.charCodeAt(Index);if(charCode<32){abort()}else if(charCode==92){charCode=source.charCodeAt(++Index);switch(charCode){case 92:case 34:case 47:case 98:case 116:case 110:case 102:case 114:value+=Unescapes[charCode];Index++;break;case 117:begin=++Index;for(position=Index+4;Index<position;Index++){charCode=source.charCodeAt(Index);if(!(charCode>=48&&charCode<=57||charCode>=97&&charCode<=102||charCode>=65&&charCode<=70)){abort()}}value+=fromCharCode(\"0x\"+source.slice(begin,Index));break;default:abort()}}else{if(charCode==34){break}charCode=source.charCodeAt(Index);begin=Index;while(charCode>=32&&charCode!=92&&charCode!=34){charCode=source.charCodeAt(++Index)}value+=source.slice(begin,Index)}}if(source.charCodeAt(Index)==34){Index++;return value}abort();default:begin=Index;if(charCode==45){isSigned=true;charCode=source.charCodeAt(++Index)}if(charCode>=48&&charCode<=57){if(charCode==48&&(charCode=source.charCodeAt(Index+1),charCode>=48&&charCode<=57)){abort()}isSigned=false;for(;Index<length&&(charCode=source.charCodeAt(Index),charCode>=48&&charCode<=57);Index++);if(source.charCodeAt(Index)==46){position=++Index;for(;position<length&&(charCode=source.charCodeAt(position),charCode>=48&&charCode<=57);position++);if(position==Index){abort()}Index=position}charCode=source.charCodeAt(Index);if(charCode==101||charCode==69){charCode=source.charCodeAt(++Index);if(charCode==43||charCode==45){Index++}for(position=Index;position<length&&(charCode=source.charCodeAt(position),charCode>=48&&charCode<=57);position++);if(position==Index){abort()}Index=position}return+source.slice(begin,Index)}if(isSigned){abort()}if(source.slice(Index,Index+4)==\"true\"){Index+=4;return true}else if(source.slice(Index,Index+5)==\"false\"){Index+=5;return false}else if(source.slice(Index,Index+4)==\"null\"){Index+=4;return null}abort()}}return\"$\"};var get=function(value){var results,hasMembers;if(value==\"$\"){abort()}if(typeof value==\"string\"){if((charIndexBuggy?value.charAt(0):value[0])==\"@\"){return value.slice(1)}if(value==\"[\"){results=[];for(;;hasMembers||(hasMembers=true)){value=lex();if(value==\"]\"){break}if(hasMembers){if(value==\",\"){value=lex();if(value==\"]\"){abort()}}else{abort()}}if(value==\",\"){abort()}results.push(get(value))}return results}else if(value==\"{\"){results={};for(;;hasMembers||(hasMembers=true)){value=lex();if(value==\"}\"){break}if(hasMembers){if(value==\",\"){value=lex();if(value==\"}\"){abort()}}else{abort()}}if(value==\",\"||typeof value!=\"string\"||(charIndexBuggy?value.charAt(0):value[0])!=\"@\"||lex()!=\":\"){abort()}results[value.slice(1)]=get(lex())}return results}abort()}return value};var update=function(source,property,callback){var element=walk(source,property,callback);if(element===undef){delete source[property]}else{source[property]=element}};var walk=function(source,property,callback){var value=source[property],length;if(typeof value==\"object\"&&value){if(getClass.call(value)==arrayClass){for(length=value.length;length--;){update(value,length,callback)}}else{forEach(value,function(property){update(value,property,callback)})}}return callback.call(source,property,value)};JSON3.parse=function(source,callback){var result,value;Index=0;Source=\"\"+source;result=get(lex());if(lex()!=\"$\"){abort()}Index=Source=null;return callback&&getClass.call(callback)==functionClass?walk((value={},value[\"\"]=result,value),\"\",callback):result}}}if(isLoader){define(function(){return JSON3})}})(this)},{}],44:[function(_dereq_,module,exports){module.exports=toArray;function toArray(list,index){var array=[];index=index||0;for(var i=index||0;i<list.length;i++){array[i-index]=list[i]}return array}},{}]},{},[1])(1)});"
  },
  {
    "path": "lib/soundcloud-waveform.js",
    "content": "window.AudioContext = window.AudioContext || window.webkitAudioContext;\n\nArray.prototype.max = function() {\n  return Math.max.apply(null, this);\n};\n\nvar audioContext= new AudioContext();\n\nvar SCWF = function () {\n\n\tvar SoundCloudWaveform = {\n\n\t\tsettings : {\n\t\t\tcanvas_width: 1200,\n\t\t\tcanvas_height: 40,\n\t\t\tbar_width: 2,\n\t\t\tbar_gap : 0,\n\t\t\twave_color: \"#AAAAFF\",\n\t\t\tdownload: false,\n\t\t\tonComplete: function(png, pixels) {}\n\t\t},\n\n\t\tgenerate: function(src, options) {\n\n\t\t\t// preparing canvas\n\t\t\tthis.settings.canvas = document.createElement('canvas');\n\t\t\tthis.settings.context = this.settings.canvas.getContext('2d');\n\n\t\t\tthis.settings.canvas.width = (options.canvas_width !== undefined) ? parseInt(options.canvas_width) : this.settings.canvas_width;\n\t\t\tthis.settings.canvas.height = (options.canvas_height !== undefined) ? parseInt(options.canvas_height) : this.settings.canvas_height;\n\n\t\t\t// setting fill color\n\t\t\tthis.settings.wave_color = (options.wave_color !== undefined) ? options.wave_color : this.settings.wave_color;\n\n\t\t\t// setting bars width and gap\n\t\t\tthis.settings.bar_width = (options.bar_width !== undefined) ? parseInt(options.bar_width) : this.settings.bar_width;\n\t\t\tthis.settings.bar_gap = (options.bar_gap !== undefined) ? parseFloat(options.bar_gap) : this.settings.bar_gap;\n\n\t\t\tthis.settings.download = (options.download !== undefined) ? options.download : this.settings.download;\n\n\t\t\tthis.settings.onComplete = (options.onComplete !== undefined) ? options.onComplete : this.settings.onComplete;\n\n\t\t\t// read file buffer\n\t\t\t/*var reader = new FileReader();\n\t        reader.onload = function(event) {\n\t            SoundCloudWaveform.audioContext.decodeAudioData(event.target.result, function(buffer) {\n\t                SoundCloudWaveform.extractBuffer(buffer);\n\t            });\n\t        };\n\t        reader.readAsArrayBuffer(file);*/\n\t        var rawData = src.split(\",\")[1]; // cut off extra filetype/etc data\n\t        var rawBuffer = Base64ArrayBuffer.decode(rawData);\n\t        audioContext.decodeAudioData(rawBuffer, function (buffer) {\n\t            if (!buffer) {\n\t                console.error(\"failed to decode:\", \"buffer null\");\n\t                return;\n\t            }\n\t            SoundCloudWaveform.extractBuffer(buffer);\n\t        }, function (error) {\n\t            console.error(\"failed to decode:\", error);\n\t        });\n\t\t},\n\n\t\textractBuffer: function(buffer) {\n\t\t    buffer = buffer.getChannelData(0);\n\t\t    var sections = this.settings.canvas.width;\n\t\t    var len = Math.floor(buffer.length / sections);\n\t\t    var maxHeight = this.settings.canvas.height;\n\t\t    var vals = [];\n\t\t    var lastval = 0;\n\t\t    for (var i = 0; i < sections; i += this.settings.bar_width) {\n\t\t    \tvar val = this.bufferMeasure(i * len, len, buffer) * 10000;\n\t\t    \tif(!isNaN(val)){\n\t\t        \tvals.push(val);\n\t\t        \tlastval = val;\n\t\t        } else {\n\t\t        \tvals.push(lastval)\n\t\t        }\n\t\t    }\n\n\t\t    for (var j = 0; j < sections; j += this.settings.bar_width) {\n\t\t        var scale = maxHeight / vals.max();\n\t\t        var val = this.bufferMeasure(j * len, len, buffer) * 10000;\n\t\t        val *= scale;\n\t\t        val += 1;\n\t\t        this.drawBar(j, val);\n\t\t    }\n\n\t\t    if (this.settings.download) {\n\t\t    \tthis.generateImage();\n\t\t    }\n\t\t    this.settings.onComplete(this.settings.canvas.toDataURL('image/png'), this.settings.context.getImageData(0, 0, this.settings.canvas.width, this.settings.canvas.height));\n\t\t    // clear canvas for redrawing\n\t\t    this.settings.context.clearRect(0, 0, this.settings.canvas.width, this.settings.canvas.height);\n\t    },\n\n\t    bufferMeasure: function(position, length, data) {\n\t        var sum = 0.0;\n\t        for (var i = position; i <= (position + length) - 1; i++) {\n\t            sum += Math.pow(data[i], 2);\n\t        }\n\t        return Math.sqrt(sum / data.length);\n\t    },\n\n\t    drawBar: function(i, h) {\n\n\t    \t//if(isNaN(h)) h = Math.random()*50\n\t    \t//h = h * 5000;\n\n\t    \tthis.settings.context.fillStyle = this.settings.wave_color;\n\n\t\t\tvar w = this.settings.bar_width;\n\t        if (this.settings.bar_gap !== 0) {\n\t            w *= Math.abs(1 - this.settings.bar_gap);\n\t        }\n\t        var x = i + (w / 2),\n\t            y = this.settings.canvas.height/2 - h/2/1.5;\n\n\n\t        this.settings.context.fillRect(x, y, w, h/1.5);\n\t    },\n\n\t    generateImage: function() {\n\t    \tvar image = this.settings.canvas.toDataURL('image/png');\n\n\t    \tvar link = document.createElement('a');\n\t    \tlink.href = image;\n\t    \tlink.setAttribute('download', '');\n\t    \tlink.click();\n\t    }\n\t}\n\n\treturn SoundCloudWaveform;\n}\n"
  },
  {
    "path": "lib/spectrum.css",
    "content": "/***\nSpectrum Colorpicker v1.8.0\nhttps://github.com/bgrins/spectrum\nAuthor: Brian Grinstead\nLicense: MIT\n***/\n\n.sp-container {\n    position:absolute;\n    top:0;\n    left:0;\n    display:inline-block;\n    *display: inline;\n    *zoom: 1;\n    /* https://github.com/bgrins/spectrum/issues/40 */\n    z-index: 9999994;\n    overflow: hidden;\n}\n.sp-container.sp-flat {\n    position: relative;\n}\n\n/* Fix for * { box-sizing: border-box; } */\n.sp-container,\n.sp-container * {\n    -webkit-box-sizing: content-box;\n       -moz-box-sizing: content-box;\n            box-sizing: content-box;\n}\n\n/* http://ansciath.tumblr.com/post/7347495869/css-aspect-ratio */\n.sp-top {\n  position:relative;\n  width: 100%;\n  display:inline-block;\n}\n.sp-top-inner {\n   position:absolute;\n   top:0;\n   left:0;\n   bottom:0;\n   right:0;\n}\n.sp-color {\n    position: absolute;\n    top:0;\n    left:0;\n    bottom:0;\n    right:20%;\n}\n.sp-hue {\n    position: absolute;\n    top:0;\n    right:0;\n    bottom:0;\n    left:84%;\n    height: 100%;\n}\n\n.sp-clear-enabled .sp-hue {\n    top:33px;\n    height: 77.5%;\n}\n\n.sp-fill {\n    padding-top: 80%;\n}\n.sp-sat, .sp-val {\n    position: absolute;\n    top:0;\n    left:0;\n    right:0;\n    bottom:0;\n}\n\n.sp-alpha-enabled .sp-top {\n    margin-bottom: 18px;\n}\n.sp-alpha-enabled .sp-alpha {\n    display: block;\n}\n.sp-alpha-handle {\n    position:absolute;\n    top:-4px;\n    bottom: -4px;\n    width: 6px;\n    left: 50%;\n    cursor: pointer;\n    border: 1px solid black;\n    background: white;\n    opacity: .8;\n}\n.sp-alpha {\n    display: none;\n    position: absolute;\n    bottom: -14px;\n    right: 0;\n    left: 0;\n    height: 8px;\n}\n.sp-alpha-inner {\n    border: solid 1px #333;\n}\n\n.sp-clear {\n    display: none;\n}\n\n.sp-clear.sp-clear-display {\n    background-position: center;\n}\n\n.sp-clear-enabled .sp-clear {\n    display: block;\n    position:absolute;\n    top:0px;\n    right:0;\n    bottom:0;\n    left:84%;\n    height: 28px;\n}\n\n/* Don't allow text selection */\n.sp-container, .sp-replacer, .sp-preview, .sp-dragger, .sp-slider, .sp-alpha, .sp-clear, .sp-alpha-handle, .sp-container.sp-dragging .sp-input, .sp-container button  {\n    -webkit-user-select:none;\n    -moz-user-select: -moz-none;\n    -o-user-select:none;\n    user-select: none;\n}\n\n.sp-container.sp-input-disabled .sp-input-container {\n    display: none;\n}\n.sp-container.sp-buttons-disabled .sp-button-container {\n    display: none;\n}\n.sp-container.sp-palette-buttons-disabled .sp-palette-button-container {\n    display: none;\n}\n.sp-palette-only .sp-picker-container {\n    display: none;\n}\n.sp-palette-disabled .sp-palette-container {\n    display: none;\n}\n\n.sp-initial-disabled .sp-initial {\n    display: none;\n}\n\n\n/* Gradients for hue, saturation and value instead of images.  Not pretty... but it works */\n.sp-sat {\n    background-image: -webkit-gradient(linear,  0 0, 100% 0, from(#FFF), to(rgba(204, 154, 129, 0)));\n    background-image: -webkit-linear-gradient(left, #FFF, rgba(204, 154, 129, 0));\n    background-image: -moz-linear-gradient(left, #fff, rgba(204, 154, 129, 0));\n    background-image: -o-linear-gradient(left, #fff, rgba(204, 154, 129, 0));\n    background-image: -ms-linear-gradient(left, #fff, rgba(204, 154, 129, 0));\n    background-image: linear-gradient(to right, #fff, rgba(204, 154, 129, 0));\n    -ms-filter: \"progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr=#FFFFFFFF, endColorstr=#00CC9A81)\";\n    filter : progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr='#FFFFFFFF', endColorstr='#00CC9A81');\n}\n.sp-val {\n    background-image: -webkit-gradient(linear, 0 100%, 0 0, from(#000000), to(rgba(204, 154, 129, 0)));\n    background-image: -webkit-linear-gradient(bottom, #000000, rgba(204, 154, 129, 0));\n    background-image: -moz-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));\n    background-image: -o-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));\n    background-image: -ms-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));\n    background-image: linear-gradient(to top, #000, rgba(204, 154, 129, 0));\n    -ms-filter: \"progid:DXImageTransform.Microsoft.gradient(startColorstr=#00CC9A81, endColorstr=#FF000000)\";\n    filter : progid:DXImageTransform.Microsoft.gradient(startColorstr='#00CC9A81', endColorstr='#FF000000');\n}\n\n.sp-hue {\n    background: -moz-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);\n    background: -ms-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);\n    background: -o-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);\n    background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), color-stop(0.17, #ffff00), color-stop(0.33, #00ff00), color-stop(0.5, #00ffff), color-stop(0.67, #0000ff), color-stop(0.83, #ff00ff), to(#ff0000));\n    background: -webkit-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);\n    background: linear-gradient(to bottom, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);\n}\n\n/* IE filters do not support multiple color stops.\n   Generate 6 divs, line them up, and do two color gradients for each.\n   Yes, really.\n */\n.sp-1 {\n    height:17%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000', endColorstr='#ffff00');\n}\n.sp-2 {\n    height:16%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff00', endColorstr='#00ff00');\n}\n.sp-3 {\n    height:17%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ff00', endColorstr='#00ffff');\n}\n.sp-4 {\n    height:17%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffff', endColorstr='#0000ff');\n}\n.sp-5 {\n    height:16%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0000ff', endColorstr='#ff00ff');\n}\n.sp-6 {\n    height:17%;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff', endColorstr='#ff0000');\n}\n\n.sp-hidden {\n    display: none !important;\n}\n\n/* Clearfix hack */\n.sp-cf:before, .sp-cf:after { content: \"\"; display: table; }\n.sp-cf:after { clear: both; }\n.sp-cf { *zoom: 1; border-radius: 3px; }\n\n/* Mobile devices, make hue slider bigger so it is easier to slide */\n@media (max-device-width: 480px) {\n    .sp-color { right: 40%; }\n    .sp-hue { left: 63%; }\n    .sp-fill { padding-top: 60%; }\n}\n.sp-dragger {\n   border-radius: 5px;\n   height: 5px;\n   width: 5px;\n   border: 1px solid #fff;\n   background: #000;\n   cursor: pointer;\n   position:absolute;\n   top:0;\n   left: 0;\n}\n.sp-slider {\n    position: absolute;\n    top:0;\n    cursor:pointer;\n    height: 3px;\n    left: -1px;\n    right: -1px;\n    border: 1px solid #000;\n    background: white;\n    opacity: .8;\n}\n\n/*\nTheme authors:\nHere are the basic themeable display options (colors, fonts, global widths).\nSee http://bgrins.github.io/spectrum/themes/ for instructions.\n*/\n\n.sp-container {\n    border-radius: 0;\n    background-color: #585757;\n    border: solid 1px #CCC;\n    padding: 0;\n}\n.sp-container, .sp-container button, .sp-container input, .sp-color, .sp-hue, .sp-clear {\n    font: normal 12px \"Lucida Grande\", \"Lucida Sans Unicode\", \"Lucida Sans\", Geneva, Verdana, sans-serif;\n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -ms-box-sizing: border-box;\n    box-sizing: border-box;\n}\n.sp-top {\n    margin-bottom: 3px;\n}\n.sp-color, .sp-hue, .sp-clear {\n    border: solid 1px #666;\n}\n\n/* Input */\n.sp-input-container {\n    float:right;\n    width: 100px;\n    margin-bottom: 4px;\n}\n.sp-initial-disabled  .sp-input-container {\n    width: 100%;\n}\n.sp-input {\n   font-size: 12px !important;\n   border: 1px inset;\n   padding: 4px 5px;\n   margin: 0;\n   width: 100%;\n   background:#FFF;\n   border-radius: 3px;\n   color: #222;\n}\n.sp-input:focus  {\n    border: 1px solid orange;\n}\n.sp-input.sp-validation-error {\n    border: 1px solid red;\n    background: #fdd;\n}\n.sp-picker-container , .sp-palette-container {\n    float:left;\n    position: relative;\n    padding: 10px;\n    padding-bottom: 300px;\n    margin-bottom: -290px;\n}\n.sp-picker-container {\n    width: 172px;\n    border-left: solid 1px #fff;\n}\n\n/* Palettes */\n.sp-palette-container {\n    border-right: solid 1px #ccc;\n}\n\n.sp-palette-only .sp-palette-container {\n    border: 0;\n}\n\n.sp-palette .sp-thumb-el {\n    display: block;\n    position:relative;\n    float:left;\n    width: 24px;\n    height: 15px;\n    margin: 3px;\n    cursor: pointer;\n    border-radius: 3px;\n}\n.sp-palette .sp-thumb-el:hover, .sp-palette .sp-thumb-el.sp-thumb-active {\n    border-color: orange;\n}\n.sp-thumb-el {\n    position:relative;\n}\n\n/* Initial */\n.sp-initial {\n    float: left;\n    border: solid 1px #333;\n}\n.sp-initial span {\n    width: 30px;\n    height: 25px;\n    border:none;\n    display:block;\n    float:left;\n    margin:0;\n}\n\n.sp-initial .sp-clear-display {\n    background-position: center;\n}\n\n/* Buttons */\n.sp-palette-button-container,\n.sp-button-container {\n    float: right;\n}\n\n/* Replacer (the little preview div that shows up instead of the <input>) */\n.sp-replacer {\n    margin:0;\n    overflow:hidden;\n    cursor:pointer;\n    /*padding: 4px;*/\n    display:inline-block;\n    *zoom: 1;\n    *display: inline;\n    border: solid 1px #FFFFFF;\n    background: #eee;\n    color: #333;\n    vertical-align: middle;\n    border-radius: 3px;\n}\n.sp-replacer:hover, .sp-replacer.sp-active {\n    border-color: #F0C49B;\n    color: #111;\n}\n.sp-replacer.sp-disabled {\n    cursor:default;\n    border-color: silver;\n    color: silver;\n}\n.sp-dd {\n    padding: 2px 0;\n    height: 16px;\n    line-height: 16px;\n    float:left;\n    font-size:10px;\n    display: none;\n}\n.sp-preview {\n    position:relative;\n    width:  17px;\n    height: 17px;\n    border: solid 0px #222;\n    margin-right: 0px;\n    float:left;\n    z-index: 0;\n    border-radius: 3px;\n}\n\n.sp-palette {\n    *width: 220px;\n    max-width: 220px;\n}\n.sp-palette .sp-thumb-el {\n    width: 16px;\n    height: 16px;\n    margin:2px 1px;\n    border: solid 1px #AAA;\n}\n\n.sp-container {\n    padding-bottom:0;\n}\n\n\n/* Buttons: http://hellohappy.org/css3-buttons/ */\n.sp-container button {\n  background-color: #eeeeee;\n  background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc);\n  background-image: -moz-linear-gradient(top, #eeeeee, #cccccc);\n  background-image: -ms-linear-gradient(top, #eeeeee, #cccccc);\n  background-image: -o-linear-gradient(top, #eeeeee, #cccccc);\n  background-image: linear-gradient(to bottom, #eeeeee, #cccccc);\n  border: 1px solid #ccc;\n  border-bottom: 1px solid #bbb;\n  border-radius: 3px;\n  color: #333;\n  font-size: 14px;\n  line-height: 1;\n  padding: 5px 4px;\n  text-align: center;\n  text-shadow: 0 1px 0 #eee;\n  vertical-align: middle;\n}\n.sp-container button:hover {\n    background-color: #dddddd;\n    background-image: -webkit-linear-gradient(top, #dddddd, #bbbbbb);\n    background-image: -moz-linear-gradient(top, #dddddd, #bbbbbb);\n    background-image: -ms-linear-gradient(top, #dddddd, #bbbbbb);\n    background-image: -o-linear-gradient(top, #dddddd, #bbbbbb);\n    background-image: linear-gradient(to bottom, #dddddd, #bbbbbb);\n    border: 1px solid #bbb;\n    border-bottom: 1px solid #999;\n    cursor: pointer;\n    text-shadow: 0 1px 0 #ddd;\n}\n.sp-container button:active {\n    border: 1px solid #aaa;\n    border-bottom: 1px solid #888;\n    -webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;\n    -moz-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;\n    -ms-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;\n    -o-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;\n    box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;\n}\n.sp-cancel {\n    font-size: 11px;\n    color: #d93f3f !important;\n    margin:0;\n    padding:2px;\n    margin-right: 5px;\n    vertical-align: middle;\n    text-decoration:none;\n\n}\n.sp-cancel:hover {\n    color: #d93f3f !important;\n    text-decoration: underline;\n}\n\n\n.sp-palette span:hover, .sp-palette span.sp-thumb-active {\n    border-color: #000;\n}\n\n.sp-preview, .sp-alpha, .sp-thumb-el {\n    position:relative;\n    border-radius:  3px;\n    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);\n}\n.sp-preview-inner, .sp-alpha-inner, .sp-thumb-inner {\n    display:block;\n    position:absolute;\n    top:0;left:0;bottom:0;right:0;\n    border-radius: 3px;\n}\n\n.sp-preview-inner {\n    border-radius: 3px;\n}\n\n.sp-palette .sp-thumb-inner {\n    background-position: 50% 50%;\n    background-repeat: no-repeat;\n}\n\n.sp-palette .sp-thumb-light.sp-thumb-active .sp-thumb-inner {\n    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIVJREFUeNpiYBhsgJFMffxAXABlN5JruT4Q3wfi/0DsT64h8UD8HmpIPCWG/KemIfOJCUB+Aoacx6EGBZyHBqI+WsDCwuQ9mhxeg2A210Ntfo8klk9sOMijaURm7yc1UP2RNCMbKE9ODK1HM6iegYLkfx8pligC9lCD7KmRof0ZhjQACDAAceovrtpVBRkAAAAASUVORK5CYII=);\n}\n\n.sp-palette .sp-thumb-dark.sp-thumb-active .sp-thumb-inner {\n    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAMdJREFUOE+tkgsNwzAMRMugEAahEAahEAZhEAqlEAZhEAohEAYh81X2dIm8fKpEspLGvudPOsUYpxE2BIJCroJmEW9qJ+MKaBFhEMNabSy9oIcIPwrB+afvAUFoK4H0tMaQ3XtlrggDhOVVMuT4E5MMG0FBbCEYzjYT7OxLEvIHQLY2zWwQ3D+9luyOQTfKDiFD3iUIfPk8VqrKjgAiSfGFPecrg6HN6m/iBcwiDAo7WiBeawa+Kwh7tZoSCGLMqwlSAzVDhoK+6vH4G0P5wdkAAAAASUVORK5CYII=);\n}\n\n.sp-clear-display {\n    background-repeat:no-repeat;\n    background-position: center;\n    background-image: url(data:image/gif;base64,R0lGODlhFAAUAPcAAAAAAJmZmZ2dnZ6enqKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq/Hx8fLy8vT09PX19ff39/j4+Pn5+fr6+vv7+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAUABQAAAihAP9FoPCvoMGDBy08+EdhQAIJCCMybCDAAYUEARBAlFiQQoMABQhKUJBxY0SPICEYHBnggEmDKAuoPMjS5cGYMxHW3IiT478JJA8M/CjTZ0GgLRekNGpwAsYABHIypcAgQMsITDtWJYBR6NSqMico9cqR6tKfY7GeBCuVwlipDNmefAtTrkSzB1RaIAoXodsABiZAEFB06gIBWC1mLVgBa0AAOw==);\n}"
  },
  {
    "path": "lib/spectrum.js",
    "content": "// Spectrum Colorpicker v1.8.0\n// https://github.com/bgrins/spectrum\n// Author: Brian Grinstead\n// License: MIT\n\n(function (factory) {\n    \"use strict\";\n\n    if (typeof define === 'function' && define.amd) { // AMD\n        define(['jquery'], factory);\n    }\n    else if (typeof exports == \"object\" && typeof module == \"object\") { // CommonJS\n        module.exports = factory(require('jquery'));\n    }\n    else { // Browser\n        factory(jQuery);\n    }\n})(function($, undefined) {\n    \"use strict\";\n\n    var defaultOpts = {\n\n        // Callbacks\n        beforeShow: noop,\n        move: noop,\n        change: noop,\n        show: noop,\n        hide: noop,\n\n        // Options\n        color: false,\n        flat: false,\n        showInput: false,\n        allowEmpty: false,\n        showButtons: true,\n        clickoutFiresChange: true,\n        showInitial: false,\n        showPalette: false,\n        showPaletteOnly: false,\n        hideAfterPaletteSelect: false,\n        togglePaletteOnly: false,\n        showSelectionPalette: true,\n        localStorageKey: false,\n        appendTo: \"body\",\n        maxSelectionSize: 7,\n        cancelText: \"cancel\",\n        chooseText: \"choose\",\n        togglePaletteMoreText: \"more\",\n        togglePaletteLessText: \"less\",\n        clearText: \"Clear Color Selection\",\n        noColorSelectedText: \"No Color Selected\",\n        preferredFormat: false,\n        className: \"\", // Deprecated - use containerClassName and replacerClassName instead.\n        containerClassName: \"\",\n        replacerClassName: \"\",\n        showAlpha: false,\n        theme: \"sp-light\",\n        palette: [[\"#ffffff\", \"#000000\", \"#ff0000\", \"#ff8000\", \"#ffff00\", \"#008000\", \"#0000ff\", \"#4b0082\", \"#9400d3\"]],\n        selectionPalette: [],\n        disabled: false,\n        offset: null\n    },\n    spectrums = [],\n    IE = !!/msie/i.exec( window.navigator.userAgent ),\n    rgbaSupport = (function() {\n        function contains( str, substr ) {\n            return !!~('' + str).indexOf(substr);\n        }\n\n        var elem = document.createElement('div');\n        var style = elem.style;\n        style.cssText = 'background-color:rgba(0,0,0,.5)';\n        return contains(style.backgroundColor, 'rgba') || contains(style.backgroundColor, 'hsla');\n    })(),\n    replaceInput = [\n        \"<div class='sp-replacer'>\",\n            \"<div class='sp-preview'><div class='sp-preview-inner'></div></div>\",\n            \"<div class='sp-dd'>&#9660;</div>\",\n        \"</div>\"\n    ].join(''),\n    markup = (function () {\n\n        // IE does not support gradients with multiple stops, so we need to simulate\n        //  that for the rainbow slider with 8 divs that each have a single gradient\n        var gradientFix = \"\";\n        if (IE) {\n            for (var i = 1; i <= 6; i++) {\n                gradientFix += \"<div class='sp-\" + i + \"'></div>\";\n            }\n        }\n\n        return [\n            \"<div class='sp-container sp-hidden'>\",\n                \"<div class='sp-palette-container'>\",\n                    \"<div class='sp-palette sp-thumb sp-cf'></div>\",\n                    \"<div class='sp-palette-button-container sp-cf'>\",\n                        \"<button type='button' class='sp-palette-toggle'></button>\",\n                    \"</div>\",\n                \"</div>\",\n                \"<div class='sp-picker-container'>\",\n                    \"<div class='sp-top sp-cf'>\",\n                        \"<div class='sp-fill'></div>\",\n                        \"<div class='sp-top-inner'>\",\n                            \"<div class='sp-color'>\",\n                                \"<div class='sp-sat'>\",\n                                    \"<div class='sp-val'>\",\n                                        \"<div class='sp-dragger'></div>\",\n                                    \"</div>\",\n                                \"</div>\",\n                            \"</div>\",\n                            \"<div class='sp-clear sp-clear-display'>\",\n                            \"</div>\",\n                            \"<div class='sp-hue'>\",\n                                \"<div class='sp-slider'></div>\",\n                                gradientFix,\n                            \"</div>\",\n                        \"</div>\",\n                        \"<div class='sp-alpha'><div class='sp-alpha-inner'><div class='sp-alpha-handle'></div></div></div>\",\n                    \"</div>\",\n                    \"<div class='sp-input-container sp-cf'>\",\n                        \"<input class='sp-input' type='text' spellcheck='false'  />\",\n                    \"</div>\",\n                    \"<div class='sp-initial sp-thumb sp-cf'></div>\",\n                    \"<div class='sp-button-container sp-cf'>\",\n                        \"<a class='sp-cancel' href='#'></a>\",\n                        \"<button type='button' class='sp-choose'></button>\",\n                    \"</div>\",\n                \"</div>\",\n            \"</div>\"\n        ].join(\"\");\n    })();\n\n    function paletteTemplate (p, color, className, opts) {\n        var html = [];\n        for (var i = 0; i < p.length; i++) {\n            var current = p[i];\n            if(current) {\n                var tiny = tinycolor(current);\n                var c = tiny.toHsl().l < 0.5 ? \"sp-thumb-el sp-thumb-dark\" : \"sp-thumb-el sp-thumb-light\";\n                c += (tinycolor.equals(color, current)) ? \" sp-thumb-active\" : \"\";\n                var formattedString = tiny.toString(opts.preferredFormat || \"rgb\");\n                var swatchStyle = rgbaSupport ? (\"background-color:\" + tiny.toRgbString()) : \"filter:\" + tiny.toFilter();\n                html.push('<span title=\"' + formattedString + '\" data-color=\"' + tiny.toRgbString() + '\" class=\"' + c + '\"><span class=\"sp-thumb-inner\" style=\"' + swatchStyle + ';\" /></span>');\n            } else {\n                var cls = 'sp-clear-display';\n                html.push($('<div />')\n                    .append($('<span data-color=\"\" style=\"background-color:transparent;\" class=\"' + cls + '\"></span>')\n                        .attr('title', opts.noColorSelectedText)\n                    )\n                    .html()\n                );\n            }\n        }\n        return \"<div class='sp-cf \" + className + \"'>\" + html.join('') + \"</div>\";\n    }\n\n    function hideAll() {\n        for (var i = 0; i < spectrums.length; i++) {\n            if (spectrums[i]) {\n                spectrums[i].hide();\n            }\n        }\n    }\n\n    function instanceOptions(o, callbackContext) {\n        var opts = $.extend({}, defaultOpts, o);\n        opts.callbacks = {\n            'move': bind(opts.move, callbackContext),\n            'change': bind(opts.change, callbackContext),\n            'show': bind(opts.show, callbackContext),\n            'hide': bind(opts.hide, callbackContext),\n            'beforeShow': bind(opts.beforeShow, callbackContext)\n        };\n\n        return opts;\n    }\n\n    function spectrum(element, o) {\n\n        var opts = instanceOptions(o, element),\n            flat = opts.flat,\n            showSelectionPalette = opts.showSelectionPalette,\n            localStorageKey = opts.localStorageKey,\n            theme = opts.theme,\n            callbacks = opts.callbacks,\n            resize = throttle(reflow, 10),\n            visible = false,\n            isDragging = false,\n            dragWidth = 0,\n            dragHeight = 0,\n            dragHelperHeight = 0,\n            slideHeight = 0,\n            slideWidth = 0,\n            alphaWidth = 0,\n            alphaSlideHelperWidth = 0,\n            slideHelperHeight = 0,\n            currentHue = 0,\n            currentSaturation = 0,\n            currentValue = 0,\n            currentAlpha = 1,\n            palette = [],\n            paletteArray = [],\n            paletteLookup = {},\n            selectionPalette = opts.selectionPalette.slice(0),\n            maxSelectionSize = opts.maxSelectionSize,\n            draggingClass = \"sp-dragging\",\n            shiftMovementDirection = null;\n\n        var doc = element.ownerDocument,\n            body = doc.body,\n            boundElement = $(element),\n            disabled = false,\n            container = $(markup, doc).addClass(theme),\n            pickerContainer = container.find(\".sp-picker-container\"),\n            dragger = container.find(\".sp-color\"),\n            dragHelper = container.find(\".sp-dragger\"),\n            slider = container.find(\".sp-hue\"),\n            slideHelper = container.find(\".sp-slider\"),\n            alphaSliderInner = container.find(\".sp-alpha-inner\"),\n            alphaSlider = container.find(\".sp-alpha\"),\n            alphaSlideHelper = container.find(\".sp-alpha-handle\"),\n            textInput = container.find(\".sp-input\"),\n            paletteContainer = container.find(\".sp-palette\"),\n            initialColorContainer = container.find(\".sp-initial\"),\n            cancelButton = container.find(\".sp-cancel\"),\n            clearButton = container.find(\".sp-clear\"),\n            chooseButton = container.find(\".sp-choose\"),\n            toggleButton = container.find(\".sp-palette-toggle\"),\n            isInput = boundElement.is(\"input\"),\n            isInputTypeColor = isInput && boundElement.attr(\"type\") === \"color\" && inputTypeColorSupport(),\n            shouldReplace = isInput && !flat,\n            replacer = (shouldReplace) ? $(replaceInput).addClass(theme).addClass(opts.className).addClass(opts.replacerClassName) : $([]),\n            offsetElement = (shouldReplace) ? replacer : boundElement,\n            previewElement = replacer.find(\".sp-preview-inner\"),\n            initialColor = opts.color || (isInput && boundElement.val()),\n            colorOnShow = false,\n            currentPreferredFormat = opts.preferredFormat,\n            clickoutFiresChange = !opts.showButtons || opts.clickoutFiresChange,\n            isEmpty = !initialColor,\n            allowEmpty = opts.allowEmpty && !isInputTypeColor;\n\n        function applyOptions() {\n\n            if (opts.showPaletteOnly) {\n                opts.showPalette = true;\n            }\n\n            toggleButton.text(opts.showPaletteOnly ? opts.togglePaletteMoreText : opts.togglePaletteLessText);\n\n            if (opts.palette) {\n                palette = opts.palette.slice(0);\n                paletteArray = $.isArray(palette[0]) ? palette : [palette];\n                paletteLookup = {};\n                for (var i = 0; i < paletteArray.length; i++) {\n                    for (var j = 0; j < paletteArray[i].length; j++) {\n                        var rgb = tinycolor(paletteArray[i][j]).toRgbString();\n                        paletteLookup[rgb] = true;\n                    }\n                }\n            }\n\n            container.toggleClass(\"sp-flat\", flat);\n            container.toggleClass(\"sp-input-disabled\", !opts.showInput);\n            container.toggleClass(\"sp-alpha-enabled\", opts.showAlpha);\n            container.toggleClass(\"sp-clear-enabled\", allowEmpty);\n            container.toggleClass(\"sp-buttons-disabled\", !opts.showButtons);\n            container.toggleClass(\"sp-palette-buttons-disabled\", !opts.togglePaletteOnly);\n            container.toggleClass(\"sp-palette-disabled\", !opts.showPalette);\n            container.toggleClass(\"sp-palette-only\", opts.showPaletteOnly);\n            container.toggleClass(\"sp-initial-disabled\", !opts.showInitial);\n            container.addClass(opts.className).addClass(opts.containerClassName);\n\n            reflow();\n        }\n\n        function initialize() {\n\n            if (IE) {\n                container.find(\"*:not(input)\").attr(\"unselectable\", \"on\");\n            }\n\n            applyOptions();\n\n            if (shouldReplace) {\n                boundElement.after(replacer).hide();\n            }\n\n            if (!allowEmpty) {\n                clearButton.hide();\n            }\n\n            if (flat) {\n                boundElement.after(container).hide();\n            }\n            else {\n\n                var appendTo = opts.appendTo === \"parent\" ? boundElement.parent() : $(opts.appendTo);\n                if (appendTo.length !== 1) {\n                    appendTo = $(\"body\");\n                }\n\n                appendTo.append(container);\n            }\n\n            updateSelectionPaletteFromStorage();\n\n            offsetElement.bind(\"click.spectrum touchstart.spectrum\", function (e) {\n                if (!disabled) {\n                    toggle();\n                }\n\n                e.stopPropagation();\n\n                if (!$(e.target).is(\"input\")) {\n                    e.preventDefault();\n                }\n            });\n\n            if(boundElement.is(\":disabled\") || (opts.disabled === true)) {\n                disable();\n            }\n\n            // Prevent clicks from bubbling up to document.  This would cause it to be hidden.\n            container.click(stopPropagation);\n\n            // Handle user typed input\n            textInput.change(setFromTextInput);\n            textInput.bind(\"paste\", function () {\n                setTimeout(setFromTextInput, 1);\n            });\n            textInput.keydown(function (e) { if (e.keyCode == 13) { setFromTextInput(); } });\n\n            cancelButton.text(opts.cancelText);\n            cancelButton.bind(\"click.spectrum\", function (e) {\n                e.stopPropagation();\n                e.preventDefault();\n                revert();\n                hide();\n            });\n\n            clearButton.attr(\"title\", opts.clearText);\n            clearButton.bind(\"click.spectrum\", function (e) {\n                e.stopPropagation();\n                e.preventDefault();\n                isEmpty = true;\n                move();\n\n                if(flat) {\n                    //for the flat style, this is a change event\n                    updateOriginalInput(true);\n                }\n            });\n\n            chooseButton.text(opts.chooseText);\n            chooseButton.bind(\"click.spectrum\", function (e) {\n                e.stopPropagation();\n                e.preventDefault();\n\n                if (IE && textInput.is(\":focus\")) {\n                    textInput.trigger('change');\n                }\n\n                if (isValid()) {\n                    updateOriginalInput(true);\n                    hide();\n                }\n            });\n\n            toggleButton.text(opts.showPaletteOnly ? opts.togglePaletteMoreText : opts.togglePaletteLessText);\n            toggleButton.bind(\"click.spectrum\", function (e) {\n                e.stopPropagation();\n                e.preventDefault();\n\n                opts.showPaletteOnly = !opts.showPaletteOnly;\n\n                // To make sure the Picker area is drawn on the right, next to the\n                // Palette area (and not below the palette), first move the Palette\n                // to the left to make space for the picker, plus 5px extra.\n                // The 'applyOptions' function puts the whole container back into place\n                // and takes care of the button-text and the sp-palette-only CSS class.\n                if (!opts.showPaletteOnly && !flat) {\n                    container.css('left', '-=' + (pickerContainer.outerWidth(true) + 5));\n                }\n                applyOptions();\n            });\n\n            draggable(alphaSlider, function (dragX, dragY, e) {\n                currentAlpha = (dragX / alphaWidth);\n                isEmpty = false;\n                if (e.shiftKey) {\n                    currentAlpha = Math.round(currentAlpha * 10) / 10;\n                }\n\n                move();\n            }, dragStart, dragStop);\n\n            draggable(slider, function (dragX, dragY) {\n                currentHue = parseFloat(dragY / slideHeight);\n                isEmpty = false;\n                if (!opts.showAlpha) {\n                    currentAlpha = 1;\n                }\n                move();\n            }, dragStart, dragStop);\n\n            draggable(dragger, function (dragX, dragY, e) {\n\n                // shift+drag should snap the movement to either the x or y axis.\n                if (!e.shiftKey) {\n                    shiftMovementDirection = null;\n                }\n                else if (!shiftMovementDirection) {\n                    var oldDragX = currentSaturation * dragWidth;\n                    var oldDragY = dragHeight - (currentValue * dragHeight);\n                    var furtherFromX = Math.abs(dragX - oldDragX) > Math.abs(dragY - oldDragY);\n\n                    shiftMovementDirection = furtherFromX ? \"x\" : \"y\";\n                }\n\n                var setSaturation = !shiftMovementDirection || shiftMovementDirection === \"x\";\n                var setValue = !shiftMovementDirection || shiftMovementDirection === \"y\";\n\n                if (setSaturation) {\n                    currentSaturation = parseFloat(dragX / dragWidth);\n                }\n                if (setValue) {\n                    currentValue = parseFloat((dragHeight - dragY) / dragHeight);\n                }\n\n                isEmpty = false;\n                if (!opts.showAlpha) {\n                    currentAlpha = 1;\n                }\n\n                move();\n\n            }, dragStart, dragStop);\n\n            if (!!initialColor) {\n                set(initialColor);\n\n                // In case color was black - update the preview UI and set the format\n                // since the set function will not run (default color is black).\n                updateUI();\n                currentPreferredFormat = opts.preferredFormat || tinycolor(initialColor).format;\n\n                addColorToSelectionPalette(initialColor);\n            }\n            else {\n                updateUI();\n            }\n\n            if (flat) {\n                show();\n            }\n\n            function paletteElementClick(e) {\n                if (e.data && e.data.ignore) {\n                    set($(e.target).closest(\".sp-thumb-el\").data(\"color\"));\n                    move();\n                }\n                else {\n                    set($(e.target).closest(\".sp-thumb-el\").data(\"color\"));\n                    move();\n                    updateOriginalInput(true);\n                    if (opts.hideAfterPaletteSelect) {\n                      hide();\n                    }\n                }\n\n                return false;\n            }\n\n            var paletteEvent = IE ? \"mousedown.spectrum\" : \"click.spectrum touchstart.spectrum\";\n            paletteContainer.delegate(\".sp-thumb-el\", paletteEvent, paletteElementClick);\n            initialColorContainer.delegate(\".sp-thumb-el:nth-child(1)\", paletteEvent, { ignore: true }, paletteElementClick);\n        }\n\n        function updateSelectionPaletteFromStorage() {\n\n            if (localStorageKey && window.localStorage) {\n\n                // Migrate old palettes over to new format.  May want to remove this eventually.\n                try {\n                    var oldPalette = window.localStorage[localStorageKey].split(\",#\");\n                    if (oldPalette.length > 1) {\n                        delete window.localStorage[localStorageKey];\n                        $.each(oldPalette, function(i, c) {\n                             addColorToSelectionPalette(c);\n                        });\n                    }\n                }\n                catch(e) { }\n\n                try {\n                    selectionPalette = window.localStorage[localStorageKey].split(\";\");\n                }\n                catch (e) { }\n            }\n        }\n\n        function addColorToSelectionPalette(color) {\n            if (showSelectionPalette) {\n                var rgb = tinycolor(color).toRgbString();\n                if (!paletteLookup[rgb] && $.inArray(rgb, selectionPalette) === -1) {\n                    selectionPalette.push(rgb);\n                    while(selectionPalette.length > maxSelectionSize) {\n                        selectionPalette.shift();\n                    }\n                }\n\n                if (localStorageKey && window.localStorage) {\n                    try {\n                        window.localStorage[localStorageKey] = selectionPalette.join(\";\");\n                    }\n                    catch(e) { }\n                }\n            }\n        }\n\n        function getUniqueSelectionPalette() {\n            var unique = [];\n            if (opts.showPalette) {\n                for (var i = 0; i < selectionPalette.length; i++) {\n                    var rgb = tinycolor(selectionPalette[i]).toRgbString();\n\n                    if (!paletteLookup[rgb]) {\n                        unique.push(selectionPalette[i]);\n                    }\n                }\n            }\n\n            return unique.reverse().slice(0, opts.maxSelectionSize);\n        }\n\n        function drawPalette() {\n\n            var currentColor = get();\n\n            var html = $.map(paletteArray, function (palette, i) {\n                return paletteTemplate(palette, currentColor, \"sp-palette-row sp-palette-row-\" + i, opts);\n            });\n\n            updateSelectionPaletteFromStorage();\n\n            if (selectionPalette) {\n                html.push(paletteTemplate(getUniqueSelectionPalette(), currentColor, \"sp-palette-row sp-palette-row-selection\", opts));\n            }\n\n            paletteContainer.html(html.join(\"\"));\n        }\n\n        function drawInitial() {\n            if (opts.showInitial) {\n                var initial = colorOnShow;\n                var current = get();\n                initialColorContainer.html(paletteTemplate([initial, current], current, \"sp-palette-row-initial\", opts));\n            }\n        }\n\n        function dragStart() {\n            if (dragHeight <= 0 || dragWidth <= 0 || slideHeight <= 0) {\n                reflow();\n            }\n            isDragging = true;\n            container.addClass(draggingClass);\n            shiftMovementDirection = null;\n            boundElement.trigger('dragstart.spectrum', [ get() ]);\n        }\n\n        function dragStop() {\n            isDragging = false;\n            container.removeClass(draggingClass);\n            boundElement.trigger('dragstop.spectrum', [ get() ]);\n        }\n\n        function setFromTextInput() {\n\n            var value = textInput.val();\n\n            if ((value === null || value === \"\") && allowEmpty) {\n                set(null);\n                updateOriginalInput(true);\n            }\n            else {\n                var tiny = tinycolor(value);\n                if (tiny.isValid()) {\n                    set(tiny);\n                    updateOriginalInput(true);\n                }\n                else {\n                    textInput.addClass(\"sp-validation-error\");\n                }\n            }\n        }\n\n        function toggle() {\n            if (visible) {\n                hide();\n            }\n            else {\n                show();\n            }\n        }\n\n        function show() {\n            var event = $.Event('beforeShow.spectrum');\n\n            if (visible) {\n                reflow();\n                return;\n            }\n\n            boundElement.trigger(event, [ get() ]);\n\n            if (callbacks.beforeShow(get()) === false || event.isDefaultPrevented()) {\n                return;\n            }\n\n            hideAll();\n            visible = true;\n\n            $(doc).bind(\"keydown.spectrum\", onkeydown);\n            $(doc).bind(\"click.spectrum\", clickout);\n            $(window).bind(\"resize.spectrum\", resize);\n            replacer.addClass(\"sp-active\");\n            container.removeClass(\"sp-hidden\");\n\n            reflow();\n            updateUI();\n\n            colorOnShow = get();\n\n            drawInitial();\n            callbacks.show(colorOnShow);\n            boundElement.trigger('show.spectrum', [ colorOnShow ]);\n        }\n\n        function onkeydown(e) {\n            // Close on ESC\n            if (e.keyCode === 27) {\n                hide();\n            }\n        }\n\n        function clickout(e) {\n            // Return on right click.\n            if (e.button == 2) { return; }\n\n            // If a drag event was happening during the mouseup, don't hide\n            // on click.\n            if (isDragging) { return; }\n\n            if (clickoutFiresChange) {\n                updateOriginalInput(true);\n            }\n            else {\n                revert();\n            }\n            hide();\n        }\n\n        function hide() {\n            // Return if hiding is unnecessary\n            if (!visible || flat) { return; }\n            visible = false;\n\n            $(doc).unbind(\"keydown.spectrum\", onkeydown);\n            $(doc).unbind(\"click.spectrum\", clickout);\n            $(window).unbind(\"resize.spectrum\", resize);\n\n            replacer.removeClass(\"sp-active\");\n            container.addClass(\"sp-hidden\");\n\n            callbacks.hide(get());\n            boundElement.trigger('hide.spectrum', [ get() ]);\n        }\n\n        function revert() {\n            set(colorOnShow, true);\n        }\n\n        function set(color, ignoreFormatChange) {\n            if (tinycolor.equals(color, get())) {\n                // Update UI just in case a validation error needs\n                // to be cleared.\n                updateUI();\n                return;\n            }\n\n            var newColor, newHsv;\n            if (!color && allowEmpty) {\n                isEmpty = true;\n            } else {\n                isEmpty = false;\n                newColor = tinycolor(color);\n                newHsv = newColor.toHsv();\n\n                currentHue = (newHsv.h % 360) / 360;\n                currentSaturation = newHsv.s;\n                currentValue = newHsv.v;\n                currentAlpha = newHsv.a;\n            }\n            updateUI();\n\n            if (newColor && newColor.isValid() && !ignoreFormatChange) {\n                currentPreferredFormat = opts.preferredFormat || newColor.getFormat();\n            }\n        }\n\n        function get(opts) {\n            opts = opts || { };\n\n            if (allowEmpty && isEmpty) {\n                return null;\n            }\n\n            return tinycolor.fromRatio({\n                h: currentHue,\n                s: currentSaturation,\n                v: currentValue,\n                a: Math.round(currentAlpha * 100) / 100\n            }, { format: opts.format || currentPreferredFormat });\n        }\n\n        function isValid() {\n            return !textInput.hasClass(\"sp-validation-error\");\n        }\n\n        function move() {\n            updateUI();\n\n            callbacks.move(get());\n            boundElement.trigger('move.spectrum', [ get() ]);\n        }\n\n        function updateUI() {\n\n            textInput.removeClass(\"sp-validation-error\");\n\n            updateHelperLocations();\n\n            // Update dragger background color (gradients take care of saturation and value).\n            var flatColor = tinycolor.fromRatio({ h: currentHue, s: 1, v: 1 });\n            dragger.css(\"background-color\", flatColor.toHexString());\n\n            // Get a format that alpha will be included in (hex and names ignore alpha)\n            var format = currentPreferredFormat;\n            if (currentAlpha < 1 && !(currentAlpha === 0 && format === \"name\")) {\n                if (format === \"hex\" || format === \"hex3\" || format === \"hex6\" || format === \"name\") {\n                    format = \"rgb\";\n                }\n            }\n\n            var realColor = get({ format: format }),\n                displayColor = '';\n\n             //reset background info for preview element\n            previewElement.removeClass(\"sp-clear-display\");\n            previewElement.css('background-color', 'transparent');\n\n            if (!realColor && allowEmpty) {\n                // Update the replaced elements background with icon indicating no color selection\n                previewElement.addClass(\"sp-clear-display\");\n            }\n            else {\n                var realHex = realColor.toHexString(),\n                    realRgb = realColor.toRgbString();\n\n                // Update the replaced elements background color (with actual selected color)\n                if (rgbaSupport || realColor.alpha === 1) {\n                    previewElement.css(\"background-color\", realRgb);\n                }\n                else {\n                    previewElement.css(\"background-color\", \"transparent\");\n                    previewElement.css(\"filter\", realColor.toFilter());\n                }\n\n                if (opts.showAlpha) {\n                    var rgb = realColor.toRgb();\n                    rgb.a = 0;\n                    var realAlpha = tinycolor(rgb).toRgbString();\n                    var gradient = \"linear-gradient(left, \" + realAlpha + \", \" + realHex + \")\";\n\n                    if (IE) {\n                        alphaSliderInner.css(\"filter\", tinycolor(realAlpha).toFilter({ gradientType: 1 }, realHex));\n                    }\n                    else {\n                        alphaSliderInner.css(\"background\", \"-webkit-\" + gradient);\n                        alphaSliderInner.css(\"background\", \"-moz-\" + gradient);\n                        alphaSliderInner.css(\"background\", \"-ms-\" + gradient);\n                        // Use current syntax gradient on unprefixed property.\n                        alphaSliderInner.css(\"background\",\n                            \"linear-gradient(to right, \" + realAlpha + \", \" + realHex + \")\");\n                    }\n                }\n\n                displayColor = realColor.toString(format);\n            }\n\n            // Update the text entry input as it changes happen\n            if (opts.showInput) {\n                textInput.val(displayColor);\n            }\n\n            if (opts.showPalette) {\n                drawPalette();\n            }\n\n            drawInitial();\n        }\n\n        function updateHelperLocations() {\n            var s = currentSaturation;\n            var v = currentValue;\n\n            if(allowEmpty && isEmpty) {\n                //if selected color is empty, hide the helpers\n                alphaSlideHelper.hide();\n                slideHelper.hide();\n                dragHelper.hide();\n            }\n            else {\n                //make sure helpers are visible\n                alphaSlideHelper.show();\n                slideHelper.show();\n                dragHelper.show();\n\n                // Where to show the little circle in that displays your current selected color\n                var dragX = s * dragWidth;\n                var dragY = dragHeight - (v * dragHeight);\n                dragWidth = 136;\n                dragHeight = 144;\n                dragX = Math.max(\n                    -dragHelperHeight,\n                    Math.min(dragWidth - dragHelperHeight, dragX - dragHelperHeight)\n                );\n                dragY = Math.max(\n                    -dragHelperHeight,\n                    Math.min(dragHeight - dragHelperHeight, dragY - dragHelperHeight)\n                );\n                dragHelper.css({\n                    \"top\": dragY + \"px\",\n                    \"left\": dragX + \"px\"\n                });\n\n                if(alphaWidth === 0) alphaWidth = 172\n                var alphaX = currentAlpha * alphaWidth;\n                alphaSlideHelper.css({\n                    \"left\": (alphaX - (alphaSlideHelperWidth / 2)) + \"px\"\n                });\n\n                // Where to show the bar that displays your current selected hue\n                slideHeight = 143;\n                var slideY = (currentHue) * slideHeight;\n                slideHelper.css({\n                    \"top\": (slideY - slideHelperHeight) + \"px\"\n                });\n            }\n        }\n\n        function updateOriginalInput(fireCallback) {\n            var color = get(),\n                displayColor = '',\n                hasChanged = !tinycolor.equals(color, colorOnShow);\n\n            if (color) {\n                displayColor = color.toString(currentPreferredFormat);\n                // Update the selection palette with the current color\n                addColorToSelectionPalette(color);\n            }\n\n            if (isInput) {\n                boundElement.val(displayColor);\n            }\n\n            if (fireCallback && hasChanged) {\n                callbacks.change(color);\n                boundElement.trigger('change', [ color ]);\n            }\n        }\n\n        function reflow() {\n            if (!visible) {\n                return; // Calculations would be useless and wouldn't be reliable anyways\n            }\n            dragWidth = dragger.width();\n            dragHeight = dragger.height();\n            dragHelperHeight = dragHelper.height();\n            slideWidth = slider.width();\n            slideHeight = slider.height();\n            slideHelperHeight = slideHelper.height();\n            alphaWidth = alphaSlider.width();\n            alphaSlideHelperWidth = alphaSlideHelper.width();\n\n            if (!flat) {\n                container.css(\"position\", \"absolute\");\n                if (opts.offset) {\n                    container.offset(opts.offset);\n                } else {\n                    container.offset(getOffset(container, offsetElement));\n                }\n            }\n\n            updateHelperLocations();\n\n            if (opts.showPalette) {\n                drawPalette();\n            }\n\n            boundElement.trigger('reflow.spectrum');\n        }\n\n        function destroy() {\n            boundElement.show();\n            offsetElement.unbind(\"click.spectrum touchstart.spectrum\");\n            container.remove();\n            replacer.remove();\n            spectrums[spect.id] = null;\n        }\n\n        function option(optionName, optionValue) {\n            if (optionName === undefined) {\n                return $.extend({}, opts);\n            }\n            if (optionValue === undefined) {\n                return opts[optionName];\n            }\n\n            opts[optionName] = optionValue;\n\n            if (optionName === \"preferredFormat\") {\n                currentPreferredFormat = opts.preferredFormat;\n            }\n            applyOptions();\n        }\n\n        function enable() {\n            disabled = false;\n            boundElement.attr(\"disabled\", false);\n            offsetElement.removeClass(\"sp-disabled\");\n        }\n\n        function disable() {\n            hide();\n            disabled = true;\n            boundElement.attr(\"disabled\", true);\n            offsetElement.addClass(\"sp-disabled\");\n        }\n\n        function setOffset(coord) {\n            opts.offset = coord;\n            reflow();\n        }\n\n        initialize();\n\n        var spect = {\n            show: show,\n            hide: hide,\n            toggle: toggle,\n            reflow: reflow,\n            option: option,\n            enable: enable,\n            disable: disable,\n            offset: setOffset,\n            set: function (c) {\n                set(c);\n                updateOriginalInput();\n            },\n            get: get,\n            destroy: destroy,\n            container: container\n        };\n\n        spect.id = spectrums.push(spect) - 1;\n\n        return spect;\n    }\n\n    /**\n    * checkOffset - get the offset below/above and left/right element depending on screen position\n    * Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js\n    */\n    function getOffset(picker, input) {\n        var extraY = 0;\n        var dpWidth = picker.outerWidth();\n        var dpHeight = picker.outerHeight();\n        var inputHeight = input.outerHeight();\n        var doc = picker[0].ownerDocument;\n        var docElem = doc.documentElement;\n        var viewWidth = docElem.clientWidth + $(doc).scrollLeft();\n        var viewHeight = docElem.clientHeight + $(doc).scrollTop();\n        var offset = input.offset();\n        offset.top += inputHeight;\n\n        offset.left -=\n            Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?\n            Math.abs(offset.left + dpWidth - viewWidth) : 0);\n\n        offset.top -=\n            Math.min(offset.top, ((offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?\n            Math.abs(dpHeight + inputHeight - extraY) : extraY));\n\n        return offset;\n    }\n\n    /**\n    * noop - do nothing\n    */\n    function noop() {\n\n    }\n\n    /**\n    * stopPropagation - makes the code only doing this a little easier to read in line\n    */\n    function stopPropagation(e) {\n        e.stopPropagation();\n    }\n\n    /**\n    * Create a function bound to a given object\n    * Thanks to underscore.js\n    */\n    function bind(func, obj) {\n        var slice = Array.prototype.slice;\n        var args = slice.call(arguments, 2);\n        return function () {\n            return func.apply(obj, args.concat(slice.call(arguments)));\n        };\n    }\n\n    /**\n    * Lightweight drag helper.  Handles containment within the element, so that\n    * when dragging, the x is within [0,element.width] and y is within [0,element.height]\n    */\n    function draggable(element, onmove, onstart, onstop) {\n        onmove = onmove || function () { };\n        onstart = onstart || function () { };\n        onstop = onstop || function () { };\n        var doc = document;\n        var dragging = false;\n        var offset = {};\n        var maxHeight = 0;\n        var maxWidth = 0;\n        var hasTouch = ('ontouchstart' in window);\n\n        var duringDragEvents = {};\n        duringDragEvents[\"selectstart\"] = prevent;\n        duringDragEvents[\"dragstart\"] = prevent;\n        duringDragEvents[\"touchmove mousemove\"] = move;\n        duringDragEvents[\"touchend mouseup\"] = stop;\n\n        function prevent(e) {\n            if (e.stopPropagation) {\n                e.stopPropagation();\n            }\n            if (e.preventDefault) {\n                e.preventDefault();\n            }\n            e.returnValue = false;\n        }\n\n        function move(e) {\n            if (dragging) {\n                // Mouseup happened outside of window\n                if (IE && doc.documentMode < 9 && !e.button) {\n                    return stop();\n                }\n\n                var t0 = e.originalEvent && e.originalEvent.touches && e.originalEvent.touches[0];\n                var pageX = t0 && t0.pageX || e.pageX;\n                var pageY = t0 && t0.pageY || e.pageY;\n\n                var dragX = Math.max(0, Math.min(pageX - offset.left, maxWidth));\n                var dragY = Math.max(0, Math.min(pageY - offset.top, maxHeight));\n\n                if (hasTouch) {\n                    // Stop scrolling in iOS\n                    prevent(e);\n                }\n\n                onmove.apply(element, [dragX, dragY, e]);\n            }\n        }\n\n        function start(e) {\n            var rightclick = (e.which) ? (e.which == 3) : (e.button == 2);\n\n            if (!rightclick && !dragging) {\n                if (onstart.apply(element, arguments) !== false) {\n                    dragging = true;\n                    maxHeight = $(element).height();\n                    maxWidth = $(element).width();\n                    offset = $(element).offset();\n\n                    $(doc).bind(duringDragEvents);\n                    $(doc.body).addClass(\"sp-dragging\");\n\n                    move(e);\n\n                    prevent(e);\n                }\n            }\n        }\n\n        function stop() {\n            if (dragging) {\n                $(doc).unbind(duringDragEvents);\n                $(doc.body).removeClass(\"sp-dragging\");\n\n                // Wait a tick before notifying observers to allow the click event\n                // to fire in Chrome.\n                setTimeout(function() {\n                    onstop.apply(element, arguments);\n                }, 0);\n            }\n            dragging = false;\n        }\n\n        $(element).bind(\"touchstart mousedown\", start);\n    }\n\n    function throttle(func, wait, debounce) {\n        var timeout;\n        return function () {\n            var context = this, args = arguments;\n            var throttler = function () {\n                timeout = null;\n                func.apply(context, args);\n            };\n            if (debounce) clearTimeout(timeout);\n            if (debounce || !timeout) timeout = setTimeout(throttler, wait);\n        };\n    }\n\n    function inputTypeColorSupport() {\n        return $.fn.spectrum.inputTypeColorSupport();\n    }\n\n    /**\n    * Define a jQuery plugin\n    */\n    var dataID = \"spectrum.id\";\n    $.fn.spectrum = function (opts, extra) {\n\n        if (typeof opts == \"string\") {\n\n            var returnValue = this;\n            var args = Array.prototype.slice.call( arguments, 1 );\n\n            this.each(function () {\n                var spect = spectrums[$(this).data(dataID)];\n                if (spect) {\n                    var method = spect[opts];\n                    if (!method) {\n                        throw new Error( \"Spectrum: no such method: '\" + opts + \"'\" );\n                    }\n\n                    if (opts == \"get\") {\n                        returnValue = spect.get();\n                    }\n                    else if (opts == \"container\") {\n                        returnValue = spect.container;\n                    }\n                    else if (opts == \"option\") {\n                        returnValue = spect.option.apply(spect, args);\n                    }\n                    else if (opts == \"destroy\") {\n                        spect.destroy();\n                        $(this).removeData(dataID);\n                    }\n                    else {\n                        method.apply(spect, args);\n                    }\n                }\n            });\n\n            return returnValue;\n        }\n\n        // Initializing a new instance of spectrum\n        return this.spectrum(\"destroy\").each(function () {\n            var options = $.extend({}, opts, $(this).data());\n            var spect = spectrum(this, options);\n            $(this).data(dataID, spect.id);\n        });\n    };\n\n    $.fn.spectrum.load = true;\n    $.fn.spectrum.loadOpts = {};\n    $.fn.spectrum.draggable = draggable;\n    $.fn.spectrum.defaults = defaultOpts;\n    $.fn.spectrum.inputTypeColorSupport = function inputTypeColorSupport() {\n        if (typeof inputTypeColorSupport._cachedResult === \"undefined\") {\n            var colorInput = $(\"<input type='color'/>\")[0]; // if color element is supported, value will default to not null\n            inputTypeColorSupport._cachedResult = colorInput.type === \"color\" && colorInput.value !== \"\";\n        }\n        return inputTypeColorSupport._cachedResult;\n    };\n\n    $.spectrum = { };\n    $.spectrum.localization = { };\n    $.spectrum.palettes = { };\n\n    $.fn.spectrum.processNativeColorInputs = function () {\n        var colorInputs = $(\"input[type=color]\");\n        if (colorInputs.length && !inputTypeColorSupport()) {\n            colorInputs.spectrum({\n                preferredFormat: \"hex6\"\n            });\n        }\n    };\n\n    // TinyColor v1.1.2\n    // https://github.com/bgrins/TinyColor\n    // Brian Grinstead, MIT License\n\n    (function() {\n\n    var trimLeft = /^[\\s,#]+/,\n        trimRight = /\\s+$/,\n        tinyCounter = 0,\n        math = Math,\n        mathRound = math.round,\n        mathMin = math.min,\n        mathMax = math.max,\n        mathRandom = math.random;\n\n    var tinycolor = function(color, opts) {\n\n        color = (color) ? color : '';\n        opts = opts || { };\n\n        // If input is already a tinycolor, return itself\n        if (color instanceof tinycolor) {\n           return color;\n        }\n        // If we are called as a function, call using new instead\n        if (!(this instanceof tinycolor)) {\n            return new tinycolor(color, opts);\n        }\n\n        var rgb = inputToRGB(color);\n        this._originalInput = color,\n        this._r = rgb.r,\n        this._g = rgb.g,\n        this._b = rgb.b,\n        this._a = rgb.a,\n        this._roundA = mathRound(100*this._a) / 100,\n        this._format = opts.format || rgb.format;\n        this._gradientType = opts.gradientType;\n\n        // Don't let the range of [0,255] come back in [0,1].\n        // Potentially lose a little bit of precision here, but will fix issues where\n        // .5 gets interpreted as half of the total, instead of half of 1\n        // If it was supposed to be 128, this was already taken care of by `inputToRgb`\n        if (this._r < 1) { this._r = mathRound(this._r); }\n        if (this._g < 1) { this._g = mathRound(this._g); }\n        if (this._b < 1) { this._b = mathRound(this._b); }\n\n        this._ok = rgb.ok;\n        this._tc_id = tinyCounter++;\n    };\n\n    tinycolor.prototype = {\n        isDark: function() {\n            return this.getBrightness() < 128;\n        },\n        isLight: function() {\n            return !this.isDark();\n        },\n        isValid: function() {\n            return this._ok;\n        },\n        getOriginalInput: function() {\n          return this._originalInput;\n        },\n        getFormat: function() {\n            return this._format;\n        },\n        getAlpha: function() {\n            return this._a;\n        },\n        getBrightness: function() {\n            var rgb = this.toRgb();\n            return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;\n        },\n        setAlpha: function(value) {\n            this._a = boundAlpha(value);\n            this._roundA = mathRound(100*this._a) / 100;\n            return this;\n        },\n        toHsv: function() {\n            var hsv = rgbToHsv(this._r, this._g, this._b);\n            return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a };\n        },\n        toHsvString: function() {\n            var hsv = rgbToHsv(this._r, this._g, this._b);\n            var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);\n            return (this._a == 1) ?\n              \"hsv(\"  + h + \", \" + s + \"%, \" + v + \"%)\" :\n              \"hsva(\" + h + \", \" + s + \"%, \" + v + \"%, \"+ this._roundA + \")\";\n        },\n        toHsl: function() {\n            var hsl = rgbToHsl(this._r, this._g, this._b);\n            return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a };\n        },\n        toHslString: function() {\n            var hsl = rgbToHsl(this._r, this._g, this._b);\n            var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);\n            return (this._a == 1) ?\n              \"hsl(\"  + h + \", \" + s + \"%, \" + l + \"%)\" :\n              \"hsla(\" + h + \", \" + s + \"%, \" + l + \"%, \"+ this._roundA + \")\";\n        },\n        toHex: function(allow3Char) {\n            return rgbToHex(this._r, this._g, this._b, allow3Char);\n        },\n        toHexString: function(allow3Char) {\n            return '#' + this.toHex(allow3Char);\n        },\n        toHex8: function() {\n            return rgbaToHex(this._r, this._g, this._b, this._a);\n        },\n        toHex8String: function() {\n            return '#' + this.toHex8();\n        },\n        toRgb: function() {\n            return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a };\n        },\n        toRgbString: function() {\n            return (this._a == 1) ?\n              \"rgb(\"  + mathRound(this._r) + \", \" + mathRound(this._g) + \", \" + mathRound(this._b) + \")\" :\n              \"rgba(\" + mathRound(this._r) + \", \" + mathRound(this._g) + \", \" + mathRound(this._b) + \", \" + this._roundA + \")\";\n        },\n        toPercentageRgb: function() {\n            return { r: mathRound(bound01(this._r, 255) * 100) + \"%\", g: mathRound(bound01(this._g, 255) * 100) + \"%\", b: mathRound(bound01(this._b, 255) * 100) + \"%\", a: this._a };\n        },\n        toPercentageRgbString: function() {\n            return (this._a == 1) ?\n              \"rgb(\"  + mathRound(bound01(this._r, 255) * 100) + \"%, \" + mathRound(bound01(this._g, 255) * 100) + \"%, \" + mathRound(bound01(this._b, 255) * 100) + \"%)\" :\n              \"rgba(\" + mathRound(bound01(this._r, 255) * 100) + \"%, \" + mathRound(bound01(this._g, 255) * 100) + \"%, \" + mathRound(bound01(this._b, 255) * 100) + \"%, \" + this._roundA + \")\";\n        },\n        toName: function() {\n            if (this._a === 0) {\n                return \"transparent\";\n            }\n\n            if (this._a < 1) {\n                return false;\n            }\n\n            return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false;\n        },\n        toFilter: function(secondColor) {\n            var hex8String = '#' + rgbaToHex(this._r, this._g, this._b, this._a);\n            var secondHex8String = hex8String;\n            var gradientType = this._gradientType ? \"GradientType = 1, \" : \"\";\n\n            if (secondColor) {\n                var s = tinycolor(secondColor);\n                secondHex8String = s.toHex8String();\n            }\n\n            return \"progid:DXImageTransform.Microsoft.gradient(\"+gradientType+\"startColorstr=\"+hex8String+\",endColorstr=\"+secondHex8String+\")\";\n        },\n        toString: function(format) {\n            var formatSet = !!format;\n            format = format || this._format;\n\n            var formattedString = false;\n            var hasAlpha = this._a < 1 && this._a >= 0;\n            var needsAlphaFormat = !formatSet && hasAlpha && (format === \"hex\" || format === \"hex6\" || format === \"hex3\" || format === \"name\");\n\n            if (needsAlphaFormat) {\n                // Special case for \"transparent\", all other non-alpha formats\n                // will return rgba when there is transparency.\n                if (format === \"name\" && this._a === 0) {\n                    return this.toName();\n                }\n                return this.toRgbString();\n            }\n            if (format === \"rgb\") {\n                formattedString = this.toRgbString();\n            }\n            if (format === \"prgb\") {\n                formattedString = this.toPercentageRgbString();\n            }\n            if (format === \"hex\" || format === \"hex6\") {\n                formattedString = this.toHexString();\n            }\n            if (format === \"hex3\") {\n                formattedString = this.toHexString(true);\n            }\n            if (format === \"hex8\") {\n                formattedString = this.toHex8String();\n            }\n            if (format === \"name\") {\n                formattedString = this.toName();\n            }\n            if (format === \"hsl\") {\n                formattedString = this.toHslString();\n            }\n            if (format === \"hsv\") {\n                formattedString = this.toHsvString();\n            }\n\n            return formattedString || this.toHexString();\n        },\n\n        _applyModification: function(fn, args) {\n            var color = fn.apply(null, [this].concat([].slice.call(args)));\n            this._r = color._r;\n            this._g = color._g;\n            this._b = color._b;\n            this.setAlpha(color._a);\n            return this;\n        },\n        lighten: function() {\n            return this._applyModification(lighten, arguments);\n        },\n        brighten: function() {\n            return this._applyModification(brighten, arguments);\n        },\n        darken: function() {\n            return this._applyModification(darken, arguments);\n        },\n        desaturate: function() {\n            return this._applyModification(desaturate, arguments);\n        },\n        saturate: function() {\n            return this._applyModification(saturate, arguments);\n        },\n        greyscale: function() {\n            return this._applyModification(greyscale, arguments);\n        },\n        spin: function() {\n            return this._applyModification(spin, arguments);\n        },\n\n        _applyCombination: function(fn, args) {\n            return fn.apply(null, [this].concat([].slice.call(args)));\n        },\n        analogous: function() {\n            return this._applyCombination(analogous, arguments);\n        },\n        complement: function() {\n            return this._applyCombination(complement, arguments);\n        },\n        monochromatic: function() {\n            return this._applyCombination(monochromatic, arguments);\n        },\n        splitcomplement: function() {\n            return this._applyCombination(splitcomplement, arguments);\n        },\n        triad: function() {\n            return this._applyCombination(triad, arguments);\n        },\n        tetrad: function() {\n            return this._applyCombination(tetrad, arguments);\n        }\n    };\n\n    // If input is an object, force 1 into \"1.0\" to handle ratios properly\n    // String input requires \"1.0\" as input, so 1 will be treated as 1\n    tinycolor.fromRatio = function(color, opts) {\n        if (typeof color == \"object\") {\n            var newColor = {};\n            for (var i in color) {\n                if (color.hasOwnProperty(i)) {\n                    if (i === \"a\") {\n                        newColor[i] = color[i];\n                    }\n                    else {\n                        newColor[i] = convertToPercentage(color[i]);\n                    }\n                }\n            }\n            color = newColor;\n        }\n\n        return tinycolor(color, opts);\n    };\n\n    // Given a string or object, convert that input to RGB\n    // Possible string inputs:\n    //\n    //     \"red\"\n    //     \"#f00\" or \"f00\"\n    //     \"#ff0000\" or \"ff0000\"\n    //     \"#ff000000\" or \"ff000000\"\n    //     \"rgb 255 0 0\" or \"rgb (255, 0, 0)\"\n    //     \"rgb 1.0 0 0\" or \"rgb (1, 0, 0)\"\n    //     \"rgba (255, 0, 0, 1)\" or \"rgba 255, 0, 0, 1\"\n    //     \"rgba (1.0, 0, 0, 1)\" or \"rgba 1.0, 0, 0, 1\"\n    //     \"hsl(0, 100%, 50%)\" or \"hsl 0 100% 50%\"\n    //     \"hsla(0, 100%, 50%, 1)\" or \"hsla 0 100% 50%, 1\"\n    //     \"hsv(0, 100%, 100%)\" or \"hsv 0 100% 100%\"\n    //\n    function inputToRGB(color) {\n\n        var rgb = { r: 0, g: 0, b: 0 };\n        var a = 1;\n        var ok = false;\n        var format = false;\n\n        if (typeof color == \"string\") {\n            color = stringInputToObject(color);\n        }\n\n        if (typeof color == \"object\") {\n            if (color.hasOwnProperty(\"r\") && color.hasOwnProperty(\"g\") && color.hasOwnProperty(\"b\")) {\n                rgb = rgbToRgb(color.r, color.g, color.b);\n                ok = true;\n                format = String(color.r).substr(-1) === \"%\" ? \"prgb\" : \"rgb\";\n            }\n            else if (color.hasOwnProperty(\"h\") && color.hasOwnProperty(\"s\") && color.hasOwnProperty(\"v\")) {\n                color.s = convertToPercentage(color.s);\n                color.v = convertToPercentage(color.v);\n                rgb = hsvToRgb(color.h, color.s, color.v);\n                ok = true;\n                format = \"hsv\";\n            }\n            else if (color.hasOwnProperty(\"h\") && color.hasOwnProperty(\"s\") && color.hasOwnProperty(\"l\")) {\n                color.s = convertToPercentage(color.s);\n                color.l = convertToPercentage(color.l);\n                rgb = hslToRgb(color.h, color.s, color.l);\n                ok = true;\n                format = \"hsl\";\n            }\n\n            if (color.hasOwnProperty(\"a\")) {\n                a = color.a;\n            }\n        }\n\n        a = boundAlpha(a);\n\n        return {\n            ok: ok,\n            format: color.format || format,\n            r: mathMin(255, mathMax(rgb.r, 0)),\n            g: mathMin(255, mathMax(rgb.g, 0)),\n            b: mathMin(255, mathMax(rgb.b, 0)),\n            a: a\n        };\n    }\n\n\n    // Conversion Functions\n    // --------------------\n\n    // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:\n    // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>\n\n    // `rgbToRgb`\n    // Handle bounds / percentage checking to conform to CSS color spec\n    // <http://www.w3.org/TR/css3-color/>\n    // *Assumes:* r, g, b in [0, 255] or [0, 1]\n    // *Returns:* { r, g, b } in [0, 255]\n    function rgbToRgb(r, g, b){\n        return {\n            r: bound01(r, 255) * 255,\n            g: bound01(g, 255) * 255,\n            b: bound01(b, 255) * 255\n        };\n    }\n\n    // `rgbToHsl`\n    // Converts an RGB color value to HSL.\n    // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]\n    // *Returns:* { h, s, l } in [0,1]\n    function rgbToHsl(r, g, b) {\n\n        r = bound01(r, 255);\n        g = bound01(g, 255);\n        b = bound01(b, 255);\n\n        var max = mathMax(r, g, b), min = mathMin(r, g, b);\n        var h, s, l = (max + min) / 2;\n\n        if(max == min) {\n            h = s = 0; // achromatic\n        }\n        else {\n            var d = max - min;\n            s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n            switch(max) {\n                case r: h = (g - b) / d + (g < b ? 6 : 0); break;\n                case g: h = (b - r) / d + 2; break;\n                case b: h = (r - g) / d + 4; break;\n            }\n\n            h /= 6;\n        }\n\n        return { h: h, s: s, l: l };\n    }\n\n    // `hslToRgb`\n    // Converts an HSL color value to RGB.\n    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]\n    // *Returns:* { r, g, b } in the set [0, 255]\n    function hslToRgb(h, s, l) {\n        var r, g, b;\n\n        h = bound01(h, 360);\n        s = bound01(s, 100);\n        l = bound01(l, 100);\n\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        if(s === 0) {\n            r = g = b = l; // achromatic\n        }\n        else {\n            var q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n            var p = 2 * l - q;\n            r = hue2rgb(p, q, h + 1/3);\n            g = hue2rgb(p, q, h);\n            b = hue2rgb(p, q, h - 1/3);\n        }\n\n        return { r: r * 255, g: g * 255, b: b * 255 };\n    }\n\n    // `rgbToHsv`\n    // Converts an RGB color value to HSV\n    // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]\n    // *Returns:* { h, s, v } in [0,1]\n    function rgbToHsv(r, g, b) {\n\n        r = bound01(r, 255);\n        g = bound01(g, 255);\n        b = bound01(b, 255);\n\n        var max = mathMax(r, g, b), min = mathMin(r, g, b);\n        var h, s, v = max;\n\n        var d = max - min;\n        s = max === 0 ? 0 : d / max;\n\n        if(max == min) {\n            h = 0; // achromatic\n        }\n        else {\n            switch(max) {\n                case r: h = (g - b) / d + (g < b ? 6 : 0); break;\n                case g: h = (b - r) / d + 2; break;\n                case b: h = (r - g) / d + 4; break;\n            }\n            h /= 6;\n        }\n        return { h: h, s: s, v: v };\n    }\n\n    // `hsvToRgb`\n    // Converts an HSV color value to RGB.\n    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]\n    // *Returns:* { r, g, b } in the set [0, 255]\n     function hsvToRgb(h, s, v) {\n\n        h = bound01(h, 360) * 6;\n        s = bound01(s, 100);\n        v = bound01(v, 100);\n\n        var i = math.floor(h),\n            f = h - i,\n            p = v * (1 - s),\n            q = v * (1 - f * s),\n            t = v * (1 - (1 - f) * s),\n            mod = i % 6,\n            r = [v, q, p, p, t, v][mod],\n            g = [t, v, v, q, p, p][mod],\n            b = [p, p, t, v, v, q][mod];\n\n        return { r: r * 255, g: g * 255, b: b * 255 };\n    }\n\n    // `rgbToHex`\n    // Converts an RGB color to hex\n    // Assumes r, g, and b are contained in the set [0, 255]\n    // Returns a 3 or 6 character hex\n    function rgbToHex(r, g, b, allow3Char) {\n\n        var hex = [\n            pad2(mathRound(r).toString(16)),\n            pad2(mathRound(g).toString(16)),\n            pad2(mathRound(b).toString(16))\n        ];\n\n        // Return a 3 character hex if possible\n        if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {\n            return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);\n        }\n\n        return hex.join(\"\");\n    }\n        // `rgbaToHex`\n        // Converts an RGBA color plus alpha transparency to hex\n        // Assumes r, g, b and a are contained in the set [0, 255]\n        // Returns an 8 character hex\n        function rgbaToHex(r, g, b, a) {\n\n            var hex = [\n                pad2(convertDecimalToHex(a)),\n                pad2(mathRound(r).toString(16)),\n                pad2(mathRound(g).toString(16)),\n                pad2(mathRound(b).toString(16))\n            ];\n\n            return hex.join(\"\");\n        }\n\n    // `equals`\n    // Can be called with any tinycolor input\n    tinycolor.equals = function (color1, color2) {\n        if (!color1 || !color2) { return false; }\n        return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();\n    };\n    tinycolor.random = function() {\n        return tinycolor.fromRatio({\n            r: mathRandom(),\n            g: mathRandom(),\n            b: mathRandom()\n        });\n    };\n\n\n    // Modification Functions\n    // ----------------------\n    // Thanks to less.js for some of the basics here\n    // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>\n\n    function desaturate(color, amount) {\n        amount = (amount === 0) ? 0 : (amount || 10);\n        var hsl = tinycolor(color).toHsl();\n        hsl.s -= amount / 100;\n        hsl.s = clamp01(hsl.s);\n        return tinycolor(hsl);\n    }\n\n    function saturate(color, amount) {\n        amount = (amount === 0) ? 0 : (amount || 10);\n        var hsl = tinycolor(color).toHsl();\n        hsl.s += amount / 100;\n        hsl.s = clamp01(hsl.s);\n        return tinycolor(hsl);\n    }\n\n    function greyscale(color) {\n        return tinycolor(color).desaturate(100);\n    }\n\n    function lighten (color, amount) {\n        amount = (amount === 0) ? 0 : (amount || 10);\n        var hsl = tinycolor(color).toHsl();\n        hsl.l += amount / 100;\n        hsl.l = clamp01(hsl.l);\n        return tinycolor(hsl);\n    }\n\n    function brighten(color, amount) {\n        amount = (amount === 0) ? 0 : (amount || 10);\n        var rgb = tinycolor(color).toRgb();\n        rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100))));\n        rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100))));\n        rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100))));\n        return tinycolor(rgb);\n    }\n\n    function darken (color, amount) {\n        amount = (amount === 0) ? 0 : (amount || 10);\n        var hsl = tinycolor(color).toHsl();\n        hsl.l -= amount / 100;\n        hsl.l = clamp01(hsl.l);\n        return tinycolor(hsl);\n    }\n\n    // Spin takes a positive or negative amount within [-360, 360] indicating the change of hue.\n    // Values outside of this range will be wrapped into this range.\n    function spin(color, amount) {\n        var hsl = tinycolor(color).toHsl();\n        var hue = (mathRound(hsl.h) + amount) % 360;\n        hsl.h = hue < 0 ? 360 + hue : hue;\n        return tinycolor(hsl);\n    }\n\n    // Combination Functions\n    // ---------------------\n    // Thanks to jQuery xColor for some of the ideas behind these\n    // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>\n\n    function complement(color) {\n        var hsl = tinycolor(color).toHsl();\n        hsl.h = (hsl.h + 180) % 360;\n        return tinycolor(hsl);\n    }\n\n    function triad(color) {\n        var hsl = tinycolor(color).toHsl();\n        var h = hsl.h;\n        return [\n            tinycolor(color),\n            tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),\n            tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })\n        ];\n    }\n\n    function tetrad(color) {\n        var hsl = tinycolor(color).toHsl();\n        var h = hsl.h;\n        return [\n            tinycolor(color),\n            tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),\n            tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),\n            tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })\n        ];\n    }\n\n    function splitcomplement(color) {\n        var hsl = tinycolor(color).toHsl();\n        var h = hsl.h;\n        return [\n            tinycolor(color),\n            tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),\n            tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})\n        ];\n    }\n\n    function analogous(color, results, slices) {\n        results = results || 6;\n        slices = slices || 30;\n\n        var hsl = tinycolor(color).toHsl();\n        var part = 360 / slices;\n        var ret = [tinycolor(color)];\n\n        for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {\n            hsl.h = (hsl.h + part) % 360;\n            ret.push(tinycolor(hsl));\n        }\n        return ret;\n    }\n\n    function monochromatic(color, results) {\n        results = results || 6;\n        var hsv = tinycolor(color).toHsv();\n        var h = hsv.h, s = hsv.s, v = hsv.v;\n        var ret = [];\n        var modification = 1 / results;\n\n        while (results--) {\n            ret.push(tinycolor({ h: h, s: s, v: v}));\n            v = (v + modification) % 1;\n        }\n\n        return ret;\n    }\n\n    // Utility Functions\n    // ---------------------\n\n    tinycolor.mix = function(color1, color2, amount) {\n        amount = (amount === 0) ? 0 : (amount || 50);\n\n        var rgb1 = tinycolor(color1).toRgb();\n        var rgb2 = tinycolor(color2).toRgb();\n\n        var p = amount / 100;\n        var w = p * 2 - 1;\n        var a = rgb2.a - rgb1.a;\n\n        var w1;\n\n        if (w * a == -1) {\n            w1 = w;\n        } else {\n            w1 = (w + a) / (1 + w * a);\n        }\n\n        w1 = (w1 + 1) / 2;\n\n        var w2 = 1 - w1;\n\n        var rgba = {\n            r: rgb2.r * w1 + rgb1.r * w2,\n            g: rgb2.g * w1 + rgb1.g * w2,\n            b: rgb2.b * w1 + rgb1.b * w2,\n            a: rgb2.a * p  + rgb1.a * (1 - p)\n        };\n\n        return tinycolor(rgba);\n    };\n\n\n    // Readability Functions\n    // ---------------------\n    // <http://www.w3.org/TR/AERT#color-contrast>\n\n    // `readability`\n    // Analyze the 2 colors and returns an object with the following properties:\n    //    `brightness`: difference in brightness between the two colors\n    //    `color`: difference in color/hue between the two colors\n    tinycolor.readability = function(color1, color2) {\n        var c1 = tinycolor(color1);\n        var c2 = tinycolor(color2);\n        var rgb1 = c1.toRgb();\n        var rgb2 = c2.toRgb();\n        var brightnessA = c1.getBrightness();\n        var brightnessB = c2.getBrightness();\n        var colorDiff = (\n            Math.max(rgb1.r, rgb2.r) - Math.min(rgb1.r, rgb2.r) +\n            Math.max(rgb1.g, rgb2.g) - Math.min(rgb1.g, rgb2.g) +\n            Math.max(rgb1.b, rgb2.b) - Math.min(rgb1.b, rgb2.b)\n        );\n\n        return {\n            brightness: Math.abs(brightnessA - brightnessB),\n            color: colorDiff\n        };\n    };\n\n    // `readable`\n    // http://www.w3.org/TR/AERT#color-contrast\n    // Ensure that foreground and background color combinations provide sufficient contrast.\n    // *Example*\n    //    tinycolor.isReadable(\"#000\", \"#111\") => false\n    tinycolor.isReadable = function(color1, color2) {\n        var readability = tinycolor.readability(color1, color2);\n        return readability.brightness > 125 && readability.color > 500;\n    };\n\n    // `mostReadable`\n    // Given a base color and a list of possible foreground or background\n    // colors for that base, returns the most readable color.\n    // *Example*\n    //    tinycolor.mostReadable(\"#123\", [\"#fff\", \"#000\"]) => \"#000\"\n    tinycolor.mostReadable = function(baseColor, colorList) {\n        var bestColor = null;\n        var bestScore = 0;\n        var bestIsReadable = false;\n        for (var i=0; i < colorList.length; i++) {\n\n            // We normalize both around the \"acceptable\" breaking point,\n            // but rank brightness constrast higher than hue.\n\n            var readability = tinycolor.readability(baseColor, colorList[i]);\n            var readable = readability.brightness > 125 && readability.color > 500;\n            var score = 3 * (readability.brightness / 125) + (readability.color / 500);\n\n            if ((readable && ! bestIsReadable) ||\n                (readable && bestIsReadable && score > bestScore) ||\n                ((! readable) && (! bestIsReadable) && score > bestScore)) {\n                bestIsReadable = readable;\n                bestScore = score;\n                bestColor = tinycolor(colorList[i]);\n            }\n        }\n        return bestColor;\n    };\n\n\n    // Big List of Colors\n    // ------------------\n    // <http://www.w3.org/TR/css3-color/#svg-color>\n    var names = tinycolor.names = {\n        aliceblue: \"f0f8ff\",\n        antiquewhite: \"faebd7\",\n        aqua: \"0ff\",\n        aquamarine: \"7fffd4\",\n        azure: \"f0ffff\",\n        beige: \"f5f5dc\",\n        bisque: \"ffe4c4\",\n        black: \"000\",\n        blanchedalmond: \"ffebcd\",\n        blue: \"00f\",\n        blueviolet: \"8a2be2\",\n        brown: \"a52a2a\",\n        burlywood: \"deb887\",\n        burntsienna: \"ea7e5d\",\n        cadetblue: \"5f9ea0\",\n        chartreuse: \"7fff00\",\n        chocolate: \"d2691e\",\n        coral: \"ff7f50\",\n        cornflowerblue: \"6495ed\",\n        cornsilk: \"fff8dc\",\n        crimson: \"dc143c\",\n        cyan: \"0ff\",\n        darkblue: \"00008b\",\n        darkcyan: \"008b8b\",\n        darkgoldenrod: \"b8860b\",\n        darkgray: \"a9a9a9\",\n        darkgreen: \"006400\",\n        darkgrey: \"a9a9a9\",\n        darkkhaki: \"bdb76b\",\n        darkmagenta: \"8b008b\",\n        darkolivegreen: \"556b2f\",\n        darkorange: \"ff8c00\",\n        darkorchid: \"9932cc\",\n        darkred: \"8b0000\",\n        darksalmon: \"e9967a\",\n        darkseagreen: \"8fbc8f\",\n        darkslateblue: \"483d8b\",\n        darkslategray: \"2f4f4f\",\n        darkslategrey: \"2f4f4f\",\n        darkturquoise: \"00ced1\",\n        darkviolet: \"9400d3\",\n        deeppink: \"ff1493\",\n        deepskyblue: \"00bfff\",\n        dimgray: \"696969\",\n        dimgrey: \"696969\",\n        dodgerblue: \"1e90ff\",\n        firebrick: \"b22222\",\n        floralwhite: \"fffaf0\",\n        forestgreen: \"228b22\",\n        fuchsia: \"f0f\",\n        gainsboro: \"dcdcdc\",\n        ghostwhite: \"f8f8ff\",\n        gold: \"ffd700\",\n        goldenrod: \"daa520\",\n        gray: \"808080\",\n        green: \"008000\",\n        greenyellow: \"adff2f\",\n        grey: \"808080\",\n        honeydew: \"f0fff0\",\n        hotpink: \"ff69b4\",\n        indianred: \"cd5c5c\",\n        indigo: \"4b0082\",\n        ivory: \"fffff0\",\n        khaki: \"f0e68c\",\n        lavender: \"e6e6fa\",\n        lavenderblush: \"fff0f5\",\n        lawngreen: \"7cfc00\",\n        lemonchiffon: \"fffacd\",\n        lightblue: \"add8e6\",\n        lightcoral: \"f08080\",\n        lightcyan: \"e0ffff\",\n        lightgoldenrodyellow: \"fafad2\",\n        lightgray: \"d3d3d3\",\n        lightgreen: \"90ee90\",\n        lightgrey: \"d3d3d3\",\n        lightpink: \"ffb6c1\",\n        lightsalmon: \"ffa07a\",\n        lightseagreen: \"20b2aa\",\n        lightskyblue: \"87cefa\",\n        lightslategray: \"789\",\n        lightslategrey: \"789\",\n        lightsteelblue: \"b0c4de\",\n        lightyellow: \"ffffe0\",\n        lime: \"0f0\",\n        limegreen: \"32cd32\",\n        linen: \"faf0e6\",\n        magenta: \"f0f\",\n        maroon: \"800000\",\n        mediumaquamarine: \"66cdaa\",\n        mediumblue: \"0000cd\",\n        mediumorchid: \"ba55d3\",\n        mediumpurple: \"9370db\",\n        mediumseagreen: \"3cb371\",\n        mediumslateblue: \"7b68ee\",\n        mediumspringgreen: \"00fa9a\",\n        mediumturquoise: \"48d1cc\",\n        mediumvioletred: \"c71585\",\n        midnightblue: \"191970\",\n        mintcream: \"f5fffa\",\n        mistyrose: \"ffe4e1\",\n        moccasin: \"ffe4b5\",\n        navajowhite: \"ffdead\",\n        navy: \"000080\",\n        oldlace: \"fdf5e6\",\n        olive: \"808000\",\n        olivedrab: \"6b8e23\",\n        orange: \"ffa500\",\n        orangered: \"ff4500\",\n        orchid: \"da70d6\",\n        palegoldenrod: \"eee8aa\",\n        palegreen: \"98fb98\",\n        paleturquoise: \"afeeee\",\n        palevioletred: \"db7093\",\n        papayawhip: \"ffefd5\",\n        peachpuff: \"ffdab9\",\n        peru: \"cd853f\",\n        pink: \"ffc0cb\",\n        plum: \"dda0dd\",\n        powderblue: \"b0e0e6\",\n        purple: \"800080\",\n        rebeccapurple: \"663399\",\n        red: \"f00\",\n        rosybrown: \"bc8f8f\",\n        royalblue: \"4169e1\",\n        saddlebrown: \"8b4513\",\n        salmon: \"fa8072\",\n        sandybrown: \"f4a460\",\n        seagreen: \"2e8b57\",\n        seashell: \"fff5ee\",\n        sienna: \"a0522d\",\n        silver: \"c0c0c0\",\n        skyblue: \"87ceeb\",\n        slateblue: \"6a5acd\",\n        slategray: \"708090\",\n        slategrey: \"708090\",\n        snow: \"fffafa\",\n        springgreen: \"00ff7f\",\n        steelblue: \"4682b4\",\n        tan: \"d2b48c\",\n        teal: \"008080\",\n        thistle: \"d8bfd8\",\n        tomato: \"ff6347\",\n        turquoise: \"40e0d0\",\n        violet: \"ee82ee\",\n        wheat: \"f5deb3\",\n        white: \"fff\",\n        whitesmoke: \"f5f5f5\",\n        yellow: \"ff0\",\n        yellowgreen: \"9acd32\"\n    };\n\n    // Make it easy to access colors via `hexNames[hex]`\n    var hexNames = tinycolor.hexNames = flip(names);\n\n\n    // Utilities\n    // ---------\n\n    // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`\n    function flip(o) {\n        var flipped = { };\n        for (var i in o) {\n            if (o.hasOwnProperty(i)) {\n                flipped[o[i]] = i;\n            }\n        }\n        return flipped;\n    }\n\n    // Return a valid alpha value [0,1] with all invalid values being set to 1\n    function boundAlpha(a) {\n        a = parseFloat(a);\n\n        if (isNaN(a) || a < 0 || a > 1) {\n            a = 1;\n        }\n\n        return a;\n    }\n\n    // Take input from [0, n] and return it as [0, 1]\n    function bound01(n, max) {\n        if (isOnePointZero(n)) { n = \"100%\"; }\n\n        var processPercent = isPercentage(n);\n        n = mathMin(max, mathMax(0, parseFloat(n)));\n\n        // Automatically convert percentage into number\n        if (processPercent) {\n            n = parseInt(n * max, 10) / 100;\n        }\n\n        // Handle floating point rounding errors\n        if ((math.abs(n - max) < 0.000001)) {\n            return 1;\n        }\n\n        // Convert into [0, 1] range if it isn't already\n        return (n % max) / parseFloat(max);\n    }\n\n    // Force a number between 0 and 1\n    function clamp01(val) {\n        return mathMin(1, mathMax(0, val));\n    }\n\n    // Parse a base-16 hex value into a base-10 integer\n    function parseIntFromHex(val) {\n        return parseInt(val, 16);\n    }\n\n    // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1\n    // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>\n    function isOnePointZero(n) {\n        return typeof n == \"string\" && n.indexOf('.') != -1 && parseFloat(n) === 1;\n    }\n\n    // Check to see if string passed in is a percentage\n    function isPercentage(n) {\n        return typeof n === \"string\" && n.indexOf('%') != -1;\n    }\n\n    // Force a hex value to have 2 characters\n    function pad2(c) {\n        return c.length == 1 ? '0' + c : '' + c;\n    }\n\n    // Replace a decimal with it's percentage value\n    function convertToPercentage(n) {\n        if (n <= 1) {\n            n = (n * 100) + \"%\";\n        }\n\n        return n;\n    }\n\n    // Converts a decimal to a hex value\n    function convertDecimalToHex(d) {\n        return Math.round(parseFloat(d) * 255).toString(16);\n    }\n    // Converts a hex value to a decimal\n    function convertHexToDecimal(h) {\n        return (parseIntFromHex(h) / 255);\n    }\n\n    var matchers = (function() {\n\n        // <http://www.w3.org/TR/css3-values/#integers>\n        var CSS_INTEGER = \"[-\\\\+]?\\\\d+%?\";\n\n        // <http://www.w3.org/TR/css3-values/#number-value>\n        var CSS_NUMBER = \"[-\\\\+]?\\\\d*\\\\.\\\\d+%?\";\n\n        // Allow positive/negative integer/number.  Don't capture the either/or, just the entire outcome.\n        var CSS_UNIT = \"(?:\" + CSS_NUMBER + \")|(?:\" + CSS_INTEGER + \")\";\n\n        // Actual matching.\n        // Parentheses and commas are optional, but not required.\n        // Whitespace can take the place of commas or opening paren\n        var PERMISSIVE_MATCH3 = \"[\\\\s|\\\\(]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")\\\\s*\\\\)?\";\n        var PERMISSIVE_MATCH4 = \"[\\\\s|\\\\(]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")\\\\s*\\\\)?\";\n\n        return {\n            rgb: new RegExp(\"rgb\" + PERMISSIVE_MATCH3),\n            rgba: new RegExp(\"rgba\" + PERMISSIVE_MATCH4),\n            hsl: new RegExp(\"hsl\" + PERMISSIVE_MATCH3),\n            hsla: new RegExp(\"hsla\" + PERMISSIVE_MATCH4),\n            hsv: new RegExp(\"hsv\" + PERMISSIVE_MATCH3),\n            hsva: new RegExp(\"hsva\" + PERMISSIVE_MATCH4),\n            hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,\n            hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,\n            hex8: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/\n        };\n    })();\n\n    // `stringInputToObject`\n    // Permissive string parsing.  Take in a number of formats, and output an object\n    // based on detected format.  Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`\n    function stringInputToObject(color) {\n\n        color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase();\n        var named = false;\n        if (names[color]) {\n            color = names[color];\n            named = true;\n        }\n        else if (color == 'transparent') {\n            return { r: 0, g: 0, b: 0, a: 0, format: \"name\" };\n        }\n\n        // Try to match string input using regular expressions.\n        // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]\n        // Just return an object and let the conversion functions handle that.\n        // This way the result will be the same whether the tinycolor is initialized with string or object.\n        var match;\n        if ((match = matchers.rgb.exec(color))) {\n            return { r: match[1], g: match[2], b: match[3] };\n        }\n        if ((match = matchers.rgba.exec(color))) {\n            return { r: match[1], g: match[2], b: match[3], a: match[4] };\n        }\n        if ((match = matchers.hsl.exec(color))) {\n            return { h: match[1], s: match[2], l: match[3] };\n        }\n        if ((match = matchers.hsla.exec(color))) {\n            return { h: match[1], s: match[2], l: match[3], a: match[4] };\n        }\n        if ((match = matchers.hsv.exec(color))) {\n            return { h: match[1], s: match[2], v: match[3] };\n        }\n        if ((match = matchers.hsva.exec(color))) {\n            return { h: match[1], s: match[2], v: match[3], a: match[4] };\n        }\n        if ((match = matchers.hex8.exec(color))) {\n            return {\n                a: convertHexToDecimal(match[1]),\n                r: parseIntFromHex(match[2]),\n                g: parseIntFromHex(match[3]),\n                b: parseIntFromHex(match[4]),\n                format: named ? \"name\" : \"hex8\"\n            };\n        }\n        if ((match = matchers.hex6.exec(color))) {\n            return {\n                r: parseIntFromHex(match[1]),\n                g: parseIntFromHex(match[2]),\n                b: parseIntFromHex(match[3]),\n                format: named ? \"name\" : \"hex\"\n            };\n        }\n        if ((match = matchers.hex3.exec(color))) {\n            return {\n                r: parseIntFromHex(match[1] + '' + match[1]),\n                g: parseIntFromHex(match[2] + '' + match[2]),\n                b: parseIntFromHex(match[3] + '' + match[3]),\n                format: named ? \"name\" : \"hex\"\n            };\n        }\n\n        return false;\n    }\n\n    window.tinycolor = tinycolor;\n    })();\n\n    $(function () {\n        if ($.fn.spectrum.load) {\n            $.fn.spectrum.processNativeColorInputs();\n        }\n    });\n\n});"
  },
  {
    "path": "lib/timer.js",
    "content": ""
  },
  {
    "path": "lib/two.js",
    "content": "/**\n * two.js\n * a two-dimensional drawing api meant for modern browsers. It is renderer\n * agnostic enabling the same api for rendering in multiple contexts: webgl,\n * canvas2d, and svg.\n *\n * Copyright (c) 2012 - 2017 jonobr1 / http://jonobr1.com\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\nthis.Two = (function(previousTwo) {\n\n  var root = typeof window != 'undefined' ? window : typeof global != 'undefined' ? global : null;\n  var _ = {\n    // http://underscorejs.org/ • 1.8.3\n    _indexAmount: 0,\n    natural: {\n      slice: Array.prototype.slice,\n      indexOf: Array.prototype.indexOf,\n      keys: Object.keys,\n      bind: Function.prototype.bind,\n      create: Object.create\n    },\n    identity: function(value) {\n      return value;\n    },\n    isArguments: function(obj) {\n      return toString.call(obj) === '[object Arguments]';\n    },\n    isFunction: function(obj) {\n      return toString.call(obj) === '[object Function]';\n    },\n    isString: function(obj) {\n      return toString.call(obj) === '[object String]';\n    },\n    isNumber: function(obj) {\n      return toString.call(obj) === '[object Number]';\n    },\n    isDate: function(obj) {\n      return toString.call(obj) === '[object Date]';\n    },\n    isRegExp: function(obj) {\n      return toString.call(obj) === '[object RegExp]';\n    },\n    isError: function(obj) {\n      return toString.call(obj) === '[object Error]';\n    },\n    isFinite: function(obj) {\n      return isFinite(obj) && !isNaN(parseFloat(obj));\n    },\n    isNaN: function(obj) {\n      return _.isNumber(obj) && obj !== +obj;\n    },\n    isBoolean: function(obj) {\n      return obj === true || obj === false || toString.call(obj) === '[object Boolean]';\n    },\n    isNull: function(obj) {\n      return obj === null;\n    },\n    isUndefined: function(obj) {\n      return obj === void 0;\n    },\n    isEmpty: function(obj) {\n      if (obj == null) return true;\n      if (isArrayLike && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;\n      return _.keys(obj).length === 0;\n    },\n    isElement: function(obj) {\n      return !!(obj && obj.nodeType === 1);\n    },\n    isArray: Array.isArray || function(obj) {\n      return toString.call(obj) === '[object Array]';\n    },\n    isObject: function(obj) {\n      var type = typeof obj;\n      return type === 'function' || type === 'object' && !!obj;\n    },\n    toArray: function(obj) {\n      if (!obj) {\n        return [];\n      }\n      if (_.isArray(obj)) {\n        return slice.call(obj);\n      }\n      if (isArrayLike(obj)) {\n        return _.map(obj, _.identity);\n      }\n      return _.values(obj);\n    },\n    range: function(start, stop, step) {\n      if (stop == null) {\n        stop = start || 0;\n        start = 0;\n      }\n      step = step || 1;\n\n      var length = Math.max(Math.ceil((stop - start) / step), 0);\n      var range = Array(length);\n\n      for (var idx = 0; idx < length; idx++, start += step) {\n        range[idx] = start;\n      }\n\n      return range;\n    },\n    indexOf: function(list, item) {\n      if (!!_.natural.indexOf) {\n        return _.natural.indexOf.call(list, item);\n      }\n      for (var i = 0; i < list.length; i++) {\n        if (list[i] === item) {\n          return i;\n        }\n      }\n      return -1;\n    },\n    has: function(obj, key) {\n      return obj != null && hasOwnProperty.call(obj, key);\n    },\n    bind: function(func, ctx) {\n      var natural = _.natural.bind;\n      if (natural && func.bind === natural) {\n        return natural.apply(func, slice.call(arguments, 1));\n      }\n      var args = slice.call(arguments, 2);\n      return function() {\n        func.apply(ctx, args);\n      };\n    },\n    extend: function(base) {\n      var sources = slice.call(arguments, 1);\n      for (var i = 0; i < sources.length; i++) {\n        var obj = sources[i];\n        for (var k in obj) {\n          base[k] = obj[k];\n        }\n      }\n      return base;\n    },\n    defaults: function(base) {\n      var sources = slice.call(arguments, 1);\n      for (var i = 0; i < sources.length; i++) {\n        var obj = sources[i];\n        for (var k in obj) {\n          if (base[k] === void 0) {\n            base[k] = obj[k];\n          }\n        }\n      }\n      return base;\n    },\n    keys: function(obj) {\n      if (!_.isObject(obj)) {\n        return [];\n      }\n      if (_.natural.keys) {\n        return _.natural.keys(obj);\n      }\n      var keys = [];\n      for (var k in obj) {\n        if (_.has(obj, k)) {\n          keys.push(k);\n        }\n      }\n      return keys;\n    },\n    values: function(obj) {\n      var keys = _.keys(obj);\n      var values = [];\n      for (var i = 0; i < keys.length; i++) {\n        var k = keys[i];\n        values.push(obj[k]);\n      }\n      return values;\n    },\n    each: function(obj, iteratee, context) {\n      var ctx = context || this;\n      var keys = !isArrayLike(obj) && _.keys(obj);\n      var length = (keys || obj).length;\n      for (var i = 0; i < length; i++) {\n        var k = keys ? keys[i] : i;\n        iteratee.call(ctx, obj[k], k, obj);\n      }\n      return obj;\n    },\n    map: function(obj, iteratee, context) {\n      var ctx = context || this;\n      var keys = !isArrayLike(obj) && _.keys(obj);\n      var length = (keys || obj).length;\n      var result = [];\n      for (var i = 0; i < length; i++) {\n        var k = keys ? keys[i] : i;\n        result[i] = iteratee.call(ctx, obj[k], k, obj);\n      }\n      return result;\n    },\n    once: function(func) {\n      var init = false;\n      return function() {\n        if (!!init) {\n          return func;\n        }\n        init = true;\n        return func.apply(this, arguments);\n      }\n    },\n    after: function(times, func) {\n      return function() {\n        while (--times < 1) {\n          return func.apply(this, arguments);\n        }\n      }\n    },\n    uniqueId: function(prefix) {\n      var id = ++_._indexAmount + '';\n      return prefix ? prefix + id : id;\n    }\n  };\n\n  /**\n   * Constants\n   */\n\n  var sin = Math.sin,\n    cos = Math.cos,\n    atan2 = Math.atan2,\n    sqrt = Math.sqrt,\n    round = Math.round,\n    abs = Math.abs,\n    PI = Math.PI,\n    TWO_PI = PI * 2,\n    HALF_PI = PI / 2,\n    pow = Math.pow,\n    min = Math.min,\n    max = Math.max;\n\n  /**\n   * Localized variables\n   */\n\n  var count = 0;\n  var slice = _.natural.slice;\n  var perf = ((root.performance && root.performance.now) ? root.performance : Date);\n  var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;\n  var getLength = function(obj) {\n    return obj == null ? void 0 : obj['length'];\n  };\n  var isArrayLike = function(collection) {\n    var length = getLength(collection);\n    return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;\n  };\n\n  /**\n   * Cross browser dom events.\n   */\n  var dom = {\n\n    temp: (root.document ? root.document.createElement('div') : {}),\n\n    hasEventListeners: _.isFunction(root.addEventListener),\n\n    bind: function(elem, event, func, bool) {\n      if (this.hasEventListeners) {\n        elem.addEventListener(event, func, !!bool);\n      } else {\n        elem.attachEvent('on' + event, func);\n      }\n      return dom;\n    },\n\n    unbind: function(elem, event, func, bool) {\n      if (dom.hasEventListeners) {\n        elem.removeEventListeners(event, func, !!bool);\n      } else {\n        elem.detachEvent('on' + event, func);\n      }\n      return dom;\n    },\n\n    getRequestAnimationFrame: function() {\n\n      var lastTime = 0;\n      var vendors = ['ms', 'moz', 'webkit', 'o'];\n      var request = root.requestAnimationFrame, cancel;\n\n      if(!request) {\n        for (var i = 0; i < vendors.length; i++) {\n          request = root[vendors[i] + 'RequestAnimationFrame'] || request;\n          cancel = root[vendors[i] + 'CancelAnimationFrame']\n            || root[vendors[i] + 'CancelRequestAnimationFrame'] || cancel;\n        }\n\n        request = request || function(callback, element) {\n          var currTime = new Date().getTime();\n          var timeToCall = Math.max(0, 16 - (currTime - lastTime));\n          var id = root.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall);\n          lastTime = currTime + timeToCall;\n          return id;\n        };\n        // cancel = cancel || function(id) {\n        //   clearTimeout(id);\n        // };\n      }\n\n      request.init = _.once(loop);\n\n      return request;\n\n    }\n\n  };\n\n  /**\n   * @class\n   */\n  var Two = root.Two = function(options) {\n\n    // Determine what Renderer to use and setup a scene.\n\n    var params = _.defaults(options || {}, {\n      fullscreen: false,\n      width: 640,\n      height: 480,\n      type: Two.Types.svg,\n      autostart: false\n    });\n\n    _.each(params, function(v, k) {\n      if (k === 'fullscreen' || k === 'autostart') {\n        return;\n      }\n      this[k] = v;\n    }, this);\n\n    // Specified domElement overrides type declaration only if the element does not support declared renderer type.\n    if (_.isElement(params.domElement)) {\n      var tagName = params.domElement.tagName.toLowerCase();\n      // TODO: Reconsider this if statement's logic.\n      if (!/^(CanvasRenderer-canvas|WebGLRenderer-canvas|SVGRenderer-svg)$/.test(this.type+'-'+tagName)) {\n        this.type = Two.Types[tagName];\n      }\n    }\n\n    this.renderer = new Two[this.type](this);\n    Two.Utils.setPlaying.call(this, params.autostart);\n    this.frameCount = 0;\n\n    if (params.fullscreen) {\n\n      var fitted = _.bind(fitToWindow, this);\n      _.extend(document.body.style, {\n        overflow: 'hidden',\n        margin: 0,\n        padding: 0,\n        top: 0,\n        left: 0,\n        right: 0,\n        bottom: 0,\n        position: 'fixed'\n      });\n      _.extend(this.renderer.domElement.style, {\n        display: 'block',\n        top: 0,\n        left: 0,\n        right: 0,\n        bottom: 0,\n        position: 'fixed'\n      });\n      dom.bind(root, 'resize', fitted);\n      fitted();\n\n\n    } else if (!_.isElement(params.domElement)) {\n\n      this.renderer.setSize(params.width, params.height, this.ratio);\n      this.width = params.width;\n      this.height = params.height;\n\n    }\n\n    this.scene = this.renderer.scene;\n\n    Two.Instances.push(this);\n    raf.init();\n\n  };\n\n  _.extend(Two, {\n\n    /**\n     * Access to root in other files.\n     */\n\n    root: root,\n\n    /**\n     * Primitive\n     */\n\n    Array: root.Float32Array || Array,\n\n    Types: {\n      webgl: 'WebGLRenderer',\n      svg: 'SVGRenderer',\n      canvas: 'CanvasRenderer'\n    },\n\n    Version: 'v0.7.0',\n\n    Identifier: 'two_',\n\n    Properties: {\n      hierarchy: 'hierarchy',\n      demotion: 'demotion'\n    },\n\n    Events: {\n      play: 'play',\n      pause: 'pause',\n      update: 'update',\n      render: 'render',\n      resize: 'resize',\n      change: 'change',\n      remove: 'remove',\n      insert: 'insert',\n      order: 'order',\n      load: 'load'\n    },\n\n    Commands: {\n      move: 'M',\n      line: 'L',\n      curve: 'C',\n      close: 'Z'\n    },\n\n    Resolution: 8,\n\n    Instances: [],\n\n    noConflict: function() {\n      root.Two = previousTwo;\n      return this;\n    },\n\n    uniqueId: function() {\n      var id = count;\n      count++;\n      return id;\n    },\n\n    Utils: _.extend(_, {\n\n      performance: perf,\n\n      defineProperty: function(property) {\n\n        var object = this;\n        var secret = '_' + property;\n        var flag = '_flag' + property.charAt(0).toUpperCase() + property.slice(1);\n\n        Object.defineProperty(object, property, {\n          enumerable: true,\n          get: function() {\n            return this[secret];\n          },\n          set: function(v) {\n            this[secret] = v;\n            this[flag] = true;\n          }\n        });\n\n      },\n\n      /**\n       * Release an arbitrary class' events from the two.js corpus and recurse\n       * through its children and or vertices.\n       */\n      release: function(obj) {\n\n        if (!_.isObject(obj)) {\n          return;\n        }\n\n        if (_.isFunction(obj.unbind)) {\n          obj.unbind();\n        }\n\n        if (obj.vertices) {\n          if (_.isFunction(obj.vertices.unbind)) {\n            obj.vertices.unbind();\n          }\n          _.each(obj.vertices, function(v) {\n            if (_.isFunction(v.unbind)) {\n              v.unbind();\n            }\n          });\n        }\n\n        if (obj.children) {\n          _.each(obj.children, function(obj) {\n            Two.Utils.release(obj);\n          });\n        }\n\n      },\n\n      xhr: function(path, callback) {\n\n        var xhr = new XMLHttpRequest();\n        xhr.open('GET', path);\n\n        xhr.onreadystatechange = function() {\n          if (xhr.readyState === 4 && xhr.status === 200) {\n            callback(xhr.responseText);\n          }\n        };\n\n        xhr.send();\n        return xhr;\n\n      },\n\n      Curve: {\n\n        CollinearityEpsilon: pow(10, -30),\n\n        RecursionLimit: 16,\n\n        CuspLimit: 0,\n\n        Tolerance: {\n          distance: 0.25,\n          angle: 0,\n          epsilon: 0.01\n        },\n\n        // Lookup tables for abscissas and weights with values for n = 2 .. 16.\n        // As values are symmetric, only store half of them and adapt algorithm\n        // to factor in symmetry.\n        abscissas: [\n          [  0.5773502691896257645091488],\n          [0,0.7745966692414833770358531],\n          [  0.3399810435848562648026658,0.8611363115940525752239465],\n          [0,0.5384693101056830910363144,0.9061798459386639927976269],\n          [  0.2386191860831969086305017,0.6612093864662645136613996,0.9324695142031520278123016],\n          [0,0.4058451513773971669066064,0.7415311855993944398638648,0.9491079123427585245261897],\n          [  0.1834346424956498049394761,0.5255324099163289858177390,0.7966664774136267395915539,0.9602898564975362316835609],\n          [0,0.3242534234038089290385380,0.6133714327005903973087020,0.8360311073266357942994298,0.9681602395076260898355762],\n          [  0.1488743389816312108848260,0.4333953941292471907992659,0.6794095682990244062343274,0.8650633666889845107320967,0.9739065285171717200779640],\n          [0,0.2695431559523449723315320,0.5190961292068118159257257,0.7301520055740493240934163,0.8870625997680952990751578,0.9782286581460569928039380],\n          [  0.1252334085114689154724414,0.3678314989981801937526915,0.5873179542866174472967024,0.7699026741943046870368938,0.9041172563704748566784659,0.9815606342467192506905491],\n          [0,0.2304583159551347940655281,0.4484927510364468528779129,0.6423493394403402206439846,0.8015780907333099127942065,0.9175983992229779652065478,0.9841830547185881494728294],\n          [  0.1080549487073436620662447,0.3191123689278897604356718,0.5152486363581540919652907,0.6872929048116854701480198,0.8272013150697649931897947,0.9284348836635735173363911,0.9862838086968123388415973],\n          [0,0.2011940939974345223006283,0.3941513470775633698972074,0.5709721726085388475372267,0.7244177313601700474161861,0.8482065834104272162006483,0.9372733924007059043077589,0.9879925180204854284895657],\n          [  0.0950125098376374401853193,0.2816035507792589132304605,0.4580167776572273863424194,0.6178762444026437484466718,0.7554044083550030338951012,0.8656312023878317438804679,0.9445750230732325760779884,0.9894009349916499325961542]\n        ],\n\n        weights: [\n          [1],\n          [0.8888888888888888888888889,0.5555555555555555555555556],\n          [0.6521451548625461426269361,0.3478548451374538573730639],\n          [0.5688888888888888888888889,0.4786286704993664680412915,0.2369268850561890875142640],\n          [0.4679139345726910473898703,0.3607615730481386075698335,0.1713244923791703450402961],\n          [0.4179591836734693877551020,0.3818300505051189449503698,0.2797053914892766679014678,0.1294849661688696932706114],\n          [0.3626837833783619829651504,0.3137066458778872873379622,0.2223810344533744705443560,0.1012285362903762591525314],\n          [0.3302393550012597631645251,0.3123470770400028400686304,0.2606106964029354623187429,0.1806481606948574040584720,0.0812743883615744119718922],\n          [0.2955242247147528701738930,0.2692667193099963550912269,0.2190863625159820439955349,0.1494513491505805931457763,0.0666713443086881375935688],\n          [0.2729250867779006307144835,0.2628045445102466621806889,0.2331937645919904799185237,0.1862902109277342514260976,0.1255803694649046246346943,0.0556685671161736664827537],\n          [0.2491470458134027850005624,0.2334925365383548087608499,0.2031674267230659217490645,0.1600783285433462263346525,0.1069393259953184309602547,0.0471753363865118271946160],\n          [0.2325515532308739101945895,0.2262831802628972384120902,0.2078160475368885023125232,0.1781459807619457382800467,0.1388735102197872384636018,0.0921214998377284479144218,0.0404840047653158795200216],\n          [0.2152638534631577901958764,0.2051984637212956039659241,0.1855383974779378137417166,0.1572031671581935345696019,0.1215185706879031846894148,0.0801580871597602098056333,0.0351194603317518630318329],\n          [0.2025782419255612728806202,0.1984314853271115764561183,0.1861610000155622110268006,0.1662692058169939335532009,0.1395706779261543144478048,0.1071592204671719350118695,0.0703660474881081247092674,0.0307532419961172683546284],\n          [0.1894506104550684962853967,0.1826034150449235888667637,0.1691565193950025381893121,0.1495959888165767320815017,0.1246289712555338720524763,0.0951585116824927848099251,0.0622535239386478928628438,0.0271524594117540948517806]\n        ]\n\n      },\n\n      /**\n       * Account for high dpi rendering.\n       * http://www.html5rocks.com/en/tutorials/canvas/hidpi/\n       */\n\n      devicePixelRatio: root.devicePixelRatio || 1,\n\n      getBackingStoreRatio: function(ctx) {\n        return ctx.webkitBackingStorePixelRatio ||\n          ctx.mozBackingStorePixelRatio ||\n          ctx.msBackingStorePixelRatio ||\n          ctx.oBackingStorePixelRatio ||\n          ctx.backingStorePixelRatio || 1;\n      },\n\n      getRatio: function(ctx) {\n        return Two.Utils.devicePixelRatio / getBackingStoreRatio(ctx);\n      },\n\n      /**\n       * Properly defer play calling until after all objects\n       * have been updated with their newest styles.\n       */\n      setPlaying: function(b) {\n\n        this.playing = !!b;\n        return this;\n\n      },\n\n      /**\n       * Return the computed matrix of a nested object.\n       * TODO: Optimize traversal.\n       */\n      getComputedMatrix: function(object, matrix) {\n\n        matrix = (matrix && matrix.identity()) || new Two.Matrix();\n        var parent = object, matrices = [];\n\n        while (parent && parent._matrix) {\n          matrices.push(parent._matrix);\n          parent = parent.parent;\n        }\n\n        matrices.reverse();\n\n        _.each(matrices, function(m) {\n\n          var e = m.elements;\n          matrix.multiply(\n            e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7], e[8], e[9]);\n\n        });\n\n        return matrix;\n\n      },\n\n      deltaTransformPoint: function(matrix, x, y) {\n\n        var dx = x * matrix.a + y * matrix.c + 0;\n        var dy = x * matrix.b + y * matrix.d + 0;\n\n        return new Two.Vector(dx, dy);\n\n      },\n\n      /**\n       * https://gist.github.com/2052247\n       */\n      decomposeMatrix: function(matrix) {\n\n        // calculate delta transform point\n        var px = Two.Utils.deltaTransformPoint(matrix, 0, 1);\n        var py = Two.Utils.deltaTransformPoint(matrix, 1, 0);\n\n        // calculate skew\n        var skewX = ((180 / Math.PI) * Math.atan2(px.y, px.x) - 90);\n        var skewY = ((180 / Math.PI) * Math.atan2(py.y, py.x));\n\n        return {\n            translateX: matrix.e,\n            translateY: matrix.f,\n            scaleX: Math.sqrt(matrix.a * matrix.a + matrix.b * matrix.b),\n            scaleY: Math.sqrt(matrix.c * matrix.c + matrix.d * matrix.d),\n            skewX: skewX,\n            skewY: skewY,\n            rotation: skewX // rotation is the same as skew x\n        };\n\n      },\n\n      /**\n       * Walk through item properties and pick the ones of interest.\n       * Will try to resolve styles applied via CSS\n       *\n       * TODO: Reverse calculate `Two.Gradient`s for fill / stroke\n       * of any given path.\n       */\n      applySvgAttributes: function(node, elem) {\n\n        var attributes = {}, styles = {}, i, key, value, attr;\n\n        // Not available in non browser environments\n        if (getComputedStyle) {\n          // Convert CSSStyleDeclaration to a normal object\n          var computedStyles = getComputedStyle(node);\n          i = computedStyles.length;\n\n          while (i--) {\n            key = computedStyles[i];\n            value = computedStyles[key];\n            // Gecko returns undefined for unset properties\n            // Webkit returns the default value\n            if (value !== undefined) {\n              styles[key] = value;\n            }\n          }\n        }\n\n        // Convert NodeMap to a normal object\n        i = node.attributes.length;\n        while (i--) {\n          attr = node.attributes[i];\n          attributes[attr.nodeName] = attr.value;\n        }\n\n        // Getting the correct opacity is a bit tricky, since SVG path elements don't\n        // support opacity as an attribute, but you can apply it via CSS.\n        // So we take the opacity and set (stroke/fill)-opacity to the same value.\n        if (!_.isUndefined(styles.opacity)) {\n          styles['stroke-opacity'] = styles.opacity;\n          styles['fill-opacity'] = styles.opacity;\n        }\n\n        // Merge attributes and applied styles (attributes take precedence)\n        _.extend(styles, attributes);\n\n        // Similarly visibility is influenced by the value of both display and visibility.\n        // Calculate a unified value here which defaults to `true`.\n        styles.visible = !(_.isUndefined(styles.display) && styles.display === 'none')\n          || (_.isUndefined(styles.visibility) && styles.visibility === 'hidden');\n\n        // Now iterate the whole thing\n        for (key in styles) {\n          value = styles[key];\n\n          switch (key) {\n            case 'transform':\n              // TODO: Check this out https://github.com/paperjs/paper.js/blob/master/src/svg/SVGImport.js#L313\n              if (value === 'none') break;\n              var m = node.getCTM ? node.getCTM() : null;\n\n              // Might happen when transform string is empty or not valid.\n              if (m === null) break;\n\n              // // Option 1: edit the underlying matrix and don't force an auto calc.\n              // var m = node.getCTM();\n              // elem._matrix.manual = true;\n              // elem._matrix.set(m.a, m.b, m.c, m.d, m.e, m.f);\n\n              // Option 2: Decompose and infer Two.js related properties.\n              var transforms = Two.Utils.decomposeMatrix(node.getCTM());\n\n              elem.translation.set(transforms.translateX, transforms.translateY);\n              elem.rotation = transforms.rotation;\n              // Warning: Two.js elements only support uniform scalars...\n              elem.scale = transforms.scaleX;\n\n              var x = parseFloat((styles.x + '').replace('px'));\n              var y = parseFloat((styles.y + '').replace('px'));\n\n              // Override based on attributes.\n              if (x) {\n                elem.translation.x = x;\n              }\n\n              if (y) {\n                elem.translation.y = y;\n              }\n\n              break;\n            case 'visible':\n              elem.visible = value;\n              break;\n            case 'stroke-linecap':\n              elem.cap = value;\n              break;\n            case 'stroke-linejoin':\n              elem.join = value;\n              break;\n            case 'stroke-miterlimit':\n              elem.miter = value;\n              break;\n            case 'stroke-width':\n              elem.linewidth = parseFloat(value);\n              break;\n            case 'stroke-opacity':\n            case 'fill-opacity':\n            case 'opacity':\n              elem.opacity = parseFloat(value);\n              break;\n            case 'fill':\n            case 'stroke':\n              if (/url\\(\\#.*\\)/i.test(value)) {\n                elem[key] = this.getById(\n                  value.replace(/url\\(\\#(.*)\\)/i, '$1'));\n              } else {\n                elem[key] = (value === 'none') ? 'transparent' : value;\n              }\n              break;\n            case 'id':\n              elem.id = value;\n              break;\n            case 'class':\n              elem.classList = value.split(' ');\n              break;\n          }\n        }\n\n        return elem;\n\n      },\n\n      /**\n       * Read any number of SVG node types and create Two equivalents of them.\n       */\n      read: {\n\n        svg: function() {\n          return Two.Utils.read.g.apply(this, arguments);\n        },\n\n        g: function(node) {\n\n          var group = new Two.Group();\n\n          // Switched up order to inherit more specific styles\n          Two.Utils.applySvgAttributes.call(this, node, group);\n\n          for (var i = 0, l = node.childNodes.length; i < l; i++) {\n            var n = node.childNodes[i];\n            var tag = n.nodeName;\n            if (!tag) return;\n\n            var tagName = tag.replace(/svg\\:/ig, '').toLowerCase();\n\n            if (tagName in Two.Utils.read) {\n              var o = Two.Utils.read[tagName].call(group, n);\n              group.add(o);\n            }\n          }\n\n          return group;\n\n        },\n\n        polygon: function(node, open) {\n\n          var points = node.getAttribute('points');\n\n          var verts = [];\n          points.replace(/(-?[\\d\\.?]+)[,|\\s](-?[\\d\\.?]+)/g, function(match, p1, p2) {\n            verts.push(new Two.Anchor(parseFloat(p1), parseFloat(p2)));\n          });\n\n          var poly = new Two.Path(verts, !open).noStroke();\n          poly.fill = 'black';\n\n          return Two.Utils.applySvgAttributes.call(this, node, poly);\n\n        },\n\n        polyline: function(node) {\n          return Two.Utils.read.polygon.call(this, node, true);\n        },\n\n        path: function(node) {\n\n          var path = node.getAttribute('d');\n\n          // Create a Two.Path from the paths.\n\n          var coord = new Two.Anchor();\n          var control, coords;\n          var closed = false, relative = false;\n          var commands = path.match(/[a-df-z][^a-df-z]*/ig);\n          var last = commands.length - 1;\n\n          // Split up polybeziers\n\n          _.each(commands.slice(0), function(command, i) {\n\n            var type = command[0];\n            var lower = type.toLowerCase();\n            var items = command.slice(1).trim().split(/[\\s,]+|(?=\\s?[+\\-])/);\n            var pre, post, result = [], bin;\n\n            if (i <= 0) {\n              commands = [];\n            }\n\n            switch (lower) {\n              case 'h':\n              case 'v':\n                if (items.length > 1) {\n                  bin = 1;\n                }\n                break;\n              case 'm':\n              case 'l':\n              case 't':\n                if (items.length > 2) {\n                  bin = 2;\n                }\n                break;\n              case 's':\n              case 'q':\n                if (items.length > 4) {\n                  bin = 4;\n                }\n                break;\n              case 'c':\n                if (items.length > 6) {\n                  bin = 6;\n                }\n                break;\n              case 'a':\n                // TODO: Handle Ellipses\n                break;\n            }\n\n            if (bin) {\n\n              for (var j = 0, l = items.length, times = 0; j < l; j+=bin) {\n\n                var ct = type;\n                if (times > 0) {\n\n                  switch (type) {\n                    case 'm':\n                      ct = 'l';\n                      break;\n                    case 'M':\n                      ct = 'L';\n                      break;\n                  }\n\n                }\n\n                result.push([ct].concat(items.slice(j, j + bin)).join(' '));\n                times++;\n\n              }\n\n              commands = Array.prototype.concat.apply(commands, result);\n\n            } else {\n\n              commands.push(command);\n\n            }\n\n          });\n\n          // Create the vertices for our Two.Path\n\n          var points = [];\n          _.each(commands, function(command, i) {\n\n            var result, x, y;\n            var type = command[0];\n            var lower = type.toLowerCase();\n\n            coords = command.slice(1).trim();\n            coords = coords.replace(/(-?\\d+(?:\\.\\d*)?)[eE]([+\\-]?\\d+)/g, function(match, n1, n2) {\n              return parseFloat(n1) * pow(10, n2);\n            });\n            coords = coords.split(/[\\s,]+|(?=\\s?[+\\-])/);\n            relative = type === lower;\n\n            var x1, y1, x2, y2, x3, y3, x4, y4, reflection;\n\n            switch (lower) {\n\n              case 'z':\n                if (i >= last) {\n                  closed = true;\n                } else {\n                  x = coord.x;\n                  y = coord.y;\n                  result = new Two.Anchor(\n                    x, y,\n                    undefined, undefined,\n                    undefined, undefined,\n                    Two.Commands.close\n                  );\n                }\n                break;\n\n              case 'm':\n              case 'l':\n\n                x = parseFloat(coords[0]);\n                y = parseFloat(coords[1]);\n\n                result = new Two.Anchor(\n                  x, y,\n                  undefined, undefined,\n                  undefined, undefined,\n                  lower === 'm' ? Two.Commands.move : Two.Commands.line\n                );\n\n                if (relative) {\n                  result.addSelf(coord);\n                }\n\n                // result.controls.left.copy(result);\n                // result.controls.right.copy(result);\n\n                coord = result;\n                break;\n\n              case 'h':\n              case 'v':\n\n                var a = lower === 'h' ? 'x' : 'y';\n                var b = a === 'x' ? 'y' : 'x';\n\n                result = new Two.Anchor(\n                  undefined, undefined,\n                  undefined, undefined,\n                  undefined, undefined,\n                  Two.Commands.line\n                );\n                result[a] = parseFloat(coords[0]);\n                result[b] = coord[b];\n\n                if (relative) {\n                  result[a] += coord[a];\n                }\n\n                // result.controls.left.copy(result);\n                // result.controls.right.copy(result);\n\n                coord = result;\n                break;\n\n              case 'c':\n              case 's':\n\n                x1 = coord.x;\n                y1 = coord.y;\n\n                if (!control) {\n                  control = new Two.Vector();//.copy(coord);\n                }\n\n                if (lower === 'c') {\n\n                  x2 = parseFloat(coords[0]);\n                  y2 = parseFloat(coords[1]);\n                  x3 = parseFloat(coords[2]);\n                  y3 = parseFloat(coords[3]);\n                  x4 = parseFloat(coords[4]);\n                  y4 = parseFloat(coords[5]);\n\n                } else {\n\n                  // Calculate reflection control point for proper x2, y2\n                  // inclusion.\n\n                  reflection = getReflection(coord, control, relative);\n\n                  x2 = reflection.x;\n                  y2 = reflection.y;\n                  x3 = parseFloat(coords[0]);\n                  y3 = parseFloat(coords[1]);\n                  x4 = parseFloat(coords[2]);\n                  y4 = parseFloat(coords[3]);\n\n                }\n\n                if (relative) {\n                  x2 += x1;\n                  y2 += y1;\n                  x3 += x1;\n                  y3 += y1;\n                  x4 += x1;\n                  y4 += y1;\n                }\n\n                if (!_.isObject(coord.controls)) {\n                  Two.Anchor.AppendCurveProperties(coord);\n                }\n\n                coord.controls.right.set(x2 - coord.x, y2 - coord.y);\n                result = new Two.Anchor(\n                  x4, y4,\n                  x3 - x4, y3 - y4,\n                  undefined, undefined,\n                  Two.Commands.curve\n                );\n\n                coord = result;\n                control = result.controls.left;\n\n                break;\n\n              case 't':\n              case 'q':\n\n                x1 = coord.x;\n                y1 = coord.y;\n\n                if (!control) {\n                  control = new Two.Vector();//.copy(coord);\n                }\n\n                if (control.isZero()) {\n                  x2 = x1;\n                  y2 = y1;\n                } else {\n                  x2 = control.x;\n                  y1 = control.y;\n                }\n\n                if (lower === 'q') {\n\n                  x3 = parseFloat(coords[0]);\n                  y3 = parseFloat(coords[1]);\n                  x4 = parseFloat(coords[1]);\n                  y4 = parseFloat(coords[2]);\n\n                } else {\n\n                  reflection = getReflection(coord, control, relative);\n\n                  x3 = reflection.x;\n                  y3 = reflection.y;\n                  x4 = parseFloat(coords[0]);\n                  y4 = parseFloat(coords[1]);\n\n                }\n\n                if (relative) {\n                  x2 += x1;\n                  y2 += y1;\n                  x3 += x1;\n                  y3 += y1;\n                  x4 += x1;\n                  y4 += y1;\n                }\n\n                if (!_.isObject(coord.controls)) {\n                  Two.Anchor.AppendCurveProperties(coord);\n                }\n\n                coord.controls.right.set(x2 - coord.x, y2 - coord.y);\n                result = new Two.Anchor(\n                  x4, y4,\n                  x3 - x4, y3 - y4,\n                  undefined, undefined,\n                  Two.Commands.curve\n                );\n\n                coord = result;\n                control = result.controls.left;\n\n                break;\n\n              case 'a':\n\n                // throw new Two.Utils.Error('not yet able to interpret Elliptical Arcs.');\n                x1 = coord.x;\n                y1 = coord.y;\n\n                var rx = parseFloat(coords[0]);\n                var ry = parseFloat(coords[1]);\n                var xAxisRotation = parseFloat(coords[2]) * Math.PI / 180;\n                var largeArcFlag = parseFloat(coords[3]);\n                var sweepFlag = parseFloat(coords[4]);\n\n                x4 = parseFloat(coords[5]);\n                y4 = parseFloat(coords[6]);\n\n                if (relative) {\n                  x4 += x1;\n                  y4 += y1;\n                }\n\n                // http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter\n\n                // Calculate midpoint mx my\n                var mx = (x4 - x1) / 2;\n                var my = (y4 - y1) / 2;\n\n                // Calculate x1' y1' F.6.5.1\n                var _x = mx * Math.cos(xAxisRotation) + my * Math.sin(xAxisRotation);\n                var _y = - mx * Math.sin(xAxisRotation) + my * Math.cos(xAxisRotation);\n\n                var rx2 = rx * rx;\n                var ry2 = ry * ry;\n                var _x2 = _x * _x;\n                var _y2 = _y * _y;\n\n                // adjust radii\n                var l = _x2 / rx2 + _y2 / ry2;\n                if (l > 1) {\n                  rx *= Math.sqrt(l);\n                  ry *= Math.sqrt(l);\n                }\n\n                var amp = Math.sqrt((rx2 * ry2 - rx2 * _y2 - ry2 * _x2) / (rx2 * _y2 + ry2 * _x2));\n\n                if (_.isNaN(amp)) {\n                  amp = 0;\n                } else if (largeArcFlag != sweepFlag && amp > 0) {\n                  amp *= -1;\n                }\n\n                // Calculate cx' cy' F.6.5.2\n                var _cx = amp * rx * _y / ry;\n                var _cy = - amp * ry * _x / rx;\n\n                // Calculate cx cy F.6.5.3\n                var cx = _cx * Math.cos(xAxisRotation) - _cy * Math.sin(xAxisRotation) + (x1 + x4) / 2;\n                var cy = _cx * Math.sin(xAxisRotation) + _cy * Math.cos(xAxisRotation) + (y1 + y4) / 2;\n\n                // vector magnitude\n                var m = function(v) { return Math.sqrt(Math.pow(v[0], 2) + Math.pow(v[1], 2)); }\n                // ratio between two vectors\n                var r = function(u, v) { return (u[0] * v[0] + u[1] * v[1]) / (m(u) * m(v)) }\n                // angle between two vectors\n                var a = function(u, v) { return (u[0] * v[1] < u[1] * v[0] ? - 1 : 1) * Math.acos(r(u,v)); }\n\n                // Calculate theta1 and delta theta F.6.5.4 + F.6.5.5\n                var t1 = a([1, 0], [(_x - _cx) / rx, (_y - _cy) / ry]);\n                var u = [(_x - _cx) / rx, (_y - _cy) / ry];\n                var v = [( - _x - _cx) / rx, ( - _y - _cy) / ry];\n                var dt = a(u, v);\n\n                if (r(u, v) <= -1) dt = Math.PI;\n                if (r(u, v) >= 1) dt = 0;\n\n                // F.6.5.6\n                if (largeArcFlag)  {\n                  dt = mod(dt, Math.PI * 2);\n                }\n\n                if (sweepFlag && dt > 0) {\n                  dt -= Math.PI * 2;\n                }\n\n                var length = Two.Resolution;\n\n                // Save a projection of our rotation and translation to apply\n                // to the set of points.\n                var projection = new Two.Matrix()\n                  .translate(cx, cy)\n                  .rotate(xAxisRotation);\n\n                // Create a resulting array of Two.Anchor's to export to the\n                // the path.\n                result = _.map(_.range(length), function(i) {\n                  var pct = 1 - (i / (length - 1));\n                  var theta = pct * dt + t1;\n                  var x = rx * Math.cos(theta);\n                  var y = ry * Math.sin(theta);\n                  var projected = projection.multiply(x, y, 1);\n                  return new Two.Anchor(projected.x, projected.y, false, false, false, false, Two.Commands.line);;\n                });\n\n                result.push(new Two.Anchor(x4, y4, false, false, false, false, Two.Commands.line));\n\n                coord = result[result.length - 1];\n                control = coord.controls.left;\n\n                break;\n\n            }\n\n            if (result) {\n              if (_.isArray(result)) {\n                points = points.concat(result);\n              } else {\n                points.push(result);\n              }\n            }\n\n          });\n\n          if (points.length <= 1) {\n            return;\n          }\n\n          var path = new Two.Path(points, closed, undefined, true).noStroke();\n          path.fill = 'black';\n\n          var rect = path.getBoundingClientRect(true);\n\n          // Center objects to stay consistent\n          // with the rest of the Two.js API.\n          rect.centroid = {\n            x: rect.left + rect.width / 2,\n            y: rect.top + rect.height / 2\n          };\n\n          _.each(path.vertices, function(v) {\n            v.subSelf(rect.centroid);\n          });\n\n          path.translation.addSelf(rect.centroid);\n\n          return Two.Utils.applySvgAttributes.call(this, node, path);\n\n        },\n\n        circle: function(node) {\n\n          var x = parseFloat(node.getAttribute('cx'));\n          var y = parseFloat(node.getAttribute('cy'));\n          var r = parseFloat(node.getAttribute('r'));\n\n          var circle = new Two.Circle(x, y, r).noStroke();\n          circle.fill = 'black';\n\n          return Two.Utils.applySvgAttributes.call(this, node, circle);\n\n        },\n\n        ellipse: function(node) {\n\n          var x = parseFloat(node.getAttribute('cx'));\n          var y = parseFloat(node.getAttribute('cy'));\n          var width = parseFloat(node.getAttribute('rx'));\n          var height = parseFloat(node.getAttribute('ry'));\n\n          var ellipse = new Two.Ellipse(x, y, width, height).noStroke();\n          ellipse.fill = 'black';\n\n          return Two.Utils.applySvgAttributes.call(this, node, ellipse);\n\n        },\n\n        rect: function(node) {\n\n          var x = parseFloat(node.getAttribute('x')) || 0;\n          var y = parseFloat(node.getAttribute('y')) || 0;\n          var width = parseFloat(node.getAttribute('width'));\n          var height = parseFloat(node.getAttribute('height'));\n\n          var w2 = width / 2;\n          var h2 = height / 2;\n\n          var rect = new Two.Rectangle(x + w2, y + h2, width, height)\n            .noStroke();\n          rect.fill = 'black';\n\n          return Two.Utils.applySvgAttributes.call(this, node, rect);\n\n        },\n\n        line: function(node) {\n\n          var x1 = parseFloat(node.getAttribute('x1'));\n          var y1 = parseFloat(node.getAttribute('y1'));\n          var x2 = parseFloat(node.getAttribute('x2'));\n          var y2 = parseFloat(node.getAttribute('y2'));\n\n          var line = new Two.Line(x1, y1, x2, y2).noFill();\n\n          return Two.Utils.applySvgAttributes.call(this, node, line);\n\n        },\n\n        lineargradient: function(node) {\n\n          var x1 = parseFloat(node.getAttribute('x1'));\n          var y1 = parseFloat(node.getAttribute('y1'));\n          var x2 = parseFloat(node.getAttribute('x2'));\n          var y2 = parseFloat(node.getAttribute('y2'));\n\n          var ox = (x2 + x1) / 2;\n          var oy = (y2 + y1) / 2;\n\n          var stops = [];\n          for (var i = 0; i < node.children.length; i++) {\n\n            var child = node.children[i];\n\n            var offset = parseFloat(child.getAttribute('offset'));\n            var color = child.getAttribute('stop-color');\n            var opacity = child.getAttribute('stop-opacity');\n            var style = child.getAttribute('style');\n\n            if (_.isNull(color)) {\n              var matches = style ? style.match(/stop\\-color\\:\\s?([\\#a-fA-F0-9]*)/) : false;\n              color = matches && matches.length > 1 ? matches[1] : undefined;\n            }\n\n            if (_.isNull(opacity)) {\n              var matches = style ? style.match(/stop\\-opacity\\:\\s?([0-9\\.\\-]*)/) : false;\n              opacity = matches && matches.length > 1 ? parseFloat(matches[1]) : 1;\n            }\n\n            stops.push(new Two.Gradient.Stop(offset, color, opacity));\n\n          }\n\n          var gradient = new Two.LinearGradient(x1 - ox, y1 - oy, x2 - ox,\n            y2 - oy, stops);\n\n          return Two.Utils.applySvgAttributes.call(this, node, gradient);\n\n        },\n\n        radialgradient: function(node) {\n\n          var cx = parseFloat(node.getAttribute('cx')) || 0;\n          var cy = parseFloat(node.getAttribute('cy')) || 0;\n          var r = parseFloat(node.getAttribute('r'));\n\n          var fx = parseFloat(node.getAttribute('fx'));\n          var fy = parseFloat(node.getAttribute('fy'));\n\n          if (_.isNaN(fx)) {\n            fx = cx;\n          }\n\n          if (_.isNaN(fy)) {\n            fy = cy;\n          }\n\n          var ox = Math.abs(cx + fx) / 2;\n          var oy = Math.abs(cy + fy) / 2;\n\n          var stops = [];\n          for (var i = 0; i < node.children.length; i++) {\n\n            var child = node.children[i];\n\n            var offset = parseFloat(child.getAttribute('offset'));\n            var color = child.getAttribute('stop-color');\n            var opacity = child.getAttribute('stop-opacity');\n            var style = child.getAttribute('style');\n\n            if (_.isNull(color)) {\n              var matches = style ? style.match(/stop\\-color\\:\\s?([\\#a-fA-F0-9]*)/) : false;\n              color = matches && matches.length > 1 ? matches[1] : undefined;\n            }\n\n            if (_.isNull(opacity)) {\n              var matches = style ? style.match(/stop\\-opacity\\:\\s?([0-9\\.\\-]*)/) : false;\n              opacity = matches && matches.length > 1 ? parseFloat(matches[1]) : 1;\n            }\n\n            stops.push(new Two.Gradient.Stop(offset, color, opacity));\n\n          }\n\n          var gradient = new Two.RadialGradient(cx - ox, cy - oy, r,\n            stops, fx - ox, fy - oy);\n\n          return Two.Utils.applySvgAttributes.call(this, node, gradient);\n\n        }\n\n      },\n\n      /**\n       * Given 2 points (a, b) and corresponding control point for each\n       * return an array of points that represent points plotted along\n       * the curve. Number points determined by limit.\n       */\n      subdivide: function(x1, y1, x2, y2, x3, y3, x4, y4, limit) {\n\n        limit = limit || Two.Utils.Curve.RecursionLimit;\n        var amount = limit + 1;\n\n        // TODO: Issue 73\n        // Don't recurse if the end points are identical\n        if (x1 === x4 && y1 === y4) {\n          return [new Two.Anchor(x4, y4)];\n        }\n\n        return _.map(_.range(0, amount), function(i) {\n\n          var t = i / amount;\n          var x = getPointOnCubicBezier(t, x1, x2, x3, x4);\n          var y = getPointOnCubicBezier(t, y1, y2, y3, y4);\n\n          return new Two.Anchor(x, y);\n\n        });\n\n      },\n\n      getPointOnCubicBezier: function(t, a, b, c, d) {\n        var k = 1 - t;\n        return (k * k * k * a) + (3 * k * k * t * b) + (3 * k * t * t * c) +\n           (t * t * t * d);\n      },\n\n      /**\n       * Given 2 points (a, b) and corresponding control point for each\n       * return a float that represents the length of the curve using\n       * Gauss-Legendre algorithm. Limit iterations of calculation by `limit`.\n       */\n      getCurveLength: function(x1, y1, x2, y2, x3, y3, x4, y4, limit) {\n\n        // TODO: Better / fuzzier equality check\n        // Linear calculation\n        if (x1 === x2 && y1 === y2 && x3 === x4 && y3 === y4) {\n          var dx = x4 - x1;\n          var dy = y4 - y1;\n          return sqrt(dx * dx + dy * dy);\n        }\n\n        // Calculate the coefficients of a Bezier derivative.\n        var ax = 9 * (x2 - x3) + 3 * (x4 - x1),\n          bx = 6 * (x1 + x3) - 12 * x2,\n          cx = 3 * (x2 - x1),\n\n          ay = 9 * (y2 - y3) + 3 * (y4 - y1),\n          by = 6 * (y1 + y3) - 12 * y2,\n          cy = 3 * (y2 - y1);\n\n        var integrand = function(t) {\n          // Calculate quadratic equations of derivatives for x and y\n          var dx = (ax * t + bx) * t + cx,\n            dy = (ay * t + by) * t + cy;\n          return sqrt(dx * dx + dy * dy);\n        };\n\n        return integrate(\n          integrand, 0, 1, limit || Two.Utils.Curve.RecursionLimit\n        );\n\n      },\n\n      /**\n       * Integration for `getCurveLength` calculations. Referenced from\n       * Paper.js: https://github.com/paperjs/paper.js/blob/master/src/util/Numerical.js#L101\n       */\n      integrate: function(f, a, b, n) {\n        var x = Two.Utils.Curve.abscissas[n - 2],\n          w = Two.Utils.Curve.weights[n - 2],\n          A = 0.5 * (b - a),\n          B = A + a,\n          i = 0,\n          m = (n + 1) >> 1,\n          sum = n & 1 ? w[i++] * f(B) : 0; // Handle odd n\n        while (i < m) {\n          var Ax = A * x[i];\n          sum += w[i++] * (f(B + Ax) + f(B - Ax));\n        }\n        return A * sum;\n      },\n\n      /**\n       * Creates a set of points that have u, v values for anchor positions\n       */\n      getCurveFromPoints: function(points, closed) {\n\n        var l = points.length, last = l - 1;\n\n        for (var i = 0; i < l; i++) {\n\n          var point = points[i];\n\n          if (!_.isObject(point.controls)) {\n            Two.Anchor.AppendCurveProperties(point);\n          }\n\n          var prev = closed ? mod(i - 1, l) : max(i - 1, 0);\n          var next = closed ? mod(i + 1, l) : min(i + 1, last);\n\n          var a = points[prev];\n          var b = point;\n          var c = points[next];\n          getControlPoints(a, b, c);\n\n          b._command = i === 0 ? Two.Commands.move : Two.Commands.curve;\n\n          b.controls.left.x = _.isNumber(b.controls.left.x) ? b.controls.left.x : b.x;\n          b.controls.left.y = _.isNumber(b.controls.left.y) ? b.controls.left.y : b.y;\n\n          b.controls.right.x = _.isNumber(b.controls.right.x) ? b.controls.right.x : b.x;\n          b.controls.right.y = _.isNumber(b.controls.right.y) ? b.controls.right.y : b.y;\n\n        }\n\n      },\n\n      /**\n       * Given three coordinates return the control points for the middle, b,\n       * vertex.\n       */\n      getControlPoints: function(a, b, c) {\n\n        var a1 = angleBetween(a, b);\n        var a2 = angleBetween(c, b);\n\n        var d1 = distanceBetween(a, b);\n        var d2 = distanceBetween(c, b);\n\n        var mid = (a1 + a2) / 2;\n\n        // So we know which angle corresponds to which side.\n\n        b.u = _.isObject(b.controls.left) ? b.controls.left : new Two.Vector(0, 0);\n        b.v = _.isObject(b.controls.right) ? b.controls.right : new Two.Vector(0, 0);\n\n        // TODO: Issue 73\n        if (d1 < 0.0001 || d2 < 0.0001) {\n          if (!b._relative) {\n            b.controls.left.copy(b);\n            b.controls.right.copy(b);\n          }\n          return b;\n        }\n\n        d1 *= 0.33; // Why 0.33?\n        d2 *= 0.33;\n\n        if (a2 < a1) {\n          mid += HALF_PI;\n        } else {\n          mid -= HALF_PI;\n        }\n\n        b.controls.left.x = cos(mid) * d1;\n        b.controls.left.y = sin(mid) * d1;\n\n        mid -= PI;\n\n        b.controls.right.x = cos(mid) * d2;\n        b.controls.right.y = sin(mid) * d2;\n\n        if (!b._relative) {\n          b.controls.left.x += b.x;\n          b.controls.left.y += b.y;\n          b.controls.right.x += b.x;\n          b.controls.right.y += b.y;\n        }\n\n        return b;\n\n      },\n\n      /**\n       * Get the reflection of a point \"b\" about point \"a\". Where \"a\" is in\n       * absolute space and \"b\" is relative to \"a\".\n       *\n       * http://www.w3.org/TR/SVG11/implnote.html#PathElementImplementationNotes\n       */\n      getReflection: function(a, b, relative) {\n\n        return new Two.Vector(\n          2 * a.x - (b.x + a.x) - (relative ? a.x : 0),\n          2 * a.y - (b.y + a.y) - (relative ? a.y : 0)\n        );\n\n      },\n\n      getAnchorsFromArcData: function(center, xAxisRotation, rx, ry, ts, td, ccw) {\n\n        var matrix = new Two.Matrix()\n          .translate(center.x, center.y)\n          .rotate(xAxisRotation);\n\n        var l = Two.Resolution;\n\n        return _.map(_.range(l), function(i) {\n\n          var pct = (i + 1) / l;\n          if (!!ccw) {\n            pct = 1 - pct;\n          }\n\n          var theta = pct * td + ts;\n          var x = rx * Math.cos(theta);\n          var y = ry * Math.sin(theta);\n\n          // x += center.x;\n          // y += center.y;\n\n          var anchor = new Two.Anchor(x, y);\n          Two.Anchor.AppendCurveProperties(anchor);\n          anchor.command = Two.Commands.line;\n\n          // TODO: Calculate control points here...\n\n          return anchor;\n\n        });\n\n      },\n\n      ratioBetween: function(A, B) {\n\n        return (A.x * B.x + A.y * B.y) / (A.length() * B.length());\n\n      },\n\n      angleBetween: function(A, B) {\n\n        var dx, dy;\n\n        if (arguments.length >= 4) {\n\n          dx = arguments[0] - arguments[2];\n          dy = arguments[1] - arguments[3];\n\n          return atan2(dy, dx);\n\n        }\n\n        dx = A.x - B.x;\n        dy = A.y - B.y;\n\n        return atan2(dy, dx);\n\n      },\n\n      distanceBetweenSquared: function(p1, p2) {\n\n        var dx = p1.x - p2.x;\n        var dy = p1.y - p2.y;\n\n        return dx * dx + dy * dy;\n\n      },\n\n      distanceBetween: function(p1, p2) {\n\n        return sqrt(distanceBetweenSquared(p1, p2));\n\n      },\n\n      lerp: function(a, b, t) {\n        return t * (b - a) + a;\n      },\n\n      // A pretty fast toFixed(3) alternative\n      // See http://jsperf.com/parsefloat-tofixed-vs-math-round/18\n      toFixed: function(v) {\n        return Math.floor(v * 1000) / 1000;\n      },\n\n      mod: function(v, l) {\n\n        while (v < 0) {\n          v += l;\n        }\n\n        return v % l;\n\n      },\n\n      /**\n       * Array like collection that triggers inserted and removed events\n       * removed : pop / shift / splice\n       * inserted : push / unshift / splice (with > 2 arguments)\n       */\n      Collection: function() {\n\n        Array.call(this);\n\n        if (arguments.length > 1) {\n          Array.prototype.push.apply(this, arguments);\n        } else if (arguments[0] && Array.isArray(arguments[0])) {\n          Array.prototype.push.apply(this, arguments[0]);\n        }\n\n      },\n\n      // Custom Error Throwing for Two.js\n\n      Error: function(message) {\n        this.name = 'two.js';\n        this.message = message;\n      },\n\n      Events: {\n\n        on: function(name, callback) {\n\n          this._events || (this._events = {});\n          var list = this._events[name] || (this._events[name] = []);\n\n          list.push(callback);\n\n          return this;\n\n        },\n\n        off: function(name, callback) {\n\n          if (!this._events) {\n            return this;\n          }\n          if (!name && !callback) {\n            this._events = {};\n            return this;\n          }\n\n          var names = name ? [name] : _.keys(this._events);\n          for (var i = 0, l = names.length; i < l; i++) {\n\n            var name = names[i];\n            var list = this._events[name];\n\n            if (!!list) {\n              var events = [];\n              if (callback) {\n                for (var j = 0, k = list.length; j < k; j++) {\n                  var ev = list[j];\n                  ev = ev.callback ? ev.callback : ev;\n                  if (callback && callback !== ev) {\n                    events.push(ev);\n                  }\n                }\n              }\n              this._events[name] = events;\n            }\n          }\n\n          return this;\n        },\n\n        trigger: function(name) {\n          if (!this._events) return this;\n          var args = slice.call(arguments, 1);\n          var events = this._events[name];\n          if (events) trigger(this, events, args);\n          return this;\n        },\n\n        listen: function (obj, name, callback) {\n\n          var bound = this;\n\n          if (obj) {\n            var ev = function () {\n              callback.apply(bound, arguments);\n            };\n\n            // add references about the object that assigned this listener\n            ev.obj = obj;\n            ev.name = name;\n            ev.callback = callback;\n\n            obj.on(name, ev);\n          }\n\n          return this;\n\n        },\n\n        ignore: function (obj, name, callback) {\n\n          obj.off(name, callback);\n\n          return this;\n\n        }\n\n      }\n\n    })\n\n  });\n\n  Two.Utils.Events.bind = Two.Utils.Events.on;\n  Two.Utils.Events.unbind = Two.Utils.Events.off;\n\n  var trigger = function(obj, events, args) {\n    var method;\n    switch (args.length) {\n    case 0:\n      method = function(i) {\n        events[i].call(obj, args[0]);\n      };\n      break;\n    case 1:\n      method = function(i) {\n        events[i].call(obj, args[0], args[1]);\n      };\n      break;\n    case 2:\n      method = function(i) {\n        events[i].call(obj, args[0], args[1], args[2]);\n      };\n      break;\n    case 3:\n      method = function(i) {\n        events[i].call(obj, args[0], args[1], args[2], args[3]);\n      };\n      break;\n    default:\n      method = function(i) {\n        events[i].apply(obj, args);\n      };\n    }\n    for (var i = 0; i < events.length; i++) {\n      method(i);\n    }\n  };\n\n  Two.Utils.Error.prototype = new Error();\n  Two.Utils.Error.prototype.constructor = Two.Utils.Error;\n\n  Two.Utils.Collection.prototype = new Array();\n  Two.Utils.Collection.prototype.constructor = Two.Utils.Collection;\n\n  _.extend(Two.Utils.Collection.prototype, Two.Utils.Events, {\n\n    pop: function() {\n      var popped = Array.prototype.pop.apply(this, arguments);\n      this.trigger(Two.Events.remove, [popped]);\n      return popped;\n    },\n\n    shift: function() {\n      var shifted = Array.prototype.shift.apply(this, arguments);\n      this.trigger(Two.Events.remove, [shifted]);\n      return shifted;\n    },\n\n    push: function() {\n      var pushed = Array.prototype.push.apply(this, arguments);\n      this.trigger(Two.Events.insert, arguments);\n      return pushed;\n    },\n\n    unshift: function() {\n      var unshifted = Array.prototype.unshift.apply(this, arguments);\n      this.trigger(Two.Events.insert, arguments);\n      return unshifted;\n    },\n\n    splice: function() {\n      var spliced = Array.prototype.splice.apply(this, arguments);\n      var inserted;\n\n      this.trigger(Two.Events.remove, spliced);\n\n      if (arguments.length > 2) {\n        inserted = this.slice(arguments[0], arguments[0] + arguments.length - 2);\n        this.trigger(Two.Events.insert, inserted);\n        this.trigger(Two.Events.order);\n      }\n      return spliced;\n    },\n\n    sort: function() {\n      Array.prototype.sort.apply(this, arguments);\n      this.trigger(Two.Events.order);\n      return this;\n    },\n\n    reverse: function() {\n      Array.prototype.reverse.apply(this, arguments);\n      this.trigger(Two.Events.order);\n      return this;\n    }\n\n  });\n\n  // Localize utils\n\n  var distanceBetween = Two.Utils.distanceBetween,\n    getAnchorsFromArcData = Two.Utils.getAnchorsFromArcData,\n    distanceBetweenSquared = Two.Utils.distanceBetweenSquared,\n    ratioBetween = Two.Utils.ratioBetween,\n    angleBetween = Two.Utils.angleBetween,\n    getControlPoints = Two.Utils.getControlPoints,\n    getCurveFromPoints = Two.Utils.getCurveFromPoints,\n    solveSegmentIntersection = Two.Utils.solveSegmentIntersection,\n    decoupleShapes = Two.Utils.decoupleShapes,\n    mod = Two.Utils.mod,\n    getBackingStoreRatio = Two.Utils.getBackingStoreRatio,\n    getPointOnCubicBezier = Two.Utils.getPointOnCubicBezier,\n    getCurveLength = Two.Utils.getCurveLength,\n    integrate = Two.Utils.integrate,\n    getReflection = Two.Utils.getReflection;\n\n  _.extend(Two.prototype, Two.Utils.Events, {\n\n    appendTo: function(elem) {\n\n      elem.appendChild(this.renderer.domElement);\n      return this;\n\n    },\n\n    play: function() {\n\n      Two.Utils.setPlaying.call(this, true);\n      return this.trigger(Two.Events.play);\n\n    },\n\n    pause: function() {\n\n      this.playing = false;\n      return this.trigger(Two.Events.pause);\n\n    },\n\n    /**\n     * Update positions and calculations in one pass before rendering.\n     */\n    update: function() {\n\n      var animated = !!this._lastFrame;\n      var now = perf.now();\n\n      this.frameCount++;\n\n      if (animated) {\n        this.timeDelta = parseFloat((now - this._lastFrame).toFixed(3));\n      }\n      this._lastFrame = now;\n\n      var width = this.width;\n      var height = this.height;\n      var renderer = this.renderer;\n\n      // Update width / height for the renderer\n      if (width !== renderer.width || height !== renderer.height) {\n        renderer.setSize(width, height, this.ratio);\n      }\n\n      this.trigger(Two.Events.update, this.frameCount, this.timeDelta);\n\n      return this.render();\n\n    },\n\n    /**\n     * Render all drawable - visible objects of the scene.\n     */\n    render: function() {\n\n      //this.renderer.render();\n      //return this.trigger(Two.Events.render, this.frameCount);\n\n    },\n\n    /**\n     * Render all drawable - visible objects of the scene.\n     */\n    forcerender: function() {\n\n      this.renderer.render();\n      return this.trigger(Two.Events.render, this.frameCount);\n\n    },\n\n    /**\n     * Convenience Methods\n     */\n\n    add: function(o) {\n\n      var objects = o;\n      if (!(objects instanceof Array)) {\n        objects = _.toArray(arguments);\n      }\n\n      this.scene.add(objects);\n      return this;\n\n    },\n\n    remove: function(o) {\n\n      var objects = o;\n      if (!(objects instanceof Array)) {\n        objects = _.toArray(arguments);\n      }\n\n      this.scene.remove(objects);\n\n      return this;\n\n    },\n\n    clear: function() {\n\n      this.scene.remove(_.toArray(this.scene.children));\n      return this;\n\n    },\n\n    makeLine: function(x1, y1, x2, y2) {\n\n      var line = new Two.Line(x1, y1, x2, y2);\n      this.scene.add(line);\n\n      return line;\n\n    },\n\n    makeRectangle: function(x, y, width, height) {\n\n      var rect = new Two.Rectangle(x, y, width, height);\n      this.scene.add(rect);\n\n      return rect;\n\n    },\n\n    makeRoundedRectangle: function(x, y, width, height, sides) {\n\n      var rect = new Two.RoundedRectangle(x, y, width, height, sides);\n      this.scene.add(rect);\n\n      return rect;\n\n    },\n\n    makeCircle: function(ox, oy, r) {\n\n      var circle = new Two.Circle(ox, oy, r);\n      this.scene.add(circle);\n\n      return circle;\n\n    },\n\n    makeEllipse: function(ox, oy, rx, ry) {\n\n      var ellipse = new Two.Ellipse(ox, oy, rx, ry);\n      this.scene.add(ellipse);\n\n      return ellipse;\n\n    },\n\n    makeStar: function(ox, oy, or, ir, sides) {\n\n      var star = new Two.Star(ox, oy, or, ir, sides);\n      this.scene.add(star);\n\n      return star;\n\n    },\n\n    makeCurve: function(p) {\n\n      var l = arguments.length, points = p;\n      if (!_.isArray(p)) {\n        points = [];\n        for (var i = 0; i < l; i+=2) {\n          var x = arguments[i];\n          if (!_.isNumber(x)) {\n            break;\n          }\n          var y = arguments[i + 1];\n          points.push(new Two.Anchor(x, y));\n        }\n      }\n\n      var last = arguments[l - 1];\n      var curve = new Two.Path(points, !(_.isBoolean(last) ? last : undefined), true);\n      var rect = curve.getBoundingClientRect();\n      curve.center().translation\n        .set(rect.left + rect.width / 2, rect.top + rect.height / 2);\n\n      this.scene.add(curve);\n\n      return curve;\n\n    },\n\n    makePolygon: function(ox, oy, r, sides) {\n\n      var poly = new Two.Polygon(ox, oy, r, sides);\n      this.scene.add(poly);\n\n      return poly;\n\n    },\n\n    /*\n    * Make an Arc Segment\n    */\n\n    makeArcSegment: function(ox, oy, ir, or, sa, ea, res) {\n      var arcSegment = new Two.ArcSegment(ox, oy, ir, or, sa, ea, res);\n      this.scene.add(arcSegment);\n      return arcSegment;\n    },\n\n    /**\n     * Convenience method to make and draw a Two.Path.\n     */\n    makePath: function(p) {\n\n      var l = arguments.length, points = p;\n      if (!_.isArray(p)) {\n        points = [];\n        for (var i = 0; i < l; i+=2) {\n          var x = arguments[i];\n          if (!_.isNumber(x)) {\n            break;\n          }\n          var y = arguments[i + 1];\n          points.push(new Two.Anchor(x, y));\n        }\n      }\n\n      var last = arguments[l - 1];\n      var path = new Two.Path(points, !(_.isBoolean(last) ? last : undefined));\n      var rect = path.getBoundingClientRect();\n      path.center().translation\n        .set(rect.left + rect.width / 2, rect.top + rect.height / 2);\n\n      this.scene.add(path);\n\n      return path;\n\n    },\n\n    /**\n     * Convenience method to make and add a Two.Text.\n     */\n    makeText: function(message, x, y, styles) {\n      var text = new Two.Text(message, x, y, styles);\n      this.add(text);\n      return text;\n    },\n\n    /**\n     * Convenience method to make and add a Two.LinearGradient.\n     */\n    makeLinearGradient: function(x1, y1, x2, y2 /* stops */) {\n\n      var stops = slice.call(arguments, 4);\n      var gradient = new Two.LinearGradient(x1, y1, x2, y2, stops);\n\n      this.add(gradient);\n\n      return gradient;\n\n    },\n\n    /**\n     * Convenience method to make and add a Two.RadialGradient.\n     */\n    makeRadialGradient: function(x1, y1, r /* stops */) {\n\n      var stops = slice.call(arguments, 3);\n      var gradient = new Two.RadialGradient(x1, y1, r, stops);\n\n      this.add(gradient);\n\n      return gradient;\n\n    },\n\n    makeSprite: function(path, x, y, cols, rows, frameRate, autostart) {\n\n      var sprite = new Two.Sprite(path, x, y, cols, rows, frameRate);\n      if (!!autostart) {\n        sprite.play();\n      }\n      this.add(sprite);\n\n      return sprite;\n\n    },\n\n    makeImageSequence: function(paths, x, y, frameRate, autostart) {\n\n      var imageSequence = new Two.ImageSequence(paths, x, y, frameRate);\n      if (!!autostart) {\n        imageSequence.play();\n      }\n      this.add(imageSequence);\n\n      return imageSequence;\n\n    },\n\n    makeTexture: function(path, callback) {\n\n      var texture = new Two.Texture(path, callback);\n      return texture;\n\n    },\n\n    makeGroup: function(o) {\n\n      var objects = o;\n      if (!(objects instanceof Array)) {\n        objects = _.toArray(arguments);\n      }\n\n      var group = new Two.Group();\n      this.scene.add(group);\n      group.add(objects);\n\n      return group;\n\n    },\n\n    /**\n     * Interpret an SVG Node and add it to this instance's scene. The\n     * distinction should be made that this doesn't `import` svg's, it solely\n     * interprets them into something compatible for Two.js — this is slightly\n     * different than a direct transcription.\n     *\n     * @param {Object} svgNode - The node to be parsed\n     * @param {Boolean} shallow - Don't create a top-most group but\n     *                                    append all contents directly\n     */\n    interpret: function(svgNode, shallow) {\n\n      var tag = svgNode.tagName.toLowerCase();\n\n      if (!(tag in Two.Utils.read)) {\n        return null;\n      }\n\n      var node = Two.Utils.read[tag].call(this, svgNode);\n\n      if (shallow && node instanceof Two.Group) {\n        this.add(node.children);\n      } else {\n        this.add(node);\n      }\n\n      return node;\n\n    },\n\n    /**\n     * Load an SVG file / text and interpret.\n     */\n    load: function(text, callback) {\n\n      var nodes = [], elem, i;\n\n      if (/.*\\.svg/ig.test(text)) {\n\n        Two.Utils.xhr(text, _.bind(function(data) {\n\n          dom.temp.innerHTML = data;\n          for (i = 0; i < dom.temp.children.length; i++) {\n            elem = dom.temp.children[i];\n            nodes.push(this.interpret(elem));\n          }\n\n          callback(nodes.length <= 1 ? nodes[0] : nodes,\n            dom.temp.children.length <= 1 ? dom.temp.children[0] : dom.temp.children);\n\n        }, this));\n\n        return this;\n\n      }\n\n      dom.temp.innerHTML = text;\n      for (i = 0; i < dom.temp.children.length; i++) {\n        elem = dom.temp.children[i];\n        nodes.push(this.interpret(elem));\n      }\n\n      callback(nodes.length <= 1 ? nodes[0] : nodes,\n        dom.temp.children.length <= 1 ? dom.temp.children[0] : dom.temp.children);\n\n      return this;\n\n    }\n\n  });\n\n  function fitToWindow() {\n\n    var wr = document.body.getBoundingClientRect();\n\n    var width = this.width = wr.width;\n    var height = this.height = wr.height;\n\n    this.renderer.setSize(width, height, this.ratio);\n    this.trigger(Two.Events.resize, width, height);\n\n  }\n\n  // Request Animation Frame\n\n  var raf = dom.getRequestAnimationFrame();\n\n  function loop() {\n\n    raf(loop);\n\n    for (var i = 0; i < Two.Instances.length; i++) {\n      var t = Two.Instances[i];\n      if (t.playing) {\n        t.update();\n      }\n    }\n\n  }\n\n  if (typeof define === 'function' && define.amd) {\n    define('two', [], function() {\n      return Two;\n    });\n  } else if (typeof module != 'undefined' && module.exports) {\n    module.exports = Two;\n  }\n\n  return Two;\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  var _ = Two.Utils;\n\n  var Registry = Two.Registry = function() {\n\n    this.map = {};\n\n  };\n\n  _.extend(Registry, {\n\n  });\n\n  _.extend(Registry.prototype, {\n\n    add: function(id, obj) {\n      this.map[id] = obj;\n      return this;\n    },\n\n    remove: function(id) {\n      delete this.map[id];\n      return this;\n    },\n\n    get: function(id) {\n      return this.map[id];\n    },\n\n    contains: function(id) {\n      return id in this.map;\n    }\n\n  });\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  var _ = Two.Utils;\n\n  var Vector = Two.Vector = function(x, y) {\n\n    this.x = x || 0;\n    this.y = y || 0;\n\n  };\n\n  _.extend(Vector, {\n\n    zero: new Two.Vector()\n\n  });\n\n  _.extend(Vector.prototype, Two.Utils.Events, {\n\n    set: function(x, y) {\n      this.x = x;\n      this.y = y;\n      return this;\n    },\n\n    copy: function(v) {\n      this.x = v.x;\n      this.y = v.y;\n      return this;\n    },\n\n    clear: function() {\n      this.x = 0;\n      this.y = 0;\n      return this;\n    },\n\n    clone: function() {\n      return new Vector(this.x, this.y);\n    },\n\n    add: function(v1, v2) {\n      this.x = v1.x + v2.x;\n      this.y = v1.y + v2.y;\n      return this;\n    },\n\n    addSelf: function(v) {\n      this.x += v.x;\n      this.y += v.y;\n      return this;\n    },\n\n    sub: function(v1, v2) {\n      this.x = v1.x - v2.x;\n      this.y = v1.y - v2.y;\n      return this;\n    },\n\n    subSelf: function(v) {\n      this.x -= v.x;\n      this.y -= v.y;\n      return this;\n    },\n\n    multiplySelf: function(v) {\n      this.x *= v.x;\n      this.y *= v.y;\n      return this;\n    },\n\n    multiplyScalar: function(s) {\n      this.x *= s;\n      this.y *= s;\n      return this;\n    },\n\n    divideScalar: function(s) {\n      if (s) {\n        this.x /= s;\n        this.y /= s;\n      } else {\n        this.set(0, 0);\n      }\n      return this;\n    },\n\n    negate: function() {\n      return this.multiplyScalar(-1);\n    },\n\n    dot: function(v) {\n      return this.x * v.x + this.y * v.y;\n    },\n\n    lengthSquared: function() {\n      return this.x * this.x + this.y * this.y;\n    },\n\n    length: function() {\n      return Math.sqrt(this.lengthSquared());\n    },\n\n    normalize: function() {\n      return this.divideScalar(this.length());\n    },\n\n    distanceTo: function(v) {\n      return Math.sqrt(this.distanceToSquared(v));\n    },\n\n    distanceToSquared: function(v) {\n      var dx = this.x - v.x,\n          dy = this.y - v.y;\n      return dx * dx + dy * dy;\n    },\n\n    setLength: function(l) {\n      return this.normalize().multiplyScalar(l);\n    },\n\n    equals: function(v, eps) {\n      eps = (typeof eps === 'undefined') ?  0.0001 : eps;\n      return (this.distanceTo(v) < eps);\n    },\n\n    lerp: function(v, t) {\n      var x = (v.x - this.x) * t + this.x;\n      var y = (v.y - this.y) * t + this.y;\n      return this.set(x, y);\n    },\n\n    isZero: function(eps) {\n      eps = (typeof eps === 'undefined') ?  0.0001 : eps;\n      return (this.length() < eps);\n    },\n\n    toString: function() {\n      return this.x + ', ' + this.y;\n    },\n\n    toObject: function() {\n      return { x: this.x, y: this.y };\n    },\n\n    rotate: function (radians) {\n      var cos = Math.cos(radians);\n      var sin = Math.sin(radians);\n      this.x = this.x * cos - this.y * sin;\n      this.y = this.x * sin + this.y * cos;\n      return this;\n    }\n\n  });\n\n  var BoundProto = {\n\n    set: function(x, y) {\n      this._x = x;\n      this._y = y;\n      return this.trigger(Two.Events.change);\n    },\n\n    copy: function(v) {\n      this._x = v.x;\n      this._y = v.y;\n      return this.trigger(Two.Events.change);\n    },\n\n    clear: function() {\n      this._x = 0;\n      this._y = 0;\n      return this.trigger(Two.Events.change);\n    },\n\n    clone: function() {\n      return new Vector(this._x, this._y);\n    },\n\n    add: function(v1, v2) {\n      this._x = v1.x + v2.x;\n      this._y = v1.y + v2.y;\n      return this.trigger(Two.Events.change);\n    },\n\n    addSelf: function(v) {\n      this._x += v.x;\n      this._y += v.y;\n      return this.trigger(Two.Events.change);\n    },\n\n    sub: function(v1, v2) {\n      this._x = v1.x - v2.x;\n      this._y = v1.y - v2.y;\n      return this.trigger(Two.Events.change);\n    },\n\n    subSelf: function(v) {\n      this._x -= v.x;\n      this._y -= v.y;\n      return this.trigger(Two.Events.change);\n    },\n\n    multiplySelf: function(v) {\n      this._x *= v.x;\n      this._y *= v.y;\n      return this.trigger(Two.Events.change);\n    },\n\n    multiplyScalar: function(s) {\n      this._x *= s;\n      this._y *= s;\n      return this.trigger(Two.Events.change);\n    },\n\n    divideScalar: function(s) {\n      if (s) {\n        this._x /= s;\n        this._y /= s;\n        return this.trigger(Two.Events.change);\n      }\n      return this.clear();\n    },\n\n    negate: function() {\n      return this.multiplyScalar(-1);\n    },\n\n    dot: function(v) {\n      return this._x * v.x + this._y * v.y;\n    },\n\n    lengthSquared: function() {\n      return this._x * this._x + this._y * this._y;\n    },\n\n    length: function() {\n      return Math.sqrt(this.lengthSquared());\n    },\n\n    normalize: function() {\n      return this.divideScalar(this.length());\n    },\n\n    distanceTo: function(v) {\n      return Math.sqrt(this.distanceToSquared(v));\n    },\n\n    distanceToSquared: function(v) {\n      var dx = this._x - v.x,\n          dy = this._y - v.y;\n      return dx * dx + dy * dy;\n    },\n\n    setLength: function(l) {\n      return this.normalize().multiplyScalar(l);\n    },\n\n    equals: function(v, eps) {\n      eps = (typeof eps === 'undefined') ?  0.0001 : eps;\n      return (this.distanceTo(v) < eps);\n    },\n\n    lerp: function(v, t) {\n      var x = (v.x - this._x) * t + this._x;\n      var y = (v.y - this._y) * t + this._y;\n      return this.set(x, y);\n    },\n\n    isZero: function(eps) {\n      eps = (typeof eps === 'undefined') ?  0.0001 : eps;\n      return (this.length() < eps);\n    },\n\n    toString: function() {\n      return this._x + ', ' + this._y;\n    },\n\n    toObject: function() {\n      return { x: this._x, y: this._y };\n    },\n\n    rotate: function (radians) {\n      var cos = Math.cos(radians);\n      var sin = Math.sin(radians);\n      this._x = this._x * cos - this._y * sin;\n      this._y = this._x * sin + this._y * cos;\n      return this;\n    }\n\n  };\n\n  var xgs = {\n    enumerable: true,\n    get: function() {\n      return this._x;\n    },\n    set: function(v) {\n      this._x = v;\n      this.trigger(Two.Events.change, 'x');\n    }\n  };\n\n  var ygs = {\n    enumerable: true,\n    get: function() {\n      return this._y;\n    },\n    set: function(v) {\n      this._y = v;\n      this.trigger(Two.Events.change, 'y');\n    }\n  };\n\n  /**\n   * Override Backbone bind / on in order to add properly broadcasting.\n   * This allows Two.Vector to not broadcast events unless event listeners\n   * are explicity bound to it.\n   */\n\n  Two.Vector.prototype.bind = Two.Vector.prototype.on = function() {\n\n    if (!this._bound) {\n      this._x = this.x;\n      this._y = this.y;\n      Object.defineProperty(this, 'x', xgs);\n      Object.defineProperty(this, 'y', ygs);\n      _.extend(this, BoundProto);\n      this._bound = true; // Reserved for event initialization check\n    }\n\n    Two.Utils.Events.bind.apply(this, arguments);\n\n    return this;\n\n  };\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  // Localized variables\n  var commands = Two.Commands;\n  var _ = Two.Utils;\n\n  /**\n   * An object that holds 3 `Two.Vector`s, the anchor point and its\n   * corresponding handles: `left` and `right`.\n   */\n  var Anchor = Two.Anchor = function(x, y, ux, uy, vx, vy, command) {\n\n    Two.Vector.call(this, x, y);\n\n    this._broadcast = _.bind(function() {\n      this.trigger(Two.Events.change);\n    }, this);\n\n    this._command = command || commands.move;\n    this._relative = true;\n\n    if (!command) {\n      return this;\n    }\n\n    Anchor.AppendCurveProperties(this);\n\n    if (_.isNumber(ux)) {\n      this.controls.left.x = ux;\n    }\n    if (_.isNumber(uy)) {\n      this.controls.left.y = uy;\n    }\n    if (_.isNumber(vx)) {\n      this.controls.right.x = vx;\n    }\n    if (_.isNumber(vy)) {\n      this.controls.right.y = vy;\n    }\n\n  };\n\n  _.extend(Anchor, {\n\n    AppendCurveProperties: function(anchor) {\n      anchor.controls = {\n        left: new Two.Vector(0, 0),\n        right: new Two.Vector(0, 0)\n      };\n    }\n\n  });\n\n  var AnchorProto = {\n\n    listen: function() {\n\n      if (!_.isObject(this.controls)) {\n        Anchor.AppendCurveProperties(this);\n      }\n\n      this.controls.left.bind(Two.Events.change, this._broadcast);\n      this.controls.right.bind(Two.Events.change, this._broadcast);\n\n      return this;\n\n    },\n\n    ignore: function() {\n\n      this.controls.left.unbind(Two.Events.change, this._broadcast);\n      this.controls.right.unbind(Two.Events.change, this._broadcast);\n\n      return this;\n\n    },\n\n    clone: function() {\n\n      var controls = this.controls;\n\n      var clone = new Two.Anchor(\n        this.x,\n        this.y,\n        controls && controls.left.x,\n        controls && controls.left.y,\n        controls && controls.right.x,\n        controls && controls.right.y,\n        this.command\n      );\n      clone.relative = this._relative;\n      return clone;\n\n    },\n\n    toObject: function() {\n      var o = {\n        x: this.x,\n        y: this.y\n      };\n      if (this._command) {\n        o.command = this._command;\n      }\n      if (this._relative) {\n        o.relative = this._relative;\n      }\n      if (this.controls) {\n        o.controls = {\n          left: this.controls.left.toObject(),\n          right: this.controls.right.toObject()\n        };\n      }\n      return o;\n    },\n\n    toString: function() {\n      if (!this.controls) {\n        return [this._x, this._y].join(', ');\n      }\n      return [this._x, this._y, this.controls.left.x, this.controls.left.y,\n        this.controls.right.x, this.controls.right.y].join(', ');\n    }\n\n  };\n\n  Object.defineProperty(Anchor.prototype, 'command', {\n\n    enumerable: true,\n\n    get: function() {\n      return this._command;\n    },\n\n    set: function(c) {\n      this._command = c;\n      if (this._command === commands.curve && !_.isObject(this.controls)) {\n        Anchor.AppendCurveProperties(this);\n      }\n      return this.trigger(Two.Events.change);\n    }\n\n  });\n\n  Object.defineProperty(Anchor.prototype, 'relative', {\n\n    enumerable: true,\n\n    get: function() {\n      return this._relative;\n    },\n\n    set: function(b) {\n      if (this._relative == b) {\n        return this;\n      }\n      this._relative = !!b;\n      return this.trigger(Two.Events.change);\n    }\n\n  });\n\n  _.extend(Anchor.prototype, Two.Vector.prototype, AnchorProto);\n\n  // Make it possible to bind and still have the Anchor specific\n  // inheritance from Two.Vector\n  Two.Anchor.prototype.bind = Two.Anchor.prototype.on = function() {\n    Two.Vector.prototype.bind.apply(this, arguments);\n    _.extend(this, AnchorProto);\n  };\n\n  Two.Anchor.prototype.unbind = Two.Anchor.prototype.off = function() {\n    Two.Vector.prototype.unbind.apply(this, arguments);\n    _.extend(this, AnchorProto);\n  };\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  /**\n   * Constants\n   */\n  var cos = Math.cos, sin = Math.sin, tan = Math.tan;\n  var _ = Two.Utils;\n\n  /**\n   * Two.Matrix contains an array of elements that represent\n   * the two dimensional 3 x 3 matrix as illustrated below:\n   *\n   * =====\n   * a b c\n   * d e f\n   * g h i  // this row is not really used in 2d transformations\n   * =====\n   *\n   * String order is for transform strings: a, d, b, e, c, f\n   *\n   * @class\n   */\n  var Matrix = Two.Matrix = function(a, b, c, d, e, f) {\n\n    this.elements = new Two.Array(9);\n\n    var elements = a;\n    if (!_.isArray(elements)) {\n      elements = _.toArray(arguments);\n    }\n\n    // initialize the elements with default values.\n\n    this.identity().set(elements);\n\n  };\n\n  _.extend(Matrix, {\n\n    Identity: [\n      1, 0, 0,\n      0, 1, 0,\n      0, 0, 1\n    ],\n\n    /**\n     * Multiply two matrix 3x3 arrays\n     */\n    Multiply: function(A, B, C) {\n\n      if (B.length <= 3) { // Multiply Vector\n\n        var x, y, z, e = A;\n\n        var a = B[0] || 0,\n            b = B[1] || 0,\n            c = B[2] || 0;\n\n        // Go down rows first\n        // a, d, g, b, e, h, c, f, i\n\n        x = e[0] * a + e[1] * b + e[2] * c;\n        y = e[3] * a + e[4] * b + e[5] * c;\n        z = e[6] * a + e[7] * b + e[8] * c;\n\n        return { x: x, y: y, z: z };\n\n      }\n\n      var A0 = A[0], A1 = A[1], A2 = A[2];\n      var A3 = A[3], A4 = A[4], A5 = A[5];\n      var A6 = A[6], A7 = A[7], A8 = A[8];\n\n      var B0 = B[0], B1 = B[1], B2 = B[2];\n      var B3 = B[3], B4 = B[4], B5 = B[5];\n      var B6 = B[6], B7 = B[7], B8 = B[8];\n\n      C = C || new Two.Array(9);\n\n      C[0] = A0 * B0 + A1 * B3 + A2 * B6;\n      C[1] = A0 * B1 + A1 * B4 + A2 * B7;\n      C[2] = A0 * B2 + A1 * B5 + A2 * B8;\n      C[3] = A3 * B0 + A4 * B3 + A5 * B6;\n      C[4] = A3 * B1 + A4 * B4 + A5 * B7;\n      C[5] = A3 * B2 + A4 * B5 + A5 * B8;\n      C[6] = A6 * B0 + A7 * B3 + A8 * B6;\n      C[7] = A6 * B1 + A7 * B4 + A8 * B7;\n      C[8] = A6 * B2 + A7 * B5 + A8 * B8;\n\n      return C;\n\n    }\n\n  });\n\n  _.extend(Matrix.prototype, Two.Utils.Events, {\n\n    /**\n     * Takes an array of elements or the arguments list itself to\n     * set and update the current matrix's elements. Only updates\n     * specified values.\n     */\n    set: function(a) {\n\n      var elements = a;\n      if (!_.isArray(elements)) {\n        elements = _.toArray(arguments);\n      }\n\n      _.extend(this.elements, elements);\n\n      return this.trigger(Two.Events.change);\n\n    },\n\n    /**\n     * Turn matrix to identity, like resetting.\n     */\n    identity: function() {\n\n      this.set(Matrix.Identity);\n\n      return this;\n\n    },\n\n    /**\n     * Multiply scalar or multiply by another matrix.\n     */\n    multiply: function(a, b, c, d, e, f, g, h, i) {\n\n      var elements = arguments, l = elements.length;\n\n      // Multiply scalar\n\n      if (l <= 1) {\n\n        _.each(this.elements, function(v, i) {\n          this.elements[i] = v * a;\n        }, this);\n\n        return this.trigger(Two.Events.change);\n\n      }\n\n      if (l <= 3) { // Multiply Vector\n\n        var x, y, z;\n        a = a || 0;\n        b = b || 0;\n        c = c || 0;\n        e = this.elements;\n\n        // Go down rows first\n        // a, d, g, b, e, h, c, f, i\n\n        x = e[0] * a + e[1] * b + e[2] * c;\n        y = e[3] * a + e[4] * b + e[5] * c;\n        z = e[6] * a + e[7] * b + e[8] * c;\n\n        return { x: x, y: y, z: z };\n\n      }\n\n      // Multiple matrix\n\n      var A = this.elements;\n      var B = elements;\n\n      var A0 = A[0], A1 = A[1], A2 = A[2];\n      var A3 = A[3], A4 = A[4], A5 = A[5];\n      var A6 = A[6], A7 = A[7], A8 = A[8];\n\n      var B0 = B[0], B1 = B[1], B2 = B[2];\n      var B3 = B[3], B4 = B[4], B5 = B[5];\n      var B6 = B[6], B7 = B[7], B8 = B[8];\n\n      this.elements[0] = A0 * B0 + A1 * B3 + A2 * B6;\n      this.elements[1] = A0 * B1 + A1 * B4 + A2 * B7;\n      this.elements[2] = A0 * B2 + A1 * B5 + A2 * B8;\n\n      this.elements[3] = A3 * B0 + A4 * B3 + A5 * B6;\n      this.elements[4] = A3 * B1 + A4 * B4 + A5 * B7;\n      this.elements[5] = A3 * B2 + A4 * B5 + A5 * B8;\n\n      this.elements[6] = A6 * B0 + A7 * B3 + A8 * B6;\n      this.elements[7] = A6 * B1 + A7 * B4 + A8 * B7;\n      this.elements[8] = A6 * B2 + A7 * B5 + A8 * B8;\n\n      return this.trigger(Two.Events.change);\n\n    },\n\n    inverse: function(out) {\n\n      var a = this.elements;\n      out = out || new Two.Matrix();\n\n      var a00 = a[0], a01 = a[1], a02 = a[2];\n      var a10 = a[3], a11 = a[4], a12 = a[5];\n      var a20 = a[6], a21 = a[7], a22 = a[8];\n\n      var b01 = a22 * a11 - a12 * a21;\n      var b11 = -a22 * a10 + a12 * a20;\n      var b21 = a21 * a10 - a11 * a20;\n\n      // Calculate the determinant\n      var det = a00 * b01 + a01 * b11 + a02 * b21;\n\n      if (!det) {\n        return null;\n      }\n\n      det = 1.0 / det;\n\n      out.elements[0] = b01 * det;\n      out.elements[1] = (-a22 * a01 + a02 * a21) * det;\n      out.elements[2] = (a12 * a01 - a02 * a11) * det;\n      out.elements[3] = b11 * det;\n      out.elements[4] = (a22 * a00 - a02 * a20) * det;\n      out.elements[5] = (-a12 * a00 + a02 * a10) * det;\n      out.elements[6] = b21 * det;\n      out.elements[7] = (-a21 * a00 + a01 * a20) * det;\n      out.elements[8] = (a11 * a00 - a01 * a10) * det;\n\n      return out;\n\n    },\n\n    /**\n     * Set a scalar onto the matrix.\n     */\n    scale: function(sx, sy) {\n\n      var l = arguments.length;\n      if (l <= 1) {\n        sy = sx;\n      }\n\n      return this.multiply(sx, 0, 0, 0, sy, 0, 0, 0, 1);\n\n    },\n\n    /**\n     * Rotate the matrix.\n     */\n    rotate: function(radians) {\n\n      var c = cos(radians);\n      var s = sin(radians);\n\n      return this.multiply(c, -s, 0, s, c, 0, 0, 0, 1);\n\n    },\n\n    /**\n     * Translate the matrix.\n     */\n    translate: function(x, y) {\n\n      return this.multiply(1, 0, x, 0, 1, y, 0, 0, 1);\n\n    },\n\n    /*\n     * Skew the matrix by an angle in the x axis direction.\n     */\n    skewX: function(radians) {\n\n      var a = tan(radians);\n\n      return this.multiply(1, a, 0, 0, 1, 0, 0, 0, 1);\n\n    },\n\n    /*\n     * Skew the matrix by an angle in the y axis direction.\n     */\n    skewY: function(radians) {\n\n      var a = tan(radians);\n\n      return this.multiply(1, 0, 0, a, 1, 0, 0, 0, 1);\n\n    },\n\n    /**\n     * Create a transform string to be used with rendering apis.\n     */\n    toString: function(fullMatrix) {\n      var temp = [];\n\n      this.toArray(fullMatrix, temp);\n\n      return temp.join(' ');\n\n    },\n\n    /**\n     * Create a transform array to be used with rendering apis.\n     */\n    toArray: function(fullMatrix, output) {\n\n     var elements = this.elements;\n     var hasOutput = !!output;\n\n     var a = parseFloat(elements[0].toFixed(3));\n     var b = parseFloat(elements[1].toFixed(3));\n     var c = parseFloat(elements[2].toFixed(3));\n     var d = parseFloat(elements[3].toFixed(3));\n     var e = parseFloat(elements[4].toFixed(3));\n     var f = parseFloat(elements[5].toFixed(3));\n\n      if (!!fullMatrix) {\n\n        var g = parseFloat(elements[6].toFixed(3));\n        var h = parseFloat(elements[7].toFixed(3));\n        var i = parseFloat(elements[8].toFixed(3));\n\n        if (hasOutput) {\n          output[0] = a;\n          output[1] = d;\n          output[2] = g;\n          output[3] = b;\n          output[4] = e;\n          output[5] = h;\n          output[6] = c;\n          output[7] = f;\n          output[8] = i;\n          return;\n        }\n\n        return [\n          a, d, g, b, e, h, c, f, i\n        ];\n      }\n\n      if (hasOutput) {\n        output[0] = a;\n        output[1] = d;\n        output[2] = b;\n        output[3] = e;\n        output[4] = c;\n        output[5] = f;\n        return;\n      }\n\n      return [\n        a, d, b, e, c, f  // Specific format see LN:19\n      ];\n\n    },\n\n    /**\n     * Clone the current matrix.\n     */\n    clone: function() {\n      var a, b, c, d, e, f, g, h, i;\n\n      a = this.elements[0];\n      b = this.elements[1];\n      c = this.elements[2];\n      d = this.elements[3];\n      e = this.elements[4];\n      f = this.elements[5];\n      g = this.elements[6];\n      h = this.elements[7];\n      i = this.elements[8];\n\n      return new Two.Matrix(a, b, c, d, e, f, g, h, i);\n\n    }\n\n  });\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  // Localize variables\n  var mod = Two.Utils.mod, toFixed = Two.Utils.toFixed;\n  var _ = Two.Utils;\n\n  var svg = {\n\n    version: 1.1,\n\n    ns: 'http://www.w3.org/2000/svg',\n    xlink: 'http://www.w3.org/1999/xlink',\n\n    alignments: {\n      left: 'start',\n      center: 'middle',\n      right: 'end'\n    },\n\n    /**\n     * Create an svg namespaced element.\n     */\n    createElement: function(name, attrs) {\n      var tag = name;\n      var elem = document.createElementNS(this.ns, tag);\n      if (tag === 'svg') {\n        attrs = _.defaults(attrs || {}, {\n          version: this.version\n        });\n      }\n      if (!_.isEmpty(attrs)) {\n        svg.setAttributes(elem, attrs);\n      }\n      return elem;\n    },\n\n    /**\n     * Add attributes from an svg element.\n     */\n    setAttributes: function(elem, attrs) {\n      var keys = Object.keys(attrs);\n      for (var i = 0; i < keys.length; i++) {\n        elem.setAttribute(keys[i], attrs[keys[i]]);\n      }\n      return this;\n    },\n\n    /**\n     * Remove attributes from an svg element.\n     */\n    removeAttributes: function(elem, attrs) {\n      for (var key in attrs) {\n        elem.removeAttribute(key);\n      }\n      return this;\n    },\n\n    /**\n     * Turn a set of vertices into a string for the d property of a path\n     * element. It is imperative that the string collation is as fast as\n     * possible, because this call will be happening multiple times a\n     * second.\n     */\n    toString: function(points, closed) {\n\n      var l = points.length,\n        last = l - 1,\n        d, // The elusive last Two.Commands.move point\n        ret = '';\n\n      for (var i = 0; i < l; i++) {\n        var b = points[i];\n        var command;\n        var prev = closed ? mod(i - 1, l) : Math.max(i - 1, 0);\n        var next = closed ? mod(i + 1, l) : Math.min(i + 1, last);\n\n        var a = points[prev];\n        var c = points[next];\n\n        var vx, vy, ux, uy, ar, bl, br, cl;\n\n        // Access x and y directly,\n        // bypassing the getter\n        var x = toFixed(b._x);\n        var y = toFixed(b._y);\n\n        switch (b._command) {\n\n          case Two.Commands.close:\n            command = Two.Commands.close;\n            break;\n\n          case Two.Commands.curve:\n\n            ar = (a.controls && a.controls.right) || Two.Vector.zero;\n            bl = (b.controls && b.controls.left) || Two.Vector.zero;\n\n            if (a._relative) {\n              vx = toFixed((ar.x + a.x));\n              vy = toFixed((ar.y + a.y));\n            } else {\n              vx = toFixed(ar.x);\n              vy = toFixed(ar.y);\n            }\n\n            if (b._relative) {\n              ux = toFixed((bl.x + b.x));\n              uy = toFixed((bl.y + b.y));\n            } else {\n              ux = toFixed(bl.x);\n              uy = toFixed(bl.y);\n            }\n\n            command = ((i === 0) ? Two.Commands.move : Two.Commands.curve) +\n              ' ' + vx + ' ' + vy + ' ' + ux + ' ' + uy + ' ' + x + ' ' + y;\n            break;\n\n          case Two.Commands.move:\n            d = b;\n            command = Two.Commands.move + ' ' + x + ' ' + y;\n            break;\n\n          default:\n            command = b._command + ' ' + x + ' ' + y;\n\n        }\n\n        // Add a final point and close it off\n\n        if (i >= last && closed) {\n\n          if (b._command === Two.Commands.curve) {\n\n            // Make sure we close to the most previous Two.Commands.move\n            c = d;\n\n            br = (b.controls && b.controls.right) || b;\n            cl = (c.controls && c.controls.left) || c;\n\n            if (b._relative) {\n              vx = toFixed((br.x + b.x));\n              vy = toFixed((br.y + b.y));\n            } else {\n              vx = toFixed(br.x);\n              vy = toFixed(br.y);\n            }\n\n            if (c._relative) {\n              ux = toFixed((cl.x + c.x));\n              uy = toFixed((cl.y + c.y));\n            } else {\n              ux = toFixed(cl.x);\n              uy = toFixed(cl.y);\n            }\n\n            x = toFixed(c.x);\n            y = toFixed(c.y);\n\n            command +=\n              ' C ' + vx + ' ' + vy + ' ' + ux + ' ' + uy + ' ' + x + ' ' + y;\n          }\n\n          command += ' Z';\n\n        }\n\n        ret += command + ' ';\n\n      }\n\n      return ret;\n\n    },\n\n    getClip: function(shape) {\n\n      var clip = shape._renderer.clip;\n\n      if (!clip) {\n\n        var root = shape;\n\n        while (root.parent) {\n          root = root.parent;\n        }\n\n        clip = shape._renderer.clip = svg.createElement('clipPath');\n        root.defs.appendChild(clip);\n\n      }\n\n      return clip;\n\n    },\n\n    group: {\n\n      // TODO: Can speed up.\n      // TODO: How does this effect a f\n      appendChild: function(object) {\n\n        var elem = object._renderer.elem;\n\n        if (!elem) {\n          return;\n        }\n\n        var tag = elem.nodeName;\n\n        if (!tag || /(radial|linear)gradient/i.test(tag) || object._clip) {\n          return;\n        }\n\n        this.elem.appendChild(elem);\n\n      },\n\n      removeChild: function(object) {\n\n        var elem = object._renderer.elem;\n\n        if (!elem || elem.parentNode != this.elem) {\n          return;\n        }\n\n        var tag = elem.nodeName;\n\n        if (!tag) {\n          return;\n        }\n\n        // Defer subtractions while clipping.\n        if (object._clip) {\n          return;\n        }\n\n        this.elem.removeChild(elem);\n\n      },\n\n      orderChild: function(object) {\n        this.elem.appendChild(object._renderer.elem);\n      },\n\n      renderChild: function(child) {\n        svg[child._renderer.type].render.call(child, this);\n      },\n\n      render: function(domElement) {\n\n        this._update();\n\n        // Shortcut for hidden objects.\n        // Doesn't reset the flags, so changes are stored and\n        // applied once the object is visible again\n        if (this._opacity === 0 && !this._flagOpacity) {\n          return this;\n        }\n\n        if (!this._renderer.elem) {\n          this._renderer.elem = svg.createElement('g', {\n            id: this.id\n          });\n          domElement.appendChild(this._renderer.elem);\n        }\n\n        // _Update styles for the <g>\n        var flagMatrix = this._matrix.manual || this._flagMatrix;\n        var context = {\n          domElement: domElement,\n          elem: this._renderer.elem\n        };\n\n        if (flagMatrix) {\n          this._renderer.elem.setAttribute('transform', 'matrix(' + this._matrix.toString() + ')');\n        }\n\n        for (var i = 0; i < this.children.length; i++) {\n          var child = this.children[i];\n          svg[child._renderer.type].render.call(child, domElement);\n        }\n\n        if (this._flagOpacity) {\n          this._renderer.elem.setAttribute('opacity', this._opacity);\n        }\n\n        if (this._flagAdditions) {\n          this.additions.forEach(svg.group.appendChild, context);\n        }\n\n        if (this._flagSubtractions) {\n          this.subtractions.forEach(svg.group.removeChild, context);\n        }\n\n        if (this._flagOrder) {\n          this.children.forEach(svg.group.orderChild, context);\n        }\n\n        /**\n         * Commented two-way functionality of clips / masks with groups and\n         * polygons. Uncomment when this bug is fixed:\n         * https://code.google.com/p/chromium/issues/detail?id=370951\n         */\n\n        // if (this._flagClip) {\n\n        //   clip = svg.getClip(this);\n        //   elem = this._renderer.elem;\n\n        //   if (this._clip) {\n        //     elem.removeAttribute('id');\n        //     clip.setAttribute('id', this.id);\n        //     clip.appendChild(elem);\n        //   } else {\n        //     clip.removeAttribute('id');\n        //     elem.setAttribute('id', this.id);\n        //     this.parent._renderer.elem.appendChild(elem); // TODO: should be insertBefore\n        //   }\n\n        // }\n\n        if (this._flagMask) {\n          if (this._mask) {\n            this._renderer.elem.setAttribute('clip-path', 'url(#' + this._mask.id + ')');\n          } else {\n            this._renderer.elem.removeAttribute('clip-path');\n          }\n        }\n\n        return this.flagReset();\n\n      }\n\n    },\n\n    path: {\n\n      render: function(domElement) {\n\n        this._update();\n\n        // Shortcut for hidden objects.\n        // Doesn't reset the flags, so changes are stored and\n        // applied once the object is visible again\n        if (this._opacity === 0 && !this._flagOpacity) {\n          return this;\n        }\n\n        // Collect any attribute that needs to be changed here\n        var changed = {};\n\n        var flagMatrix = this._matrix.manual || this._flagMatrix;\n\n        if (flagMatrix) {\n          changed.transform = 'matrix(' + this._matrix.toString() + ')';\n        }\n\n        if (this._flagVertices) {\n          var vertices = svg.toString(this._vertices, this._closed);\n          changed.d = vertices;\n        }\n\n        if (this._fill && this._fill._renderer) {\n          this._fill._update();\n          svg[this._fill._renderer.type].render.call(this._fill, domElement, true);\n        }\n\n        if (this._flagFill) {\n          changed.fill = this._fill && this._fill.id\n            ? 'url(#' + this._fill.id + ')' : this._fill;\n        }\n\n        if (this._stroke && this._stroke._renderer) {\n          this._stroke._update();\n          svg[this._stroke._renderer.type].render.call(this._stroke, domElement, true);\n        }\n\n        if (this._flagStroke) {\n          changed.stroke = this._stroke && this._stroke.id\n            ? 'url(#' + this._stroke.id + ')' : this._stroke;\n        }\n\n        if (this._flagLinewidth) {\n          changed['stroke-width'] = this._linewidth;\n        }\n\n        if (this._flagOpacity) {\n          changed['stroke-opacity'] = this._opacity;\n          changed['fill-opacity'] = this._opacity;\n        }\n\n        if (this._flagVisible) {\n          changed.visibility = this._visible ? 'visible' : 'hidden';\n        }\n\n        if (this._flagCap) {\n          changed['stroke-linecap'] = this._cap;\n        }\n\n        if (this._flagJoin) {\n          changed['stroke-linejoin'] = this._join;\n        }\n\n        if (this._flagMiter) {\n          changed['stroke-miterlimit'] = this._miter;\n        }\n\n        // If there is no attached DOM element yet,\n        // create it with all necessary attributes.\n        if (!this._renderer.elem) {\n\n          changed.id = this.id;\n          this._renderer.elem = svg.createElement('path', changed);\n          domElement.appendChild(this._renderer.elem);\n\n        // Otherwise apply all pending attributes\n        } else {\n          svg.setAttributes(this._renderer.elem, changed);\n        }\n\n        if (this._flagClip) {\n\n          var clip = svg.getClip(this);\n          var elem = this._renderer.elem;\n\n          if (this._clip) {\n            elem.removeAttribute('id');\n            clip.setAttribute('id', this.id);\n            clip.appendChild(elem);\n          } else {\n            clip.removeAttribute('id');\n            elem.setAttribute('id', this.id);\n            this.parent._renderer.elem.appendChild(elem); // TODO: should be insertBefore\n          }\n\n        }\n\n        /**\n         * Commented two-way functionality of clips / masks with groups and\n         * polygons. Uncomment when this bug is fixed:\n         * https://code.google.com/p/chromium/issues/detail?id=370951\n         */\n\n        // if (this._flagMask) {\n        //   if (this._mask) {\n        //     elem.setAttribute('clip-path', 'url(#' + this._mask.id + ')');\n        //   } else {\n        //     elem.removeAttribute('clip-path');\n        //   }\n        // }\n\n        return this.flagReset();\n\n      }\n\n    },\n\n    text: {\n\n      render: function(domElement) {\n\n        this._update();\n\n        var changed = {};\n\n        var flagMatrix = this._matrix.manual || this._flagMatrix;\n\n        if (flagMatrix) {\n          changed.transform = 'matrix(' + this._matrix.toString() + ')';\n        }\n\n        if (this._flagFamily) {\n          changed['font-family'] = this._family;\n        }\n        if (this._flagSize) {\n          changed['font-size'] = this._size;\n        }\n        if (this._flagLeading) {\n          changed['line-height'] = this._leading;\n        }\n        if (this._flagAlignment) {\n          changed['text-anchor'] = svg.alignments[this._alignment] || this._alignment;\n        }\n        if (this._flagBaseline) {\n          changed['alignment-baseline'] = changed['dominant-baseline'] = this._baseline;\n        }\n        if (this._flagStyle) {\n          changed['font-style'] = this._style;\n        }\n        if (this._flagWeight) {\n          changed['font-weight'] = this._weight;\n        }\n        if (this._flagDecoration) {\n          changed['text-decoration'] = this._decoration;\n        }\n        if (this._fill && this._fill._renderer) {\n          this._fill._update();\n          svg[this._fill._renderer.type].render.call(this._fill, domElement, true);\n        }\n        if (this._flagFill) {\n          changed.fill = this._fill && this._fill.id\n            ? 'url(#' + this._fill.id + ')' : this._fill;\n        }\n        if (this._stroke && this._stroke._renderer) {\n          this._stroke._update();\n          svg[this._stroke._renderer.type].render.call(this._stroke, domElement, true);\n        }\n        if (this._flagStroke) {\n          changed.stroke = this._stroke && this._stroke.id\n            ? 'url(#' + this._stroke.id + ')' : this._stroke;\n        }\n        if (this._flagLinewidth) {\n          changed['stroke-width'] = this._linewidth;\n        }\n        if (this._flagOpacity) {\n          changed.opacity = this._opacity;\n        }\n        if (this._flagVisible) {\n          changed.visibility = this._visible ? 'visible' : 'hidden';\n        }\n\n        if (!this._renderer.elem) {\n\n          changed.id = this.id;\n\n          this._renderer.elem = svg.createElement('text', changed);\n          domElement.defs.appendChild(this._renderer.elem);\n\n        } else {\n\n          svg.setAttributes(this._renderer.elem, changed);\n\n        }\n\n        if (this._flagClip) {\n\n          var clip = svg.getClip(this);\n          var elem = this._renderer.elem;\n\n          if (this._clip) {\n            elem.removeAttribute('id');\n            clip.setAttribute('id', this.id);\n            clip.appendChild(elem);\n          } else {\n            clip.removeAttribute('id');\n            elem.setAttribute('id', this.id);\n            this.parent._renderer.elem.appendChild(elem); // TODO: should be insertBefore\n          }\n\n        }\n\n        if (this._flagValue) {\n          this._renderer.elem.textContent = this._value;\n        }\n\n        return this.flagReset();\n\n      }\n\n    },\n\n    'linear-gradient': {\n\n      render: function(domElement, silent) {\n\n        if (!silent) {\n          this._update();\n        }\n\n        var changed = {};\n\n        if (this._flagEndPoints) {\n          changed.x1 = this.left._x;\n          changed.y1 = this.left._y;\n          changed.x2 = this.right._x;\n          changed.y2 = this.right._y;\n        }\n\n        if (this._flagSpread) {\n          changed.spreadMethod = this._spread;\n        }\n\n        // If there is no attached DOM element yet,\n        // create it with all necessary attributes.\n        if (!this._renderer.elem) {\n\n          changed.id = this.id;\n          changed.gradientUnits = 'userSpaceOnUse';\n          this._renderer.elem = svg.createElement('linearGradient', changed);\n          domElement.defs.appendChild(this._renderer.elem);\n\n        // Otherwise apply all pending attributes\n        } else {\n\n          svg.setAttributes(this._renderer.elem, changed);\n\n        }\n\n        if (this._flagStops) {\n\n          var lengthChanged = this._renderer.elem.childNodes.length\n            !== this.stops.length;\n\n          if (lengthChanged) {\n            this._renderer.elem.childNodes.length = 0;\n          }\n\n          for (var i = 0; i < this.stops.length; i++) {\n\n            var stop = this.stops[i];\n            var attrs = {};\n\n            if (stop._flagOffset) {\n              attrs.offset = 100 * stop._offset + '%';\n            }\n            if (stop._flagColor) {\n              attrs['stop-color'] = stop._color;\n            }\n            if (stop._flagOpacity) {\n              attrs['stop-opacity'] = stop._opacity;\n            }\n\n            if (!stop._renderer.elem) {\n              stop._renderer.elem = svg.createElement('stop', attrs);\n            } else {\n              svg.setAttributes(stop._renderer.elem, attrs);\n            }\n\n            if (lengthChanged) {\n              this._renderer.elem.appendChild(stop._renderer.elem);\n            }\n            stop.flagReset();\n\n          }\n\n        }\n\n        return this.flagReset();\n\n      }\n\n    },\n\n    'radial-gradient': {\n\n      render: function(domElement, silent) {\n\n        if (!silent) {\n          this._update();\n        }\n\n        var changed = {};\n\n        if (this._flagCenter) {\n          changed.cx = this.center._x;\n          changed.cy = this.center._y;\n        }\n        if (this._flagFocal) {\n          changed.fx = this.focal._x;\n          changed.fy = this.focal._y;\n        }\n\n        if (this._flagRadius) {\n          changed.r = this._radius;\n        }\n\n        if (this._flagSpread) {\n          changed.spreadMethod = this._spread;\n        }\n\n        // If there is no attached DOM element yet,\n        // create it with all necessary attributes.\n        if (!this._renderer.elem) {\n\n          changed.id = this.id;\n          changed.gradientUnits = 'userSpaceOnUse';\n          this._renderer.elem = svg.createElement('radialGradient', changed);\n          domElement.defs.appendChild(this._renderer.elem);\n\n        // Otherwise apply all pending attributes\n        } else {\n\n          svg.setAttributes(this._renderer.elem, changed);\n\n        }\n\n        if (this._flagStops) {\n\n          var lengthChanged = this._renderer.elem.childNodes.length\n            !== this.stops.length;\n\n          if (lengthChanged) {\n            this._renderer.elem.childNodes.length = 0;\n          }\n\n          for (var i = 0; i < this.stops.length; i++) {\n\n            var stop = this.stops[i];\n            var attrs = {};\n\n            if (stop._flagOffset) {\n              attrs.offset = 100 * stop._offset + '%';\n            }\n            if (stop._flagColor) {\n              attrs['stop-color'] = stop._color;\n            }\n            if (stop._flagOpacity) {\n              attrs['stop-opacity'] = stop._opacity;\n            }\n\n            if (!stop._renderer.elem) {\n              stop._renderer.elem = svg.createElement('stop', attrs);\n            } else {\n              svg.setAttributes(stop._renderer.elem, attrs);\n            }\n\n            if (lengthChanged) {\n              this._renderer.elem.appendChild(stop._renderer.elem);\n            }\n            stop.flagReset();\n\n          }\n\n        }\n\n        return this.flagReset();\n\n      }\n\n    },\n\n    texture: {\n\n      render: function(domElement, silent) {\n\n        if (!silent) {\n          this._update();\n        }\n\n        var changed = {};\n        var styles = {};\n        var image = this.image;\n\n        if (this._flagLoaded && this.loaded) {\n\n          switch (image.nodeName.toLowerCase()) {\n\n            case 'canvas':\n              styles.href = image.toDataURL('image/png');\n              break;\n            case 'img':\n            case 'image':\n              styles.href = this.src;\n              break;\n\n          }\n\n        }\n\n        if (this._flagOffset || this._flagLoaded || this._flagScale) {\n\n          changed.x = this._offset.x;\n          changed.y = this._offset.y;\n\n          if (image) {\n\n            changed.x -= image.width / 2;\n            changed.y -= image.height / 2;\n\n            if (this._scale instanceof Two.Vector) {\n              changed.x *= this._scale.x;\n              changed.y *= this._scale.y;\n            } else {\n              changed.x *= this._scale;\n              changed.y *= this._scale;\n            }\n          }\n\n        }\n\n        if (this._flagScale || this._flagLoaded || this._flagRepeat) {\n\n          changed.width = 0;\n          changed.height = 0;\n\n          if (image) {\n\n            styles.width = changed.width = image.width;\n            styles.height = changed.height = image.height;\n\n            // TODO: Hack / Bandaid\n            switch (this._repeat) {\n              case 'no-repeat':\n                changed.width += 1;\n                changed.height += 1;\n                break;\n            }\n\n            if (this._scale instanceof Two.Vector) {\n              changed.width *= this._scale.x;\n              changed.height *= this._scale.y;\n            } else {\n              changed.width *= this._scale;\n              changed.height *= this._scale;\n            }\n          }\n\n        }\n\n        if (this._flagScale || this._flagLoaded) {\n          if (!this._renderer.image) {\n            this._renderer.image = svg.createElement('image', styles);\n          } else if (!_.isEmpty(styles)) {\n            svg.setAttributes(this._renderer.image, styles);\n          }\n        }\n\n        if (!this._renderer.elem) {\n\n          changed.id = this.id;\n          changed.patternUnits = 'userSpaceOnUse';\n          this._renderer.elem = svg.createElement('pattern', changed);\n          domElement.defs.appendChild(this._renderer.elem);\n\n        } else if (!_.isEmpty(changed)) {\n\n          svg.setAttributes(this._renderer.elem, changed);\n\n        }\n\n        if (this._renderer.elem && this._renderer.image && !this._renderer.appended) {\n          this._renderer.elem.appendChild(this._renderer.image);\n          this._renderer.appended = true;\n        }\n\n        return this.flagReset();\n\n      }\n\n    }\n\n  };\n\n  /**\n   * @class\n   */\n  var Renderer = Two[Two.Types.svg] = function(params) {\n\n    this.domElement = params.domElement || svg.createElement('svg');\n\n    this.scene = new Two.Group();\n    this.scene.parent = this;\n\n    this.defs = svg.createElement('defs');\n    this.domElement.appendChild(this.defs);\n    this.domElement.defs = this.defs;\n    this.domElement.style.overflow = 'hidden';\n\n  };\n\n  _.extend(Renderer, {\n\n    Utils: svg\n\n  });\n\n  _.extend(Renderer.prototype, Two.Utils.Events, {\n\n    setSize: function(width, height) {\n\n      this.width = width;\n      this.height = height;\n\n      svg.setAttributes(this.domElement, {\n        width: width,\n        height: height\n      });\n\n      return this;\n\n    },\n\n    render: function() {\n\n      svg.group.render.call(this.scene, this.domElement);\n\n      return this;\n\n    }\n\n  });\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  /**\n   * Constants\n   */\n  var mod = Two.Utils.mod, toFixed = Two.Utils.toFixed;\n  var getRatio = Two.Utils.getRatio;\n  var _ = Two.Utils;\n\n  // Returns true if this is a non-transforming matrix\n  var isDefaultMatrix = function (m) {\n    return (m[0] == 1 && m[3] == 0 && m[1] == 0 && m[4] == 1 && m[2] == 0 && m[5] == 0);\n  };\n\n  var canvas = {\n\n    isHidden: /(none|transparent)/i,\n\n    alignments: {\n      left: 'start',\n      middle: 'center',\n      right: 'end'\n    },\n\n    shim: function(elem) {\n      elem.tagName = 'canvas';\n      elem.nodeType = 1;\n      return elem;\n    },\n\n    group: {\n\n      renderChild: function(child) {\n        canvas[child._renderer.type].render.call(child, this.ctx, true, this.clip);\n      },\n\n      render: function(ctx) {\n\n        // TODO: Add a check here to only invoke _update if need be.\n        this._update();\n\n        var matrix = this._matrix.elements;\n        var parent = this.parent;\n        this._renderer.opacity = this._opacity * (parent && parent._renderer ? parent._renderer.opacity : 1);\n\n        var defaultMatrix = isDefaultMatrix(matrix);\n\n        var mask = this._mask;\n        // var clip = this._clip;\n\n        if (!this._renderer.context) {\n          this._renderer.context = {};\n        }\n\n        this._renderer.context.ctx = ctx;\n        // this._renderer.context.clip = clip;\n\n        if (!defaultMatrix) {\n          ctx.save();\n          ctx.transform(matrix[0], matrix[3], matrix[1], matrix[4], matrix[2], matrix[5]);\n        }\n\n        if (mask) {\n          canvas[mask._renderer.type].render.call(mask, ctx, true);\n        }\n\n        for (var i = 0; i < this.children.length; i++) {\n          var child = this.children[i];\n          canvas[child._renderer.type].render.call(child, ctx);\n        }\n\n        if (!defaultMatrix) {\n          ctx.restore();\n        }\n\n       /**\n         * Commented two-way functionality of clips / masks with groups and\n         * polygons. Uncomment when this bug is fixed:\n         * https://code.google.com/p/chromium/issues/detail?id=370951\n         */\n\n        // if (clip) {\n        //   ctx.clip();\n        // }\n\n        return this.flagReset();\n\n      }\n\n    },\n\n    path: {\n\n      render: function(ctx, forced, parentClipped) {\n\n        var matrix, stroke, linewidth, fill, opacity, visible, cap, join, miter,\n            closed, commands, length, last, next, prev, a, b, c, d, ux, uy, vx, vy,\n            ar, bl, br, cl, x, y, mask, clip, defaultMatrix, isOffset;\n\n        // TODO: Add a check here to only invoke _update if need be.\n        this._update();\n\n        matrix = this._matrix.elements;\n        stroke = this._stroke;\n        linewidth = this._linewidth;\n        fill = this._fill;\n        opacity = this._opacity * this.parent._renderer.opacity;\n        visible = this._visible;\n        cap = this._cap;\n        join = this._join;\n        miter = this._miter;\n        closed = this._closed;\n        commands = this._vertices; // Commands\n        length = commands.length;\n        last = length - 1;\n        defaultMatrix = isDefaultMatrix(matrix);\n\n        // mask = this._mask;\n        clip = this._clip;\n\n        if (!forced && (!visible || clip)) {\n          return this;\n        }\n\n        // Transform\n        if (!defaultMatrix) {\n          ctx.save();\n          ctx.transform(matrix[0], matrix[3], matrix[1], matrix[4], matrix[2], matrix[5]);\n        }\n\n       /**\n         * Commented two-way functionality of clips / masks with groups and\n         * polygons. Uncomment when this bug is fixed:\n         * https://code.google.com/p/chromium/issues/detail?id=370951\n         */\n\n        // if (mask) {\n        //   canvas[mask._renderer.type].render.call(mask, ctx, true);\n        // }\n\n        // Styles\n        if (fill) {\n          if (_.isString(fill)) {\n            ctx.fillStyle = fill;\n          } else {\n            canvas[fill._renderer.type].render.call(fill, ctx);\n            ctx.fillStyle = fill._renderer.effect;\n          }\n        }\n        if (stroke) {\n          if (_.isString(stroke)) {\n            ctx.strokeStyle = stroke;\n          } else {\n            canvas[stroke._renderer.type].render.call(stroke, ctx);\n            ctx.strokeStyle = stroke._renderer.effect;\n          }\n        }\n        if (linewidth) {\n          ctx.lineWidth = linewidth;\n        }\n        if (miter) {\n          ctx.miterLimit = miter;\n        }\n        if (join) {\n          ctx.lineJoin = join;\n        }\n        if (cap) {\n          ctx.lineCap = cap;\n        }\n        if (_.isNumber(opacity)) {\n          ctx.globalAlpha = opacity;\n        }\n\n        ctx.beginPath();\n\n        for (var i = 0; i < commands.length; i++) {\n\n          b = commands[i];\n\n          x = toFixed(b._x);\n          y = toFixed(b._y);\n\n          switch (b._command) {\n\n            case Two.Commands.close:\n              ctx.closePath();\n              break;\n\n            case Two.Commands.curve:\n\n              prev = closed ? mod(i - 1, length) : Math.max(i - 1, 0);\n              next = closed ? mod(i + 1, length) : Math.min(i + 1, last);\n\n              a = commands[prev];\n              c = commands[next];\n              ar = (a.controls && a.controls.right) || Two.Vector.zero;\n              bl = (b.controls && b.controls.left) || Two.Vector.zero;\n\n              if (a._relative) {\n                vx = (ar.x + toFixed(a._x));\n                vy = (ar.y + toFixed(a._y));\n              } else {\n                vx = toFixed(ar.x);\n                vy = toFixed(ar.y);\n              }\n\n              if (b._relative) {\n                ux = (bl.x + toFixed(b._x));\n                uy = (bl.y + toFixed(b._y));\n              } else {\n                ux = toFixed(bl.x);\n                uy = toFixed(bl.y);\n              }\n\n              ctx.bezierCurveTo(vx, vy, ux, uy, x, y);\n\n              if (i >= last && closed) {\n\n                c = d;\n\n                br = (b.controls && b.controls.right) || Two.Vector.zero;\n                cl = (c.controls && c.controls.left) || Two.Vector.zero;\n\n                if (b._relative) {\n                  vx = (br.x + toFixed(b._x));\n                  vy = (br.y + toFixed(b._y));\n                } else {\n                  vx = toFixed(br.x);\n                  vy = toFixed(br.y);\n                }\n\n                if (c._relative) {\n                  ux = (cl.x + toFixed(c._x));\n                  uy = (cl.y + toFixed(c._y));\n                } else {\n                  ux = toFixed(cl.x);\n                  uy = toFixed(cl.y);\n                }\n\n                x = toFixed(c._x);\n                y = toFixed(c._y);\n\n                ctx.bezierCurveTo(vx, vy, ux, uy, x, y);\n\n              }\n\n              break;\n\n            case Two.Commands.line:\n              ctx.lineTo(x, y);\n              break;\n\n            case Two.Commands.move:\n              d = b;\n              ctx.moveTo(x, y);\n              break;\n\n          }\n        }\n\n        // Loose ends\n\n        if (closed) {\n          ctx.closePath();\n        }\n\n        if (!clip && !parentClipped) {\n          if (!canvas.isHidden.test(fill)) {\n            isOffset = fill._renderer && fill._renderer.offset\n            if (isOffset) {\n              ctx.save();\n              ctx.translate(\n                - fill._renderer.offset.x, - fill._renderer.offset.y);\n              ctx.scale(fill._renderer.scale.x, fill._renderer.scale.y);\n            }\n            ctx.fill();\n            if (isOffset) {\n              ctx.restore();\n            }\n          }\n          if (!canvas.isHidden.test(stroke)) {\n            isOffset = stroke._renderer && stroke._renderer.offset;\n            if (isOffset) {\n              ctx.save();\n              ctx.translate(\n                - stroke._renderer.offset.x, - stroke._renderer.offset.y);\n              ctx.scale(stroke._renderer.scale.x, stroke._renderer.scale.y);\n              ctx.lineWidth = linewidth / stroke._renderer.scale.x;\n            }\n            ctx.stroke();\n            if (isOffset) {\n              ctx.restore();\n            }\n          }\n        }\n\n        if (!defaultMatrix) {\n          ctx.restore();\n        }\n\n        if (clip && !parentClipped) {\n          ctx.clip();\n        }\n\n        return this.flagReset();\n\n      }\n\n    },\n\n    text: {\n\n      render: function(ctx, forced, parentClipped) {\n\n        // TODO: Add a check here to only invoke _update if need be.\n        this._update();\n\n        var matrix = this._matrix.elements;\n        var stroke = this._stroke;\n        var linewidth = this._linewidth;\n        var fill = this._fill;\n        var opacity = this._opacity * this.parent._renderer.opacity;\n        var visible = this._visible;\n        var defaultMatrix = isDefaultMatrix(matrix);\n        var isOffset = fill._renderer && fill._renderer.offset\n          && stroke._renderer && stroke._renderer.offset;\n\n        var a, b, c, d, e, sx, sy;\n\n        // mask = this._mask;\n        var clip = this._clip;\n\n        if (!forced && (!visible || clip)) {\n          return this;\n        }\n\n        // Transform\n        if (!defaultMatrix) {\n          ctx.save();\n          ctx.transform(matrix[0], matrix[3], matrix[1], matrix[4], matrix[2], matrix[5]);\n        }\n\n       /**\n         * Commented two-way functionality of clips / masks with groups and\n         * polygons. Uncomment when this bug is fixed:\n         * https://code.google.com/p/chromium/issues/detail?id=370951\n         */\n\n        // if (mask) {\n        //   canvas[mask._renderer.type].render.call(mask, ctx, true);\n        // }\n\n        if (!isOffset) {\n          ctx.font = [this._style, this._weight, this._size + 'px/' +\n            this._leading + 'px', this._family].join(' ');\n        }\n\n        ctx.textAlign = canvas.alignments[this._alignment] || this._alignment;\n        ctx.textBaseline = this._baseline;\n\n        // Styles\n        if (fill) {\n          if (_.isString(fill)) {\n            ctx.fillStyle = fill;\n          } else {\n            canvas[fill._renderer.type].render.call(fill, ctx);\n            ctx.fillStyle = fill._renderer.effect;\n          }\n        }\n        if (stroke) {\n          if (_.isString(stroke)) {\n            ctx.strokeStyle = stroke;\n          } else {\n            canvas[stroke._renderer.type].render.call(stroke, ctx);\n            ctx.strokeStyle = stroke._renderer.effect;\n          }\n        }\n        if (linewidth) {\n          ctx.lineWidth = linewidth;\n        }\n        if (_.isNumber(opacity)) {\n          ctx.globalAlpha = opacity;\n        }\n\n        if (!clip && !parentClipped) {\n\n          if (!canvas.isHidden.test(fill)) {\n\n            if (fill._renderer && fill._renderer.offset) {\n\n              sx = toFixed(fill._renderer.scale.x);\n              sy = toFixed(fill._renderer.scale.y);\n\n              ctx.save();\n              ctx.translate( - toFixed(fill._renderer.offset.x),\n                - toFixed(fill._renderer.offset.y));\n              ctx.scale(sx, sy);\n\n              a = this._size / fill._renderer.scale.y;\n              b = this._leading / fill._renderer.scale.y;\n              ctx.font = [this._style, this._weight, toFixed(a) + 'px/',\n                toFixed(b) + 'px', this._family].join(' ');\n\n              c = fill._renderer.offset.x / fill._renderer.scale.x;\n              d = fill._renderer.offset.y / fill._renderer.scale.y;\n\n              ctx.fillText(this.value, toFixed(c), toFixed(d));\n              ctx.restore();\n\n            } else {\n              ctx.fillText(this.value, 0, 0);\n            }\n\n          }\n\n          if (!canvas.isHidden.test(stroke)) {\n\n            if (stroke._renderer && stroke._renderer.offset) {\n\n              sx = toFixed(stroke._renderer.scale.x);\n              sy = toFixed(stroke._renderer.scale.y);\n\n              ctx.save();\n              ctx.translate(- toFixed(stroke._renderer.offset.x),\n                - toFixed(stroke._renderer.offset.y));\n              ctx.scale(sx, sy);\n\n              a = this._size / stroke._renderer.scale.y;\n              b = this._leading / stroke._renderer.scale.y;\n              ctx.font = [this._style, this._weight, toFixed(a) + 'px/',\n                toFixed(b) + 'px', this._family].join(' ');\n\n              c = stroke._renderer.offset.x / stroke._renderer.scale.x;\n              d = stroke._renderer.offset.y / stroke._renderer.scale.y;\n              e = linewidth / stroke._renderer.scale.x;\n\n              ctx.lineWidth = toFixed(e);\n              ctx.strokeText(this.value, toFixed(c), toFixed(d));\n              ctx.restore();\n\n            } else {\n              ctx.strokeText(this.value, 0, 0);\n            }\n          }\n        }\n\n        if (!defaultMatrix) {\n          ctx.restore();\n        }\n\n        // TODO: Test for text\n        if (clip && !parentClipped) {\n          ctx.clip();\n        }\n\n        return this.flagReset();\n\n      }\n\n    },\n\n    'linear-gradient': {\n\n      render: function(ctx) {\n\n        this._update();\n\n        if (!this._renderer.effect || this._flagEndPoints || this._flagStops) {\n\n          this._renderer.effect = ctx.createLinearGradient(\n            this.left._x, this.left._y,\n            this.right._x, this.right._y\n          );\n\n          for (var i = 0; i < this.stops.length; i++) {\n            var stop = this.stops[i];\n            this._renderer.effect.addColorStop(stop._offset, stop._color);\n          }\n\n        }\n\n        return this.flagReset();\n\n      }\n\n    },\n\n    'radial-gradient': {\n\n      render: function(ctx) {\n\n        this._update();\n\n        if (!this._renderer.effect || this._flagCenter || this._flagFocal\n            || this._flagRadius || this._flagStops) {\n\n          this._renderer.effect = ctx.createRadialGradient(\n            this.center._x, this.center._y, 0,\n            this.focal._x, this.focal._y, this._radius\n          );\n\n          for (var i = 0; i < this.stops.length; i++) {\n            var stop = this.stops[i];\n            this._renderer.effect.addColorStop(stop._offset, stop._color);\n          }\n\n        }\n\n        return this.flagReset();\n\n      }\n\n    },\n\n    texture: {\n\n      render: function(ctx) {\n\n        this._update();\n\n        var image = this.image;\n        var repeat;\n\n        if (!this._renderer.effect || ((this._flagLoaded || this._flagImage || this._flagRepeat) && this.loaded)) {\n          this._renderer.effect = ctx.createPattern(this.image, this._repeat);\n        }\n\n        if (this._flagOffset || this._flagLoaded || this._flagScale) {\n\n          if (!(this._renderer.offset instanceof Two.Vector)) {\n            this._renderer.offset = new Two.Vector();\n          }\n\n          this._renderer.offset.x = this._offset.x;\n          this._renderer.offset.y = this._offset.y;\n\n          if (image) {\n\n            this._renderer.offset.x -= image.width / 2;\n            this._renderer.offset.y += image.height / 2;\n\n            if (this._scale instanceof Two.Vector) {\n              this._renderer.offset.x *= this._scale.x;\n              this._renderer.offset.y *= this._scale.y;\n            } else {\n              this._renderer.offset.x *= this._scale;\n              this._renderer.offset.y *= this._scale;\n            }\n          }\n\n        }\n\n        if (this._flagScale || this._flagLoaded) {\n\n          if (!(this._renderer.scale instanceof Two.Vector)) {\n            this._renderer.scale = new Two.Vector();\n          }\n\n          if (this._scale instanceof Two.Vector) {\n            this._renderer.scale.copy(this._scale);\n          } else {\n            this._renderer.scale.set(this._scale, this._scale);\n          }\n\n        }\n\n        return this.flagReset();\n\n      }\n\n    }\n\n  };\n\n  var Renderer = Two[Two.Types.canvas] = function(params) {\n    // Smoothing property. Defaults to true\n    // Set it to false when working with pixel art.\n    // false can lead to better performance, since it would use a cheaper interpolation algorithm.\n    // It might not make a big difference on GPU backed canvases.\n    var smoothing = (params.smoothing !== false);\n    this.domElement = params.domElement || document.createElement('canvas');\n    this.ctx = this.domElement.getContext('2d');\n    this.overdraw = params.overdraw || false;\n\n    if (!_.isUndefined(this.ctx.imageSmoothingEnabled)) {\n      this.ctx.imageSmoothingEnabled = smoothing;\n    }\n\n    // Everything drawn on the canvas needs to be added to the scene.\n    this.scene = new Two.Group();\n    this.scene.parent = this;\n  };\n\n\n  _.extend(Renderer, {\n\n    Utils: canvas\n\n  });\n\n  _.extend(Renderer.prototype, Two.Utils.Events, {\n\n    setSize: function(width, height, ratio) {\n\n      this.width = width;\n      this.height = height;\n\n      this.ratio = _.isUndefined(ratio) ? getRatio(this.ctx) : ratio;\n\n      this.domElement.width = width * this.ratio;\n      this.domElement.height = height * this.ratio;\n\n      if (this.domElement.style) {\n        _.extend(this.domElement.style, {\n          width: width + 'px',\n          height: height + 'px'\n        });\n      }\n\n      return this;\n\n    },\n\n    render: function() {\n\n      var isOne = this.ratio === 1;\n\n      if (!isOne) {\n        this.ctx.save();\n        this.ctx.scale(this.ratio, this.ratio);\n      }\n\n      if (!this.overdraw) {\n        this.ctx.clearRect(0, 0, this.width, this.height);\n      }\n\n      canvas.group.render.call(this.scene, this.ctx);\n\n      if (!isOne) {\n        this.ctx.restore();\n      }\n\n      return this;\n\n    }\n\n  });\n\n  function resetTransform(ctx) {\n    ctx.setTransform(1, 0, 0, 1, 0, 0);\n  }\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  /**\n   * Constants\n   */\n\n  var root = Two.root,\n    multiplyMatrix = Two.Matrix.Multiply,\n    mod = Two.Utils.mod,\n    identity = [1, 0, 0, 0, 1, 0, 0, 0, 1],\n    transformation = new Two.Array(9),\n    getRatio = Two.Utils.getRatio,\n    getComputedMatrix = Two.Utils.getComputedMatrix,\n    toFixed = Two.Utils.toFixed,\n    _ = Two.Utils;\n\n  var webgl = {\n\n    isHidden: /(none|transparent)/i,\n\n    canvas: (root.document ? root.document.createElement('canvas') : { getContext: _.identity }),\n\n    alignments: {\n      left: 'start',\n      middle: 'center',\n      right: 'end'\n    },\n\n    matrix: new Two.Matrix(),\n\n    uv: new Two.Array([\n      0, 0,\n      1, 0,\n      0, 1,\n      0, 1,\n      1, 0,\n      1, 1\n    ]),\n\n    group: {\n\n      removeChild: function(child, gl) {\n        if (child.children) {\n          for (var i = 0; i < child.children.length; i++) {\n            webgl.group.removeChild(child.children[i], gl);\n          }\n          return;\n        }\n        // Deallocate texture to free up gl memory.\n        gl.deleteTexture(child._renderer.texture);\n        delete child._renderer.texture;\n      },\n\n      renderChild: function(child) {\n        webgl[child._renderer.type].render.call(child, this.gl, this.program);\n      },\n\n      render: function(gl, program) {\n\n        this._update();\n\n        var parent = this.parent;\n        var flagParentMatrix = (parent._matrix && parent._matrix.manual) || parent._flagMatrix;\n        var flagMatrix = this._matrix.manual || this._flagMatrix;\n\n        if (flagParentMatrix || flagMatrix) {\n\n          if (!this._renderer.matrix) {\n            this._renderer.matrix = new Two.Array(9);\n          }\n\n          // Reduce amount of object / array creation / deletion\n          this._matrix.toArray(true, transformation);\n\n          multiplyMatrix(transformation, parent._renderer.matrix, this._renderer.matrix);\n          this._renderer.scale = this._scale * parent._renderer.scale;\n\n          if (flagParentMatrix) {\n            this._flagMatrix = true;\n          }\n\n        }\n\n        if (this._mask) {\n\n          gl.enable(gl.STENCIL_TEST);\n          gl.stencilFunc(gl.ALWAYS, 1, 1);\n\n          gl.colorMask(false, false, false, true);\n          gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR);\n\n          webgl[this._mask._renderer.type].render.call(this._mask, gl, program, this);\n\n          gl.colorMask(true, true, true, true);\n          gl.stencilFunc(gl.NOTEQUAL, 0, 1);\n          gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);\n\n        }\n\n        this._flagOpacity = parent._flagOpacity || this._flagOpacity;\n\n        this._renderer.opacity = this._opacity\n          * (parent && parent._renderer ? parent._renderer.opacity : 1);\n\n        if (this._flagSubtractions) {\n          for (var i = 0; i < this.subtractions.length; i++) {\n            webgl.group.removeChild(this.subtractions[i], gl);\n          }\n        }\n\n        this.children.forEach(webgl.group.renderChild, {\n          gl: gl,\n          program: program\n        });\n\n        if (this._mask) {\n\n          gl.colorMask(false, false, false, false);\n          gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR);\n\n          webgl[this._mask._renderer.type].render.call(this._mask, gl, program, this);\n\n          gl.colorMask(true, true, true, true);\n          gl.stencilFunc(gl.NOTEQUAL, 0, 1);\n          gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);\n\n          gl.disable(gl.STENCIL_TEST);\n\n        }\n\n        return this.flagReset();\n\n      }\n\n    },\n\n    path: {\n\n      updateCanvas: function(elem) {\n\n        var next, prev, a, c, ux, uy, vx, vy, ar, bl, br, cl, x, y;\n        var isOffset;\n\n        var commands = elem._vertices;\n        var canvas = this.canvas;\n        var ctx = this.ctx;\n\n        // Styles\n        var scale = elem._renderer.scale;\n        var stroke = elem._stroke;\n        var linewidth = elem._linewidth;\n        var fill = elem._fill;\n        var opacity = elem._renderer.opacity || elem._opacity;\n        var cap = elem._cap;\n        var join = elem._join;\n        var miter = elem._miter;\n        var closed = elem._closed;\n        var length = commands.length;\n        var last = length - 1;\n\n        canvas.width = Math.max(Math.ceil(elem._renderer.rect.width * scale), 1);\n        canvas.height = Math.max(Math.ceil(elem._renderer.rect.height * scale), 1);\n\n        var centroid = elem._renderer.rect.centroid;\n        var cx = centroid.x;\n        var cy = centroid.y;\n\n        ctx.clearRect(0, 0, canvas.width, canvas.height);\n\n        if (fill) {\n          if (_.isString(fill)) {\n            ctx.fillStyle = fill;\n          } else {\n            webgl[fill._renderer.type].render.call(fill, ctx, elem);\n            ctx.fillStyle = fill._renderer.effect;\n          }\n        }\n        if (stroke) {\n          if (_.isString(stroke)) {\n            ctx.strokeStyle = stroke;\n          } else {\n            webgl[stroke._renderer.type].render.call(stroke, ctx, elem);\n            ctx.strokeStyle = stroke._renderer.effect;\n          }\n        }\n        if (linewidth) {\n          ctx.lineWidth = linewidth;\n        }\n        if (miter) {\n          ctx.miterLimit = miter;\n        }\n        if (join) {\n          ctx.lineJoin = join;\n        }\n        if (cap) {\n          ctx.lineCap = cap;\n        }\n        if (_.isNumber(opacity)) {\n          ctx.globalAlpha = opacity;\n        }\n\n        var d;\n        ctx.save();\n        ctx.scale(scale, scale);\n        ctx.translate(cx, cy);\n\n        ctx.beginPath();\n        for (var i = 0; i < commands.length; i++) {\n\n          b = commands[i];\n\n          x = toFixed(b._x);\n          y = toFixed(b._y);\n\n          switch (b._command) {\n\n            case Two.Commands.close:\n              ctx.closePath();\n              break;\n\n            case Two.Commands.curve:\n\n              prev = closed ? mod(i - 1, length) : Math.max(i - 1, 0);\n              next = closed ? mod(i + 1, length) : Math.min(i + 1, last);\n\n              a = commands[prev];\n              c = commands[next];\n              ar = (a.controls && a.controls.right) || Two.Vector.zero;\n              bl = (b.controls && b.controls.left) || Two.Vector.zero;\n\n              if (a._relative) {\n                vx = toFixed((ar.x + a._x));\n                vy = toFixed((ar.y + a._y));\n              } else {\n                vx = toFixed(ar.x);\n                vy = toFixed(ar.y);\n              }\n\n              if (b._relative) {\n                ux = toFixed((bl.x + b._x));\n                uy = toFixed((bl.y + b._y));\n              } else {\n                ux = toFixed(bl.x);\n                uy = toFixed(bl.y);\n              }\n\n              ctx.bezierCurveTo(vx, vy, ux, uy, x, y);\n\n              if (i >= last && closed) {\n\n                c = d;\n\n                br = (b.controls && b.controls.right) || Two.Vector.zero;\n                cl = (c.controls && c.controls.left) || Two.Vector.zero;\n\n                if (b._relative) {\n                  vx = toFixed((br.x + b._x));\n                  vy = toFixed((br.y + b._y));\n                } else {\n                  vx = toFixed(br.x);\n                  vy = toFixed(br.y);\n                }\n\n                if (c._relative) {\n                  ux = toFixed((cl.x + c._x));\n                  uy = toFixed((cl.y + c._y));\n                } else {\n                  ux = toFixed(cl.x);\n                  uy = toFixed(cl.y);\n                }\n\n                x = toFixed(c._x);\n                y = toFixed(c._y);\n\n                ctx.bezierCurveTo(vx, vy, ux, uy, x, y);\n\n              }\n\n              break;\n\n            case Two.Commands.line:\n              ctx.lineTo(x, y);\n              break;\n\n            case Two.Commands.move:\n              d = b;\n              ctx.moveTo(x, y);\n              break;\n\n          }\n\n        }\n\n        // Loose ends\n\n        if (closed) {\n          ctx.closePath();\n        }\n\n        if (!webgl.isHidden.test(fill)) {\n          isOffset = fill._renderer && fill._renderer.offset\n          if (isOffset) {\n            ctx.save();\n            ctx.translate(\n              - fill._renderer.offset.x, - fill._renderer.offset.y);\n            ctx.scale(fill._renderer.scale.x, fill._renderer.scale.y);\n          }\n          ctx.fill();\n          if (isOffset) {\n            ctx.restore();\n          }\n        }\n\n        if (!webgl.isHidden.test(stroke)) {\n          isOffset = stroke._renderer && stroke._renderer.offset;\n          if (isOffset) {\n            ctx.save();\n            ctx.translate(\n              - stroke._renderer.offset.x, - stroke._renderer.offset.y);\n            ctx.scale(stroke._renderer.scale.x, stroke._renderer.scale.y);\n            ctx.lineWidth = linewidth / stroke._renderer.scale.x;\n          }\n          ctx.stroke();\n          if (isOffset) {\n            ctx.restore();\n          }\n        }\n\n        ctx.restore();\n\n      },\n\n      /**\n       * Returns the rect of a set of verts. Typically takes vertices that are\n       * \"centered\" around 0 and returns them to be anchored upper-left.\n       */\n      getBoundingClientRect: function(vertices, border, rect) {\n\n        var left = Infinity, right = -Infinity,\n            top = Infinity, bottom = -Infinity,\n            width, height;\n\n        vertices.forEach(function(v) {\n\n          var x = v.x, y = v.y, controls = v.controls;\n          var a, b, c, d, cl, cr;\n\n          top = Math.min(y, top);\n          left = Math.min(x, left);\n          right = Math.max(x, right);\n          bottom = Math.max(y, bottom);\n\n          if (!v.controls) {\n            return;\n          }\n\n          cl = controls.left;\n          cr = controls.right;\n\n          if (!cl || !cr) {\n            return;\n          }\n\n          a = v._relative ? cl.x + x : cl.x;\n          b = v._relative ? cl.y + y : cl.y;\n          c = v._relative ? cr.x + x : cr.x;\n          d = v._relative ? cr.y + y : cr.y;\n\n          if (!a || !b || !c || !d) {\n            return;\n          }\n\n          top = Math.min(b, d, top);\n          left = Math.min(a, c, left);\n          right = Math.max(a, c, right);\n          bottom = Math.max(b, d, bottom);\n\n        });\n\n        // Expand borders\n\n        if (_.isNumber(border)) {\n          top -= border;\n          left -= border;\n          right += border;\n          bottom += border;\n        }\n\n        width = right - left;\n        height = bottom - top;\n\n        rect.top = top;\n        rect.left = left;\n        rect.right = right;\n        rect.bottom = bottom;\n        rect.width = width;\n        rect.height = height;\n\n        if (!rect.centroid) {\n          rect.centroid = {};\n        }\n\n        rect.centroid.x = - left;\n        rect.centroid.y = - top;\n\n      },\n\n      render: function(gl, program, forcedParent) {\n\n        if (!this._visible || !this._opacity) {\n          return this;\n        }\n\n        this._update();\n\n        // Calculate what changed\n\n        var parent = this.parent;\n        var flagParentMatrix = parent._matrix.manual || parent._flagMatrix;\n        var flagMatrix = this._matrix.manual || this._flagMatrix;\n        var flagTexture = this._flagVertices || this._flagFill\n          || (this._fill instanceof Two.LinearGradient && (this._fill._flagSpread || this._fill._flagStops || this._fill._flagEndPoints))\n          || (this._fill instanceof Two.RadialGradient && (this._fill._flagSpread || this._fill._flagStops || this._fill._flagRadius || this._fill._flagCenter || this._fill._flagFocal))\n          || (this._fill instanceof Two.Texture && (this._fill._flagLoaded && this._fill.loaded || this._fill._flagOffset || this._fill._flagScale))\n          || (this._stroke instanceof Two.LinearGradient && (this._stroke._flagSpread || this._stroke._flagStops || this._stroke._flagEndPoints))\n          || (this._stroke instanceof Two.RadialGradient && (this._stroke._flagSpread || this._stroke._flagStops || this._stroke._flagRadius || this._stroke._flagCenter || this._stroke._flagFocal))\n          || (this._stroke instanceof Two.Texture && (this._stroke._flagLoaded && this._stroke.loaded || this._stroke._flagOffset || this._fill._flagScale))\n          || this._flagStroke || this._flagLinewidth || this._flagOpacity\n          || parent._flagOpacity || this._flagVisible || this._flagCap\n          || this._flagJoin || this._flagMiter || this._flagScale\n          || !this._renderer.texture;\n\n        if (flagParentMatrix || flagMatrix) {\n\n          if (!this._renderer.matrix) {\n            this._renderer.matrix = new Two.Array(9);\n          }\n\n          // Reduce amount of object / array creation / deletion\n\n          this._matrix.toArray(true, transformation);\n\n          multiplyMatrix(transformation, parent._renderer.matrix, this._renderer.matrix);\n          this._renderer.scale = this._scale * parent._renderer.scale;\n\n        }\n\n        if (flagTexture) {\n\n          if (!this._renderer.rect) {\n            this._renderer.rect = {};\n          }\n\n          if (!this._renderer.triangles) {\n            this._renderer.triangles = new Two.Array(12);\n          }\n\n          this._renderer.opacity = this._opacity * parent._renderer.opacity;\n\n          webgl.path.getBoundingClientRect(this._vertices, this._linewidth, this._renderer.rect);\n          webgl.getTriangles(this._renderer.rect, this._renderer.triangles);\n\n          webgl.updateBuffer.call(webgl, gl, this, program);\n          webgl.updateTexture.call(webgl, gl, this);\n\n        }\n\n        // if (this._mask) {\n        //   webgl[this._mask._renderer.type].render.call(mask, gl, program, this);\n        // }\n\n        if (this._clip && !forcedParent) {\n          return;\n        }\n\n        // Draw Texture\n\n        gl.bindBuffer(gl.ARRAY_BUFFER, this._renderer.textureCoordsBuffer);\n\n        gl.vertexAttribPointer(program.textureCoords, 2, gl.FLOAT, false, 0, 0);\n\n        gl.bindTexture(gl.TEXTURE_2D, this._renderer.texture);\n\n\n        // Draw Rect\n\n        gl.uniformMatrix3fv(program.matrix, false, this._renderer.matrix);\n\n        gl.bindBuffer(gl.ARRAY_BUFFER, this._renderer.buffer);\n\n        gl.vertexAttribPointer(program.position, 2, gl.FLOAT, false, 0, 0);\n\n        gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n        return this.flagReset();\n\n      }\n\n    },\n\n    text: {\n\n      updateCanvas: function(elem) {\n\n        var canvas = this.canvas;\n        var ctx = this.ctx;\n\n        // Styles\n        var scale = elem._renderer.scale;\n        var stroke = elem._stroke;\n        var linewidth = elem._linewidth * scale;\n        var fill = elem._fill;\n        var opacity = elem._renderer.opacity || elem._opacity;\n\n        canvas.width = Math.max(Math.ceil(elem._renderer.rect.width * scale), 1);\n        canvas.height = Math.max(Math.ceil(elem._renderer.rect.height * scale), 1);\n\n        var centroid = elem._renderer.rect.centroid;\n        var cx = centroid.x;\n        var cy = centroid.y;\n\n        var a, b, c, d, e, sx, sy;\n        var isOffset = fill._renderer && fill._renderer.offset\n          && stroke._renderer && stroke._renderer.offset;\n\n        ctx.clearRect(0, 0, canvas.width, canvas.height);\n\n        if (!isOffset) {\n          ctx.font = [elem._style, elem._weight, elem._size + 'px/' +\n            elem._leading + 'px', elem._family].join(' ');\n        }\n\n        ctx.textAlign = 'center';\n        ctx.textBaseline = 'middle';\n\n        // Styles\n        if (fill) {\n          if (_.isString(fill)) {\n            ctx.fillStyle = fill;\n          } else {\n            webgl[fill._renderer.type].render.call(fill, ctx, elem);\n            ctx.fillStyle = fill._renderer.effect;\n          }\n        }\n        if (stroke) {\n          if (_.isString(stroke)) {\n            ctx.strokeStyle = stroke;\n          } else {\n            webgl[stroke._renderer.type].render.call(stroke, ctx, elem);\n            ctx.strokeStyle = stroke._renderer.effect;\n          }\n        }\n        if (linewidth) {\n          ctx.lineWidth = linewidth;\n        }\n        if (_.isNumber(opacity)) {\n          ctx.globalAlpha = opacity;\n        }\n\n        ctx.save();\n        ctx.scale(scale, scale);\n        ctx.translate(cx, cy);\n\n        if (!webgl.isHidden.test(fill)) {\n\n          if (fill._renderer && fill._renderer.offset) {\n\n            sx = toFixed(fill._renderer.scale.x);\n            sy = toFixed(fill._renderer.scale.y);\n\n            ctx.save();\n            ctx.translate( - toFixed(fill._renderer.offset.x),\n              - toFixed(fill._renderer.offset.y));\n            ctx.scale(sx, sy);\n\n            a = elem._size / fill._renderer.scale.y;\n            b = elem._leading / fill._renderer.scale.y;\n            ctx.font = [elem._style, elem._weight, toFixed(a) + 'px/',\n              toFixed(b) + 'px', elem._family].join(' ');\n\n            c = fill._renderer.offset.x / fill._renderer.scale.x;\n            d = fill._renderer.offset.y / fill._renderer.scale.y;\n\n            ctx.fillText(elem.value, toFixed(c), toFixed(d));\n            ctx.restore();\n\n          } else {\n            ctx.fillText(elem.value, 0, 0);\n          }\n\n        }\n\n        if (!webgl.isHidden.test(stroke)) {\n\n          if (stroke._renderer && stroke._renderer.offset) {\n\n            sx = toFixed(stroke._renderer.scale.x);\n            sy = toFixed(stroke._renderer.scale.y);\n\n            ctx.save();\n            ctx.translate(- toFixed(stroke._renderer.offset.x),\n              - toFixed(stroke._renderer.offset.y));\n            ctx.scale(sx, sy);\n\n            a = elem._size / stroke._renderer.scale.y;\n            b = elem._leading / stroke._renderer.scale.y;\n            ctx.font = [elem._style, elem._weight, toFixed(a) + 'px/',\n              toFixed(b) + 'px', elem._family].join(' ');\n\n            c = stroke._renderer.offset.x / stroke._renderer.scale.x;\n            d = stroke._renderer.offset.y / stroke._renderer.scale.y;\n            e = linewidth / stroke._renderer.scale.x;\n\n            ctx.lineWidth = toFixed(e);\n            ctx.strokeText(elem.value, toFixed(c), toFixed(d));\n            ctx.restore();\n\n          } else {\n            ctx.strokeText(elem.value, 0, 0);\n          }\n\n        }\n\n        ctx.restore();\n\n      },\n\n      getBoundingClientRect: function(elem, rect) {\n\n        var ctx = webgl.ctx;\n\n        ctx.font = [elem._style, elem._weight, elem._size + 'px/' +\n          elem._leading + 'px', elem._family].join(' ');\n\n        ctx.textAlign = 'center';\n        ctx.textBaseline = elem._baseline;\n\n        // TODO: Estimate this better\n        var width = ctx.measureText(elem._value).width;\n        var height = Math.max(elem._size || elem._leading);\n\n        if (this._linewidth && !webgl.isHidden.test(this._stroke)) {\n          // width += this._linewidth; // TODO: Not sure if the `measure` calcs this.\n          height += this._linewidth;\n        }\n\n        var w = width / 2;\n        var h = height / 2;\n\n        switch (webgl.alignments[elem._alignment] || elem._alignment) {\n\n          case webgl.alignments.left:\n            rect.left = 0;\n            rect.right = width;\n            break;\n          case webgl.alignments.right:\n            rect.left = - width;\n            rect.right = 0;\n            break;\n          default:\n            rect.left = - w;\n            rect.right = w;\n        }\n\n        // TODO: Gradients aren't inherited...\n        switch (elem._baseline) {\n          case 'bottom':\n            rect.top = - height;\n            rect.bottom = 0;\n            break;\n          case 'top':\n            rect.top = 0;\n            rect.bottom = height;\n            break;\n          default:\n            rect.top = - h;\n            rect.bottom = h;\n        }\n\n        rect.width = width;\n        rect.height = height;\n\n        if (!rect.centroid) {\n          rect.centroid = {};\n        }\n\n        // TODO:\n        rect.centroid.x = w;\n        rect.centroid.y = h;\n\n      },\n\n      render: function(gl, program, forcedParent) {\n\n        if (!this._visible || !this._opacity) {\n          return this;\n        }\n\n        this._update();\n\n        // Calculate what changed\n\n        var parent = this.parent;\n        var flagParentMatrix = parent._matrix.manual || parent._flagMatrix;\n        var flagMatrix = this._matrix.manual || this._flagMatrix;\n        var flagTexture = this._flagVertices || this._flagFill\n          || (this._fill instanceof Two.LinearGradient && (this._fill._flagSpread || this._fill._flagStops || this._fill._flagEndPoints))\n          || (this._fill instanceof Two.RadialGradient && (this._fill._flagSpread || this._fill._flagStops || this._fill._flagRadius || this._fill._flagCenter || this._fill._flagFocal))\n          || (this._fill instanceof Two.Texture && (this._fill._flagLoaded && this._fill.loaded))\n          || (this._stroke instanceof Two.LinearGradient && (this._stroke._flagSpread || this._stroke._flagStops || this._stroke._flagEndPoints))\n          || (this._stroke instanceof Two.RadialGradient && (this._stroke._flagSpread || this._stroke._flagStops || this._stroke._flagRadius || this._stroke._flagCenter || this._stroke._flagFocal))\n          || (this._texture instanceof Two.Texture && (this._texture._flagLoaded && this._texture.loaded))\n          || this._flagStroke || this._flagLinewidth || this._flagOpacity\n          || parent._flagOpacity || this._flagVisible || this._flagScale\n          || this._flagValue || this._flagFamily || this._flagSize\n          || this._flagLeading || this._flagAlignment || this._flagBaseline\n          || this._flagStyle || this._flagWeight || this._flagDecoration\n          || !this._renderer.texture;\n\n        if (flagParentMatrix || flagMatrix) {\n\n          if (!this._renderer.matrix) {\n            this._renderer.matrix = new Two.Array(9);\n          }\n\n          // Reduce amount of object / array creation / deletion\n\n          this._matrix.toArray(true, transformation);\n\n          multiplyMatrix(transformation, parent._renderer.matrix, this._renderer.matrix);\n          this._renderer.scale = this._scale * parent._renderer.scale;\n\n        }\n\n        if (flagTexture) {\n\n          if (!this._renderer.rect) {\n            this._renderer.rect = {};\n          }\n\n          if (!this._renderer.triangles) {\n            this._renderer.triangles = new Two.Array(12);\n          }\n\n          this._renderer.opacity = this._opacity * parent._renderer.opacity;\n\n          webgl.text.getBoundingClientRect(this, this._renderer.rect);\n          webgl.getTriangles(this._renderer.rect, this._renderer.triangles);\n\n          webgl.updateBuffer.call(webgl, gl, this, program);\n          webgl.updateTexture.call(webgl, gl, this);\n\n        }\n\n        // if (this._mask) {\n        //   webgl[this._mask._renderer.type].render.call(mask, gl, program, this);\n        // }\n\n        if (this._clip && !forcedParent) {\n          return;\n        }\n\n        // Draw Texture\n\n        gl.bindBuffer(gl.ARRAY_BUFFER, this._renderer.textureCoordsBuffer);\n\n        gl.vertexAttribPointer(program.textureCoords, 2, gl.FLOAT, false, 0, 0);\n\n        gl.bindTexture(gl.TEXTURE_2D, this._renderer.texture);\n\n\n        // Draw Rect\n\n        gl.uniformMatrix3fv(program.matrix, false, this._renderer.matrix);\n\n        gl.bindBuffer(gl.ARRAY_BUFFER, this._renderer.buffer);\n\n        gl.vertexAttribPointer(program.position, 2, gl.FLOAT, false, 0, 0);\n\n        gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n        return this.flagReset();\n\n      }\n\n    },\n\n    'linear-gradient': {\n\n      render: function(ctx, elem) {\n\n        if (!ctx.canvas.getContext('2d')) {\n          return;\n        }\n\n        this._update();\n\n        if (!this._renderer.effect || this._flagEndPoints || this._flagStops) {\n\n          this._renderer.effect = ctx.createLinearGradient(\n            this.left._x, this.left._y,\n            this.right._x, this.right._y\n          );\n\n          for (var i = 0; i < this.stops.length; i++) {\n            var stop = this.stops[i];\n            this._renderer.effect.addColorStop(stop._offset, stop._color);\n          }\n\n        }\n\n        return this.flagReset();\n\n      }\n\n    },\n\n    'radial-gradient': {\n\n      render: function(ctx, elem) {\n\n        if (!ctx.canvas.getContext('2d')) {\n          return;\n        }\n\n        this._update();\n\n        if (!this._renderer.effect || this._flagCenter || this._flagFocal\n            || this._flagRadius || this._flagStops) {\n\n          this._renderer.effect = ctx.createRadialGradient(\n            this.center._x, this.center._y, 0,\n            this.focal._x, this.focal._y, this._radius\n          );\n\n          for (var i = 0; i < this.stops.length; i++) {\n            var stop = this.stops[i];\n            this._renderer.effect.addColorStop(stop._offset, stop._color);\n          }\n\n        }\n\n        return this.flagReset();\n\n      }\n\n    },\n\n    texture: {\n\n      render: function(ctx, elem) {\n\n        if (!ctx.canvas.getContext('2d')) {\n          return;\n        }\n\n        this._update();\n\n        var image = this.image;\n        var repeat;\n\n        if (!this._renderer.effect || ((this._flagLoaded || this._flagRepeat) && this.loaded)) {\n          this._renderer.effect = ctx.createPattern(image, this._repeat);\n        }\n\n        if (this._flagOffset || this._flagLoaded || this._flagScale) {\n\n          if (!(this._renderer.offset instanceof Two.Vector)) {\n            this._renderer.offset = new Two.Vector();\n          }\n\n          this._renderer.offset.x = this._offset.x;\n          this._renderer.offset.y = this._offset.y;\n\n          if (image) {\n\n            this._renderer.offset.x -= image.width / 2;\n            this._renderer.offset.y += image.height / 2;\n\n            if (this._scale instanceof Two.Vector) {\n              this._renderer.offset.x *= this._scale.x;\n              this._renderer.offset.y *= this._scale.y;\n            } else {\n              this._renderer.offset.x *= this._scale;\n              this._renderer.offset.y *= this._scale;\n            }\n          }\n\n        }\n\n        if (this._flagScale || this._flagLoaded) {\n\n          if (!(this._renderer.scale instanceof Two.Vector)) {\n            this._renderer.scale = new Two.Vector();\n          }\n\n          if (this._scale instanceof Two.Vector) {\n            this._renderer.scale.copy(this._scale);\n          } else {\n            this._renderer.scale.set(this._scale, this._scale);\n          }\n\n        }\n\n        return this.flagReset();\n\n      }\n\n    },\n\n    getTriangles: function(rect, triangles) {\n\n      var top = rect.top,\n          left = rect.left,\n          right = rect.right,\n          bottom = rect.bottom;\n\n      // First Triangle\n\n      triangles[0] = left;\n      triangles[1] = top;\n\n      triangles[2] = right;\n      triangles[3] = top;\n\n      triangles[4] = left;\n      triangles[5] = bottom;\n\n      // Second Triangle\n\n      triangles[6] = left;\n      triangles[7] = bottom;\n\n      triangles[8] = right;\n      triangles[9] = top;\n\n      triangles[10] = right;\n      triangles[11] = bottom;\n\n    },\n\n    updateTexture: function(gl, elem) {\n\n      this[elem._renderer.type].updateCanvas.call(webgl, elem);\n\n      if (elem._renderer.texture) {\n        gl.deleteTexture(elem._renderer.texture);\n      }\n\n      gl.bindBuffer(gl.ARRAY_BUFFER, elem._renderer.textureCoordsBuffer);\n\n      // TODO: Is this necessary every time or can we do once?\n      // TODO: Create a registry for textures\n      elem._renderer.texture = gl.createTexture();\n      gl.bindTexture(gl.TEXTURE_2D, elem._renderer.texture);\n\n      // Set the parameters so we can render any size image.\n      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n      // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n      // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n      // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n\n      if (this.canvas.width <= 0 || this.canvas.height <= 0) {\n        return;\n      }\n\n      // Upload the image into the texture.\n      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.canvas);\n\n    },\n\n    updateBuffer: function(gl, elem, program) {\n\n      if (_.isObject(elem._renderer.buffer)) {\n        gl.deleteBuffer(elem._renderer.buffer);\n      }\n\n      elem._renderer.buffer = gl.createBuffer();\n\n      gl.bindBuffer(gl.ARRAY_BUFFER, elem._renderer.buffer);\n      gl.enableVertexAttribArray(program.position);\n\n      gl.bufferData(gl.ARRAY_BUFFER, elem._renderer.triangles, gl.STATIC_DRAW);\n\n      if (_.isObject(elem._renderer.textureCoordsBuffer)) {\n        gl.deleteBuffer(elem._renderer.textureCoordsBuffer);\n      }\n\n      elem._renderer.textureCoordsBuffer = gl.createBuffer();\n\n      gl.bindBuffer(gl.ARRAY_BUFFER, elem._renderer.textureCoordsBuffer);\n      gl.enableVertexAttribArray(program.textureCoords);\n\n      gl.bufferData(gl.ARRAY_BUFFER, this.uv, gl.STATIC_DRAW);\n\n    },\n\n    program: {\n\n      create: function(gl, shaders) {\n        var program, linked, error;\n        program = gl.createProgram();\n        _.each(shaders, function(s) {\n          gl.attachShader(program, s);\n        });\n\n        gl.linkProgram(program);\n        linked = gl.getProgramParameter(program, gl.LINK_STATUS);\n        if (!linked) {\n          error = gl.getProgramInfoLog(program);\n          gl.deleteProgram(program);\n          throw new Two.Utils.Error('unable to link program: ' + error);\n        }\n\n        return program;\n\n      }\n\n    },\n\n    shaders: {\n\n      create: function(gl, source, type) {\n        var shader, compiled, error;\n        shader = gl.createShader(gl[type]);\n        gl.shaderSource(shader, source);\n        gl.compileShader(shader);\n\n        compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);\n        if (!compiled) {\n          error = gl.getShaderInfoLog(shader);\n          gl.deleteShader(shader);\n          throw new Two.Utils.Error('unable to compile shader ' + shader + ': ' + error);\n        }\n\n        return shader;\n\n      },\n\n      types: {\n        vertex: 'VERTEX_SHADER',\n        fragment: 'FRAGMENT_SHADER'\n      },\n\n      vertex: [\n        'attribute vec2 a_position;',\n        'attribute vec2 a_textureCoords;',\n        '',\n        'uniform mat3 u_matrix;',\n        'uniform vec2 u_resolution;',\n        '',\n        'varying vec2 v_textureCoords;',\n        '',\n        'void main() {',\n        '   vec2 projected = (u_matrix * vec3(a_position, 1.0)).xy;',\n        '   vec2 normal = projected / u_resolution;',\n        '   vec2 clipspace = (normal * 2.0) - 1.0;',\n        '',\n        '   gl_Position = vec4(clipspace * vec2(1.0, -1.0), 0.0, 1.0);',\n        '   v_textureCoords = a_textureCoords;',\n        '}'\n      ].join('\\n'),\n\n      fragment: [\n        'precision mediump float;',\n        '',\n        'uniform sampler2D u_image;',\n        'varying vec2 v_textureCoords;',\n        '',\n        'void main() {',\n        '  gl_FragColor = texture2D(u_image, v_textureCoords);',\n        '}'\n      ].join('\\n')\n\n    },\n\n    TextureRegistry: new Two.Registry()\n\n  };\n\n  webgl.ctx = webgl.canvas.getContext('2d');\n\n  var Renderer = Two[Two.Types.webgl] = function(options) {\n\n    var params, gl, vs, fs;\n    this.domElement = options.domElement || document.createElement('canvas');\n\n    // Everything drawn on the canvas needs to come from the stage.\n    this.scene = new Two.Group();\n    this.scene.parent = this;\n\n    this._renderer = {\n      matrix: new Two.Array(identity),\n      scale: 1,\n      opacity: 1\n    };\n    this._flagMatrix = true;\n\n    // http://games.greggman.com/game/webgl-and-alpha/\n    // http://www.khronos.org/registry/webgl/specs/latest/#5.2\n    params = _.defaults(options || {}, {\n      antialias: false,\n      alpha: true,\n      premultipliedAlpha: true,\n      stencil: true,\n      preserveDrawingBuffer: true,\n      overdraw: false\n    });\n\n    this.overdraw = params.overdraw;\n\n    gl = this.ctx = this.domElement.getContext('webgl', params) ||\n      this.domElement.getContext('experimental-webgl', params);\n\n    if (!this.ctx) {\n      throw new Two.Utils.Error(\n        'unable to create a webgl context. Try using another renderer.');\n    }\n\n    // Compile Base Shaders to draw in pixel space.\n    vs = webgl.shaders.create(\n      gl, webgl.shaders.vertex, webgl.shaders.types.vertex);\n    fs = webgl.shaders.create(\n      gl, webgl.shaders.fragment, webgl.shaders.types.fragment);\n\n    this.program = webgl.program.create(gl, [vs, fs]);\n    gl.useProgram(this.program);\n\n    // Create and bind the drawing buffer\n\n    // look up where the vertex data needs to go.\n    this.program.position = gl.getAttribLocation(this.program, 'a_position');\n    this.program.matrix = gl.getUniformLocation(this.program, 'u_matrix');\n    this.program.textureCoords = gl.getAttribLocation(this.program, 'a_textureCoords');\n\n    // Copied from Three.js WebGLRenderer\n    gl.disable(gl.DEPTH_TEST);\n\n    // Setup some initial statements of the gl context\n    gl.enable(gl.BLEND);\n\n    // https://code.google.com/p/chromium/issues/detail?id=316393\n    // gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, gl.TRUE);\n\n    gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);\n    gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA,\n      gl.ONE, gl.ONE_MINUS_SRC_ALPHA );\n\n  };\n\n  _.extend(Renderer, {\n\n    Utils: webgl\n\n  });\n\n  _.extend(Renderer.prototype, Two.Utils.Events, {\n\n    setSize: function(width, height, ratio) {\n\n      this.width = width;\n      this.height = height;\n\n      this.ratio = _.isUndefined(ratio) ? getRatio(this.ctx) : ratio;\n\n      this.domElement.width = width * this.ratio;\n      this.domElement.height = height * this.ratio;\n\n      _.extend(this.domElement.style, {\n        width: width + 'px',\n        height: height + 'px'\n      });\n\n      width *= this.ratio;\n      height *= this.ratio;\n\n      // Set for this.stage parent scaling to account for HDPI\n      this._renderer.matrix[0] = this._renderer.matrix[4] = this._renderer.scale = this.ratio;\n\n      this._flagMatrix = true;\n\n      this.ctx.viewport(0, 0, width, height);\n\n      var resolutionLocation = this.ctx.getUniformLocation(\n        this.program, 'u_resolution');\n      this.ctx.uniform2f(resolutionLocation, width, height);\n\n      return this;\n\n    },\n\n    render: function() {\n\n      var gl = this.ctx;\n\n      if (!this.overdraw) {\n        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);\n      }\n\n      webgl.group.render.call(this.scene, gl, this.program);\n      this._flagMatrix = false;\n\n      if(window.twojsisdonerendering) window.twojsisdonerendering();\n\n      return this;\n\n    }\n\n  });\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  var _ = Two.Utils;\n\n  var Shape = Two.Shape = function() {\n\n    // Private object for renderer specific variables.\n    this._renderer = {};\n    this._renderer.flagMatrix = _.bind(Shape.FlagMatrix, this);\n    this.isShape = true;\n\n    this.id = Two.Identifier + Two.uniqueId();\n    this.classList = [];\n\n    // Define matrix properties which all inherited\n    // objects of Shape have.\n\n    this._matrix = new Two.Matrix();\n\n    this.translation = new Two.Vector();\n    this.rotation = 0;\n    this.scale = 1;\n\n  };\n\n  _.extend(Shape, {\n\n    FlagMatrix: function() {\n      this._flagMatrix = true;\n    },\n\n    MakeObservable: function(object) {\n\n      Object.defineProperty(object, 'translation', {\n        enumerable: true,\n        get: function() {\n          return this._translation;\n        },\n        set: function(v) {\n          if (this._translation) {\n            this._translation.unbind(Two.Events.change, this._renderer.flagMatrix);\n          }\n          this._translation = v;\n          this._translation.bind(Two.Events.change, this._renderer.flagMatrix);\n          Shape.FlagMatrix.call(this);\n        }\n      });\n\n      Object.defineProperty(object, 'rotation', {\n        enumerable: true,\n        get: function() {\n          return this._rotation;\n        },\n        set: function(v) {\n          this._rotation = v;\n          this._flagMatrix = true;\n        }\n      });\n\n      Object.defineProperty(object, 'scale', {\n        enumerable: true,\n        get: function() {\n          return this._scale;\n        },\n        set: function(v) {\n\n          if (this._scale instanceof Two.Vector) {\n            this._scale.unbind(Two.Events.change, this._renderer.flagMatrix);\n          }\n\n          this._scale = v;\n\n          if (this._scale instanceof Two.Vector) {\n            this._scale.bind(Two.Events.change, this._renderer.flagMatrix);\n          }\n\n          this._flagMatrix = true;\n          this._flagScale = true;\n\n        }\n      });\n\n    }\n\n  });\n\n  _.extend(Shape.prototype, Two.Utils.Events, {\n\n    // Flags\n\n    _flagMatrix: true,\n    _flagScale: false,\n\n    // _flagMask: false,\n    // _flagClip: false,\n\n    // Underlying Properties\n\n    _rotation: 0,\n    _scale: 1,\n    _translation: null,\n\n    // _mask: null,\n    // _clip: false,\n\n    addTo: function(group) {\n      group.add(this);\n      return this;\n    },\n\n    clone: function() {\n      var clone = new Shape();\n      clone.translation.copy(this.translation);\n      clone.rotation = this.rotation;\n      clone.scale = this.scale;\n      _.each(Shape.Properties, function(k) {\n        clone[k] = this[k];\n      }, this);\n      return clone._update();\n    },\n\n    /**\n     * To be called before render that calculates and collates all information\n     * to be as up-to-date as possible for the render. Called once a frame.\n     */\n    _update: function(deep) {\n\n      if (!this._matrix.manual && this._flagMatrix) {\n\n        this._matrix\n          .identity()\n          .translate(this.translation.x, this.translation.y);\n\n          if (this._scale instanceof Two.Vector) {\n            this._matrix.scale(this._scale.x, this._scale.y);\n          } else {\n            this._matrix.scale(this._scale);\n          }\n\n          this._matrix.rotate(this.rotation);\n\n      }\n\n      if (deep) {\n        // Bubble up to parents mainly for `getBoundingClientRect` method.\n        if (this.parent && this.parent._update) {\n          this.parent._update();\n        }\n      }\n\n      return this;\n\n    },\n\n    flagReset: function() {\n\n      this._flagMatrix = this._flagScale = false;\n\n      return this;\n\n    }\n\n  });\n\n  Shape.MakeObservable(Shape.prototype);\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  /**\n   * Constants\n   */\n\n  var min = Math.min, max = Math.max, round = Math.round,\n    getComputedMatrix = Two.Utils.getComputedMatrix;\n\n  var commands = {};\n  var _ = Two.Utils;\n\n  _.each(Two.Commands, function(v, k) {\n    commands[k] = new RegExp(v);\n  });\n\n  var Path = Two.Path = function(vertices, closed, curved, manual) {\n\n    Two.Shape.call(this);\n\n    this._renderer.type = 'path';\n    this._renderer.flagVertices = _.bind(Path.FlagVertices, this);\n    this._renderer.bindVertices = _.bind(Path.BindVertices, this);\n    this._renderer.unbindVertices = _.bind(Path.UnbindVertices, this);\n\n    this._renderer.flagFill = _.bind(Path.FlagFill, this);\n    this._renderer.flagStroke = _.bind(Path.FlagStroke, this);\n\n    this._closed = !!closed;\n    this._curved = !!curved;\n\n    this.beginning = 0;\n    this.ending = 1;\n\n    // Style properties\n\n    this.fill = '#fff';\n    this.stroke = '#000';\n    this.linewidth = 1.0;\n    this.opacity = 1.0;\n    this.visible = true;\n\n    this.cap = 'butt';      // Default of Adobe Illustrator\n    this.join = 'miter';    // Default of Adobe Illustrator\n    this.miter = 4;         // Default of Adobe Illustrator\n\n    this._vertices = [];\n    this.vertices = vertices;\n\n    // Determines whether or not two.js should calculate curves, lines, and\n    // commands automatically for you or to let the developer manipulate them\n    // for themselves.\n    this.automatic = !manual;\n\n  };\n\n  _.extend(Path, {\n\n    Properties: [\n      'fill',\n      'stroke',\n      'linewidth',\n      'opacity',\n      'visible',\n      'cap',\n      'join',\n      'miter',\n\n      'closed',\n      'curved',\n      'automatic',\n      'beginning',\n      'ending'\n    ],\n\n    FlagVertices: function() {\n      this._flagVertices = true;\n      this._flagLength = true;\n    },\n\n    BindVertices: function(items) {\n\n      // This function is called a lot\n      // when importing a large SVG\n      var i = items.length;\n      while (i--) {\n        items[i].bind(Two.Events.change, this._renderer.flagVertices);\n      }\n\n      this._renderer.flagVertices();\n\n    },\n\n    UnbindVertices: function(items) {\n\n      var i = items.length;\n      while (i--) {\n        items[i].unbind(Two.Events.change, this._renderer.flagVertices);\n      }\n\n      this._renderer.flagVertices();\n\n    },\n\n    FlagFill: function() {\n      this._flagFill = true;\n    },\n\n    FlagStroke: function() {\n      this._flagStroke = true;\n    },\n\n    MakeObservable: function(object) {\n\n      Two.Shape.MakeObservable(object);\n\n      // Only the 6 defined properties are flagged like this. The subsequent\n      // properties behave differently and need to be hand written.\n      _.each(Path.Properties.slice(2, 8), Two.Utils.defineProperty, object);\n\n      Object.defineProperty(object, 'fill', {\n        enumerable: true,\n        get: function() {\n          return this._fill;\n        },\n        set: function(f) {\n\n          if (this._fill instanceof Two.Gradient\n            || this._fill instanceof Two.LinearGradient\n            || this._fill instanceof Two.RadialGradient\n            || this._fill instanceof Two.Texture) {\n            this._fill.unbind(Two.Events.change, this._renderer.flagFill);\n          }\n\n          this._fill = f;\n          this._flagFill = true;\n\n          if (this._fill instanceof Two.Gradient\n            || this._fill instanceof Two.LinearGradient\n            || this._fill instanceof Two.RadialGradient\n            || this._fill instanceof Two.Texture) {\n            this._fill.bind(Two.Events.change, this._renderer.flagFill);\n          }\n\n        }\n      });\n\n      Object.defineProperty(object, 'stroke', {\n        enumerable: true,\n        get: function() {\n          return this._stroke;\n        },\n        set: function(f) {\n\n          if (this._stroke instanceof Two.Gradient\n            || this._stroke instanceof Two.LinearGradient\n            || this._stroke instanceof Two.RadialGradient\n            || this._stroke instanceof Two.Texture) {\n            this._stroke.unbind(Two.Events.change, this._renderer.flagStroke);\n          }\n\n          this._stroke = f;\n          this._flagStroke = true;\n\n          if (this._stroke instanceof Two.Gradient\n            || this._stroke instanceof Two.LinearGradient\n            || this._stroke instanceof Two.RadialGradient\n            || this._stroke instanceof Two.Texture) {\n            this._stroke.bind(Two.Events.change, this._renderer.flagStroke);\n          }\n\n        }\n      });\n\n      Object.defineProperty(object, 'length', {\n        get: function() {\n          if (this._flagLength) {\n            this._updateLength();\n          }\n          return this._length;\n        }\n      });\n\n      Object.defineProperty(object, 'closed', {\n        enumerable: true,\n        get: function() {\n          return this._closed;\n        },\n        set: function(v) {\n          this._closed = !!v;\n          this._flagVertices = true;\n        }\n      });\n\n      Object.defineProperty(object, 'curved', {\n        enumerable: true,\n        get: function() {\n          return this._curved;\n        },\n        set: function(v) {\n          this._curved = !!v;\n          this._flagVertices = true;\n        }\n      });\n\n      Object.defineProperty(object, 'automatic', {\n        enumerable: true,\n        get: function() {\n          return this._automatic;\n        },\n        set: function(v) {\n          if (v === this._automatic) {\n            return;\n          }\n          this._automatic = !!v;\n          var method = this._automatic ? 'ignore' : 'listen';\n          _.each(this.vertices, function(v) {\n            v[method]();\n          });\n        }\n      });\n\n      Object.defineProperty(object, 'beginning', {\n        enumerable: true,\n        get: function() {\n          return this._beginning;\n        },\n        set: function(v) {\n          this._beginning = v;\n          this._flagVertices = true;\n        }\n      });\n\n      Object.defineProperty(object, 'ending', {\n        enumerable: true,\n        get: function() {\n          return this._ending;\n        },\n        set: function(v) {\n          this._ending = v;\n          this._flagVertices = true;\n        }\n      });\n\n      Object.defineProperty(object, 'vertices', {\n\n        enumerable: true,\n\n        get: function() {\n          return this._collection;\n        },\n\n        set: function(vertices) {\n\n          var updateVertices = this._renderer.flagVertices;\n          var bindVertices = this._renderer.bindVertices;\n          var unbindVertices = this._renderer.unbindVertices;\n\n          // Remove previous listeners\n          if (this._collection) {\n            this._collection\n              .unbind(Two.Events.insert, bindVertices)\n              .unbind(Two.Events.remove, unbindVertices);\n          }\n\n          // Create new Collection with copy of vertices\n          this._collection = new Two.Utils.Collection((vertices || []).slice(0));\n\n          // Listen for Collection changes and bind / unbind\n          this._collection\n            .bind(Two.Events.insert, bindVertices)\n            .bind(Two.Events.remove, unbindVertices);\n\n          // Bind Initial Vertices\n          bindVertices(this._collection);\n\n        }\n\n      });\n\n      Object.defineProperty(object, 'clip', {\n        enumerable: true,\n        get: function() {\n          return this._clip;\n        },\n        set: function(v) {\n          this._clip = v;\n          this._flagClip = true;\n        }\n      });\n\n    }\n\n  });\n\n  _.extend(Path.prototype, Two.Shape.prototype, {\n\n    // Flags\n    // http://en.wikipedia.org/wiki/Flag\n\n    _flagVertices: true,\n    _flagLength: true,\n\n    _flagFill: true,\n    _flagStroke: true,\n    _flagLinewidth: true,\n    _flagOpacity: true,\n    _flagVisible: true,\n\n    _flagCap: true,\n    _flagJoin: true,\n    _flagMiter: true,\n\n    _flagClip: false,\n\n    // Underlying Properties\n\n    _length: 0,\n\n    _fill: '#fff',\n    _stroke: '#000',\n    _linewidth: 1.0,\n    _opacity: 1.0,\n    _visible: true,\n\n    _cap: 'round',\n    _join: 'round',\n    _miter: 4,\n\n    _closed: true,\n    _curved: false,\n    _automatic: true,\n    _beginning: 0,\n    _ending: 1.0,\n\n    _clip: false,\n\n    clone: function(parent) {\n\n      parent = parent || this.parent;\n\n      var points = _.map(this.vertices, function(v) {\n        return v.clone();\n      });\n\n      var clone = new Path(points, this.closed, this.curved, !this.automatic);\n\n      _.each(Two.Path.Properties, function(k) {\n        clone[k] = this[k];\n      }, this);\n\n      clone.translation.copy(this.translation);\n      clone.rotation = this.rotation;\n      clone.scale = this.scale;\n\n      if (parent) {\n        parent.add(clone);\n      }\n\n      return clone;\n\n    },\n\n    toObject: function() {\n\n      var result = {\n        vertices: _.map(this.vertices, function(v) {\n          return v.toObject();\n        })\n      };\n\n      _.each(Two.Shape.Properties, function(k) {\n        result[k] = this[k];\n      }, this);\n\n      result.translation = this.translation.toObject;\n      result.rotation = this.rotation;\n      result.scale = this.scale;\n\n      return result;\n\n    },\n\n    noFill: function() {\n      this.fill = 'transparent';\n      return this;\n    },\n\n    noStroke: function() {\n      this.stroke = 'transparent';\n      return this;\n    },\n\n    /**\n     * Orient the vertices of the shape to the upper lefthand\n     * corner of the path.\n     */\n    corner: function() {\n\n      var rect = this.getBoundingClientRect(true);\n\n      rect.centroid = {\n        x: rect.left + rect.width / 2,\n        y: rect.top + rect.height / 2\n      };\n\n      _.each(this.vertices, function(v) {\n        v.addSelf(rect.centroid);\n      });\n\n      return this;\n\n    },\n\n    /**\n     * Orient the vertices of the shape to the center of the\n     * path.\n     */\n    center: function() {\n\n      var rect = this.getBoundingClientRect(true);\n\n      rect.centroid = {\n        x: rect.left + rect.width / 2,\n        y: rect.top + rect.height / 2\n      };\n\n      _.each(this.vertices, function(v) {\n        v.subSelf(rect.centroid);\n      });\n\n      // this.translation.addSelf(rect.centroid);\n\n      return this;\n\n    },\n\n    /**\n     * Remove self from the scene / parent.\n     */\n    remove: function() {\n\n      if (!this.parent) {\n        return this;\n      }\n\n      this.parent.remove(this);\n\n      return this;\n\n    },\n\n    /**\n     * Return an object with top, left, right, bottom, width, and height\n     * parameters of the group.\n     */\n    getBoundingClientRect: function(shallow) {\n      var matrix, border, l, x, y, i, v;\n\n      var left = Infinity, right = -Infinity,\n          top = Infinity, bottom = -Infinity;\n\n      // TODO: Update this to not __always__ update. Just when it needs to.\n      this._update(true);\n\n      matrix = !!shallow ? this._matrix : getComputedMatrix(this);\n\n      border = this.linewidth / 2;\n      l = this._vertices.length;\n\n      if (l <= 0) {\n        v = matrix.multiply(0, 0, 1);\n        return {\n          top: v.y,\n          left: v.x,\n          right: v.x,\n          bottom: v.y,\n          width: 0,\n          height: 0\n        };\n      }\n\n      for (i = 0; i < l; i++) {\n        v = this._vertices[i];\n\n        x = v.x;\n        y = v.y;\n\n        v = matrix.multiply(x, y, 1);\n        top = min(v.y - border, top);\n        left = min(v.x - border, left);\n        right = max(v.x + border, right);\n        bottom = max(v.y + border, bottom);\n      }\n\n      return {\n        top: top,\n        left: left,\n        right: right,\n        bottom: bottom,\n        width: right - left,\n        height: bottom - top\n      };\n\n    },\n\n    /**\n     * Given a float `t` from 0 to 1, return a point or assign a passed `obj`'s\n     * coordinates to that percentage on this Two.Path's curve.\n     */\n    getPointAt: function(t, obj) {\n      var x, x1, x2, x3, x4, y, y1, y2, y3, y4, left, right;\n      var target = this.length * Math.min(Math.max(t, 0), 1);\n      var length = this.vertices.length;\n      var last = length - 1;\n\n      var a = null;\n      var b = null;\n\n      for (var i = 0, l = this._lengths.length, sum = 0; i < l; i++) {\n\n        if (sum + this._lengths[i] > target) {\n          a = this.vertices[this.closed ? Two.Utils.mod(i, length) : i];\n          b = this.vertices[Math.min(Math.max(i - 1, 0), last)];\n          target -= sum;\n          t = target / this._lengths[i];\n          break;\n        }\n\n        sum += this._lengths[i];\n\n      }\n\n      if (_.isNull(a) || _.isNull(b)) {\n        return null;\n      }\n\n      right = b.controls && b.controls.right;\n      left = a.controls && a.controls.left;\n\n      x1 = b.x;\n      y1 = b.y;\n      x2 = (right || b).x;\n      y2 = (right || b).y;\n      x3 = (left || a).x;\n      y3 = (left || a).y;\n      x4 = a.x;\n      y4 = a.y;\n\n      if (right && b._relative) {\n        x2 += b.x;\n        y2 += b.y;\n      }\n\n      if (left && a._relative) {\n        x3 += a.x;\n        y3 += a.y;\n      }\n\n      x = Two.Utils.getPointOnCubicBezier(t, x1, x2, x3, x4);\n      y = Two.Utils.getPointOnCubicBezier(t, y1, y2, y3, y4);\n\n      if (_.isObject(obj)) {\n        obj.x = x;\n        obj.y = y;\n        return obj;\n      }\n\n      return new Two.Vector(x, y);\n\n    },\n\n    /**\n     * Based on closed / curved and sorting of vertices plot where all points\n     * should be and where the respective handles should be too.\n     */\n    plot: function() {\n\n      if (this.curved) {\n        Two.Utils.getCurveFromPoints(this._vertices, this.closed);\n        return this;\n      }\n\n      for (var i = 0; i < this._vertices.length; i++) {\n        this._vertices[i]._command = i === 0 ? Two.Commands.move : Two.Commands.line;\n      }\n\n      return this;\n\n    },\n\n    subdivide: function(limit) {\n      //TODO: DRYness (function below)\n      this._update();\n\n      var last = this.vertices.length - 1;\n      var b = this.vertices[last];\n      var closed = this._closed || this.vertices[last]._command === Two.Commands.close;\n      var points = [];\n      _.each(this.vertices, function(a, i) {\n\n        if (i <= 0 && !closed) {\n          b = a;\n          return;\n        }\n\n        if (a.command === Two.Commands.move) {\n          points.push(new Two.Anchor(b.x, b.y));\n          if (i > 0) {\n            points[points.length - 1].command = Two.Commands.line;\n          }\n          b = a;\n          return;\n        }\n\n        var verts = getSubdivisions(a, b, limit);\n        points = points.concat(verts);\n\n        // Assign commands to all the verts\n        _.each(verts, function(v, i) {\n          if (i <= 0 && b.command === Two.Commands.move) {\n            v.command = Two.Commands.move;\n          } else {\n            v.command = Two.Commands.line;\n          }\n        });\n\n        if (i >= last) {\n\n          // TODO: Add check if the two vectors in question are the same values.\n          if (this._closed && this._automatic) {\n\n            b = a;\n\n            verts = getSubdivisions(a, b, limit);\n            points = points.concat(verts);\n\n            // Assign commands to all the verts\n            _.each(verts, function(v, i) {\n              if (i <= 0 && b.command === Two.Commands.move) {\n                v.command = Two.Commands.move;\n              } else {\n                v.command = Two.Commands.line;\n              }\n            });\n\n          } else if (closed) {\n            points.push(new Two.Anchor(a.x, a.y));\n          }\n\n          points[points.length - 1].command = closed ? Two.Commands.close : Two.Commands.line;\n\n        }\n\n        b = a;\n\n      }, this);\n\n      this._automatic = false;\n      this._curved = false;\n      this.vertices = points;\n\n      return this;\n\n    },\n\n    _updateLength: function(limit) {\n      //TODO: DRYness (function above)\n      this._update();\n\n      var last = this.vertices.length - 1;\n      var b = this.vertices[last];\n      var closed = this._closed || this.vertices[last]._command === Two.Commands.close;\n      var sum = 0;\n\n      if (_.isUndefined(this._lengths)) {\n        this._lengths = [];\n      }\n\n      _.each(this.vertices, function(a, i) {\n\n        if ((i <= 0 && !closed) || a.command === Two.Commands.move) {\n          b = a;\n          this._lengths[i] = 0;\n          return;\n        }\n\n        this._lengths[i] = getCurveLength(a, b, limit);\n        sum += this._lengths[i];\n\n        if (i >= last && closed) {\n\n          b = a;\n\n          this._lengths[i + 1] = getCurveLength(a, b, limit);\n          sum += this._lengths[i + 1];\n\n        }\n\n        b = a;\n\n      }, this);\n\n      this._length = sum;\n\n      return this;\n\n    },\n\n    _update: function() {\n\n      if (this._flagVertices) {\n\n        var l = this.vertices.length;\n        var last = l - 1, v;\n\n        // TODO: Should clamp this so that `ia` and `ib`\n        // cannot select non-verts.\n        var ia = round((this._beginning) * last);\n        var ib = round((this._ending) * last);\n\n        this._vertices.length = 0;\n\n        for (var i = ia; i < ib + 1; i++) {\n          v = this.vertices[i];\n          this._vertices.push(v);\n        }\n\n        if (this._automatic) {\n          this.plot();\n        }\n\n      }\n\n      Two.Shape.prototype._update.apply(this, arguments);\n\n      return this;\n\n    },\n\n    flagReset: function() {\n\n      this._flagVertices =  this._flagFill =  this._flagStroke =\n         this._flagLinewidth = this._flagOpacity = this._flagVisible =\n         this._flagCap = this._flagJoin = this._flagMiter =\n         this._flagClip = false;\n\n      Two.Shape.prototype.flagReset.call(this);\n\n      return this;\n\n    }\n\n  });\n\n  Path.MakeObservable(Path.prototype);\n\n  /**\n   * Utility functions\n   */\n\n  function getCurveLength(a, b, limit) {\n    // TODO: DRYness\n    var x1, x2, x3, x4, y1, y2, y3, y4;\n\n    var right = b.controls && b.controls.right;\n    var left = a.controls && a.controls.left;\n\n    x1 = b.x;\n    y1 = b.y;\n    x2 = (right || b).x;\n    y2 = (right || b).y;\n    x3 = (left || a).x;\n    y3 = (left || a).y;\n    x4 = a.x;\n    y4 = a.y;\n\n    if (right && b._relative) {\n      x2 += b.x;\n      y2 += b.y;\n    }\n\n    if (left && a._relative) {\n      x3 += a.x;\n      y3 += a.y;\n    }\n\n    return Two.Utils.getCurveLength(x1, y1, x2, y2, x3, y3, x4, y4, limit);\n\n  }\n\n  function getSubdivisions(a, b, limit) {\n    // TODO: DRYness\n    var x1, x2, x3, x4, y1, y2, y3, y4;\n\n    var right = b.controls && b.controls.right;\n    var left = a.controls && a.controls.left;\n\n    x1 = b.x;\n    y1 = b.y;\n    x2 = (right || b).x;\n    y2 = (right || b).y;\n    x3 = (left || a).x;\n    y3 = (left || a).y;\n    x4 = a.x;\n    y4 = a.y;\n\n    if (right && b._relative) {\n      x2 += b.x;\n      y2 += b.y;\n    }\n\n    if (left && a._relative) {\n      x3 += a.x;\n      y3 += a.y;\n    }\n\n    return Two.Utils.subdivide(x1, y1, x2, y2, x3, y3, x4, y4, limit);\n\n  }\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  var Path = Two.Path;\n  var _ = Two.Utils;\n\n  var Line = Two.Line = function(x1, y1, x2, y2) {\n\n    var width = x2 - x1;\n    var height = y2 - y1;\n\n    var w2 = width / 2;\n    var h2 = height / 2;\n\n    Path.call(this, [\n        new Two.Anchor(- w2, - h2),\n        new Two.Anchor(w2, h2)\n    ]);\n\n    this.translation.set(x1 + w2, y1 + h2);\n\n  };\n\n  _.extend(Line.prototype, Path.prototype);\n\n  Path.MakeObservable(Line.prototype);\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  var Path = Two.Path;\n  var _ = Two.Utils;\n\n  var Rectangle = Two.Rectangle = function(x, y, width, height) {\n\n    Path.call(this, [\n      new Two.Anchor(),\n      new Two.Anchor(),\n      new Two.Anchor(),\n      new Two.Anchor()\n    ], true);\n\n    this.width = width;\n    this.height = height;\n    this._update();\n\n    this.translation.set(x, y);\n\n  };\n\n  _.extend(Rectangle, {\n\n    Properties: ['width', 'height'],\n\n    MakeObservable: function(obj) {\n      Path.MakeObservable(obj);\n      _.each(Rectangle.Properties, Two.Utils.defineProperty, obj);\n    }\n\n  });\n\n  _.extend(Rectangle.prototype, Path.prototype, {\n\n    _width: 0,\n    _height: 0,\n\n    _flagWidth: 0,\n    _flagHeight: 0,\n\n    _update: function() {\n\n      if (this._flagWidth || this._flagHeight) {\n\n        var xr = this._width / 2;\n        var yr = this._height / 2;\n\n        this.vertices[0].set(-xr, -yr);\n        this.vertices[1].set(xr, -yr);\n        this.vertices[2].set(xr, yr);\n        this.vertices[3].set(-xr, yr);\n\n      }\n\n      Path.prototype._update.call(this);\n\n      return this;\n\n    },\n\n    flagReset: function() {\n\n      this._flagWidth = this._flagHeight = false;\n      Path.prototype.flagReset.call(this);\n\n      return this;\n\n    }\n\n  });\n\n  Rectangle.MakeObservable(Rectangle.prototype);\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  var Path = Two.Path, TWO_PI = Math.PI * 2, cos = Math.cos, sin = Math.sin;\n  var _ = Two.Utils;\n\n  var Ellipse = Two.Ellipse = function(ox, oy, rx, ry) {\n\n    if (!_.isNumber(ry)) {\n      ry = rx;\n    }\n\n    var amount = Two.Resolution;\n\n    var points = _.map(_.range(amount), function(i) {\n      return new Two.Anchor();\n    }, this);\n\n    Path.call(this, points, true, true);\n\n    this.width = rx * 2;\n    this.height = ry * 2;\n\n    this._update();\n    this.translation.set(ox, oy);\n\n  };\n\n  _.extend(Ellipse, {\n\n    Properties: ['width', 'height'],\n\n    MakeObservable: function(obj) {\n\n      Path.MakeObservable(obj);\n      _.each(Ellipse.Properties, Two.Utils.defineProperty, obj);\n\n    }\n\n  });\n\n  _.extend(Ellipse.prototype, Path.prototype, {\n\n    _width: 0,\n    _height: 0,\n\n    _flagWidth: false,\n    _flagHeight: false,\n\n    _update: function() {\n\n      if (this._flagWidth || this._flagHeight) {\n        for (var i = 0, l = this.vertices.length; i < l; i++) {\n          var pct = i / l;\n          var theta = pct * TWO_PI;\n          var x = this._width * cos(theta) / 2;\n          var y = this._height * sin(theta) / 2;\n          this.vertices[i].set(x, y);\n        }\n      }\n\n      Path.prototype._update.call(this);\n      return this;\n\n    },\n\n    flagReset: function() {\n\n      this._flagWidth = this._flagHeight = false;\n\n      Path.prototype.flagReset.call(this);\n      return this;\n\n    }\n\n  });\n\n  Ellipse.MakeObservable(Ellipse.prototype);\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  var Path = Two.Path, TWO_PI = Math.PI * 2, cos = Math.cos, sin = Math.sin;\n  var _ = Two.Utils;\n\n  var Circle = Two.Circle = function(ox, oy, r) {\n\n    var amount = Two.Resolution;\n\n    var points = _.map(_.range(amount), function(i) {\n      return new Two.Anchor();\n    }, this);\n\n    Path.call(this, points, true, true);\n\n    this.radius = r;\n\n    this._update();\n    this.translation.set(ox, oy);\n\n  };\n\n  _.extend(Circle, {\n\n    Properties: ['radius'],\n\n    MakeObservable: function(obj) {\n\n      Path.MakeObservable(obj);\n      _.each(Circle.Properties, Two.Utils.defineProperty, obj);\n\n    }\n\n  });\n\n  _.extend(Circle.prototype, Path.prototype, {\n\n    _radius: 0,\n    _flagRadius: false,\n\n    _update: function() {\n\n      if (this._flagRadius) {\n        for (var i = 0, l = this.vertices.length; i < l; i++) {\n          var pct = i / l;\n          var theta = pct * TWO_PI;\n          var x = this._radius * cos(theta);\n          var y = this._radius * sin(theta);\n          this.vertices[i].set(x, y);\n        }\n      }\n\n      Path.prototype._update.call(this);\n      return this;\n\n    },\n\n    flagReset: function() {\n\n      this._flagRadius = false;\n\n      Path.prototype.flagReset.call(this);\n      return this;\n\n    }\n\n  });\n\n  Circle.MakeObservable(Circle.prototype);\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  var Path = Two.Path, TWO_PI = Math.PI * 2, cos = Math.cos, sin = Math.sin;\n  var _ = Two.Utils;\n\n  var Polygon = Two.Polygon = function(ox, oy, r, sides) {\n\n    sides = Math.max(sides || 0, 3);\n\n    var points = _.map(_.range(sides), function(i) {\n      return new Two.Anchor();\n    });\n\n    Path.call(this, points, true);\n\n    this.width = r * 2;\n    this.height = r * 2;\n    this.sides = sides;\n\n    this._update();\n    this.translation.set(ox, oy);\n\n  };\n\n  _.extend(Polygon, {\n\n    Properties: ['width', 'height', 'sides'],\n\n    MakeObservable: function(obj) {\n\n      Path.MakeObservable(obj);\n      _.each(Polygon.Properties, Two.Utils.defineProperty, obj);\n\n    }\n\n  });\n\n  _.extend(Polygon.prototype, Path.prototype, {\n\n    _width: 0,\n    _height: 0,\n    _sides: 0,\n\n    _flagWidth: false,\n    _flagHeight: false,\n    _flagSides: false,\n\n    _update: function() {\n\n      if (this._flagWidth || this._flagHeight || this._flagSides) {\n\n        var sides = this._sides;\n        var amount = this.vertices.length;\n\n        if (amount > sides) {\n          this.vertices.splice(sides - 1, amount - sides);\n        }\n\n        for (var i = 0; i < sides; i++) {\n\n          var pct = (i + 0.5) / sides;\n          var theta = TWO_PI * pct + Math.PI / 2;\n          var x = this._width * cos(theta);\n          var y = this._height * sin(theta);\n\n          if (i >= amount) {\n            this.vertices.push(new Two.Anchor(x, y));\n          } else {\n            this.vertices[i].set(x, y);\n          }\n\n        }\n\n      }\n\n      Path.prototype._update.call(this);\n      return this;\n\n    },\n\n    flagReset: function() {\n\n      this._flagWidth = this._flagHeight = this._flagSides = false;\n      Path.prototype.flagReset.call(this);\n\n      return this;\n\n    }\n\n  });\n\n  Polygon.MakeObservable(Polygon.prototype);\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  var Path = Two.Path, PI = Math.PI, TWO_PI = Math.PI * 2, HALF_PI = Math.PI / 2,\n    cos = Math.cos, sin = Math.sin, abs = Math.abs, _ = Two.Utils;\n\n  var ArcSegment = Two.ArcSegment = function(ox, oy, ir, or, sa, ea, res) {\n\n    var points = _.map(_.range(res || (Two.Resolution * 3)), function() {\n      return new Two.Anchor();\n    });\n\n    Path.call(this, points, false, false, true);\n\n    this.innerRadius = ir;\n    this.outerRadius = or;\n\n    this.startAngle = sa;\n    this.endAngle = ea;\n\n    this._update();\n    this.translation.set(ox, oy);\n\n  }\n\n  _.extend(ArcSegment, {\n\n    Properties: ['startAngle', 'endAngle', 'innerRadius', 'outerRadius'],\n\n    MakeObservable: function(obj) {\n\n      Path.MakeObservable(obj);\n      _.each(ArcSegment.Properties, Two.Utils.defineProperty, obj);\n\n    }\n\n  });\n\n  _.extend(ArcSegment.prototype, Path.prototype, {\n\n    _flagStartAngle: false,\n    _flagEndAngle: false,\n    _flagInnerRadius: false,\n    _flagOuterRadius: false,\n\n    _startAngle: 0,\n    _endAngle: TWO_PI,\n    _innerRadius: 0,\n    _outerRadius: 0,\n\n    _update: function() {\n\n      if (this._flagStartAngle || this._flagEndAngle || this._flagInnerRadius\n        || this._flagOuterRadius) {\n\n        var sa = this._startAngle;\n        var ea = this._endAngle;\n\n        var ir = this._innerRadius;\n        var or = this._outerRadius;\n\n        var connected = mod(sa, TWO_PI) === mod(ea, TWO_PI);\n        var punctured = ir > 0;\n\n        var vertices = this.vertices;\n        var length = (punctured ? vertices.length / 2 : vertices.length);\n        var command, id = 0;\n\n        if (connected) {\n          length--;\n        } else if (!punctured) {\n          length -= 2;\n        }\n\n        /**\n         * Outer Circle\n         */\n        for (var i = 0, last = length - 1; i < length; i++) {\n\n          var pct = i / last;\n          var v = vertices[id];\n          var theta = pct * (ea - sa) + sa;\n          var step = (ea - sa) / length;\n\n          var x = or * Math.cos(theta);\n          var y = or * Math.sin(theta);\n\n          switch (i) {\n            case 0:\n              command = Two.Commands.move;\n              break;\n            default:\n              command = Two.Commands.curve;\n          }\n\n          v.command = command;\n          v.x = x;\n          v.y = y;\n          v.controls.left.clear();\n          v.controls.right.clear();\n\n          if (v.command === Two.Commands.curve) {\n            var amp = or * step / Math.PI;\n            v.controls.left.x = amp * Math.cos(theta - HALF_PI);\n            v.controls.left.y = amp * Math.sin(theta - HALF_PI);\n            v.controls.right.x = amp * Math.cos(theta + HALF_PI);\n            v.controls.right.y = amp * Math.sin(theta + HALF_PI);\n            if (i === 1) {\n              v.controls.left.multiplyScalar(2);\n            }\n            if (i === last) {\n              v.controls.right.multiplyScalar(2);\n            }\n          }\n\n          id++;\n\n        }\n\n        if (punctured) {\n\n          if (connected) {\n            vertices[id].command = Two.Commands.close;\n            id++;\n          } else {\n            length--;\n            last = length - 1;\n          }\n\n          /**\n           * Inner Circle\n           */\n          for (i = 0; i < length; i++) {\n\n            pct = i / last;\n            v = vertices[id];\n            theta = (1 - pct) * (ea - sa) + sa;\n            step = (ea - sa) / length;\n\n            x = ir * Math.cos(theta);\n            y = ir * Math.sin(theta);\n            command = Two.Commands.curve;\n            if (i <= 0) {\n              command = connected ? Two.Commands.move : Two.Commands.line;\n            }\n\n            v.command = command;\n            v.x = x;\n            v.y = y;\n            v.controls.left.clear();\n            v.controls.right.clear();\n\n            if (v.command === Two.Commands.curve) {\n              amp = ir * step / Math.PI;\n              v.controls.left.x = amp * Math.cos(theta + HALF_PI);\n              v.controls.left.y = amp * Math.sin(theta + HALF_PI);\n              v.controls.right.x = amp * Math.cos(theta - HALF_PI);\n              v.controls.right.y = amp * Math.sin(theta - HALF_PI);\n              if (i === 1) {\n                v.controls.left.multiplyScalar(2);\n              }\n              if (i === last) {\n                v.controls.right.multiplyScalar(2);\n              }\n            }\n\n            id++;\n\n          }\n\n        } else if (!connected) {\n\n          vertices[id].command = Two.Commands.line;\n          vertices[id].x = 0;\n          vertices[id].y = 0;\n          id++;\n\n        }\n\n        /**\n         * Final Point\n         */\n        vertices[id].command = Two.Commands.close;\n\n      }\n\n      Path.prototype._update.call(this);\n\n      return this;\n\n    },\n\n    flagReset: function() {\n\n      Path.prototype.flagReset.call(this);\n\n      this._flagStartAngle = this._flagEndAngle\n        = this._flagInnerRadius = this._flagOuterRadius = false;\n\n      return this;\n\n    }\n\n  });\n\n  ArcSegment.MakeObservable(ArcSegment.prototype);\n\n  function mod(v, l) {\n    while (v < 0) {\n      v += l;\n    }\n    return v % l;\n  }\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  var Path = Two.Path, TWO_PI = Math.PI * 2, cos = Math.cos, sin = Math.sin;\n  var _ = Two.Utils;\n\n  var Star = Two.Star = function(ox, oy, or, ir, sides) {\n\n    if (!_.isNumber(ir)) {\n      ir = or / 2;\n    }\n\n    if (!_.isNumber(sides) || sides <= 0) {\n      sides = 5;\n    }\n\n    var length = sides * 2;\n\n    var points = _.map(_.range(length), function(i) {\n      return new Two.Anchor();\n    });\n\n    Path.call(this, points, true);\n\n    this.innerRadius = ir;\n    this.outerRadius = or;\n    this.sides = sides;\n\n    this._update();\n    this.translation.set(ox, oy);\n\n  };\n\n  _.extend(Star, {\n\n    Properties: ['innerRadius', 'outerRadius', 'sides'],\n\n    MakeObservable: function(obj) {\n\n      Path.MakeObservable(obj);\n      _.each(Star.Properties, Two.Utils.defineProperty, obj);\n\n    }\n\n  });\n\n  _.extend(Star.prototype, Path.prototype, {\n\n    _innerRadius: 0,\n    _outerRadius: 0,\n    _sides: 0,\n\n    _flagInnerRadius: false,\n    _flagOuterRadius: false,\n    _flagSides: false,\n\n    _update: function() {\n\n      if (this._flagInnerRadius || this._flagOuterRadius || this._flagSides) {\n\n        var sides = this._sides * 2;\n        var amount = this.vertices.length;\n\n        if (amount > sides) {\n          this.vertices.splice(sides - 1, amount - sides);\n        }\n\n        for (var i = 0; i < sides; i++) {\n\n          var pct = (i + 0.5) / sides;\n          var theta = TWO_PI * pct;\n          var r = (i % 2 ? this._innerRadius : this._outerRadius);\n          var x = r * cos(theta);\n          var y = r * sin(theta);\n\n          if (i >= amount) {\n            this.vertices.push(new Two.Anchor(x, y));\n          } else {\n            this.vertices[i].set(x, y);\n          }\n\n        }\n\n      }\n\n      Path.prototype._update.call(this);\n\n      return this;\n\n    },\n\n    flagReset: function() {\n\n      this._flagInnerRadius = this._flagOuterRadius = this._flagSides = false;\n      Path.prototype.flagReset.call(this);\n\n      return this;\n\n    }\n\n  });\n\n  Star.MakeObservable(Star.prototype);\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  var Path = Two.Path;\n  var _ = Two.Utils;\n\n  var RoundedRectangle = Two.RoundedRectangle = function(ox, oy, width, height, radius) {\n\n    if (!_.isNumber(radius)) {\n      radius = Math.floor(Math.min(width, height) / 12);\n    }\n\n    var amount = 10;\n\n    var points = _.map(_.range(amount), function(i) {\n      return new Two.Anchor(0, 0, 0, 0, 0, 0,\n        i === 0 ? Two.Commands.move : Two.Commands.curve);\n    });\n\n    points[points.length - 1].command = Two.Commands.close;\n\n    Path.call(this, points, false, false, true);\n\n    this.width = width;\n    this.height = height;\n    this.radius = radius;\n\n    this._update();\n    this.translation.set(ox, oy);\n\n  };\n\n  _.extend(RoundedRectangle, {\n\n    Properties: ['width', 'height', 'radius'],\n\n    MakeObservable: function(obj) {\n\n      Path.MakeObservable(obj);\n      _.each(RoundedRectangle.Properties, Two.Utils.defineProperty, obj);\n\n    }\n\n  });\n\n  _.extend(RoundedRectangle.prototype, Path.prototype, {\n\n    _width: 0,\n    _height: 0,\n    _radius: 0,\n\n    _flagWidth: false,\n    _flagHeight: false,\n    _flagRadius: false,\n\n    _update: function() {\n\n      if (this._flagWidth || this._flagHeight || this._flagRadius) {\n\n        var width = this._width;\n        var height = this._height;\n        var radius = Math.min(Math.max(this._radius, 0),\n          Math.min(width, height));\n\n        var v;\n        var w = width / 2;\n        var h = height / 2;\n\n        v = this.vertices[0];\n        v.x = - (w - radius);\n        v.y = - h;\n\n        // Upper Right Corner\n\n        v = this.vertices[1];\n        v.x = (w - radius);\n        v.y = - h;\n        v.controls.left.clear();\n        v.controls.right.x = radius;\n        v.controls.right.y = 0;\n\n        v = this.vertices[2];\n        v.x = w;\n        v.y = - (h - radius);\n        v.controls.right.clear();\n        v.controls.left.clear();\n\n        // Bottom Right Corner\n\n        v = this.vertices[3];\n        v.x = w;\n        v.y = (h - radius);\n        v.controls.left.clear();\n        v.controls.right.x = 0;\n        v.controls.right.y = radius;\n\n        v = this.vertices[4];\n        v.x = (w - radius);\n        v.y = h;\n        v.controls.right.clear();\n        v.controls.left.clear();\n\n        // Bottom Left Corner\n\n        v = this.vertices[5];\n        v.x = - (w - radius);\n        v.y = h;\n        v.controls.left.clear();\n        v.controls.right.x = - radius;\n        v.controls.right.y = 0;\n\n        v = this.vertices[6];\n        v.x = - w;\n        v.y = (h - radius);\n        v.controls.left.clear();\n        v.controls.right.clear();\n\n        // Upper Left Corner\n\n        v = this.vertices[7];\n        v.x = - w;\n        v.y = - (h - radius);\n        v.controls.left.clear();\n        v.controls.right.x = 0;\n        v.controls.right.y = - radius;\n\n        v = this.vertices[8];\n        v.x = - (w - radius);\n        v.y = - h;\n        v.controls.left.clear();\n        v.controls.right.clear();\n\n        v = this.vertices[9];\n        v.copy(this.vertices[8]);\n\n      }\n\n      Path.prototype._update.call(this);\n\n      return this;\n\n    },\n\n    flagReset: function() {\n\n      this._flagWidth = this._flagHeight = this._flagRadius = false;\n      Path.prototype.flagReset.call(this);\n\n      return this;\n\n    }\n\n  });\n\n  RoundedRectangle.MakeObservable(RoundedRectangle.prototype);\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  var root = Two.root;\n  var getComputedMatrix = Two.Utils.getComputedMatrix;\n  var _ = Two.Utils;\n\n  var canvas = (root.document ? root.document.createElement('canvas') : { getContext: _.identity });\n  var ctx = canvas.getContext('2d');\n\n  var Text = Two.Text = function(message, x, y, styles) {\n\n    Two.Shape.call(this);\n\n    this._renderer.type = 'text';\n    this._renderer.flagFill = _.bind(Text.FlagFill, this);\n    this._renderer.flagStroke = _.bind(Text.FlagStroke, this);\n\n    this.value = message;\n\n    if (_.isNumber(x)) {\n        this.translation.x = x;\n    }\n    if (_.isNumber(y)) {\n        this.translation.y = y;\n    }\n\n    if (!_.isObject(styles)) {\n      return this;\n    }\n\n    _.each(Two.Text.Properties, function(property) {\n\n      if (property in styles) {\n        this[property] = styles[property];\n      }\n\n    }, this);\n\n  };\n\n  _.extend(Two.Text, {\n\n    Properties: [\n      'value', 'family', 'size', 'leading', 'alignment', 'linewidth', 'style',\n      'weight', 'decoration', 'baseline', 'opacity', 'visible', 'fill', 'stroke'\n    ],\n\n    FlagFill: function() {\n      this._flagFill = true;\n    },\n\n    FlagStroke: function() {\n      this._flagStroke = true;\n    },\n\n    MakeObservable: function(object) {\n\n      Two.Shape.MakeObservable(object);\n\n      _.each(Two.Text.Properties.slice(0, 12), Two.Utils.defineProperty, object);\n\n      Object.defineProperty(object, 'fill', {\n        enumerable: true,\n        get: function() {\n          return this._fill;\n        },\n        set: function(f) {\n\n          if (this._fill instanceof Two.Gradient\n            || this._fill instanceof Two.LinearGradient\n            || this._fill instanceof Two.RadialGradient\n            || this._fill instanceof Two.Texture) {\n            this._fill.unbind(Two.Events.change, this._renderer.flagFill);\n          }\n\n          this._fill = f;\n          this._flagFill = true;\n\n          if (this._fill instanceof Two.Gradient\n            || this._fill instanceof Two.LinearGradient\n            || this._fill instanceof Two.RadialGradient\n            || this._fill instanceof Two.Texture) {\n            this._fill.bind(Two.Events.change, this._renderer.flagFill);\n          }\n\n        }\n      });\n\n      Object.defineProperty(object, 'stroke', {\n        enumerable: true,\n        get: function() {\n          return this._stroke;\n        },\n        set: function(f) {\n\n          if (this._stroke instanceof Two.Gradient\n            || this._stroke instanceof Two.LinearGradient\n            || this._stroke instanceof Two.RadialGradient\n            || this._stroke instanceof Two.Texture) {\n            this._stroke.unbind(Two.Events.change, this._renderer.flagStroke);\n          }\n\n          this._stroke = f;\n          this._flagStroke = true;\n\n          if (this._stroke instanceof Two.Gradient\n            || this._stroke instanceof Two.LinearGradient\n            || this._stroke instanceof Two.RadialGradient\n            || this._stroke instanceof Two.Texture) {\n            this._stroke.bind(Two.Events.change, this._renderer.flagStroke);\n          }\n\n        }\n      });\n\n      Object.defineProperty(object, 'clip', {\n        enumerable: true,\n        get: function() {\n          return this._clip;\n        },\n        set: function(v) {\n          this._clip = v;\n          this._flagClip = true;\n        }\n      });\n\n    }\n\n  });\n\n  _.extend(Two.Text.prototype, Two.Shape.prototype, {\n\n    // Flags\n    // http://en.wikipedia.org/wiki/Flag\n\n    _flagValue: true,\n    _flagFamily: true,\n    _flagSize: true,\n    _flagLeading: true,\n    _flagAlignment: true,\n    _flagBaseline: true,\n    _flagStyle: true,\n    _flagWeight: true,\n    _flagDecoration: true,\n\n    _flagFill: true,\n    _flagStroke: true,\n    _flagLinewidth: true,\n    _flagOpacity: true,\n    _flagVisible: true,\n\n    _flagClip: false,\n\n    // Underlying Properties\n\n    _value: '',\n    _family: 'sans-serif',\n    _size: 13,\n    _leading: 17,\n    _alignment: 'center',\n    _baseline: 'middle',\n    _style: 'normal',\n    _weight: 500,\n    _decoration: 'none',\n\n    _fill: '#000',\n    _stroke: 'transparent',\n    _linewidth: 1,\n    _opacity: 1,\n    _visible: true,\n\n    _clip: false,\n\n    remove: function() {\n\n      if (!this.parent) {\n        return this;\n      }\n\n      this.parent.remove(this);\n\n      return this;\n\n    },\n\n    clone: function(parent) {\n\n      var parent = parent || this.parent;\n\n      var clone = new Two.Text(this.value);\n      clone.translation.copy(this.translation);\n      clone.rotation = this.rotation;\n      clone.scale = this.scale;\n\n      _.each(Two.Text.Properties, function(property) {\n        clone[property] = this[property];\n      }, this);\n\n      if (parent) {\n        parent.add(clone);\n      }\n\n      return clone;\n\n    },\n\n    toObject: function() {\n\n      var result = {\n        translation: this.translation.toObject(),\n        rotation: this.rotation,\n        scale: this.scale\n      };\n\n      _.each(Two.Text.Properties, function(property) {\n        result[property] = this[property];\n      }, this);\n\n      return result;\n\n    },\n\n    noStroke: function() {\n      this.stroke = 'transparent';\n      return this;\n    },\n\n    noFill: function() {\n      this.fill = 'transparent';\n      return this;\n    },\n\n    /**\n     * A shim to not break `getBoundingClientRect` calls. TODO: Implement a\n     * way to calculate proper bounding boxes of `Two.Text`.\n     */\n    getBoundingClientRect: function(shallow) {\n\n      var matrix, border, l, x, y, i, v;\n\n      var left = Infinity, right = -Infinity,\n          top = Infinity, bottom = -Infinity;\n\n      // TODO: Update this to not __always__ update. Just when it needs to.\n      this._update(true);\n\n      matrix = !!shallow ? this._matrix : getComputedMatrix(this);\n\n      v = matrix.multiply(0, 0, 1);\n\n      return {\n        top: v.x,\n        left: v.y,\n        right: v.x,\n        bottom: v.y,\n        width: 0,\n        height: 0\n      };\n\n    },\n\n    flagReset: function() {\n\n      this._flagValue = this._flagFamily = this._flagSize =\n        this._flagLeading = this._flagAlignment = this._flagFill =\n        this._flagStroke = this._flagLinewidth = this._flagOpaicty =\n        this._flagVisible = this._flagClip = this._flagDecoration =\n        this._flagBaseline = false;\n\n      Two.Shape.prototype.flagReset.call(this);\n\n      return this;\n\n    }\n\n  });\n\n  Two.Text.MakeObservable(Two.Text.prototype);\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  var _ = Two.Utils;\n\n  var Stop = Two.Stop = function(offset, color, opacity) {\n\n    this._renderer = {};\n    this._renderer.type = 'stop';\n\n    this.offset = _.isNumber(offset) ? offset\n      : Stop.Index <= 0 ? 0 : 1;\n\n    this.opacity = _.isNumber(opacity) ? opacity : 1;\n\n    this.color = _.isString(color) ? color\n      : Stop.Index <= 0 ? '#fff' : '#000';\n\n    Stop.Index = (Stop.Index + 1) % 2;\n\n  };\n\n  _.extend(Stop, {\n\n    Index: 0,\n\n    Properties: [\n      'offset',\n      'opacity',\n      'color'\n    ],\n\n    MakeObservable: function(object) {\n\n      _.each(Stop.Properties, function(property) {\n\n        var object = this;\n        var secret = '_' + property;\n        var flag = '_flag' + property.charAt(0).toUpperCase() + property.slice(1);\n\n        Object.defineProperty(object, property, {\n          enumerable: true,\n          get: function() {\n            return this[secret];\n          },\n          set: function(v) {\n            this[secret] = v;\n            this[flag] = true;\n            if (this.parent) {\n              this.parent._flagStops = true;\n            }\n          }\n        });\n\n      }, object);\n\n    }\n\n  });\n\n  _.extend(Stop.prototype, Two.Utils.Events, {\n\n    clone: function() {\n\n      var clone = new Stop();\n\n      _.each(Stop.Properties, function(property) {\n        clone[property] = this[property];\n      }, this);\n\n      return clone;\n\n    },\n\n    toObject: function() {\n\n      var result = {};\n\n      _.each(Stop.Properties, function(k) {\n        result[k] = this[k];\n      }, this);\n\n      return result;\n\n    },\n\n    flagReset: function() {\n\n      this._flagOffset = this._flagColor = this._flagOpacity = false;\n\n      return this;\n\n    }\n\n  });\n\n  Stop.MakeObservable(Stop.prototype);\n\n  var Gradient = Two.Gradient = function(stops) {\n\n    this._renderer = {};\n    this._renderer.type = 'gradient';\n\n    this.id = Two.Identifier + Two.uniqueId();\n    this.classList = [];\n\n    this._renderer.flagStops = _.bind(Gradient.FlagStops, this);\n    this._renderer.bindStops = _.bind(Gradient.BindStops, this);\n    this._renderer.unbindStops = _.bind(Gradient.UnbindStops, this);\n\n    this.spread = 'pad';\n\n    this.stops = stops;\n\n  };\n\n  _.extend(Gradient, {\n\n    Stop: Stop,\n\n    Properties: [\n      'spread'\n    ],\n\n    MakeObservable: function(object) {\n\n      _.each(Gradient.Properties, Two.Utils.defineProperty, object);\n\n      Object.defineProperty(object, 'stops', {\n\n        enumerable: true,\n\n        get: function() {\n          return this._stops;\n        },\n\n        set: function(stops) {\n\n          var updateStops = this._renderer.flagStops;\n          var bindStops = this._renderer.bindStops;\n          var unbindStops = this._renderer.unbindStops;\n\n          // Remove previous listeners\n          if (this._stops) {\n            this._stops\n              .unbind(Two.Events.insert, bindStops)\n              .unbind(Two.Events.remove, unbindStops);\n          }\n\n          // Create new Collection with copy of Stops\n          this._stops = new Two.Utils.Collection((stops || []).slice(0));\n\n          // Listen for Collection changes and bind / unbind\n          this._stops\n            .bind(Two.Events.insert, bindStops)\n            .bind(Two.Events.remove, unbindStops);\n\n          // Bind Initial Stops\n          bindStops(this._stops);\n\n        }\n\n      });\n\n    },\n\n    FlagStops: function() {\n      this._flagStops = true;\n    },\n\n    BindStops: function(items) {\n\n      // This function is called a lot\n      // when importing a large SVG\n      var i = items.length;\n      while(i--) {\n        items[i].bind(Two.Events.change, this._renderer.flagStops);\n        items[i].parent = this;\n      }\n\n      this._renderer.flagStops();\n\n    },\n\n    UnbindStops: function(items) {\n\n      var i = items.length;\n      while(i--) {\n        items[i].unbind(Two.Events.change, this._renderer.flagStops);\n        delete items[i].parent;\n      }\n\n      this._renderer.flagStops();\n\n    }\n\n  });\n\n  _.extend(Gradient.prototype, Two.Utils.Events, {\n\n    _flagStops: false,\n    _flagSpread: false,\n\n    clone: function(parent) {\n\n      parent = parent || this.parent;\n\n      var stops = _.map(this.stops, function(s) {\n        return s.clone();\n      });\n\n      var clone = new Gradient(stops);\n\n      _.each(Two.Gradient.Properties, function(k) {\n        clone[k] = this[k];\n      }, this);\n\n      if (parent) {\n        parent.add(clone);\n      }\n\n      return clone;\n\n    },\n\n    toObject: function() {\n\n      var result = {\n        stops: _.map(this.stops, function(s) {\n          return s.toObject();\n        })\n      };\n\n      _.each(Gradient.Properties, function(k) {\n        result[k] = this[k];\n      }, this);\n\n      return result;\n\n    },\n\n    _update: function() {\n\n      if (this._flagSpread || this._flagStops) {\n        this.trigger(Two.Events.change);\n      }\n\n      return this;\n\n    },\n\n    flagReset: function() {\n\n      this._flagSpread = this._flagStops = false;\n\n      return this;\n\n    }\n\n  });\n\n  Gradient.MakeObservable(Gradient.prototype);\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  var _ = Two.Utils;\n\n  var LinearGradient = Two.LinearGradient = function(x1, y1, x2, y2, stops) {\n\n    Two.Gradient.call(this, stops);\n\n    this._renderer.type = 'linear-gradient';\n\n    var flagEndPoints = _.bind(LinearGradient.FlagEndPoints, this);\n    this.left = new Two.Vector().bind(Two.Events.change, flagEndPoints);\n    this.right = new Two.Vector().bind(Two.Events.change, flagEndPoints);\n\n    if (_.isNumber(x1)) {\n      this.left.x = x1;\n    }\n    if (_.isNumber(y1)) {\n      this.left.y = y1;\n    }\n    if (_.isNumber(x2)) {\n      this.right.x = x2;\n    }\n    if (_.isNumber(y2)) {\n      this.right.y = y2;\n    }\n\n  };\n\n  _.extend(LinearGradient, {\n\n    Stop: Two.Gradient.Stop,\n\n    MakeObservable: function(object) {\n      Two.Gradient.MakeObservable(object);\n    },\n\n    FlagEndPoints: function() {\n      this._flagEndPoints = true;\n    }\n\n  });\n\n  _.extend(LinearGradient.prototype, Two.Gradient.prototype, {\n\n    _flagEndPoints: false,\n\n    clone: function(parent) {\n\n      parent = parent || this.parent;\n\n      var stops = _.map(this.stops, function(stop) {\n        return stop.clone();\n      });\n\n      var clone = new LinearGradient(this.left._x, this.left._y,\n        this.right._x, this.right._y, stops);\n\n      _.each(Two.Gradient.Properties, function(k) {\n        clone[k] = this[k];\n      }, this);\n\n      if (parent) {\n        parent.add(clone);\n      }\n\n      return clone;\n\n    },\n\n    toObject: function() {\n\n      var result = Two.Gradient.prototype.toObject.call(this);\n\n      result.left = this.left.toObject();\n      result.right = this.right.toObject();\n\n      return result;\n\n    },\n\n    _update: function() {\n\n      if (this._flagEndPoints || this._flagSpread || this._flagStops) {\n        this.trigger(Two.Events.change);\n      }\n\n      return this;\n\n    },\n\n    flagReset: function() {\n\n      this._flagEndPoints = false;\n\n      Two.Gradient.prototype.flagReset.call(this);\n\n      return this;\n\n    }\n\n  });\n\n  LinearGradient.MakeObservable(LinearGradient.prototype);\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  var _ = Two.Utils;\n\n  var RadialGradient = Two.RadialGradient = function(cx, cy, r, stops, fx, fy) {\n\n    Two.Gradient.call(this, stops);\n\n    this._renderer.type = 'radial-gradient';\n\n    this.center = new Two.Vector()\n      .bind(Two.Events.change, _.bind(function() {\n        this._flagCenter = true;\n      }, this));\n\n    this.radius = _.isNumber(r) ? r : 20;\n\n    this.focal = new Two.Vector()\n      .bind(Two.Events.change, _.bind(function() {\n        this._flagFocal = true;\n      }, this));\n\n    if (_.isNumber(cx)) {\n      this.center.x = cx;\n    }\n    if (_.isNumber(cy)) {\n      this.center.y = cy;\n    }\n\n    this.focal.copy(this.center);\n\n    if (_.isNumber(fx)) {\n      this.focal.x = fx;\n    }\n    if (_.isNumber(fy)) {\n      this.focal.y = fy;\n    }\n\n  };\n\n  _.extend(RadialGradient, {\n\n    Stop: Two.Gradient.Stop,\n\n    Properties: [\n      'radius'\n    ],\n\n    MakeObservable: function(object) {\n\n      Two.Gradient.MakeObservable(object);\n\n      _.each(RadialGradient.Properties, Two.Utils.defineProperty, object);\n\n    }\n\n  });\n\n  _.extend(RadialGradient.prototype, Two.Gradient.prototype, {\n\n    _flagRadius: false,\n    _flagCenter: false,\n    _flagFocal: false,\n\n    clone: function(parent) {\n\n      parent = parent || this.parent;\n\n      var stops = _.map(this.stops, function(stop) {\n        return stop.clone();\n      });\n\n      var clone = new RadialGradient(this.center._x, this.center._y,\n          this._radius, stops, this.focal._x, this.focal._y);\n\n      _.each(Two.Gradient.Properties.concat(RadialGradient.Properties), function(k) {\n        clone[k] = this[k];\n      }, this);\n\n      if (parent) {\n        parent.add(clone);\n      }\n\n      return clone;\n\n    },\n\n    toObject: function() {\n\n      var result = Two.Gradient.prototype.toObject.call(this);\n\n      _.each(RadialGradient.Properties, function(k) {\n        result[k] = this[k];\n      }, this);\n\n      result.center = this.center.toObject();\n      result.focal = this.focal.toObject();\n\n      return result;\n\n    },\n\n    _update: function() {\n\n      if (this._flagRadius || this._flatCenter || this._flagFocal\n        || this._flagSpread || this._flagStops) {\n        this.trigger(Two.Events.change);\n      }\n\n      return this;\n\n    },\n\n    flagReset: function() {\n\n      this._flagRadius = this._flagCenter = this._flagFocal = false;\n\n      Two.Gradient.prototype.flagReset.call(this);\n\n      return this;\n\n    }\n\n  });\n\n  RadialGradient.MakeObservable(RadialGradient.prototype);\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  var _ = Two.Utils;\n  var regex = {\n    video: /\\.(mp4|webm)$/i,\n    image: /\\.(jpe?g|png|gif|tiff)$/i\n  };\n\n  var Texture = Two.Texture = function(src, callback) {\n\n    this._renderer = {};\n    this._renderer.type = 'texture';\n    this._renderer.flagOffset = _.bind(Texture.FlagOffset, this);\n    this._renderer.flagScale = _.bind(Texture.FlagScale, this);\n\n    this.id = Two.Identifier + Two.uniqueId();\n    this.classList = [];\n\n    this.offset = new Two.Vector();\n\n    if (_.isFunction(callback)) {\n      var loaded = _.bind(function() {\n        this.unbind(Two.Events.load, loaded);\n        if (_.isFunction(callback)) {\n          callback();\n        }\n      }, this);\n      this.bind(Two.Events.load, loaded);\n    }\n\n    if (_.isString(src)) {\n      this.src = src;\n    } else if (_.isElement(src)) {\n      this.image = src;\n    }\n\n    this._update();\n\n  };\n\n  _.extend(Texture, {\n\n    Properties: [\n      'src',\n      'image',\n      'loaded',\n      'repeat'\n    ],\n\n    ImageRegistry: new Two.Registry(),\n\n    getImage: function(src) {\n\n      if (Texture.ImageRegistry.contains(src)) {\n        return Texture.ImageRegistry.get(src);\n      }\n\n      var image;\n\n      if (regex.video.test(src)) {\n        image = document.createElement('video');\n      } else {\n        image = document.createElement('img');\n      }\n\n      image.crossOrigin = 'anonymous';\n\n      return image;\n\n    },\n\n    Register: {\n      canvas: function(texture, callback) {\n        texture._src = '#' + texture.id;\n        Texture.ImageRegistry.add(texture.src, texture.image);\n        if (_.isFunction(callback)) {\n          callback();\n        }\n      },\n      img: function(texture, callback) {\n\n        if (texture.image && texture.image.getAttribute('two-src')) {\n          return;\n        }\n\n        var loaded = function(e) {\n          texture.image.removeEventListener('load', loaded, false);\n          texture.image.removeEventListener('error', error, false);\n          if (_.isFunction(callback)) {\n            callback();\n          }\n        };\n        var error = function(e) {\n          texture.image.removeEventListener('load', loaded, false);\n          texture.image.removeEventListener('error', error, false);\n          throw new Two.Utils.Error('unable to load ' + texture.src);\n        };\n\n        texture.image.addEventListener('load', loaded, false);\n        texture.image.addEventListener('error', error, false);\n        texture.image.setAttribute('two-src', texture.src);\n        Texture.ImageRegistry.add(texture.src, texture.image);\n        texture.image.src = texture.src;\n\n      },\n      video: function(texture, callback) {\n\n        if (texture.image && texture.image.getAttribute('two-src')) {\n          return;\n        }\n\n        var loaded = function(e) {\n          texture.image.removeEventListener('load', loaded, false);\n          texture.image.removeEventListener('error', error, false);\n          texture.image.width = texture.image.videoWidth;\n          texture.image.height = texture.image.videoHeight;\n          texture.image.play();\n          if (_.isFunction(callback)) {\n            callback();\n          }\n        };\n        var error = function(e) {\n          texture.image.removeEventListener('load', loaded, false);\n          texture.image.removeEventListener('error', error, false);\n          throw new Two.Utils.Error('unable to load ' + texture.src);\n        };\n\n        texture.image.addEventListener('canplaythrough', loaded, false);\n        texture.image.addEventListener('error', error, false);\n        texture.image.setAttribute('two-src', texture.src);\n        Texture.ImageRegistry.add(texture.src, texture.image);\n        texture.image.src = texture.src;\n        texture.image.loop = true;\n        texture.image.load();\n\n      }\n    },\n\n    load: function(texture, callback) {\n\n      var src = texture.src;\n      var image = texture.image;\n      var tag = image && image.nodeName.toLowerCase();\n\n      if (texture._flagImage) {\n        if (/canvas/i.test(tag)) {\n          Texture.Register.canvas(texture, callback);\n        } else {\n          texture._src = image.getAttribute('two-src') || image.src;\n          Texture.Register[tag](texture, callback);\n        }\n      }\n\n      if (texture._flagSrc) {\n        if (!image) {\n          texture.image = Texture.getImage(texture.src);\n        }\n        tag = texture.image.nodeName.toLowerCase();\n        Texture.Register[tag](texture, callback);\n      }\n\n    },\n\n    FlagOffset: function() {\n      this._flagOffset = true;\n    },\n\n    FlagScale: function() {\n      this._flagScale = true;\n    },\n\n    MakeObservable: function(object) {\n\n      _.each(Texture.Properties, Two.Utils.defineProperty, object);\n\n      Object.defineProperty(object, 'offset', {\n        enumerable: true,\n        get: function() {\n          return this._offset;\n        },\n        set: function(v) {\n          if (this._offset) {\n            this._offset.unbind(Two.Events.change, this._renderer.flagOffset);\n          }\n          this._offset = v;\n          this._offset.bind(Two.Events.change, this._renderer.flagOffset);\n          this._flagOffset = true;\n        }\n      });\n\n      Object.defineProperty(object, 'scale', {\n        enumerable: true,\n        get: function() {\n          return this._scale;\n        },\n        set: function(v) {\n\n          if (this._scale instanceof Two.Vector) {\n            this._scale.unbind(Two.Events.change, this._renderer.flagScale);\n          }\n\n          this._scale = v;\n\n          if (this._scale instanceof Two.Vector) {\n            this._scale.bind(Two.Events.change, this._renderer.flagScale);\n          }\n\n          this._flagScale = true;\n\n        }\n      });\n\n    }\n\n  });\n\n  _.extend(Texture.prototype, Two.Utils.Events, Two.Shape.prototype, {\n\n    _flagSrc: false,\n    _flagImage: false,\n    _flagLoaded: false,\n    _flagRepeat: false,\n\n    _flagOffset: false,\n    _flagScale: false,\n\n    _src: '',\n    _image: null,\n    _loaded: false,\n    _repeat: 'no-repeat',\n\n    _scale: 1,\n    _offset: null,\n\n    clone: function() {\n      return new Texture(this.src);\n    },\n\n    toObject: function() {\n      return {\n        src: this.src,\n        image: this.image\n      }\n    },\n\n    _update: function() {\n\n      if (this._flagSrc || this._flagImage) {\n        this.trigger(Two.Events.change);\n        this.loaded = false;\n        Texture.load(this, _.bind(function() {\n          this.loaded = true;\n          this\n            .trigger(Two.Events.change)\n            .trigger(Two.Events.load);\n        }, this));\n      }\n\n      if (this.image.readyState >= 4) {\n        this._flagImage = true;\n      }\n\n      return this;\n\n    },\n\n    flagReset: function() {\n\n      this._flagSrc = this._flagImage = this._flagLoaded\n        = this._flagScale = this._flagOffset = false;\n\n      return this;\n\n    }\n\n  });\n\n  Texture.MakeObservable(Texture.prototype);\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  var _ = Two.Utils;\n  var Path = Two.Path;\n  var Rectangle = Two.Rectangle;\n\n  var Sprite = Two.Sprite = function(path, ox, oy, cols, rows, frameRate) {\n\n    Path.call(this, [\n      new Two.Anchor(),\n      new Two.Anchor(),\n      new Two.Anchor(),\n      new Two.Anchor()\n    ], true);\n\n    this.noStroke();\n    this.noFill();\n\n    if (path instanceof Two.Texture) {\n      this.texture = path;\n    } else if (_.isString(path)) {\n      this.texture = new Two.Texture(path);\n    }\n\n    this._update();\n    this.translation.set(ox || 0, oy || 0);\n\n    if (_.isNumber(cols)) {\n      this.columns = cols;\n    }\n    if (_.isNumber(rows)) {\n      this.rows = rows;\n    }\n    if (_.isNumber(frameRate)) {\n      this.frameRate = frameRate;\n    }\n\n  };\n\n  _.extend(Sprite, {\n\n    Properties: [\n      'texture', 'columns', 'rows', 'frameRate'\n    ],\n\n    MakeObservable: function(obj) {\n\n      Rectangle.MakeObservable(obj);\n      _.each(Sprite.Properties, Two.Utils.defineProperty, obj);\n\n    }\n\n  })\n\n  _.extend(Sprite.prototype, Rectangle.prototype, {\n\n    _flagTexture: false,\n    _flagColumns: false,\n    _flagRows: false,\n    _flagFrameRate: false,\n\n    // Private variables\n    _amount: 1,\n    _duration: 0,\n    _index: 0,\n    _startTime: 0,\n    _playing: false,\n    _firstFrame: 0,\n    _lastFrame: 0,\n    _loop: true,\n\n    // Exposed through getter-setter\n    _texture: null,\n    _columns: 1,\n    _rows: 1,\n    _frameRate: 0,\n\n    play: function(firstFrame, lastFrame, onLastFrame) {\n\n      this._playing = true;\n      this._firstFrame = 0;\n      this._lastFrame = this.amount - 1;\n      this._startTime = _.performance.now();\n\n      if (_.isNumber(firstFrame)) {\n        this._firstFrame = firstFrame;\n      }\n      if (_.isNumber(lastFrame)) {\n        this._lastFrame = lastFrame;\n      }\n      if (_.isFunction(onLastFrame)) {\n        this._onLastFrame = onLastFrame;\n      } else {\n        delete this._onLastFrame;\n      }\n\n      return this;\n\n    },\n\n    pause: function() {\n\n      this._playing = false;\n      return this;\n\n    },\n\n    stop: function() {\n\n      this._playing = false;\n      this._index = 0;\n\n      return this;\n\n    },\n\n    clone: function(parent) {\n\n      parent = parent || this.parent;\n\n      var clone = new Sprite(\n        this.texture, this.translation.x, this.translation.y,\n        this.columns, this.rows, this.frameRate\n      );\n\n      if (this.playing) {\n        clone.play(this._firstFrame, this._lastFrame);\n        clone._loop = this._loop;\n      }\n\n      if (parent) {\n        parent.add(clone);\n      }\n\n      return clone;\n\n    },\n\n    _update: function() {\n\n      var effect = this._texture;\n      var cols = this._columns;\n      var rows = this._rows;\n\n      var width, height, elapsed, amount, duration;\n      var index, iw, ih, isRange;\n\n      if (this._flagColumns || this._flagRows) {\n        this._amount = this._columns * this._rows;\n      }\n\n      if (this._flagFrameRate) {\n        this._duration = 1000 * this._amount / this._frameRate;\n      }\n\n      if (this._flagTexture) {\n        this.fill = this._texture;\n      }\n\n      if (this._texture.loaded) {\n\n        iw = effect.image.width;\n        ih = effect.image.height;\n\n        width = iw / cols;\n        height = ih / rows;\n        amount = this._amount;\n\n        if (this.width !== width) {\n          this.width = width;\n        }\n        if (this.height !== height) {\n          this.height = height;\n        }\n\n        if (this._playing && this._frameRate > 0) {\n\n          if (_.isNaN(this._lastFrame)) {\n            this._lastFrame = amount - 1;\n          }\n\n          // TODO: Offload perf logic to instance of `Two`.\n          elapsed = _.performance.now() - this._startTime;\n          duration = 1000 * (this._lastFrame - this._firstFrame)\n            / this._frameRate;\n\n          if (this._loop) {\n            elapsed = elapsed % duration;\n          } else {\n            elapsed = Math.min(elapsed, duration);\n          }\n\n          index = _.lerp(this._firstFrame, this._lastFrame, elapsed / duration);\n          index = Math.floor(index);\n\n          if (index !== this._index) {\n            this._index = index;\n            if (index >= this._lastFrame - 1 && this._onLastFrame) {\n              this._onLastFrame();  // Shortcut for chainable sprite animations\n            }\n          }\n\n        }\n\n        var ox = (iw - width) / 2 + width * ((this._index % cols) + 1);\n        var oy = height * Math.floor((this._index / cols))\n          - (ih - height) / 2;\n\n        // TODO: Improve performance\n        if (ox !== effect.offset.x) {\n          effect.offset.x = ox;\n        }\n        if (oy !== effect.offset.y) {\n          effect.offset.y = oy;\n        }\n\n      }\n\n      Rectangle.prototype._update.call(this);\n\n      return this;\n\n    },\n\n    flagReset: function() {\n\n      this._flagTexture = this._flagColumns = this._flagRows\n        = this._flagFrameRate = false;\n\n      Rectangle.prototype.flagReset.call(this);\n\n      return this;\n    }\n\n\n  });\n\n  Sprite.MakeObservable(Sprite.prototype);\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  var _ = Two.Utils;\n  var Path = Two.Path;\n  var Rectangle = Two.Rectangle;\n\n  var ImageSequence = Two.ImageSequence = function(paths, ox, oy, frameRate) {\n\n    Path.call(this, [\n      new Two.Anchor(),\n      new Two.Anchor(),\n      new Two.Anchor(),\n      new Two.Anchor()\n    ], true);\n\n    this._renderer.flagTextures = _.bind(ImageSequence.FlagTextures, this);\n    this._renderer.bindTextures = _.bind(ImageSequence.BindTextures, this);\n    this._renderer.unbindTextures = _.bind(ImageSequence.UnbindTextures, this);\n\n    this.noStroke();\n    this.noFill();\n\n    this.textures = _.map(paths, ImageSequence.GenerateTexture, this);\n\n    this._update();\n    this.translation.set(ox || 0, oy || 0);\n\n    if (_.isNumber(frameRate)) {\n      this.frameRate = frameRate;\n    } else {\n      this.frameRate = ImageSequence.DefaultFrameRate;\n    }\n\n  };\n\n  _.extend(ImageSequence, {\n\n    Properties: [\n      'frameRate'\n    ],\n\n    DefaultFrameRate: 30,\n\n    FlagTextures: function() {\n      this._flagTextures = true;\n    },\n\n    BindTextures: function(items) {\n\n      var i = items.length;\n      while (i--) {\n        items[i].bind(Two.Events.change, this._renderer.flagTextures);\n      }\n\n      this._renderer.flagTextures();\n\n    },\n\n    UnbindTextures: function(items) {\n\n      var i = items.length;\n      while (i--) {\n        items[i].unbind(Two.Events.change, this._renderer.flagTextures);\n      }\n\n      this._renderer.flagTextures();\n\n    },\n\n    MakeObservable: function(obj) {\n\n      Rectangle.MakeObservable(obj);\n      _.each(ImageSequence.Properties, Two.Utils.defineProperty, obj);\n\n      Object.defineProperty(obj, 'textures', {\n\n        enumerable: true,\n\n        get: function() {\n          return this._textures;\n        },\n\n        set: function(textures) {\n\n          var updateTextures = this._renderer.flagTextures;\n          var bindTextures = this._renderer.bindTextures;\n          var unbindTextures = this._renderer.unbindTextures;\n\n          // Remove previous listeners\n          if (this._textures) {\n            this._textures\n              .unbind(Two.Events.insert, bindTextures)\n              .unbind(Two.Events.remove, unbindTextures);\n          }\n\n          // Create new Collection with copy of vertices\n          this._textures = new Two.Utils.Collection((textures || []).slice(0));\n\n          // Listen for Collection changes and bind / unbind\n          this._textures\n            .bind(Two.Events.insert, bindTextures)\n            .bind(Two.Events.remove, unbindTextures);\n\n          // Bind Initial Textures\n          bindTextures(this._textures);\n\n        }\n\n      });\n\n    },\n\n    GenerateTexture: function(obj) {\n      if (obj instanceof Two.Texture) {\n        return obj;\n      } else if (_.isString(obj)) {\n        return new Two.Texture(obj);\n      }\n    }\n\n  });\n\n  _.extend(ImageSequence.prototype, Rectangle.prototype, {\n\n    _flagTextures: false,\n    _flagFrameRate: false,\n\n    // Private variables\n    _amount: 1,\n    _duration: 0,\n    _index: 0,\n    _startTime: 0,\n    _playing: false,\n    _firstFrame: 0,\n    _lastFrame: 0,\n    _loop: true,\n\n    // Exposed through getter-setter\n    _textures: null,\n    _frameRate: 0,\n\n    play: function(firstFrame, lastFrame, onLastFrame) {\n\n      this._playing = true;\n      this._firstFrame = 0;\n      this._lastFrame = this.amount - 1;\n      this._startTime = _.performance.now();\n\n      if (_.isNumber(firstFrame)) {\n        this._firstFrame = firstFrame;\n      }\n      if (_.isNumber(lastFrame)) {\n        this._lastFrame = lastFrame;\n      }\n      if (_.isFunction(onLastFrame)) {\n        this._onLastFrame = onLastFrame;\n      } else {\n        delete this._onLastFrame;\n      }\n\n      return this;\n\n    },\n\n    pause: function() {\n\n      this._playing = false;\n      return this;\n\n    },\n\n    stop: function() {\n\n      this._playing = false;\n      this._index = 0;\n\n      return this;\n\n    },\n\n    clone: function(parent) {\n\n      parent = parent || this.parent;\n\n      var clone = new ImageSequence(this.textures, this.translation.x,\n        this.translation.y, this.frameRate)\n\n        clone._loop = this._loop;\n\n        if (this._playing) {\n          clone.play();\n        }\n\n        if (parent) {\n          parent.add(clone);\n        }\n\n        return clone;\n\n    },\n\n    _update: function() {\n\n      var effects = this._textures;\n      var width, height, elapsed, amount, duration, texture;\n      var index;\n\n      if (this._flagTextures) {\n        this._amount = effects.length;\n      }\n\n      if (this._flagFrameRate) {\n        this._duration = 1000 * this._amount / this._frameRate;\n      }\n\n      if (this._playing && this._frameRate > 0) {\n\n        amount = this._amount;\n\n        if (_.isNaN(this._lastFrame)) {\n          this._lastFrame = amount - 1;\n        }\n\n        // TODO: Offload perf logic to instance of `Two`.\n        elapsed = _.performance.now() - this._startTime;\n        duration = 1000 * (this._lastFrame - this._firstFrame)\n          / this._frameRate;\n\n        if (this._loop) {\n          elapsed = elapsed % duration;\n        } else {\n          elapsed = Math.min(elapsed, duration);\n        }\n\n        index = _.lerp(this._firstFrame, this._lastFrame, elapsed / duration);\n        index = Math.floor(index);\n\n        if (index !== this._index) {\n\n          this._index = index;\n          texture = effects[this._index];\n\n          if (texture.loaded) {\n\n            width = texture.image.width;\n            height = texture.image.height;\n\n            if (this.width !== width) {\n              this.width = width;\n            }\n            if (this.height !== height) {\n              this.height = height;\n            }\n\n            this.fill = texture;\n\n            if (index >= this._lastFrame - 1 && this._onLastFrame) {\n              this._onLastFrame();  // Shortcut for chainable sprite animations\n            }\n\n          }\n\n        }\n\n      } else if (!(this.fill instanceof Two.Texture)) {\n\n        texture = effects[this._index];\n\n        if (texture.loaded) {\n\n          width = texture.image.width;\n          height = texture.image.height;\n\n          if (this.width !== width) {\n            this.width = width;\n          }\n          if (this.height !== height) {\n            this.height = height;\n          }\n\n          this.fill = texture;\n\n        }\n\n      }\n\n      Rectangle.prototype._update.call(this);\n\n      return this;\n\n    },\n\n    flagReset: function() {\n\n      this._flagTextures = this._flagFrameRate = false;\n      Rectangle.prototype.flagReset.call(this);\n\n      return this;\n\n    }\n\n  });\n\n  ImageSequence.MakeObservable(ImageSequence.prototype);\n\n})((typeof global !== 'undefined' ? global : this).Two);\n\n(function(Two) {\n\n  /**\n   * Constants\n   */\n  var min = Math.min, max = Math.max;\n  var _ = Two.Utils;\n\n  /**\n   * A children collection which is accesible both by index and by object id\n   * @constructor\n   */\n  var Children = function() {\n\n    Two.Utils.Collection.apply(this, arguments);\n\n    Object.defineProperty(this, '_events', {\n      value : {},\n      enumerable: false\n    });\n\n    this.ids = {};\n\n    this.on(Two.Events.insert, this.attach);\n    this.on(Two.Events.remove, this.detach);\n    Children.prototype.attach.apply(this, arguments);\n\n  };\n\n  Children.prototype = new Two.Utils.Collection();\n  Children.prototype.constructor = Children;\n\n  _.extend(Children.prototype, {\n\n    attach: function(children) {\n      for (var i = 0; i < children.length; i++) {\n        this.ids[children[i].id] = children[i];\n      }\n      return this;\n    },\n\n    detach: function(children) {\n      for (var i = 0; i < children.length; i++) {\n        delete this.ids[children[i].id];\n      }\n      return this;\n    }\n\n  });\n\n  var Group = Two.Group = function() {\n\n    Two.Shape.call(this, true);\n\n    this._renderer.type = 'group';\n\n    this.additions = [];\n    this.subtractions = [];\n\n    this.children = arguments;\n\n  };\n\n  _.extend(Group, {\n\n    Children: Children,\n\n    InsertChildren: function(children) {\n      for (var i = 0; i < children.length; i++) {\n        replaceParent.call(this, children[i], this);\n      }\n    },\n\n    RemoveChildren: function(children) {\n      for (var i = 0; i < children.length; i++) {\n        replaceParent.call(this, children[i]);\n      }\n    },\n\n    OrderChildren: function(children) {\n      this._flagOrder = true;\n    },\n\n    MakeObservable: function(object) {\n\n      var properties = Two.Path.Properties.slice(0);\n      var oi = _.indexOf(properties, 'opacity');\n\n      if (oi >= 0) {\n\n        properties.splice(oi, 1);\n\n        Object.defineProperty(object, 'opacity', {\n\n          enumerable: true,\n\n          get: function() {\n            return this._opacity;\n          },\n\n          set: function(v) {\n            // Only set flag if there is an actual difference\n            this._flagOpacity = (this._opacity != v);\n            this._opacity = v;\n          }\n\n        });\n\n      }\n\n      Two.Shape.MakeObservable(object);\n      Group.MakeGetterSetters(object, properties);\n\n      Object.defineProperty(object, 'children', {\n\n        enumerable: true,\n\n        get: function() {\n          return this._children;\n        },\n\n        set: function(children) {\n\n          var insertChildren = _.bind(Group.InsertChildren, this);\n          var removeChildren = _.bind(Group.RemoveChildren, this);\n          var orderChildren = _.bind(Group.OrderChildren, this);\n\n          if (this._children) {\n            this._children.unbind();\n          }\n\n          this._children = new Children(children);\n          this._children.bind(Two.Events.insert, insertChildren);\n          this._children.bind(Two.Events.remove, removeChildren);\n          this._children.bind(Two.Events.order, orderChildren);\n\n        }\n\n      });\n\n      Object.defineProperty(object, 'mask', {\n\n        enumerable: true,\n\n        get: function() {\n          return this._mask;\n        },\n\n        set: function(v) {\n          this._mask = v;\n          this._flagMask = true;\n          if (!v.clip) {\n            v.clip = true;\n          }\n        }\n\n      });\n\n    },\n\n    MakeGetterSetters: function(group, properties) {\n\n      if (!_.isArray(properties)) {\n        properties = [properties];\n      }\n\n      _.each(properties, function(k) {\n        Group.MakeGetterSetter(group, k);\n      });\n\n    },\n\n    MakeGetterSetter: function(group, k) {\n\n      var secret = '_' + k;\n\n      Object.defineProperty(group, k, {\n\n        enumerable: true,\n\n        get: function() {\n          return this[secret];\n        },\n\n        set: function(v) {\n          this[secret] = v;\n          _.each(this.children, function(child) { // Trickle down styles\n            child[k] = v;\n          });\n        }\n\n      });\n\n    }\n\n  });\n\n  _.extend(Group.prototype, Two.Shape.prototype, {\n\n    // Flags\n    // http://en.wikipedia.org/wiki/Flag\n\n    _flagAdditions: false,\n    _flagSubtractions: false,\n    _flagOrder: false,\n    _flagOpacity: true,\n\n    _flagMask: false,\n\n    // Underlying Properties\n\n    _fill: '#fff',\n    _stroke: '#000',\n    _linewidth: 1.0,\n    _opacity: 1.0,\n    _visible: true,\n\n    _cap: 'round',\n    _join: 'round',\n    _miter: 4,\n\n    _closed: true,\n    _curved: false,\n    _automatic: true,\n    _beginning: 0,\n    _ending: 1.0,\n\n    _mask: null,\n\n    /**\n     * TODO: Group has a gotcha in that it's at the moment required to be bound to\n     * an instance of two in order to add elements correctly. This needs to\n     * be rethought and fixed.\n     */\n    clone: function(parent) {\n\n      parent = parent || this.parent;\n\n      var group = new Group();\n      var children = _.map(this.children, function(child) {\n        return child.clone(group);\n      });\n\n      group.add(children);\n\n      group.opacity = this.opacity;\n\n      if (this.mask) {\n        group.mask = this.mask;\n      }\n\n      group.translation.copy(this.translation);\n      group.rotation = this.rotation;\n      group.scale = this.scale;\n\n      if (parent) {\n        parent.add(group);\n      }\n\n      return group;\n\n    },\n\n    /**\n     * Export the data from the instance of Two.Group into a plain JavaScript\n     * object. This also makes all children plain JavaScript objects. Great\n     * for turning into JSON and storing in a database.\n     */\n    toObject: function() {\n\n      var result = {\n        children: [],\n        translation: this.translation.toObject(),\n        rotation: this.rotation,\n        scale: this.scale,\n        opacity: this.opacity,\n        mask: (this.mask ? this.mask.toObject() : null)\n      };\n\n      _.each(this.children, function(child, i) {\n        result.children[i] = child.toObject();\n      }, this);\n\n      return result;\n\n    },\n\n    /**\n     * Anchor all children to the upper left hand corner\n     * of the group.\n     */\n    corner: function() {\n\n      var rect = this.getBoundingClientRect(true),\n       corner = { x: rect.left, y: rect.top };\n\n      this.children.forEach(function(child) {\n        child.translation.subSelf(corner);\n      });\n\n      return this;\n\n    },\n\n    /**\n     * Anchors all children around the center of the group,\n     * effectively placing the shape around the unit circle.\n     */\n    center: function() {\n\n      var rect = this.getBoundingClientRect(true);\n\n      rect.centroid = {\n        x: rect.left + rect.width / 2,\n        y: rect.top + rect.height / 2\n      };\n\n      this.children.forEach(function(child) {\n        if (child.isShape) {\n          child.translation.subSelf(rect.centroid);\n        }\n      });\n\n      // this.translation.copy(rect.centroid);\n\n      return this;\n\n    },\n\n    /**\n     * Recursively search for id. Returns the first element found.\n     * Returns null if none found.\n     */\n    getById: function (id) {\n      var search = function (node, id) {\n        if (node.id === id) {\n          return node;\n        } else if (node.children) {\n          var i = node.children.length;\n          while (i--) {\n            var found = search(node.children[i], id);\n            if (found) return found;\n          }\n        }\n\n      };\n      return search(this, id) || null;\n    },\n\n    /**\n     * Recursively search for classes. Returns an array of matching elements.\n     * Empty array if none found.\n     */\n    getByClassName: function (cl) {\n      var found = [];\n      var search = function (node, cl) {\n        if (node.classList.indexOf(cl) != -1) {\n          found.push(node);\n        } else if (node.children) {\n          node.children.forEach(function (child) {\n            search(child, cl);\n          });\n        }\n        return found;\n      };\n      return search(this, cl);\n    },\n\n    /**\n     * Recursively search for children of a specific type,\n     * e.g. Two.Polygon. Pass a reference to this type as the param.\n     * Returns an empty array if none found.\n     */\n    getByType: function(type) {\n      var found = [];\n      var search = function (node, type) {\n        for (var id in node.children) {\n          if (node.children[id] instanceof type) {\n            found.push(node.children[id]);\n          } else if (node.children[id] instanceof Two.Group) {\n            search(node.children[id], type);\n          }\n        }\n        return found;\n      };\n      return search(this, type);\n    },\n\n    /**\n     * Add objects to the group.\n     */\n    add: function(objects) {\n\n      // Allow to pass multiple objects either as array or as multiple arguments\n      // If it's an array also create copy of it in case we're getting passed\n      // a childrens array directly.\n      if (!(objects instanceof Array)) {\n        objects = _.toArray(arguments);\n      } else {\n        objects = objects.slice();\n      }\n\n      // Add the objects\n      for (var i = 0; i < objects.length; i++) {\n        if (!(objects[i] && objects[i].id)) continue;\n        this.children.push(objects[i]);\n      }\n\n      return this;\n\n    },\n\n    /**\n     * Remove objects from the group.\n     */\n    remove: function(objects) {\n\n      var l = arguments.length,\n        grandparent = this.parent;\n\n      // Allow to call remove without arguments\n      // This will detach the object from the scene.\n      if (l <= 0 && grandparent) {\n        grandparent.remove(this);\n        return this;\n      }\n\n      // Allow to pass multiple objects either as array or as multiple arguments\n      // If it's an array also create copy of it in case we're getting passed\n      // a childrens array directly.\n      if (!(objects instanceof Array)) {\n        objects = _.toArray(arguments);\n      } else {\n        objects = objects.slice();\n      }\n\n      // Remove the objects\n      for (var i = 0; i < objects.length; i++) {\n        if (!objects[i] || !(this.children.ids[objects[i].id])) continue;\n        this.children.splice(_.indexOf(this.children, objects[i]), 1);\n      }\n\n      return this;\n\n    },\n\n    /**\n     * Return an object with top, left, right, bottom, width, and height\n     * parameters of the group.\n     */\n    getBoundingClientRect: function(shallow) {\n      var rect;\n\n      // TODO: Update this to not __always__ update. Just when it needs to.\n      this._update(true);\n\n      // Variables need to be defined here, because of nested nature of groups.\n      var left = Infinity, right = -Infinity,\n          top = Infinity, bottom = -Infinity;\n\n      this.children.forEach(function(child) {\n\n        if (/(linear-gradient|radial-gradient|gradient)/.test(child._renderer.type)) {\n          return;\n        }\n\n        rect = child.getBoundingClientRect(shallow);\n\n        if (!_.isNumber(rect.top)   || !_.isNumber(rect.left)   ||\n            !_.isNumber(rect.right) || !_.isNumber(rect.bottom)) {\n          return;\n        }\n\n        top = min(rect.top, top);\n        left = min(rect.left, left);\n        right = max(rect.right, right);\n        bottom = max(rect.bottom, bottom);\n\n      }, this);\n\n      return {\n        top: top,\n        left: left,\n        right: right,\n        bottom: bottom,\n        width: right - left,\n        height: bottom - top\n      };\n\n    },\n\n    /**\n     * Trickle down of noFill\n     */\n    noFill: function() {\n      this.children.forEach(function(child) {\n        child.noFill();\n      });\n      return this;\n    },\n\n    /**\n     * Trickle down of noStroke\n     */\n    noStroke: function() {\n      this.children.forEach(function(child) {\n        child.noStroke();\n      });\n      return this;\n    },\n\n    /**\n     * Trickle down subdivide\n     */\n    subdivide: function() {\n      var args = arguments;\n      this.children.forEach(function(child) {\n        child.subdivide.apply(child, args);\n      });\n      return this;\n    },\n\n    flagReset: function() {\n\n      if (this._flagAdditions) {\n        this.additions.length = 0;\n        this._flagAdditions = false;\n      }\n\n      if (this._flagSubtractions) {\n        this.subtractions.length = 0;\n        this._flagSubtractions = false;\n      }\n\n      this._flagOrder = this._flagMask = this._flagOpacity = false;\n\n      Two.Shape.prototype.flagReset.call(this);\n\n      return this;\n\n    }\n\n  });\n\n  Group.MakeObservable(Group.prototype);\n\n  /**\n   * Helper function used to sync parent-child relationship within the\n   * `Two.Group.children` object.\n   *\n   * Set the parent of the passed object to another object\n   * and updates parent-child relationships\n   * Calling with one arguments will simply remove the parenting\n   */\n  function replaceParent(child, newParent) {\n\n    var parent = child.parent;\n    var index;\n\n    if (parent === newParent) {\n      this.additions.push(child);\n      this._flagAdditions = true;\n      return;\n    }\n\n    if (parent && parent.children.ids[child.id]) {\n\n      index = _.indexOf(parent.children, child);\n      parent.children.splice(index, 1);\n\n      // If we're passing from one parent to another...\n      index = _.indexOf(parent.additions, child);\n\n      if (index >= 0) {\n        parent.additions.splice(index, 1);\n      } else {\n        parent.subtractions.push(child);\n        parent._flagSubtractions = true;\n      }\n\n    }\n\n    if (newParent) {\n      child.parent = newParent;\n      this.additions.push(child);\n      this._flagAdditions = true;\n      return;\n    }\n\n    // If we're passing from one parent to another...\n    index = _.indexOf(this.additions, child);\n\n    if (index >= 0) {\n      this.additions.splice(index, 1);\n    } else {\n      this.subtractions.push(child);\n      this._flagSubtractions = true;\n    }\n\n    delete child.parent;\n\n  }\n\n})((typeof global !== 'undefined' ? global : this).Two);\n"
  },
  {
    "path": "lib/video-export/videoExporter.js",
    "content": "var VideoExporter = function () {\n    \n    var self = this; \n\n    var worker;\n    var onFinishedCallback;\n    var audioTracks = [];\n    var currentVideoLength;\n    var setProgressBarPercent = function () {};\n\n    this.setProgressBarFn = function (fn) {\n        setProgressBarPercent = fn;\n    }\n\n    this.init = function () {\n        worker = new Worker(\"lib/video-export/worker-asm.js\");\n        worker.onmessage = function (event) {\n            handleMessage(event.data);\n        };\n    }\n\n    this.addAudioTrack = function (buffer, trimStart, trimEnd, delay) {\n        audioTracks.push({\n            buffer: buffer,\n            trimStart, trimStart,\n            trimEnd: trimEnd,\n            delay: delay\n        })\n    }\n\n    this.mergeAudioTracks = function (args) {\n        var ffmpegCommandFormat = '-i in1.mp3 -i in2.mp3 -i in3.mp3 -filter_complex \"[0]atrim=1:2[a]; [1]adelay=3000|3000[b]; [2]adelay=2000|2000[c]; [a][b][c]amix=3,volume=3\" out.ogg'\n        var ffmpegCommand = '';\n\n        var sampleFilenames = [];\n        for(var i = 0; i < audioTracks.length; i++) {\n            var filename = 'in'+(i+1)+'.mp3';\n            sampleFilenames.push(filename);\n            ffmpegCommand += '-i ' + filename + ' ';\n        }\n\n        ffmpegCommand += '-filter_complex \"'\n\n        var letters = ['a','b','c']\n        var sampleBuffers = [];\n        for(var i = 0; i < audioTracks.length; i++) {\n            var audioTrack = audioTracks[i];\n            sampleBuffers.push(audioTrack.buffer);\n            var filter_in = i\n            var filter_delay_out = String.fromCharCode(97 + i);\n            var filter_trim_out = String.fromCharCode(97 + i) + '2';\n            ffmpegCommand += '['+filter_in+']adelay='+audioTrack.delay+'|'+audioTrack.delay+'['+filter_delay_out+']; '\n            ffmpegCommand += '['+filter_delay_out+']atrim=0:'+(audioTrack.delay/1000+audioTrack.trimEnd)+'['+filter_trim_out+']; ';\n        }\n\n        var letters = ''\n        for(var i = 0; i < audioTracks.length; i++) {\n            letters += '[' + String.fromCharCode(97 + i) + '2' + ']';\n        }\n        ffmpegCommand += letters+'amix='+audioTracks.length+',volume='+audioTracks.length+'\" out.ogg'\n\n        // set callback for command.\n        onFinishedCallback = function (o) {\n            audioTracks = [];\n            args.callback(o)\n        }; \n\n        // parse command arguments\n        var commandArgs = parseArguments(ffmpegCommand);\n        var allFiles = []; \n\n        // Update filenames for fileInfo\n        if (sampleFilenames.length !== sampleBuffers.length) {\n            console.error(\"Files are not the same!\"); \n            return;\n        }\n\n        for (var i=0; i<sampleFilenames.length; i++) {\n            var fileInfo = {\n                \"name\": sampleFilenames[i],\n                \"data\": sampleBuffers[i],\n            }\n            allFiles.push(fileInfo); \n        }\n\n        // Send command to worker\n        worker.postMessage({\n            type: \"command\",\n            arguments: commandArgs,\n            files: allFiles,\n            commandName: 'audio_track_generation', \n        });\n    }\n\n    //  renderVideoFromFrames (args)\n    //  args.frames,                  type: Image Array\n    //  args.framerate,               type: Number\n    //  args.width,                   type: Number\n    //  args.height,                  type: Number\n    //  args.codec,                   type: String\n    //  args.quality,                 type: String\n    //  args.pixel_format,            type: String\n    //  args.callback                 type: Function\n    this.renderVideoFromFrames = function (args) {\n        var commandFormat = '-r <FRAMERATE> -f image2 -s <WIDTH>x<HEIGHT> -i pic%12d.jpg -vcodec <CODEC> -q:v <QUALITY> -vf showinfo test.mp4';\n        \n        var framerate = args.framerate || 30;\n        var width = args.width || 720;\n        var height = args.height || 480;\n        var codec = args.codec || 'mpeg4';\n        var quality = args.quality || '31';\n        var frames = args.frames;\n        var callback = args.callback;\n\n        onFinishedCallback = args.completedCallback;\n        \n        var command = commandFormat;\n        command = command.replace('<FRAMERATE>', framerate)\n        command = command.replace('<WIDTH>', width)\n        command = command.replace('<HEIGHT>', height)\n        command = command.replace('<QUALITY>', quality)\n        command = command.replace('<CODEC>', codec)\n\n        currentVideoLength = frames.length;\n\n        var files = [];\n        frames.forEach(function (frame) {\n            var i = frames.indexOf(frame);\n            var paddedIndex = zeroFill(i, 12)\n            var frameData = convertDataURIToBinary(frame.src);\n            files.push({\n                name: 'pic'+paddedIndex+'.jpg',\n                data: frameData,\n            })\n        })\n\n        var parsedArgs = parseArguments(command);\n        worker.postMessage({\n            commandName: 'convert_frames_to_video',\n            type: \"command\",\n            arguments: parsedArgs,\n            files: files\n        });\n    }\n\n    //  args parameters\n    //  videoBuffer,             type: Uint8Array;           // REQUIRED, video input (mp4)\n    //  soundBuffer,             type: Uint8Array;           // REQUIRED, sound input (ogg)\n    //  framerate,               type: Number;               // desired export framerate\n    //  filename,                type: String;               // output filename\n    //  percentCallback,         type: function              // function should receive a number of percentage complete\n    //  completedCallback,       type: function              // function should receive a Uint8Array buffer with completed video\n    this.combineAudioAndVideo = function(args) {\n\n        console.log(args)\n            \n        if (args.videoBuffer === undefined) {\n            console.log(\"Error: No video data submitted\"); \n            return; \n        } else if (args.soundBuffer === undefined) {\n            console.log(\"Error: No sound data submitted\"); \n            return; \n        } \n    \n        if (args.framerate === undefined) {\n            args.framerate = 30; \n        }\n\n        if (args.filename === undefined) {\n            args.filename = \"wick-output.mp4\"; \n        }\n    \n        if (args.percentCallback !== undefined) {\n            self.percentCallback = args.percentCallback; \n        }\n    \n        if (args.completedCallback !== undefined) {\n            onFinishedCallback = args.completedCallback;\n        }\n\n        var videoExtension = \"mp4\"; \n        var soundExtension = \"ogg\";\n        \n        var videoFilename = \"video.\" + videoExtension; \n        var soundFilename = \"input.\" + soundExtension;\n\n        var command = \"-r \" + args.framerate + \" \" + \"-i \" + videoFilename + \" -i \" + soundFilename + \" -c:v copy -c:a aac -strict -2 \" + \"-r \" + args.framerate + \" \" + args.filename; \n\n        var videoArgs = parseArguments(command);\n        worker.postMessage({\n            commandName: 'video_audio_merge',\n            type: \"command\",\n            arguments: videoArgs,\n            files: [\n                {\n                    \"name\": videoFilename,\n                    \"data\": args.videoBuffer\n                },\n                {\n                    \"name\": soundFilename,\n                    \"data\": args.soundBuffer\n                }\n            ]\n         });\n    }\n\n    function handleMessage (message) {\n        console.log(message.data)\n\n        if (message.type == \"ready\") {\n            \n        } else if (message.type == \"stdout\") {\n            if (message.data.indexOf(\"pts_time:\") !== -1) {\n                var splitMessage = message.data.split(\"n:\");\n                var pts = splitMessage[1].split(\" \")[0];\n                setProgressBarPercent(pts/currentVideoLength);\n            }\n        } else if (message.type == \"start\") {\n            \n        } else if (message.type == \"done\") {\n            if(message.data instanceof Array) {\n                onFinishedCallback(message.data[0].data);\n            } else if(message.data instanceof ArrayBuffer) {\n                onFinishedCallback(message.data);\n            }\n        }\n    }\n\n    function parseArguments(text) {\n        text = text.replace(/\\s+/g, ' ');\n        var args = [];\n        // Allow double quotes to not split args.\n        text.split('\"').forEach(function(t, i) {\n            t = t.trim();\n            if ((i % 2) === 1) {\n                args.push(t);\n            } else {\n                args = args.concat(t.split(\" \"));\n            }\n        });\n        return args;\n    }\n}\n"
  },
  {
    "path": "lib/video-export/worker-asm.js",
    "content": "importScripts('ffmpeg.js');\n\nvar now = Date.now;\n\nfunction print(text) {\n  postMessage({\n    'type' : 'stdout',\n    'data' : text\n  });\n}\n\nonmessage = function(event) {\n\n  var message = event.data;\n\n  if (message.type === \"command\") {\n\n    var Module = {\n      print: print,\n      printErr: print,\n      files: message.files || [],\n      arguments: message.arguments || [],\n      TOTAL_MEMORY: 268435456\n      // Can play around with this option - must be a power of 2\n      // TOTAL_MEMORY: 268435456\n    };\n\n    postMessage({\n      'type' : 'start',\n      'data' : Module.arguments.join(\" \")\n    });\n\n    postMessage({\n      'type' : 'stdout',\n      'data' : 'Received command: ' +\n                Module.arguments.join(\" \") +\n                ((Module.TOTAL_MEMORY) ? \".  Processing with \" + Module.TOTAL_MEMORY + \" bits.\" : \"\")\n    });\n\n    var time = now();\n    var result = ffmpeg_run(Module);\n\n    var totalTime = now() - time;\n    postMessage({\n      'type' : 'stdout',\n      'data' : 'Finished processing (took ' + totalTime + 'ms)'\n    });\n\n    postMessage({\n      'type' : 'done',\n      'data' : result,\n      'time' : totalTime\n    });\n  }\n};\n\npostMessage({\n  'type' : 'ready'\n});\n"
  },
  {
    "path": "lib/webfont.js",
    "content": "/*\n * Copyright 2016 Small Batch, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * use this file except in compliance with the License. You may obtain a copy of\n * the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations under\n * the License.\n */\n/* Web Font Loader v1.6.26 - (c) Adobe Systems, Google. License: Apache 2.0 */(function(){function aa(a,b,c){return a.call.apply(a.bind,arguments)}function ba(a,b,c){if(!a)throw Error();if(2<arguments.length){var d=Array.prototype.slice.call(arguments,2);return function(){var c=Array.prototype.slice.call(arguments);Array.prototype.unshift.apply(c,d);return a.apply(b,c)}}return function(){return a.apply(b,arguments)}}function p(a,b,c){p=Function.prototype.bind&&-1!=Function.prototype.bind.toString().indexOf(\"native code\")?aa:ba;return p.apply(null,arguments)}var q=Date.now||function(){return+new Date};function ca(a,b){this.a=a;this.m=b||a;this.c=this.m.document}var da=!!window.FontFace;function t(a,b,c,d){b=a.c.createElement(b);if(c)for(var e in c)c.hasOwnProperty(e)&&(\"style\"==e?b.style.cssText=c[e]:b.setAttribute(e,c[e]));d&&b.appendChild(a.c.createTextNode(d));return b}function u(a,b,c){a=a.c.getElementsByTagName(b)[0];a||(a=document.documentElement);a.insertBefore(c,a.lastChild)}function v(a){a.parentNode&&a.parentNode.removeChild(a)}\nfunction w(a,b,c){b=b||[];c=c||[];for(var d=a.className.split(/\\s+/),e=0;e<b.length;e+=1){for(var f=!1,g=0;g<d.length;g+=1)if(b[e]===d[g]){f=!0;break}f||d.push(b[e])}b=[];for(e=0;e<d.length;e+=1){f=!1;for(g=0;g<c.length;g+=1)if(d[e]===c[g]){f=!0;break}f||b.push(d[e])}a.className=b.join(\" \").replace(/\\s+/g,\" \").replace(/^\\s+|\\s+$/,\"\")}function y(a,b){for(var c=a.className.split(/\\s+/),d=0,e=c.length;d<e;d++)if(c[d]==b)return!0;return!1}\nfunction z(a){if(\"string\"===typeof a.f)return a.f;var b=a.m.location.protocol;\"about:\"==b&&(b=a.a.location.protocol);return\"https:\"==b?\"https:\":\"http:\"}function ea(a){return a.m.location.hostname||a.a.location.hostname}\nfunction A(a,b,c){function d(){k&&e&&f&&(k(g),k=null)}b=t(a,\"link\",{rel:\"stylesheet\",href:b,media:\"all\"});var e=!1,f=!0,g=null,k=c||null;da?(b.onload=function(){e=!0;d()},b.onerror=function(){e=!0;g=Error(\"Stylesheet failed to load\");d()}):setTimeout(function(){e=!0;d()},0);u(a,\"head\",b)}\nfunction B(a,b,c,d){var e=a.c.getElementsByTagName(\"head\")[0];if(e){var f=t(a,\"script\",{src:b}),g=!1;f.onload=f.onreadystatechange=function(){g||this.readyState&&\"loaded\"!=this.readyState&&\"complete\"!=this.readyState||(g=!0,c&&c(null),f.onload=f.onreadystatechange=null,\"HEAD\"==f.parentNode.tagName&&e.removeChild(f))};e.appendChild(f);setTimeout(function(){g||(g=!0,c&&c(Error(\"Script load timeout\")))},d||5E3);return f}return null};function C(){this.a=0;this.c=null}function D(a){a.a++;return function(){a.a--;E(a)}}function F(a,b){a.c=b;E(a)}function E(a){0==a.a&&a.c&&(a.c(),a.c=null)};function G(a){this.a=a||\"-\"}G.prototype.c=function(a){for(var b=[],c=0;c<arguments.length;c++)b.push(arguments[c].replace(/[\\W_]+/g,\"\").toLowerCase());return b.join(this.a)};function H(a,b){this.c=a;this.f=4;this.a=\"n\";var c=(b||\"n4\").match(/^([nio])([1-9])$/i);c&&(this.a=c[1],this.f=parseInt(c[2],10))}function fa(a){return I(a)+\" \"+(a.f+\"00\")+\" 300px \"+J(a.c)}function J(a){var b=[];a=a.split(/,\\s*/);for(var c=0;c<a.length;c++){var d=a[c].replace(/['\"]/g,\"\");-1!=d.indexOf(\" \")||/^\\d/.test(d)?b.push(\"'\"+d+\"'\"):b.push(d)}return b.join(\",\")}function K(a){return a.a+a.f}function I(a){var b=\"normal\";\"o\"===a.a?b=\"oblique\":\"i\"===a.a&&(b=\"italic\");return b}\nfunction ga(a){var b=4,c=\"n\",d=null;a&&((d=a.match(/(normal|oblique|italic)/i))&&d[1]&&(c=d[1].substr(0,1).toLowerCase()),(d=a.match(/([1-9]00|normal|bold)/i))&&d[1]&&(/bold/i.test(d[1])?b=7:/[1-9]00/.test(d[1])&&(b=parseInt(d[1].substr(0,1),10))));return c+b};function ha(a,b){this.c=a;this.f=a.m.document.documentElement;this.h=b;this.a=new G(\"-\");this.j=!1!==b.events;this.g=!1!==b.classes}function ia(a){a.g&&w(a.f,[a.a.c(\"wf\",\"loading\")]);L(a,\"loading\")}function M(a){if(a.g){var b=y(a.f,a.a.c(\"wf\",\"active\")),c=[],d=[a.a.c(\"wf\",\"loading\")];b||c.push(a.a.c(\"wf\",\"inactive\"));w(a.f,c,d)}L(a,\"inactive\")}function L(a,b,c){if(a.j&&a.h[b])if(c)a.h[b](c.c,K(c));else a.h[b]()};function ja(){this.c={}}function ka(a,b,c){var d=[],e;for(e in b)if(b.hasOwnProperty(e)){var f=a.c[e];f&&d.push(f(b[e],c))}return d};function N(a,b){this.c=a;this.f=b;this.a=t(this.c,\"span\",{\"aria-hidden\":\"true\"},this.f)}function O(a){u(a.c,\"body\",a.a)}function P(a){return\"display:block;position:absolute;top:-9999px;left:-9999px;font-size:300px;width:auto;height:auto;line-height:normal;margin:0;padding:0;font-variant:normal;white-space:nowrap;font-family:\"+J(a.c)+\";\"+(\"font-style:\"+I(a)+\";font-weight:\"+(a.f+\"00\")+\";\")};function Q(a,b,c,d,e,f){this.g=a;this.j=b;this.a=d;this.c=c;this.f=e||3E3;this.h=f||void 0}Q.prototype.start=function(){var a=this.c.m.document,b=this,c=q(),d=new Promise(function(d,e){function k(){q()-c>=b.f?e():a.fonts.load(fa(b.a),b.h).then(function(a){1<=a.length?d():setTimeout(k,25)},function(){e()})}k()}),e=new Promise(function(a,d){setTimeout(d,b.f)});Promise.race([e,d]).then(function(){b.g(b.a)},function(){b.j(b.a)})};function R(a,b,c,d,e,f,g){this.v=a;this.B=b;this.c=c;this.a=d;this.s=g||\"BESbswy\";this.f={};this.w=e||3E3;this.u=f||null;this.o=this.j=this.h=this.g=null;this.g=new N(this.c,this.s);this.h=new N(this.c,this.s);this.j=new N(this.c,this.s);this.o=new N(this.c,this.s);a=new H(this.a.c+\",serif\",K(this.a));a=P(a);this.g.a.style.cssText=a;a=new H(this.a.c+\",sans-serif\",K(this.a));a=P(a);this.h.a.style.cssText=a;a=new H(\"serif\",K(this.a));a=P(a);this.j.a.style.cssText=a;a=new H(\"sans-serif\",K(this.a));a=\nP(a);this.o.a.style.cssText=a;O(this.g);O(this.h);O(this.j);O(this.o)}var S={D:\"serif\",C:\"sans-serif\"},T=null;function U(){if(null===T){var a=/AppleWebKit\\/([0-9]+)(?:\\.([0-9]+))/.exec(window.navigator.userAgent);T=!!a&&(536>parseInt(a[1],10)||536===parseInt(a[1],10)&&11>=parseInt(a[2],10))}return T}R.prototype.start=function(){this.f.serif=this.j.a.offsetWidth;this.f[\"sans-serif\"]=this.o.a.offsetWidth;this.A=q();la(this)};\nfunction ma(a,b,c){for(var d in S)if(S.hasOwnProperty(d)&&b===a.f[S[d]]&&c===a.f[S[d]])return!0;return!1}function la(a){var b=a.g.a.offsetWidth,c=a.h.a.offsetWidth,d;(d=b===a.f.serif&&c===a.f[\"sans-serif\"])||(d=U()&&ma(a,b,c));d?q()-a.A>=a.w?U()&&ma(a,b,c)&&(null===a.u||a.u.hasOwnProperty(a.a.c))?V(a,a.v):V(a,a.B):na(a):V(a,a.v)}function na(a){setTimeout(p(function(){la(this)},a),50)}function V(a,b){setTimeout(p(function(){v(this.g.a);v(this.h.a);v(this.j.a);v(this.o.a);b(this.a)},a),0)};function W(a,b,c){this.c=a;this.a=b;this.f=0;this.o=this.j=!1;this.s=c}var X=null;W.prototype.g=function(a){var b=this.a;b.g&&w(b.f,[b.a.c(\"wf\",a.c,K(a).toString(),\"active\")],[b.a.c(\"wf\",a.c,K(a).toString(),\"loading\"),b.a.c(\"wf\",a.c,K(a).toString(),\"inactive\")]);L(b,\"fontactive\",a);this.o=!0;oa(this)};\nW.prototype.h=function(a){var b=this.a;if(b.g){var c=y(b.f,b.a.c(\"wf\",a.c,K(a).toString(),\"active\")),d=[],e=[b.a.c(\"wf\",a.c,K(a).toString(),\"loading\")];c||d.push(b.a.c(\"wf\",a.c,K(a).toString(),\"inactive\"));w(b.f,d,e)}L(b,\"fontinactive\",a);oa(this)};function oa(a){0==--a.f&&a.j&&(a.o?(a=a.a,a.g&&w(a.f,[a.a.c(\"wf\",\"active\")],[a.a.c(\"wf\",\"loading\"),a.a.c(\"wf\",\"inactive\")]),L(a,\"active\")):M(a.a))};function pa(a){this.j=a;this.a=new ja;this.h=0;this.f=this.g=!0}pa.prototype.load=function(a){this.c=new ca(this.j,a.context||this.j);this.g=!1!==a.events;this.f=!1!==a.classes;qa(this,new ha(this.c,a),a)};\nfunction ra(a,b,c,d,e){var f=0==--a.h;(a.f||a.g)&&setTimeout(function(){var a=e||null,k=d||null||{};if(0===c.length&&f)M(b.a);else{b.f+=c.length;f&&(b.j=f);var h,m=[];for(h=0;h<c.length;h++){var l=c[h],n=k[l.c],r=b.a,x=l;r.g&&w(r.f,[r.a.c(\"wf\",x.c,K(x).toString(),\"loading\")]);L(r,\"fontloading\",x);r=null;null===X&&(X=window.FontFace?(x=/Gecko.*Firefox\\/(\\d+)/.exec(window.navigator.userAgent))?42<parseInt(x[1],10):!0:!1);X?r=new Q(p(b.g,b),p(b.h,b),b.c,l,b.s,n):r=new R(p(b.g,b),p(b.h,b),b.c,l,b.s,a,\nn);m.push(r)}for(h=0;h<m.length;h++)m[h].start()}},0)}function qa(a,b,c){var d=[],e=c.timeout;ia(b);var d=ka(a.a,c,a.c),f=new W(a.c,b,e);a.h=d.length;b=0;for(c=d.length;b<c;b++)d[b].load(function(b,d,c){ra(a,f,b,d,c)})};function sa(a,b){this.c=a;this.a=b}function ta(a,b,c){var d=z(a.c);a=(a.a.api||\"fast.fonts.net/jsapi\").replace(/^.*http(s?):(\\/\\/)?/,\"\");return d+\"//\"+a+\"/\"+b+\".js\"+(c?\"?v=\"+c:\"\")}\nsa.prototype.load=function(a){function b(){if(f[\"__mti_fntLst\"+d]){var c=f[\"__mti_fntLst\"+d](),e=[],h;if(c)for(var m=0;m<c.length;m++){var l=c[m].fontfamily;void 0!=c[m].fontStyle&&void 0!=c[m].fontWeight?(h=c[m].fontStyle+c[m].fontWeight,e.push(new H(l,h))):e.push(new H(l))}a(e)}else setTimeout(function(){b()},50)}var c=this,d=c.a.projectId,e=c.a.version;if(d){var f=c.c.m;B(this.c,ta(c,d,e),function(e){e?a([]):(f[\"__MonotypeConfiguration__\"+d]=function(){return c.a},b())}).id=\"__MonotypeAPIScript__\"+\nd}else a([])};function ua(a,b){this.c=a;this.a=b}ua.prototype.load=function(a){var b,c,d=this.a.urls||[],e=this.a.families||[],f=this.a.testStrings||{},g=new C;b=0;for(c=d.length;b<c;b++)A(this.c,d[b],D(g));var k=[];b=0;for(c=e.length;b<c;b++)if(d=e[b].split(\":\"),d[1])for(var h=d[1].split(\",\"),m=0;m<h.length;m+=1)k.push(new H(d[0],h[m]));else k.push(new H(d[0]));F(g,function(){a(k,f)})};function va(a,b,c){a?this.c=a:this.c=b+wa;this.a=[];this.f=[];this.g=c||\"\"}var wa=\"//fonts.googleapis.com/css\";function xa(a,b){for(var c=b.length,d=0;d<c;d++){var e=b[d].split(\":\");3==e.length&&a.f.push(e.pop());var f=\"\";2==e.length&&\"\"!=e[1]&&(f=\":\");a.a.push(e.join(f))}}\nfunction ya(a){if(0==a.a.length)throw Error(\"No fonts to load!\");if(-1!=a.c.indexOf(\"kit=\"))return a.c;for(var b=a.a.length,c=[],d=0;d<b;d++)c.push(a.a[d].replace(/ /g,\"+\"));b=a.c+\"?family=\"+c.join(\"%7C\");0<a.f.length&&(b+=\"&subset=\"+a.f.join(\",\"));0<a.g.length&&(b+=\"&text=\"+encodeURIComponent(a.g));return b};function za(a){this.f=a;this.a=[];this.c={}}\nvar Aa={latin:\"BESbswy\",\"latin-ext\":\"\\u00e7\\u00f6\\u00fc\\u011f\\u015f\",cyrillic:\"\\u0439\\u044f\\u0416\",greek:\"\\u03b1\\u03b2\\u03a3\",khmer:\"\\u1780\\u1781\\u1782\",Hanuman:\"\\u1780\\u1781\\u1782\"},Ba={thin:\"1\",extralight:\"2\",\"extra-light\":\"2\",ultralight:\"2\",\"ultra-light\":\"2\",light:\"3\",regular:\"4\",book:\"4\",medium:\"5\",\"semi-bold\":\"6\",semibold:\"6\",\"demi-bold\":\"6\",demibold:\"6\",bold:\"7\",\"extra-bold\":\"8\",extrabold:\"8\",\"ultra-bold\":\"8\",ultrabold:\"8\",black:\"9\",heavy:\"9\",l:\"3\",r:\"4\",b:\"7\"},Ca={i:\"i\",italic:\"i\",n:\"n\",normal:\"n\"},\nDa=/^(thin|(?:(?:extra|ultra)-?)?light|regular|book|medium|(?:(?:semi|demi|extra|ultra)-?)?bold|black|heavy|l|r|b|[1-9]00)?(n|i|normal|italic)?$/;\nfunction Ea(a){for(var b=a.f.length,c=0;c<b;c++){var d=a.f[c].split(\":\"),e=d[0].replace(/\\+/g,\" \"),f=[\"n4\"];if(2<=d.length){var g;var k=d[1];g=[];if(k)for(var k=k.split(\",\"),h=k.length,m=0;m<h;m++){var l;l=k[m];if(l.match(/^[\\w-]+$/)){var n=Da.exec(l.toLowerCase());if(null==n)l=\"\";else{l=n[2];l=null==l||\"\"==l?\"n\":Ca[l];n=n[1];if(null==n||\"\"==n)n=\"4\";else var r=Ba[n],n=r?r:isNaN(n)?\"4\":n.substr(0,1);l=[l,n].join(\"\")}}else l=\"\";l&&g.push(l)}0<g.length&&(f=g);3==d.length&&(d=d[2],g=[],d=d?d.split(\",\"):\ng,0<d.length&&(d=Aa[d[0]])&&(a.c[e]=d))}a.c[e]||(d=Aa[e])&&(a.c[e]=d);for(d=0;d<f.length;d+=1)a.a.push(new H(e,f[d]))}};function Fa(a,b){this.c=a;this.a=b}var Ga={Arimo:!0,Cousine:!0,Tinos:!0};Fa.prototype.load=function(a){var b=new C,c=this.c,d=new va(this.a.api,z(c),this.a.text),e=this.a.families;xa(d,e);var f=new za(e);Ea(f);A(c,ya(d),D(b));F(b,function(){a(f.a,f.c,Ga)})};function Ha(a,b){this.c=a;this.a=b}Ha.prototype.load=function(a){var b=this.a.id,c=this.c.m;b?B(this.c,(this.a.api||\"https://use.typekit.net\")+\"/\"+b+\".js\",function(b){if(b)a([]);else if(c.Typekit&&c.Typekit.config&&c.Typekit.config.fn){b=c.Typekit.config.fn;for(var e=[],f=0;f<b.length;f+=2)for(var g=b[f],k=b[f+1],h=0;h<k.length;h++)e.push(new H(g,k[h]));try{c.Typekit.load({events:!1,classes:!1,async:!0})}catch(m){}a(e)}},2E3):a([])};function Ia(a,b){this.c=a;this.f=b;this.a=[]}Ia.prototype.load=function(a){var b=this.f.id,c=this.c.m,d=this;b?(c.__webfontfontdeckmodule__||(c.__webfontfontdeckmodule__={}),c.__webfontfontdeckmodule__[b]=function(b,c){for(var g=0,k=c.fonts.length;g<k;++g){var h=c.fonts[g];d.a.push(new H(h.name,ga(\"font-weight:\"+h.weight+\";font-style:\"+h.style)))}a(d.a)},B(this.c,z(this.c)+(this.f.api||\"//f.fontdeck.com/s/css/js/\")+ea(this.c)+\"/\"+b+\".js\",function(b){b&&a([])})):a([])};var Y=new pa(window);Y.a.c.custom=function(a,b){return new ua(b,a)};Y.a.c.fontdeck=function(a,b){return new Ia(b,a)};Y.a.c.monotype=function(a,b){return new sa(b,a)};Y.a.c.typekit=function(a,b){return new Ha(b,a)};Y.a.c.google=function(a,b){return new Fa(b,a)};var Z={load:p(Y.load,Y)};\"function\"===typeof define&&define.amd?define(function(){return Z}):\"undefined\"!==typeof module&&module.exports?module.exports=Z:(window.WebFont=Z,window.WebFontConfig&&Y.load(window.WebFontConfig));}());\n"
  },
  {
    "path": "lib/whammy.js",
    "content": "/*\n\tvar vid = new Whammy.Video();\n\tvid.add(canvas or data url)\n\tvid.compile()\n*/\n\nwindow.Whammy = (function(){\n\t// in this case, frames has a very specific meaning, which will be\n\t// detailed once i finish writing the code\n\n\tfunction toWebM(frames, outputAsArray){\n\t\tvar info = checkFrames(frames);\n\n\t\t//max duration by cluster in milliseconds\n\t\tvar CLUSTER_MAX_DURATION = 30000;\n\n\t\tvar EBML = [\n\t\t\t{\n\t\t\t\t\"id\": 0x1a45dfa3, // EBML\n\t\t\t\t\"data\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"data\": 1,\n\t\t\t\t\t\t\"id\": 0x4286 // EBMLVersion\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"data\": 1,\n\t\t\t\t\t\t\"id\": 0x42f7 // EBMLReadVersion\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"data\": 4,\n\t\t\t\t\t\t\"id\": 0x42f2 // EBMLMaxIDLength\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"data\": 8,\n\t\t\t\t\t\t\"id\": 0x42f3 // EBMLMaxSizeLength\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"data\": \"webm\",\n\t\t\t\t\t\t\"id\": 0x4282 // DocType\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"data\": 2,\n\t\t\t\t\t\t\"id\": 0x4287 // DocTypeVersion\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"data\": 2,\n\t\t\t\t\t\t\"id\": 0x4285 // DocTypeReadVersion\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"id\": 0x18538067, // Segment\n\t\t\t\t\"data\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"id\": 0x1549a966, // Info\n\t\t\t\t\t\t\"data\": [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\"data\": 1e6, //do things in millisecs (num of nanosecs for duration scale)\n\t\t\t\t\t\t\t\t\"id\": 0x2ad7b1 // TimecodeScale\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\"data\": \"whammy\",\n\t\t\t\t\t\t\t\t\"id\": 0x4d80 // MuxingApp\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\"data\": \"whammy\",\n\t\t\t\t\t\t\t\t\"id\": 0x5741 // WritingApp\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\"data\": doubleToString(info.duration),\n\t\t\t\t\t\t\t\t\"id\": 0x4489 // Duration\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"id\": 0x1654ae6b, // Tracks\n\t\t\t\t\t\t\"data\": [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\"id\": 0xae, // TrackEntry\n\t\t\t\t\t\t\t\t\"data\": [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\"data\": 1,\n\t\t\t\t\t\t\t\t\t\t\"id\": 0xd7 // TrackNumber\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\"data\": 1,\n\t\t\t\t\t\t\t\t\t\t\"id\": 0x73c5 // TrackUID\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\"data\": 0,\n\t\t\t\t\t\t\t\t\t\t\"id\": 0x9c // FlagLacing\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\"data\": \"und\",\n\t\t\t\t\t\t\t\t\t\t\"id\": 0x22b59c // Language\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\"data\": \"V_VP8\",\n\t\t\t\t\t\t\t\t\t\t\"id\": 0x86 // CodecID\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\"data\": \"VP8\",\n\t\t\t\t\t\t\t\t\t\t\"id\": 0x258688 // CodecName\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\"data\": 1,\n\t\t\t\t\t\t\t\t\t\t\"id\": 0x83 // TrackType\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\"id\": 0xe0,  // Video\n\t\t\t\t\t\t\t\t\t\t\"data\": [\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\"data\": info.width,\n\t\t\t\t\t\t\t\t\t\t\t\t\"id\": 0xb0 // PixelWidth\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\"data\": info.height,\n\t\t\t\t\t\t\t\t\t\t\t\t\"id\": 0xba // PixelHeight\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"id\": 0x1c53bb6b, // Cues\n\t\t\t\t\t\t\"data\": [\n\t\t\t\t\t\t\t//cue insertion point\n\t\t\t\t\t\t]\n\t\t\t\t\t}\n\n\t\t\t\t\t//cluster insertion point\n\t\t\t\t]\n\t\t\t}\n\t\t ];\n\n\n\t\tvar segment = EBML[1];\n\t\tvar cues = segment.data[2];\n\n\t\t//Generate clusters (max duration)\n\t\tvar frameNumber = 0;\n\t\tvar clusterTimecode = 0;\n\t\twhile(frameNumber < frames.length){\n\n\t\t\tvar cuePoint = {\n\t\t\t\t\t\"id\": 0xbb, // CuePoint\n\t\t\t\t\t\"data\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"data\": Math.round(clusterTimecode),\n\t\t\t\t\t\t\t\"id\": 0xb3 // CueTime\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": 0xb7, // CueTrackPositions\n\t\t\t\t\t\t\t\"data\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"data\": 1,\n\t\t\t\t\t\t\t\t\t\"id\": 0xf7 // CueTrack\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"data\": 0, // to be filled in when we know it\n\t\t\t\t\t\t\t\t\t\"size\": 8,\n\t\t\t\t\t\t\t\t\t\"id\": 0xf1 // CueClusterPosition\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t};\n\n\t\t\tcues.data.push(cuePoint);\n\n\t\t\tvar clusterFrames = [];\n\t\t\tvar clusterDuration = 0;\n\t\t\tdo {\n\t\t\t\tclusterFrames.push(frames[frameNumber]);\n\t\t\t\tclusterDuration += frames[frameNumber].duration;\n\t\t\t\tframeNumber++;\n\t\t\t}while(frameNumber < frames.length && clusterDuration < CLUSTER_MAX_DURATION);\n\n\t\t\tvar clusterCounter = 0;\n\t\t\tvar cluster = {\n\t\t\t\t\t\"id\": 0x1f43b675, // Cluster\n\t\t\t\t\t\"data\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"data\": Math.round(clusterTimecode),\n\t\t\t\t\t\t\t\"id\": 0xe7 // Timecode\n\t\t\t\t\t\t}\n\t\t\t\t\t].concat(clusterFrames.map(function(webp){\n\t\t\t\t\t\tvar block = makeSimpleBlock({\n\t\t\t\t\t\t\tdiscardable: 0,\n\t\t\t\t\t\t\tframe: webp.data.slice(4),\n\t\t\t\t\t\t\tinvisible: 0,\n\t\t\t\t\t\t\tkeyframe: 1,\n\t\t\t\t\t\t\tlacing: 0,\n\t\t\t\t\t\t\ttrackNum: 1,\n\t\t\t\t\t\t\ttimecode: Math.round(clusterCounter)\n\t\t\t\t\t\t});\n\t\t\t\t\t\tclusterCounter += webp.duration;\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tdata: block,\n\t\t\t\t\t\t\tid: 0xa3\n\t\t\t\t\t\t};\n\t\t\t\t\t}))\n\t\t\t\t}\n\n\t\t\t//Add cluster to segment\n\t\t\tsegment.data.push(cluster);\n\t\t\tclusterTimecode += clusterDuration;\n\t\t}\n\n\t\t//First pass to compute cluster positions\n\t\tvar position = 0;\n\t\tfor(var i = 0; i < segment.data.length; i++){\n\t\t\tif (i >= 3) {\n\t\t\t\tcues.data[i-3].data[1].data[1].data = position;\n\t\t\t}\n\t\t\tvar data = generateEBML([segment.data[i]], outputAsArray);\n\t\t\tposition += data.size || data.byteLength || data.length;\n\t\t\tif (i != 2) { // not cues\n\t\t\t\t//Save results to avoid having to encode everything twice\n\t\t\t\tsegment.data[i] = data;\n\t\t\t}\n\t\t}\n\n\t\treturn generateEBML(EBML, outputAsArray)\n\t}\n\n\t// sums the lengths of all the frames and gets the duration, woo\n\n\tfunction checkFrames(frames){\n\t\tvar width = frames[0].width,\n\t\t\theight = frames[0].height,\n\t\t\tduration = frames[0].duration;\n\t\tfor(var i = 1; i < frames.length; i++){\n\t\t\tif(frames[i].width != width) throw \"Frame \" + (i + 1) + \" has a different width\";\n\t\t\tif(frames[i].height != height) throw \"Frame \" + (i + 1) + \" has a different height\";\n\t\t\tif(frames[i].duration < 0 || frames[i].duration > 0x7fff) throw \"Frame \" + (i + 1) + \" has a weird duration (must be between 0 and 32767)\";\n\t\t\tduration += frames[i].duration;\n\t\t}\n\t\treturn {\n\t\t\tduration: duration,\n\t\t\twidth: width,\n\t\t\theight: height\n\t\t};\n\t}\n\n\n\tfunction numToBuffer(num){\n\t\tvar parts = [];\n\t\twhile(num > 0){\n\t\t\tparts.push(num & 0xff)\n\t\t\tnum = num >> 8\n\t\t}\n\t\treturn new Uint8Array(parts.reverse());\n\t}\n\n\tfunction numToFixedBuffer(num, size){\n\t\tvar parts = new Uint8Array(size);\n\t\tfor(var i = size - 1; i >= 0; i--){\n\t\t\tparts[i] = num & 0xff;\n\t\t\tnum = num >> 8;\n\t\t}\n\t\treturn parts;\n\t}\n\n\tfunction strToBuffer(str){\n\t\t// return new Blob([str]);\n\n\t\tvar arr = new Uint8Array(str.length);\n\t\tfor(var i = 0; i < str.length; i++){\n\t\t\tarr[i] = str.charCodeAt(i)\n\t\t}\n\t\treturn arr;\n\t\t// this is slower\n\t\t// return new Uint8Array(str.split('').map(function(e){\n\t\t// \treturn e.charCodeAt(0)\n\t\t// }))\n\t}\n\n\n\t//sorry this is ugly, and sort of hard to understand exactly why this was done\n\t// at all really, but the reason is that there's some code below that i dont really\n\t// feel like understanding, and this is easier than using my brain.\n\n\tfunction bitsToBuffer(bits){\n\t\tvar data = [];\n\t\tvar pad = (bits.length % 8) ? (new Array(1 + 8 - (bits.length % 8))).join('0') : '';\n\t\tbits = pad + bits;\n\t\tfor(var i = 0; i < bits.length; i+= 8){\n\t\t\tdata.push(parseInt(bits.substr(i,8),2))\n\t\t}\n\t\treturn new Uint8Array(data);\n\t}\n\n\tfunction generateEBML(json, outputAsArray){\n\t\tvar ebml = [];\n\t\tfor(var i = 0; i < json.length; i++){\n\t\t\tif (!('id' in json[i])){\n\t\t\t\t//already encoded blob or byteArray\n\t\t\t\tebml.push(json[i]);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tvar data = json[i].data;\n\t\t\tif(typeof data == 'object') data = generateEBML(data, outputAsArray);\n\t\t\tif(typeof data == 'number') data = ('size' in json[i]) ? numToFixedBuffer(data, json[i].size) : bitsToBuffer(data.toString(2));\n\t\t\tif(typeof data == 'string') data = strToBuffer(data);\n\n\t\t\tif(data.length){\n\t\t\t\tvar z = z;\n\t\t\t}\n\n\t\t\tvar len = data.size || data.byteLength || data.length;\n\t\t\tvar zeroes = Math.ceil(Math.ceil(Math.log(len)/Math.log(2))/8);\n\t\t\tvar size_str = len.toString(2);\n\t\t\tvar padded = (new Array((zeroes * 7 + 7 + 1) - size_str.length)).join('0') + size_str;\n\t\t\tvar size = (new Array(zeroes)).join('0') + '1' + padded;\n\n\t\t\t//i actually dont quite understand what went on up there, so I'm not really\n\t\t\t//going to fix this, i'm probably just going to write some hacky thing which\n\t\t\t//converts that string into a buffer-esque thing\n\n\t\t\tebml.push(numToBuffer(json[i].id));\n\t\t\tebml.push(bitsToBuffer(size));\n\t\t\tebml.push(data)\n\n\n\t\t}\n\n\t\t//output as blob or byteArray\n\t\tif(outputAsArray){\n\t\t\t//convert ebml to an array\n\t\t\tvar buffer = toFlatArray(ebml)\n\t\t\treturn new Uint8Array(buffer);\n\t\t}else{\n\t\t\treturn new Blob(ebml, {type: \"video/webm\"});\n\t\t}\n\t}\n\n\tfunction toFlatArray(arr, outBuffer){\n\t\tif(outBuffer == null){\n\t\t\toutBuffer = [];\n\t\t}\n\t\tfor(var i = 0; i < arr.length; i++){\n\t\t\tif(typeof arr[i] == 'object'){\n\t\t\t\t//an array\n\t\t\t\ttoFlatArray(arr[i], outBuffer)\n\t\t\t}else{\n\t\t\t\t//a simple element\n\t\t\t\toutBuffer.push(arr[i]);\n\t\t\t}\n\t\t}\n\t\treturn outBuffer;\n\t}\n\n\t//OKAY, so the following two functions are the string-based old stuff, the reason they're\n\t//still sort of in here, is that they're actually faster than the new blob stuff because\n\t//getAsFile isn't widely implemented, or at least, it doesn't work in chrome, which is the\n\t// only browser which supports get as webp\n\n\t//Converting between a string of 0010101001's and binary back and forth is probably inefficient\n\t//TODO: get rid of this function\n\tfunction toBinStr_old(bits){\n\t\tvar data = '';\n\t\tvar pad = (bits.length % 8) ? (new Array(1 + 8 - (bits.length % 8))).join('0') : '';\n\t\tbits = pad + bits;\n\t\tfor(var i = 0; i < bits.length; i+= 8){\n\t\t\tdata += String.fromCharCode(parseInt(bits.substr(i,8),2))\n\t\t}\n\t\treturn data;\n\t}\n\n\tfunction generateEBML_old(json){\n\t\tvar ebml = '';\n\t\tfor(var i = 0; i < json.length; i++){\n\t\t\tvar data = json[i].data;\n\t\t\tif(typeof data == 'object') data = generateEBML_old(data);\n\t\t\tif(typeof data == 'number') data = toBinStr_old(data.toString(2));\n\n\t\t\tvar len = data.length;\n\t\t\tvar zeroes = Math.ceil(Math.ceil(Math.log(len)/Math.log(2))/8);\n\t\t\tvar size_str = len.toString(2);\n\t\t\tvar padded = (new Array((zeroes * 7 + 7 + 1) - size_str.length)).join('0') + size_str;\n\t\t\tvar size = (new Array(zeroes)).join('0') + '1' + padded;\n\n\t\t\tebml += toBinStr_old(json[i].id.toString(2)) + toBinStr_old(size) + data;\n\n\t\t}\n\t\treturn ebml;\n\t}\n\n\t//woot, a function that's actually written for this project!\n\t//this parses some json markup and makes it into that binary magic\n\t//which can then get shoved into the matroska comtainer (peaceably)\n\n\tfunction makeSimpleBlock(data){\n\t\tvar flags = 0;\n\t\tif (data.keyframe) flags |= 128;\n\t\tif (data.invisible) flags |= 8;\n\t\tif (data.lacing) flags |= (data.lacing << 1);\n\t\tif (data.discardable) flags |= 1;\n\t\tif (data.trackNum > 127) {\n\t\t\tthrow \"TrackNumber > 127 not supported\";\n\t\t}\n\t\tvar out = [data.trackNum | 0x80, data.timecode >> 8, data.timecode & 0xff, flags].map(function(e){\n\t\t\treturn String.fromCharCode(e)\n\t\t}).join('') + data.frame;\n\n\t\treturn out;\n\t}\n\n\t// here's something else taken verbatim from weppy, awesome rite?\n\n\tfunction parseWebP(riff){\n\t\tvar VP8 = riff.RIFF[0].WEBP[0];\n\n\t\tvar frame_start = VP8.indexOf('\\x9d\\x01\\x2a'); //A VP8 keyframe starts with the 0x9d012a header\n\t\tfor(var i = 0, c = []; i < 4; i++) c[i] = VP8.charCodeAt(frame_start + 3 + i);\n\n\t\tvar width, horizontal_scale, height, vertical_scale, tmp;\n\n\t\t//the code below is literally copied verbatim from the bitstream spec\n\t\ttmp = (c[1] << 8) | c[0];\n\t\twidth = tmp & 0x3FFF;\n\t\thorizontal_scale = tmp >> 14;\n\t\ttmp = (c[3] << 8) | c[2];\n\t\theight = tmp & 0x3FFF;\n\t\tvertical_scale = tmp >> 14;\n\t\treturn {\n\t\t\twidth: width,\n\t\t\theight: height,\n\t\t\tdata: VP8,\n\t\t\triff: riff\n\t\t}\n\t}\n\n\t// i think i'm going off on a riff by pretending this is some known\n\t// idiom which i'm making a casual and brilliant pun about, but since\n\t// i can't find anything on google which conforms to this idiomatic\n\t// usage, I'm assuming this is just a consequence of some psychotic\n\t// break which makes me make up puns. well, enough riff-raff (aha a\n\t// rescue of sorts), this function was ripped wholesale from weppy\n\n\tfunction parseRIFF(string){\n\t\tvar offset = 0;\n\t\tvar chunks = {};\n\n\t\twhile (offset < string.length) {\n\t\t\tvar id = string.substr(offset, 4);\n\t\t\tchunks[id] = chunks[id] || [];\n\t\t\tif (id == 'RIFF' || id == 'LIST') {\n\t\t\t\tvar len = parseInt(string.substr(offset + 4, 4).split('').map(function(i){\n\t\t\t\t\tvar unpadded = i.charCodeAt(0).toString(2);\n\t\t\t\t\treturn (new Array(8 - unpadded.length + 1)).join('0') + unpadded\n\t\t\t\t}).join(''),2);\n\t\t\t\tvar data = string.substr(offset + 4 + 4, len);\n\t\t\t\toffset += 4 + 4 + len;\n\t\t\t\tchunks[id].push(parseRIFF(data));\n\t\t\t} else if (id == 'WEBP') {\n\t\t\t\t// Use (offset + 8) to skip past \"VP8 \"/\"VP8L\"/\"VP8X\" field after \"WEBP\"\n\t\t\t\tchunks[id].push(string.substr(offset + 8));\n\t\t\t\toffset = string.length;\n\t\t\t} else {\n\t\t\t\t// Unknown chunk type; push entire payload\n\t\t\t\tchunks[id].push(string.substr(offset + 4));\n\t\t\t\toffset = string.length;\n\t\t\t}\n\t\t}\n\t\treturn chunks;\n\t}\n\n\t// here's a little utility function that acts as a utility for other functions\n\t// basically, the only purpose is for encoding \"Duration\", which is encoded as\n\t// a double (considerably more difficult to encode than an integer)\n\tfunction doubleToString(num){\n\t\treturn [].slice.call(\n\t\t\tnew Uint8Array(\n\t\t\t\t(\n\t\t\t\t\tnew Float64Array([num]) //create a float64 array\n\t\t\t\t).buffer) //extract the array buffer\n\t\t\t, 0) // convert the Uint8Array into a regular array\n\t\t\t.map(function(e){ //since it's a regular array, we can now use map\n\t\t\t\treturn String.fromCharCode(e) // encode all the bytes individually\n\t\t\t})\n\t\t\t.reverse() //correct the byte endianness (assume it's little endian for now)\n\t\t\t.join('') // join the bytes in holy matrimony as a string\n\t}\n\n\tfunction WhammyVideo(speed, quality){ // a more abstract-ish API\n\t\tthis.frames = [];\n\t\tthis.duration = 1000 / speed;\n\t\tthis.quality = quality || 0.8;\n\t}\n\n\tWhammyVideo.prototype.add = function(frame, duration){\n\t\tif(typeof duration != 'undefined' && this.duration) throw \"you can't pass a duration if the fps is set\";\n\t\tif(typeof duration == 'undefined' && !this.duration) throw \"if you don't have the fps set, you need to have durations here.\";\n\t\tif(frame.canvas){ //CanvasRenderingContext2D\n\t\t\tframe = frame.canvas;\n\t\t}\n\t\tif(frame.toDataURL){\n\t\t\t// frame = frame.toDataURL('image/webp', this.quality);\n\t\t\t// quickly store image data so we don't block cpu. encode in compile method.\n\t\t\tframe = frame.getContext('2d').getImageData(0, 0, frame.width, frame.height);\n\t\t}else if(typeof frame != \"string\"){\n\t\t\tthrow \"frame must be a a HTMLCanvasElement, a CanvasRenderingContext2D or a DataURI formatted string\"\n\t\t}\n\t\tif (typeof frame === \"string\" && !(/^data:image\\/webp;base64,/ig).test(frame)) {\n\t\t\tthrow \"Input must be formatted properly as a base64 encoded DataURI of type image/webp\";\n\t\t}\n\t\tthis.frames.push({\n\t\t\timage: frame,\n\t\t\tduration: duration || this.duration\n\t\t});\n\t};\n\n\t// deferred webp encoding. Draws image data to canvas, then encodes as dataUrl\n\tWhammyVideo.prototype.encodeFrames = function(callback){\n\n\t\tif(this.frames[0].image instanceof ImageData){\n\n\t\t\tvar frames = this.frames;\n\t\t\tvar tmpCanvas = document.createElement('canvas');\n\t\t\tvar tmpContext = tmpCanvas.getContext('2d');\n\t\t\ttmpCanvas.width = this.frames[0].image.width;\n\t\t\ttmpCanvas.height = this.frames[0].image.height;\n\n\t\t\tvar encodeFrame = function(index){\n\t\t\t\tconsole.log('encodeFrame', index);\n\t\t\t\tvar frame = frames[index];\n\t\t\t\ttmpContext.putImageData(frame.image, 0, 0);\n\t\t\t\tframe.image = tmpCanvas.toDataURL('image/webp', this.quality);\n\t\t\t\tconsole.log('this should be png in ff, webp in chrome...')\n\t\t\t\tconsole.log(frame.image)\n\t\t\t\tif(index < frames.length-1){\n\t\t\t\t\tsetTimeout(function(){ encodeFrame(index + 1); }, 1);\n\t\t\t\t}else{\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}.bind(this);\n\n\t\t\tencodeFrame(0);\n\t\t}else{\n\t\t\tcallback();\n\t\t}\n\t};\n\n\tWhammyVideo.prototype.compile = function(outputAsArray, callback){\n\n\t\tthis.encodeFrames(function(){\n\n\t\t\tvar webm = new toWebM(this.frames.map(function(frame){\n\t\t\t\tconsole.log(frame.image)\n\t\t\t\tvar webp = parseWebP(parseRIFF(atob(frame.image.slice(23))));\n\t\t\t\twebp.duration = frame.duration;\n\t\t\t\treturn webp;\n\t\t\t}), outputAsArray);\n\t\t\tcallback(webm);\n\t\t\t\n\t\t}.bind(this));\n\t};\n\n\treturn {\n\t\tVideo: WhammyVideo,\n\t\tfromImageArray: function(images, fps, outputAsArray){\n\t\t\treturn toWebM(images.map(function(image){\n\t\t\t\tvar webp = parseWebP(parseRIFF(atob(image.slice(23))))\n\t\t\t\twebp.duration = 1000 / fps;\n\t\t\t\treturn webp;\n\t\t\t}), outputAsArray)\n\t\t},\n\t\ttoWebM: toWebM\n\t\t// expose methods of madness\n\t}\n})()\n"
  },
  {
    "path": "main.js",
    "content": "// https://electron.atom.io/docs/tutorial/quick-start/\n\nconst {app, BrowserWindow} = require('electron')\nconst path = require('path')\nconst url = require('url')\n\n// Keep a global reference of the window object, if you don't, the window will\n// be closed automatically when the JavaScript object is garbage collected.\nlet win\n\nfunction createWindow () {\n  // Create the browser window.\n  win = new BrowserWindow({\n     width: 1281,\n     height: 800,\n     minWidth: 800,\n     minHeight: 600,\n     show: false,\n     /*frame: false,*/\n    icon: path.join(__dirname, 'assets/icons/png/64x64.png')\n  })\n\n  // and load the index.html of the app.\n  win.loadURL(url.format({\n    pathname: path.join(__dirname, 'editor.html'),\n    protocol: 'file:',\n    slashes: true\n  }))\n\n  //https://electron.atom.io/docs/api/browser-window/\n  // 'graceful show'\n  win.once('ready-to-show', () => {\n    win.show()\n    console.log(win)\n  });\n\n  // Open the DevTools.\n  //win.webContents.openDevTools()\n\n  // Disable menubar\n  win.setMenu(null);\n\n\n  win.on('closed', () => {\n    // Dereference the window object, usually you would store windows\n    // in an array if your app supports multi windows, this is the time\n    // when you should delete the corresponding element.\n    win = null\n    app.quit()\n  })\n\n}\n\n// This method will be called when Electron has finished\n// initialization and is ready to create browser windows.\n// Some APIs can only be used after this event occurs.\napp.on('ready', createWindow)\n\napp.on('activate', () => {\n  // On macOS it's common to re-create a window in the app when the\n  // dock icon is clicked and there are no other windows open.\n  if (win === null) {\n    createWindow()\n  }\n})\n\n// In this file you can include the rest of your app's specific main process\n// code. You can also put them in separate files and require them here."
  },
  {
    "path": "player.html",
    "content": "﻿<!-- \n    You've peeked inside the source code for a Wick project... you are clever!\n\n    This file was generated by the WickProject exporter. \n    (see src/editor/WickProject.Exporter.js) at https://github.com/zrispo/wick/ \n\n    Send any questions to https://twitter.com/zrispo !!!\n -->\n\n<head>\n    <style>\n        /* remove the top and left whitespace */\n    \t* { margin:0; padding:0; }\n\n        /* just to be sure these are full screen */\n    \thtml, body { width:100%; height:100%; background-color: #FFFFFF; }\n\n        /* To remove the scrollbars */\n    \tcanvas { display:block; }\n\n        canvas:focus {\n            outline: none;\n            outline-style: none;\n        }\n\n        /* Cross browser cursor hide class */\n        .hideCursor {\n            cursor: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjbQg61aAAAADUlEQVQYV2P4//8/IwAI/QL/+TZZdwAAAABJRU5ErkJggg=='),\n            none !important;\n        }\n    </style>\n</head>\n\n<script>wickEditor = null;</script>\n\n<body>\n\t<div id=\"playerCanvasContainer\" readonly=\"readonly\"></div>\n</body>\n\n\n<script>/*!\n * pixi.js - v4.5.6\n * Compiled Wed, 20 Sep 2017 15:08:21 UTC\n *\n * pixi.js is licensed under the MIT License.\n * http://www.opensource.org/licenses/mit-license\n */\n!function(t){if(\"object\"==typeof exports&&\"undefined\"!=typeof module)module.exports=t();else if(\"function\"==typeof define&&define.amd)define([],t);else{var e;e=\"undefined\"!=typeof window?window:\"undefined\"!=typeof global?global:\"undefined\"!=typeof self?self:this,e.PIXI=t()}}(function(){var t;return function t(e,r,n){function i(s,a){if(!r[s]){if(!e[s]){var u=\"function\"==typeof require&&require;if(!a&&u)return u(s,!0);if(o)return o(s,!0);var h=new Error(\"Cannot find module '\"+s+\"'\");throw h.code=\"MODULE_NOT_FOUND\",h}var l=r[s]={exports:{}};e[s][0].call(l.exports,function(t){var r=e[s][1][t];return i(r||t)},l,l.exports,t,e,r,n)}return r[s].exports}for(var o=\"function\"==typeof require&&require,s=0;s<n.length;s++)i(n[s]);return i}({1:[function(t,e,r){\"use strict\";\"use restrict\";function n(t){var e=32;return t&=-t,t&&e--,65535&t&&(e-=16),16711935&t&&(e-=8),252645135&t&&(e-=4),858993459&t&&(e-=2),1431655765&t&&(e-=1),e}r.INT_BITS=32,r.INT_MAX=2147483647,r.INT_MIN=-1<<31,r.sign=function(t){return(t>0)-(t<0)},r.abs=function(t){var e=t>>31;return(t^e)-e},r.min=function(t,e){return e^(t^e)&-(t<e)},r.max=function(t,e){return t^(t^e)&-(t<e)},r.isPow2=function(t){return!(t&t-1||!t)},r.log2=function(t){var e,r;return e=(t>65535)<<4,t>>>=e,r=(t>255)<<3,t>>>=r,e|=r,r=(t>15)<<2,t>>>=r,e|=r,r=(t>3)<<1,t>>>=r,(e|=r)|t>>1},r.log10=function(t){return t>=1e9?9:t>=1e8?8:t>=1e7?7:t>=1e6?6:t>=1e5?5:t>=1e4?4:t>=1e3?3:t>=100?2:t>=10?1:0},r.popCount=function(t){return t-=t>>>1&1431655765,16843009*((t=(858993459&t)+(t>>>2&858993459))+(t>>>4)&252645135)>>>24},r.countTrailingZeros=n,r.nextPow2=function(t){return t+=0===t,--t,t|=t>>>1,t|=t>>>2,t|=t>>>4,t|=t>>>8,(t|=t>>>16)+1},r.prevPow2=function(t){return t|=t>>>1,t|=t>>>2,t|=t>>>4,t|=t>>>8,(t|=t>>>16)-(t>>>1)},r.parity=function(t){return t^=t>>>16,t^=t>>>8,t^=t>>>4,27030>>>(t&=15)&1};var i=new Array(256);!function(t){for(var e=0;e<256;++e){var r=e,n=e,i=7;for(r>>>=1;r;r>>>=1)n<<=1,n|=1&r,--i;t[e]=n<<i&255}}(i),r.reverse=function(t){return i[255&t]<<24|i[t>>>8&255]<<16|i[t>>>16&255]<<8|i[t>>>24&255]},r.interleave2=function(t,e){return t&=65535,t=16711935&(t|t<<8),t=252645135&(t|t<<4),t=858993459&(t|t<<2),t=1431655765&(t|t<<1),e&=65535,e=16711935&(e|e<<8),e=252645135&(e|e<<4),e=858993459&(e|e<<2),e=1431655765&(e|e<<1),t|e<<1},r.deinterleave2=function(t,e){return t=t>>>e&1431655765,t=858993459&(t|t>>>1),t=252645135&(t|t>>>2),t=16711935&(t|t>>>4),(t=65535&(t|t>>>16))<<16>>16},r.interleave3=function(t,e,r){return t&=1023,t=4278190335&(t|t<<16),t=251719695&(t|t<<8),t=3272356035&(t|t<<4),t=1227133513&(t|t<<2),e&=1023,e=4278190335&(e|e<<16),e=251719695&(e|e<<8),e=3272356035&(e|e<<4),e=1227133513&(e|e<<2),t|=e<<1,r&=1023,r=4278190335&(r|r<<16),r=251719695&(r|r<<8),r=3272356035&(r|r<<4),r=1227133513&(r|r<<2),t|r<<2},r.deinterleave3=function(t,e){return t=t>>>e&1227133513,t=3272356035&(t|t>>>2),t=251719695&(t|t>>>4),t=4278190335&(t|t>>>8),(t=1023&(t|t>>>16))<<22>>22},r.nextCombination=function(t){var e=t|t-1;return e+1|(~e&-~e)-1>>>n(t)+1}},{}],2:[function(t,e,r){\"use strict\";function n(t,e,r){r=r||2;var n=e&&e.length,o=n?e[0]*r:t.length,a=i(t,0,o,r,!0),u=[];if(!a)return u;var h,l,d,f,p,v,y;if(n&&(a=c(t,e,a,r)),t.length>80*r){h=d=t[0],l=f=t[1];for(var g=r;g<o;g+=r)p=t[g],v=t[g+1],p<h&&(h=p),v<l&&(l=v),p>d&&(d=p),v>f&&(f=v);y=Math.max(d-h,f-l)}return s(a,u,r,h,l,y),u}function i(t,e,r,n,i){var o,s;if(i===A(t,e,r,n)>0)for(o=e;o<r;o+=n)s=P(o,t[o],t[o+1],s);else for(o=r-n;o>=e;o-=n)s=P(o,t[o],t[o+1],s);return s&&T(s,s.next)&&(C(s),s=s.next),s}function o(t,e){if(!t)return t;e||(e=t);var r,n=t;do{if(r=!1,n.steiner||!T(n,n.next)&&0!==x(n.prev,n,n.next))n=n.next;else{if(C(n),(n=e=n.prev)===n.next)return null;r=!0}}while(r||n!==e);return e}function s(t,e,r,n,i,c,d){if(t){!d&&c&&v(t,n,i,c);for(var f,p,y=t;t.prev!==t.next;)if(f=t.prev,p=t.next,c?u(t,n,i,c):a(t))e.push(f.i/r),e.push(t.i/r),e.push(p.i/r),C(t),t=p.next,y=p.next;else if((t=p)===y){d?1===d?(t=h(t,e,r),s(t,e,r,n,i,c,2)):2===d&&l(t,e,r,n,i,c):s(o(t),e,r,n,i,c,1);break}}}function a(t){var e=t.prev,r=t,n=t.next;if(x(e,r,n)>=0)return!1;for(var i=t.next.next;i!==t.prev;){if(_(e.x,e.y,r.x,r.y,n.x,n.y,i.x,i.y)&&x(i.prev,i,i.next)>=0)return!1;i=i.next}return!0}function u(t,e,r,n){var i=t.prev,o=t,s=t.next;if(x(i,o,s)>=0)return!1;for(var a=i.x<o.x?i.x<s.x?i.x:s.x:o.x<s.x?o.x:s.x,u=i.y<o.y?i.y<s.y?i.y:s.y:o.y<s.y?o.y:s.y,h=i.x>o.x?i.x>s.x?i.x:s.x:o.x>s.x?o.x:s.x,l=i.y>o.y?i.y>s.y?i.y:s.y:o.y>s.y?o.y:s.y,c=g(a,u,e,r,n),d=g(h,l,e,r,n),f=t.nextZ;f&&f.z<=d;){if(f!==t.prev&&f!==t.next&&_(i.x,i.y,o.x,o.y,s.x,s.y,f.x,f.y)&&x(f.prev,f,f.next)>=0)return!1;f=f.nextZ}for(f=t.prevZ;f&&f.z>=c;){if(f!==t.prev&&f!==t.next&&_(i.x,i.y,o.x,o.y,s.x,s.y,f.x,f.y)&&x(f.prev,f,f.next)>=0)return!1;f=f.prevZ}return!0}function h(t,e,r){var n=t;do{var i=n.prev,o=n.next.next;!T(i,o)&&w(i,n,n.next,o)&&S(i,o)&&S(o,i)&&(e.push(i.i/r),e.push(n.i/r),e.push(o.i/r),C(n),C(n.next),n=t=o),n=n.next}while(n!==t);return n}function l(t,e,r,n,i,a){var u=t;do{for(var h=u.next.next;h!==u.prev;){if(u.i!==h.i&&b(u,h)){var l=M(u,h);return u=o(u,u.next),l=o(l,l.next),s(u,e,r,n,i,a),void s(l,e,r,n,i,a)}h=h.next}u=u.next}while(u!==t)}function c(t,e,r,n){var s,a,u,h,l,c=[];for(s=0,a=e.length;s<a;s++)u=e[s]*n,h=s<a-1?e[s+1]*n:t.length,l=i(t,u,h,n,!1),l===l.next&&(l.steiner=!0),c.push(m(l));for(c.sort(d),s=0;s<c.length;s++)f(c[s],r),r=o(r,r.next);return r}function d(t,e){return t.x-e.x}function f(t,e){if(e=p(t,e)){var r=M(e,t);o(r,r.next)}}function p(t,e){var r,n=e,i=t.x,o=t.y,s=-1/0;do{if(o<=n.y&&o>=n.next.y){var a=n.x+(o-n.y)*(n.next.x-n.x)/(n.next.y-n.y);if(a<=i&&a>s){if(s=a,a===i){if(o===n.y)return n;if(o===n.next.y)return n.next}r=n.x<n.next.x?n:n.next}}n=n.next}while(n!==e);if(!r)return null;if(i===s)return r.prev;var u,h=r,l=r.x,c=r.y,d=1/0;for(n=r.next;n!==h;)i>=n.x&&n.x>=l&&_(o<c?i:s,o,l,c,o<c?s:i,o,n.x,n.y)&&((u=Math.abs(o-n.y)/(i-n.x))<d||u===d&&n.x>r.x)&&S(n,t)&&(r=n,d=u),n=n.next;return r}function v(t,e,r,n){var i=t;do{null===i.z&&(i.z=g(i.x,i.y,e,r,n)),i.prevZ=i.prev,i.nextZ=i.next,i=i.next}while(i!==t);i.prevZ.nextZ=null,i.prevZ=null,y(i)}function y(t){var e,r,n,i,o,s,a,u,h=1;do{for(r=t,t=null,o=null,s=0;r;){for(s++,n=r,a=0,e=0;e<h&&(a++,n=n.nextZ);e++);for(u=h;a>0||u>0&&n;)0===a?(i=n,n=n.nextZ,u--):0!==u&&n?r.z<=n.z?(i=r,r=r.nextZ,a--):(i=n,n=n.nextZ,u--):(i=r,r=r.nextZ,a--),o?o.nextZ=i:t=i,i.prevZ=o,o=i;r=n}o.nextZ=null,h*=2}while(s>1);return t}function g(t,e,r,n,i){return t=32767*(t-r)/i,e=32767*(e-n)/i,t=16711935&(t|t<<8),t=252645135&(t|t<<4),t=858993459&(t|t<<2),t=1431655765&(t|t<<1),e=16711935&(e|e<<8),e=252645135&(e|e<<4),e=858993459&(e|e<<2),e=1431655765&(e|e<<1),t|e<<1}function m(t){var e=t,r=t;do{e.x<r.x&&(r=e),e=e.next}while(e!==t);return r}function _(t,e,r,n,i,o,s,a){return(i-s)*(e-a)-(t-s)*(o-a)>=0&&(t-s)*(n-a)-(r-s)*(e-a)>=0&&(r-s)*(o-a)-(i-s)*(n-a)>=0}function b(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!E(t,e)&&S(t,e)&&S(e,t)&&O(t,e)}function x(t,e,r){return(e.y-t.y)*(r.x-e.x)-(e.x-t.x)*(r.y-e.y)}function T(t,e){return t.x===e.x&&t.y===e.y}function w(t,e,r,n){return!!(T(t,e)&&T(r,n)||T(t,n)&&T(r,e))||x(t,e,r)>0!=x(t,e,n)>0&&x(r,n,t)>0!=x(r,n,e)>0}function E(t,e){var r=t;do{if(r.i!==t.i&&r.next.i!==t.i&&r.i!==e.i&&r.next.i!==e.i&&w(r,r.next,t,e))return!0;r=r.next}while(r!==t);return!1}function S(t,e){return x(t.prev,t,t.next)<0?x(t,e,t.next)>=0&&x(t,t.prev,e)>=0:x(t,e,t.prev)<0||x(t,t.next,e)<0}function O(t,e){var r=t,n=!1,i=(t.x+e.x)/2,o=(t.y+e.y)/2;do{r.y>o!=r.next.y>o&&i<(r.next.x-r.x)*(o-r.y)/(r.next.y-r.y)+r.x&&(n=!n),r=r.next}while(r!==t);return n}function M(t,e){var r=new R(t.i,t.x,t.y),n=new R(e.i,e.x,e.y),i=t.next,o=e.prev;return t.next=e,e.prev=t,r.next=i,i.prev=r,n.next=r,r.prev=n,o.next=n,n.prev=o,n}function P(t,e,r,n){var i=new R(t,e,r);return n?(i.next=n.next,i.prev=n,n.next.prev=i,n.next=i):(i.prev=i,i.next=i),i}function C(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ)}function R(t,e,r){this.i=t,this.x=e,this.y=r,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}function A(t,e,r,n){for(var i=0,o=e,s=r-n;o<r;o+=n)i+=(t[s]-t[o])*(t[o+1]+t[s+1]),s=o;return i}e.exports=n,n.deviation=function(t,e,r,n){var i=e&&e.length,o=i?e[0]*r:t.length,s=Math.abs(A(t,0,o,r));if(i)for(var a=0,u=e.length;a<u;a++){var h=e[a]*r,l=a<u-1?e[a+1]*r:t.length;s-=Math.abs(A(t,h,l,r))}var c=0;for(a=0;a<n.length;a+=3){var d=n[a]*r,f=n[a+1]*r,p=n[a+2]*r;c+=Math.abs((t[d]-t[p])*(t[f+1]-t[d+1])-(t[d]-t[f])*(t[p+1]-t[d+1]))}return 0===s&&0===c?0:Math.abs((c-s)/s)},n.flatten=function(t){for(var e=t[0][0].length,r={vertices:[],holes:[],dimensions:e},n=0,i=0;i<t.length;i++){for(var o=0;o<t[i].length;o++)for(var s=0;s<e;s++)r.vertices.push(t[i][o][s]);i>0&&(n+=t[i-1].length,r.holes.push(n))}return r}},{}],3:[function(t,e,r){\"use strict\";function n(){}function i(t,e,r){this.fn=t,this.context=e,this.once=r||!1}function o(){this._events=new n,this._eventsCount=0}var s=Object.prototype.hasOwnProperty,a=\"~\";Object.create&&(n.prototype=Object.create(null),(new n).__proto__||(a=!1)),o.prototype.eventNames=function(){var t,e,r=[];if(0===this._eventsCount)return r;for(e in t=this._events)s.call(t,e)&&r.push(a?e.slice(1):e);return Object.getOwnPropertySymbols?r.concat(Object.getOwnPropertySymbols(t)):r},o.prototype.listeners=function(t,e){var r=a?a+t:t,n=this._events[r];if(e)return!!n;if(!n)return[];if(n.fn)return[n.fn];for(var i=0,o=n.length,s=new Array(o);i<o;i++)s[i]=n[i].fn;return s},o.prototype.emit=function(t,e,r,n,i,o){var s=a?a+t:t;if(!this._events[s])return!1;var u,h,l=this._events[s],c=arguments.length;if(l.fn){switch(l.once&&this.removeListener(t,l.fn,void 0,!0),c){case 1:return l.fn.call(l.context),!0;case 2:return l.fn.call(l.context,e),!0;case 3:return l.fn.call(l.context,e,r),!0;case 4:return l.fn.call(l.context,e,r,n),!0;case 5:return l.fn.call(l.context,e,r,n,i),!0;case 6:return l.fn.call(l.context,e,r,n,i,o),!0}for(h=1,u=new Array(c-1);h<c;h++)u[h-1]=arguments[h];l.fn.apply(l.context,u)}else{var d,f=l.length;for(h=0;h<f;h++)switch(l[h].once&&this.removeListener(t,l[h].fn,void 0,!0),c){case 1:l[h].fn.call(l[h].context);break;case 2:l[h].fn.call(l[h].context,e);break;case 3:l[h].fn.call(l[h].context,e,r);break;case 4:l[h].fn.call(l[h].context,e,r,n);break;default:if(!u)for(d=1,u=new Array(c-1);d<c;d++)u[d-1]=arguments[d];l[h].fn.apply(l[h].context,u)}}return!0},o.prototype.on=function(t,e,r){var n=new i(e,r||this),o=a?a+t:t;return this._events[o]?this._events[o].fn?this._events[o]=[this._events[o],n]:this._events[o].push(n):(this._events[o]=n,this._eventsCount++),this},o.prototype.once=function(t,e,r){var n=new i(e,r||this,!0),o=a?a+t:t;return this._events[o]?this._events[o].fn?this._events[o]=[this._events[o],n]:this._events[o].push(n):(this._events[o]=n,this._eventsCount++),this},o.prototype.removeListener=function(t,e,r,i){var o=a?a+t:t;if(!this._events[o])return this;if(!e)return 0==--this._eventsCount?this._events=new n:delete this._events[o],this;var s=this._events[o];if(s.fn)s.fn!==e||i&&!s.once||r&&s.context!==r||(0==--this._eventsCount?this._events=new n:delete this._events[o]);else{for(var u=0,h=[],l=s.length;u<l;u++)(s[u].fn!==e||i&&!s[u].once||r&&s[u].context!==r)&&h.push(s[u]);h.length?this._events[o]=1===h.length?h[0]:h:0==--this._eventsCount?this._events=new n:delete this._events[o]}return this},o.prototype.removeAllListeners=function(t){var e;return t?(e=a?a+t:t,this._events[e]&&(0==--this._eventsCount?this._events=new n:delete this._events[e])):(this._events=new n,this._eventsCount=0),this},o.prototype.off=o.prototype.removeListener,o.prototype.addListener=o.prototype.on,o.prototype.setMaxListeners=function(){return this},o.prefixed=a,o.EventEmitter=o,void 0!==e&&(e.exports=o)},{}],4:[function(e,r,n){!function(e){var n=/iPhone/i,i=/iPod/i,o=/iPad/i,s=/(?=.*\\bAndroid\\b)(?=.*\\bMobile\\b)/i,a=/Android/i,u=/(?=.*\\bAndroid\\b)(?=.*\\bSD4930UR\\b)/i,h=/(?=.*\\bAndroid\\b)(?=.*\\b(?:KFOT|KFTT|KFJWI|KFJWA|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|KFARWI|KFASWI|KFSAWI|KFSAWA)\\b)/i,l=/Windows Phone/i,c=/(?=.*\\bWindows\\b)(?=.*\\bARM\\b)/i,d=/BlackBerry/i,f=/BB10/i,p=/Opera Mini/i,v=/(CriOS|Chrome)(?=.*\\bMobile\\b)/i,y=/(?=.*\\bFirefox\\b)(?=.*\\bMobile\\b)/i,g=new RegExp(\"(?:Nexus 7|BNTV250|Kindle Fire|Silk|GT-P1000)\",\"i\"),m=function(t,e){return t.test(e)},_=function(t){var e=t||navigator.userAgent,r=e.split(\"[FBAN\");if(void 0!==r[1]&&(e=r[0]),r=e.split(\"Twitter\"),void 0!==r[1]&&(e=r[0]),this.apple={phone:m(n,e),ipod:m(i,e),tablet:!m(n,e)&&m(o,e),device:m(n,e)||m(i,e)||m(o,e)},this.amazon={phone:m(u,e),tablet:!m(u,e)&&m(h,e),device:m(u,e)||m(h,e)},this.android={phone:m(u,e)||m(s,e),tablet:!m(u,e)&&!m(s,e)&&(m(h,e)||m(a,e)),device:m(u,e)||m(h,e)||m(s,e)||m(a,e)},this.windows={phone:m(l,e),tablet:m(c,e),device:m(l,e)||m(c,e)},this.other={blackberry:m(d,e),blackberry10:m(f,e),opera:m(p,e),firefox:m(y,e),chrome:m(v,e),device:m(d,e)||m(f,e)||m(p,e)||m(y,e)||m(v,e)},this.seven_inch=m(g,e),this.any=this.apple.device||this.android.device||this.windows.device||this.other.device||this.seven_inch,this.phone=this.apple.phone||this.android.phone||this.windows.phone,this.tablet=this.apple.tablet||this.android.tablet||this.windows.tablet,\"undefined\"==typeof window)return this},b=function(){var t=new _;return t.Class=_,t};void 0!==r&&r.exports&&\"undefined\"==typeof window?r.exports=_:void 0!==r&&r.exports&&\"undefined\"!=typeof window?r.exports=b():\"function\"==typeof t&&t.amd?t(\"isMobile\",[],e.isMobile=b()):e.isMobile=b()}(this)},{}],5:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){return t._head?(t._tail._next=e,e._prev=t._tail,t._tail=e):(t._head=e,t._tail=e),e._owner=t,e}Object.defineProperty(r,\"__esModule\",{value:!0});var o=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),s=function(){function t(e,r,i){void 0===r&&(r=!1),n(this,t),this._fn=e,this._once=r,this._thisArg=i,this._next=this._prev=this._owner=null}return o(t,[{key:\"detach\",value:function(){return null!==this._owner&&(this._owner.detach(this),!0)}}]),t}(),a=function(){function t(){n(this,t),this._head=this._tail=void 0}return o(t,[{key:\"handlers\",value:function(){var t=!(arguments.length<=0||void 0===arguments[0])&&arguments[0],e=this._head;if(t)return!!e;for(var r=[];e;)r.push(e),e=e._next;return r}},{key:\"has\",value:function(t){if(!(t instanceof s))throw new Error(\"MiniSignal#has(): First arg must be a MiniSignalBinding object.\");return t._owner===this}},{key:\"dispatch\",value:function(){var t=this._head;if(!t)return!1;for(;t;)t._once&&this.detach(t),t._fn.apply(t._thisArg,arguments),t=t._next;return!0}},{key:\"add\",value:function(t){var e=arguments.length<=1||void 0===arguments[1]?null:arguments[1];if(\"function\"!=typeof t)throw new Error(\"MiniSignal#add(): First arg must be a Function.\");return i(this,new s(t,!1,e))}},{key:\"once\",value:function(t){var e=arguments.length<=1||void 0===arguments[1]?null:arguments[1];if(\"function\"!=typeof t)throw new Error(\"MiniSignal#once(): First arg must be a Function.\");return i(this,new s(t,!0,e))}},{key:\"detach\",value:function(t){if(!(t instanceof s))throw new Error(\"MiniSignal#detach(): First arg must be a MiniSignalBinding object.\");return t._owner!==this?this:(t._prev&&(t._prev._next=t._next),t._next&&(t._next._prev=t._prev),t===this._head?(this._head=t._next,null===t._next&&(this._tail=null)):t===this._tail&&(this._tail=t._prev,this._tail._next=null),t._owner=null,this)}},{key:\"detachAll\",value:function(){var t=this._head;if(!t)return this;for(this._head=this._tail=null;t;)t._owner=null,t=t._next;return this}}]),t}();a.MiniSignalBinding=s,r.default=a,e.exports=r.default},{}],6:[function(t,e,r){\"use strict\";function n(t){if(null===t||void 0===t)throw new TypeError(\"Object.assign cannot be called with null or undefined\");return Object(t)}var i=Object.getOwnPropertySymbols,o=Object.prototype.hasOwnProperty,s=Object.prototype.propertyIsEnumerable;e.exports=function(){try{if(!Object.assign)return!1;var t=new String(\"abc\");if(t[5]=\"de\",\"5\"===Object.getOwnPropertyNames(t)[0])return!1;for(var e={},r=0;r<10;r++)e[\"_\"+String.fromCharCode(r)]=r;if(\"0123456789\"!==Object.getOwnPropertyNames(e).map(function(t){return e[t]}).join(\"\"))return!1;var n={};return\"abcdefghijklmnopqrst\".split(\"\").forEach(function(t){n[t]=t}),\"abcdefghijklmnopqrst\"===Object.keys(Object.assign({},n)).join(\"\")}catch(t){return!1}}()?Object.assign:function(t,e){for(var r,a,u=n(t),h=1;h<arguments.length;h++){r=Object(arguments[h]);for(var l in r)o.call(r,l)&&(u[l]=r[l]);if(i){a=i(r);for(var c=0;c<a.length;c++)s.call(r,a[c])&&(u[a[c]]=r[a[c]])}}return u}},{}],7:[function(t,e,r){\"use strict\";e.exports=function(t,e){e=e||{};for(var r={key:[\"source\",\"protocol\",\"authority\",\"userInfo\",\"user\",\"password\",\"host\",\"port\",\"relative\",\"path\",\"directory\",\"file\",\"query\",\"anchor\"],q:{name:\"queryKey\",parser:/(?:^|&)([^&=]*)=?([^&]*)/g},parser:{strict:/^(?:([^:\\/?#]+):)?(?:\\/\\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\\/?#]*)(?::(\\d*))?))?((((?:[^?#\\/]*\\/)*)([^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/,loose:/^(?:(?![^:@]+:[^:@\\/]*@)([^:\\/?#.]+):)?(?:\\/\\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\\/?#]*)(?::(\\d*))?)(((\\/(?:[^?#](?![^?#\\/]*\\.[^?#\\/.]+(?:[?#]|$)))*\\/?)?([^?#\\/]*))(?:\\?([^#]*))?(?:#(.*))?)/}},n=r.parser[e.strictMode?\"strict\":\"loose\"].exec(t),i={},o=14;o--;)i[r.key[o]]=n[o]||\"\";return i[r.q.name]={},i[r.key[12]].replace(r.q.parser,function(t,e,n){e&&(i[r.q.name][e]=n)}),i}},{}],8:[function(t,e,r){(function(t){function e(t,e){for(var r=0,n=t.length-1;n>=0;n--){var i=t[n];\".\"===i?t.splice(n,1):\"..\"===i?(t.splice(n,1),r++):r&&(t.splice(n,1),r--)}if(e)for(;r--;r)t.unshift(\"..\");return t}function n(t,e){if(t.filter)return t.filter(e);for(var r=[],n=0;n<t.length;n++)e(t[n],n,t)&&r.push(t[n]);return r}var i=/^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/,o=function(t){return i.exec(t).slice(1)};r.resolve=function(){for(var r=\"\",i=!1,o=arguments.length-1;o>=-1&&!i;o--){var s=o>=0?arguments[o]:t.cwd();if(\"string\"!=typeof s)throw new TypeError(\"Arguments to path.resolve must be strings\");s&&(r=s+\"/\"+r,i=\"/\"===s.charAt(0))}return r=e(n(r.split(\"/\"),function(t){return!!t}),!i).join(\"/\"),(i?\"/\":\"\")+r||\".\"},r.normalize=function(t){var i=r.isAbsolute(t),o=\"/\"===s(t,-1);return t=e(n(t.split(\"/\"),function(t){return!!t}),!i).join(\"/\"),t||i||(t=\".\"),t&&o&&(t+=\"/\"),(i?\"/\":\"\")+t},r.isAbsolute=function(t){return\"/\"===t.charAt(0)},r.join=function(){var t=Array.prototype.slice.call(arguments,0);return r.normalize(n(t,function(t,e){if(\"string\"!=typeof t)throw new TypeError(\"Arguments to path.join must be strings\");return t}).join(\"/\"))},r.relative=function(t,e){function n(t){for(var e=0;e<t.length&&\"\"===t[e];e++);for(var r=t.length-1;r>=0&&\"\"===t[r];r--);return e>r?[]:t.slice(e,r-e+1)}t=r.resolve(t).substr(1),e=r.resolve(e).substr(1);for(var i=n(t.split(\"/\")),o=n(e.split(\"/\")),s=Math.min(i.length,o.length),a=s,u=0;u<s;u++)if(i[u]!==o[u]){a=u;break}for(var h=[],u=a;u<i.length;u++)h.push(\"..\");return h=h.concat(o.slice(a)),h.join(\"/\")},r.sep=\"/\",r.delimiter=\":\",r.dirname=function(t){var e=o(t),r=e[0],n=e[1];return r||n?(n&&(n=n.substr(0,n.length-1)),r+n):\".\"},r.basename=function(t,e){var r=o(t)[2];return e&&r.substr(-1*e.length)===e&&(r=r.substr(0,r.length-e.length)),r},r.extname=function(t){return o(t)[3]};var s=\"b\"===\"ab\".substr(-1)?function(t,e,r){return t.substr(e,r)}:function(t,e,r){return e<0&&(e=t.length+e),t.substr(e,r)}}).call(this,t(\"_process\"))},{_process:26}],9:[function(t,e,r){var n=new ArrayBuffer(0),i=function(t,e,r,i){this.gl=t,this.buffer=t.createBuffer(),this.type=e||t.ARRAY_BUFFER,this.drawType=i||t.STATIC_DRAW,this.data=n,r&&this.upload(r),this._updateID=0};i.prototype.upload=function(t,e,r){r||this.bind();var n=this.gl;t=t||this.data,e=e||0,this.data.byteLength>=t.byteLength?n.bufferSubData(this.type,e,t):n.bufferData(this.type,t,this.drawType),this.data=t},i.prototype.bind=function(){this.gl.bindBuffer(this.type,this.buffer)},i.createVertexBuffer=function(t,e,r){return new i(t,t.ARRAY_BUFFER,e,r)},i.createIndexBuffer=function(t,e,r){return new i(t,t.ELEMENT_ARRAY_BUFFER,e,r)},i.create=function(t,e,r,n){return new i(t,e,r,n)},i.prototype.destroy=function(){this.gl.deleteBuffer(this.buffer)},e.exports=i},{}],10:[function(t,e,r){var n=t(\"./GLTexture\"),i=function(t,e,r){this.gl=t,this.framebuffer=t.createFramebuffer(),this.stencil=null,this.texture=null,this.width=e||100,this.height=r||100};i.prototype.enableTexture=function(t){var e=this.gl;this.texture=t||new n(e),this.texture.bind(),this.bind(),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,this.texture.texture,0)},i.prototype.enableStencil=function(){if(!this.stencil){var t=this.gl;this.stencil=t.createRenderbuffer(),t.bindRenderbuffer(t.RENDERBUFFER,this.stencil),t.framebufferRenderbuffer(t.FRAMEBUFFER,t.DEPTH_STENCIL_ATTACHMENT,t.RENDERBUFFER,this.stencil),t.renderbufferStorage(t.RENDERBUFFER,t.DEPTH_STENCIL,this.width,this.height)}},i.prototype.clear=function(t,e,r,n){this.bind();var i=this.gl;i.clearColor(t,e,r,n),i.clear(i.COLOR_BUFFER_BIT|i.DEPTH_BUFFER_BIT)},i.prototype.bind=function(){var t=this.gl;t.bindFramebuffer(t.FRAMEBUFFER,this.framebuffer)},i.prototype.unbind=function(){var t=this.gl;t.bindFramebuffer(t.FRAMEBUFFER,null)},i.prototype.resize=function(t,e){var r=this.gl;this.width=t,this.height=e,this.texture&&this.texture.uploadData(null,t,e),this.stencil&&(r.bindRenderbuffer(r.RENDERBUFFER,this.stencil),r.renderbufferStorage(r.RENDERBUFFER,r.DEPTH_STENCIL,t,e))},i.prototype.destroy=function(){var t=this.gl;this.texture&&this.texture.destroy(),t.deleteFramebuffer(this.framebuffer),this.gl=null,this.stencil=null,this.texture=null},i.createRGBA=function(t,e,r,o){var s=n.fromData(t,null,e,r);s.enableNearestScaling(),s.enableWrapClamp();var a=new i(t,e,r);return a.enableTexture(s),a.unbind(),a},i.createFloat32=function(t,e,r,o){var s=new n.fromData(t,o,e,r);s.enableNearestScaling(),s.enableWrapClamp();var a=new i(t,e,r);return a.enableTexture(s),a.unbind(),a},e.exports=i},{\"./GLTexture\":12}],11:[function(t,e,r){var n=t(\"./shader/compileProgram\"),i=t(\"./shader/extractAttributes\"),o=t(\"./shader/extractUniforms\"),s=t(\"./shader/setPrecision\"),a=t(\"./shader/generateUniformAccessObject\"),u=function(t,e,r,u,h){this.gl=t,u&&(e=s(e,u),r=s(r,u)),this.program=n(t,e,r,h),this.attributes=i(t,this.program),this.uniformData=o(t,this.program),this.uniforms=a(t,this.uniformData)};u.prototype.bind=function(){this.gl.useProgram(this.program)},u.prototype.destroy=function(){this.attributes=null,this.uniformData=null,this.uniforms=null,this.gl.deleteProgram(this.program)},e.exports=u},{\"./shader/compileProgram\":17,\"./shader/extractAttributes\":19,\"./shader/extractUniforms\":20,\"./shader/generateUniformAccessObject\":21,\"./shader/setPrecision\":25}],12:[function(t,e,r){var n=function(t,e,r,n,i){this.gl=t,this.texture=t.createTexture(),this.mipmap=!1,this.premultiplyAlpha=!1,this.width=e||-1,this.height=r||-1,this.format=n||t.RGBA,this.type=i||t.UNSIGNED_BYTE};n.prototype.upload=function(t){this.bind();var e=this.gl;e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,this.premultiplyAlpha);var r=t.videoWidth||t.width,n=t.videoHeight||t.height;n!==this.height||r!==this.width?e.texImage2D(e.TEXTURE_2D,0,this.format,this.format,this.type,t):e.texSubImage2D(e.TEXTURE_2D,0,0,0,this.format,this.type,t),this.width=r,this.height=n};var i=!1;n.prototype.uploadData=function(t,e,r){this.bind();var n=this.gl;if(t instanceof Float32Array){if(!i){if(!n.getExtension(\"OES_texture_float\"))throw new Error(\"floating point textures not available\");i=!0}this.type=n.FLOAT}else this.type=this.type||n.UNSIGNED_BYTE;n.pixelStorei(n.UNPACK_PREMULTIPLY_ALPHA_WEBGL,this.premultiplyAlpha),e!==this.width||r!==this.height?n.texImage2D(n.TEXTURE_2D,0,this.format,e,r,0,this.format,this.type,t||null):n.texSubImage2D(n.TEXTURE_2D,0,0,0,e,r,this.format,this.type,t||null),this.width=e,this.height=r},n.prototype.bind=function(t){var e=this.gl;void 0!==t&&e.activeTexture(e.TEXTURE0+t),e.bindTexture(e.TEXTURE_2D,this.texture)},n.prototype.unbind=function(){var t=this.gl;t.bindTexture(t.TEXTURE_2D,null)},n.prototype.minFilter=function(t){var e=this.gl;this.bind(),this.mipmap?e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,t?e.LINEAR_MIPMAP_LINEAR:e.NEAREST_MIPMAP_NEAREST):e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,t?e.LINEAR:e.NEAREST)},n.prototype.magFilter=function(t){var e=this.gl;this.bind(),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,t?e.LINEAR:e.NEAREST)},n.prototype.enableMipmap=function(){var t=this.gl;this.bind(),this.mipmap=!0,t.generateMipmap(t.TEXTURE_2D)},n.prototype.enableLinearScaling=function(){this.minFilter(!0),this.magFilter(!0)},n.prototype.enableNearestScaling=function(){this.minFilter(!1),this.magFilter(!1)},n.prototype.enableWrapClamp=function(){var t=this.gl;this.bind(),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE)},n.prototype.enableWrapRepeat=function(){var t=this.gl;this.bind(),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.REPEAT),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.REPEAT)},n.prototype.enableWrapMirrorRepeat=function(){var t=this.gl;this.bind(),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.MIRRORED_REPEAT),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.MIRRORED_REPEAT)},n.prototype.destroy=function(){this.gl.deleteTexture(this.texture)},n.fromSource=function(t,e,r){var i=new n(t);return i.premultiplyAlpha=r||!1,i.upload(e),i},n.fromData=function(t,e,r,i){var o=new n(t);return o.uploadData(e,r,i),o},e.exports=n},{}],13:[function(t,e,r){function n(t,e){if(this.nativeVaoExtension=null,n.FORCE_NATIVE||(this.nativeVaoExtension=t.getExtension(\"OES_vertex_array_object\")||t.getExtension(\"MOZ_OES_vertex_array_object\")||t.getExtension(\"WEBKIT_OES_vertex_array_object\")),this.nativeState=e,this.nativeVaoExtension){this.nativeVao=this.nativeVaoExtension.createVertexArrayOES();var r=t.getParameter(t.MAX_VERTEX_ATTRIBS);this.nativeState={tempAttribState:new Array(r),attribState:new Array(r)}}this.gl=t,this.attributes=[],this.indexBuffer=null,this.dirty=!1}var i=t(\"./setVertexAttribArrays\");n.prototype.constructor=n,e.exports=n,n.FORCE_NATIVE=!1,n.prototype.bind=function(){return this.nativeVao?(this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao),this.dirty&&(this.dirty=!1,this.activate())):this.activate(),this},n.prototype.unbind=function(){return this.nativeVao&&this.nativeVaoExtension.bindVertexArrayOES(null),this},n.prototype.activate=function(){for(var t=this.gl,e=null,r=0;r<this.attributes.length;r++){var n=this.attributes[r];e!==n.buffer&&(n.buffer.bind(),e=n.buffer),t.vertexAttribPointer(n.attribute.location,n.attribute.size,n.type||t.FLOAT,n.normalized||!1,n.stride||0,n.start||0)}return i(t,this.attributes,this.nativeState),this.indexBuffer&&this.indexBuffer.bind(),this},n.prototype.addAttribute=function(t,e,r,n,i,o){return this.attributes.push({buffer:t,attribute:e,location:e.location,type:r||this.gl.FLOAT,normalized:n||!1,stride:i||0,start:o||0}),this.dirty=!0,this},n.prototype.addIndex=function(t){return this.indexBuffer=t,this.dirty=!0,this},n.prototype.clear=function(){return this.nativeVao&&this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao),this.attributes.length=0,this.indexBuffer=null,this},n.prototype.draw=function(t,e,r){var n=this.gl;return this.indexBuffer?n.drawElements(t,e||this.indexBuffer.data.length,n.UNSIGNED_SHORT,2*(r||0)):n.drawArrays(t,r,e||this.getSize()),this},n.prototype.destroy=function(){this.gl=null,this.indexBuffer=null,this.attributes=null,this.nativeState=null,this.nativeVao&&this.nativeVaoExtension.deleteVertexArrayOES(this.nativeVao),this.nativeVaoExtension=null,this.nativeVao=null},n.prototype.getSize=function(){var t=this.attributes[0];return t.buffer.data.length/(t.stride/4||t.attribute.size)}},{\"./setVertexAttribArrays\":16}],14:[function(t,e,r){var n=function(t,e){var r=t.getContext(\"webgl\",e)||t.getContext(\"experimental-webgl\",e);if(!r)throw new Error(\"This browser does not support webGL. Try using the canvas renderer\");return r};e.exports=n},{}],15:[function(t,e,r){var n={createContext:t(\"./createContext\"),setVertexAttribArrays:t(\"./setVertexAttribArrays\"),GLBuffer:t(\"./GLBuffer\"),GLFramebuffer:t(\"./GLFramebuffer\"),GLShader:t(\"./GLShader\"),GLTexture:t(\"./GLTexture\"),VertexArrayObject:t(\"./VertexArrayObject\"),shader:t(\"./shader\")};void 0!==e&&e.exports&&(e.exports=n),\"undefined\"!=typeof window&&(window.PIXI=window.PIXI||{},window.PIXI.glCore=n)},{\"./GLBuffer\":9,\"./GLFramebuffer\":10,\"./GLShader\":11,\"./GLTexture\":12,\"./VertexArrayObject\":13,\"./createContext\":14,\"./setVertexAttribArrays\":16,\"./shader\":22}],16:[function(t,e,r){var n=function(t,e,r){var n;if(r){var i=r.tempAttribState,o=r.attribState;for(n=0;n<i.length;n++)i[n]=!1;for(n=0;n<e.length;n++)i[e[n].attribute.location]=!0;for(n=0;n<o.length;n++)o[n]!==i[n]&&(o[n]=i[n],r.attribState[n]?t.enableVertexAttribArray(n):t.disableVertexAttribArray(n))}else for(n=0;n<e.length;n++){var s=e[n];t.enableVertexAttribArray(s.attribute.location)}};e.exports=n},{}],17:[function(t,e,r){var n=function(t,e,r,n){var o=i(t,t.VERTEX_SHADER,e),s=i(t,t.FRAGMENT_SHADER,r),a=t.createProgram();if(t.attachShader(a,o),t.attachShader(a,s),n)for(var u in n)t.bindAttribLocation(a,n[u],u);return t.linkProgram(a),t.getProgramParameter(a,t.LINK_STATUS)||(console.error(\"Pixi.js Error: Could not initialize shader.\"),console.error(\"gl.VALIDATE_STATUS\",t.getProgramParameter(a,t.VALIDATE_STATUS)),console.error(\"gl.getError()\",t.getError()),\"\"!==t.getProgramInfoLog(a)&&console.warn(\"Pixi.js Warning: gl.getProgramInfoLog()\",t.getProgramInfoLog(a)),t.deleteProgram(a),a=null),t.deleteShader(o),t.deleteShader(s),a},i=function(t,e,r){var n=t.createShader(e);return t.shaderSource(n,r),t.compileShader(n),t.getShaderParameter(n,t.COMPILE_STATUS)?n:(console.log(t.getShaderInfoLog(n)),null)};e.exports=n},{}],18:[function(t,e,r){var n=function(t,e){switch(t){case\"float\":return 0;case\"vec2\":return new Float32Array(2*e);case\"vec3\":return new Float32Array(3*e);case\"vec4\":return new Float32Array(4*e);case\"int\":case\"sampler2D\":return 0;case\"ivec2\":return new Int32Array(2*e);case\"ivec3\":return new Int32Array(3*e);case\"ivec4\":return new Int32Array(4*e);case\"bool\":return!1;case\"bvec2\":return i(2*e);case\"bvec3\":return i(3*e);case\"bvec4\":return i(4*e);case\"mat2\":return new Float32Array([1,0,0,1]);case\"mat3\":return new Float32Array([1,0,0,0,1,0,0,0,1]);case\"mat4\":return new Float32Array([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1])}},i=function(t){for(var e=new Array(t),r=0;r<e.length;r++)e[r]=!1;return e};e.exports=n},{}],19:[function(t,e,r){var n=t(\"./mapType\"),i=t(\"./mapSize\"),o=function(t,e){for(var r={},o=t.getProgramParameter(e,t.ACTIVE_ATTRIBUTES),a=0;a<o;a++){var u=t.getActiveAttrib(e,a),h=n(t,u.type);r[u.name]={type:h,size:i(h),location:t.getAttribLocation(e,u.name),pointer:s}}return r},s=function(t,e,r,n){gl.vertexAttribPointer(this.location,this.size,t||gl.FLOAT,e||!1,r||0,n||0)};e.exports=o},{\"./mapSize\":23,\"./mapType\":24}],20:[function(t,e,r){var n=t(\"./mapType\"),i=t(\"./defaultValue\"),o=function(t,e){for(var r={},o=t.getProgramParameter(e,t.ACTIVE_UNIFORMS),s=0;s<o;s++){var a=t.getActiveUniform(e,s),u=a.name.replace(/\\[.*?\\]/,\"\"),h=n(t,a.type);r[u]={type:h,size:a.size,location:t.getUniformLocation(e,u),value:i(h,a.size)}}return r};e.exports=o},{\"./defaultValue\":18,\"./mapType\":24}],21:[function(t,e,r){var n=function(t,e){var r={data:{}};r.gl=t;for(var n=Object.keys(e),a=0;a<n.length;a++){var u=n[a],h=u.split(\".\"),l=h[h.length-1],c=s(h,r),d=e[u];c.data[l]=d,c.gl=t,Object.defineProperty(c,l,{get:i(l),set:o(l,d)})}return r},i=function(t){var e=a.replace(\"%%\",t);return new Function(e)},o=function(t,e){var r,n=u.replace(/%%/g,t);return r=1===e.size?h[e.type]:l[e.type],r&&(n+=\"\\nthis.gl.\"+r+\";\"),\nnew Function(\"value\",n)},s=function(t,e){for(var r=e,n=0;n<t.length-1;n++){var i=r[t[n]]||{data:{}};r[t[n]]=i,r=i}return r},a=[\"return this.data.%%.value;\"].join(\"\\n\"),u=[\"this.data.%%.value = value;\",\"var location = this.data.%%.location;\"].join(\"\\n\"),h={float:\"uniform1f(location, value)\",vec2:\"uniform2f(location, value[0], value[1])\",vec3:\"uniform3f(location, value[0], value[1], value[2])\",vec4:\"uniform4f(location, value[0], value[1], value[2], value[3])\",int:\"uniform1i(location, value)\",ivec2:\"uniform2i(location, value[0], value[1])\",ivec3:\"uniform3i(location, value[0], value[1], value[2])\",ivec4:\"uniform4i(location, value[0], value[1], value[2], value[3])\",bool:\"uniform1i(location, value)\",bvec2:\"uniform2i(location, value[0], value[1])\",bvec3:\"uniform3i(location, value[0], value[1], value[2])\",bvec4:\"uniform4i(location, value[0], value[1], value[2], value[3])\",mat2:\"uniformMatrix2fv(location, false, value)\",mat3:\"uniformMatrix3fv(location, false, value)\",mat4:\"uniformMatrix4fv(location, false, value)\",sampler2D:\"uniform1i(location, value)\"},l={float:\"uniform1fv(location, value)\",vec2:\"uniform2fv(location, value)\",vec3:\"uniform3fv(location, value)\",vec4:\"uniform4fv(location, value)\",int:\"uniform1iv(location, value)\",ivec2:\"uniform2iv(location, value)\",ivec3:\"uniform3iv(location, value)\",ivec4:\"uniform4iv(location, value)\",bool:\"uniform1iv(location, value)\",bvec2:\"uniform2iv(location, value)\",bvec3:\"uniform3iv(location, value)\",bvec4:\"uniform4iv(location, value)\",sampler2D:\"uniform1iv(location, value)\"};e.exports=n},{}],22:[function(t,e,r){e.exports={compileProgram:t(\"./compileProgram\"),defaultValue:t(\"./defaultValue\"),extractAttributes:t(\"./extractAttributes\"),extractUniforms:t(\"./extractUniforms\"),generateUniformAccessObject:t(\"./generateUniformAccessObject\"),setPrecision:t(\"./setPrecision\"),mapSize:t(\"./mapSize\"),mapType:t(\"./mapType\")}},{\"./compileProgram\":17,\"./defaultValue\":18,\"./extractAttributes\":19,\"./extractUniforms\":20,\"./generateUniformAccessObject\":21,\"./mapSize\":23,\"./mapType\":24,\"./setPrecision\":25}],23:[function(t,e,r){var n=function(t){return i[t]},i={float:1,vec2:2,vec3:3,vec4:4,int:1,ivec2:2,ivec3:3,ivec4:4,bool:1,bvec2:2,bvec3:3,bvec4:4,mat2:4,mat3:9,mat4:16,sampler2D:1};e.exports=n},{}],24:[function(t,e,r){var n=function(t,e){if(!i){var r=Object.keys(o);i={};for(var n=0;n<r.length;++n){var s=r[n];i[t[s]]=o[s]}}return i[e]},i=null,o={FLOAT:\"float\",FLOAT_VEC2:\"vec2\",FLOAT_VEC3:\"vec3\",FLOAT_VEC4:\"vec4\",INT:\"int\",INT_VEC2:\"ivec2\",INT_VEC3:\"ivec3\",INT_VEC4:\"ivec4\",BOOL:\"bool\",BOOL_VEC2:\"bvec2\",BOOL_VEC3:\"bvec3\",BOOL_VEC4:\"bvec4\",FLOAT_MAT2:\"mat2\",FLOAT_MAT3:\"mat3\",FLOAT_MAT4:\"mat4\",SAMPLER_2D:\"sampler2D\"};e.exports=n},{}],25:[function(t,e,r){var n=function(t,e){return\"precision\"!==t.substring(0,9)?\"precision \"+e+\" float;\\n\"+t:t};e.exports=n},{}],26:[function(t,e,r){function n(){throw new Error(\"setTimeout has not been defined\")}function i(){throw new Error(\"clearTimeout has not been defined\")}function o(t){if(c===setTimeout)return setTimeout(t,0);if((c===n||!c)&&setTimeout)return c=setTimeout,setTimeout(t,0);try{return c(t,0)}catch(e){try{return c.call(null,t,0)}catch(e){return c.call(this,t,0)}}}function s(t){if(d===clearTimeout)return clearTimeout(t);if((d===i||!d)&&clearTimeout)return d=clearTimeout,clearTimeout(t);try{return d(t)}catch(e){try{return d.call(null,t)}catch(e){return d.call(this,t)}}}function a(){y&&p&&(y=!1,p.length?v=p.concat(v):g=-1,v.length&&u())}function u(){if(!y){var t=o(a);y=!0;for(var e=v.length;e;){for(p=v,v=[];++g<e;)p&&p[g].run();g=-1,e=v.length}p=null,y=!1,s(t)}}function h(t,e){this.fun=t,this.array=e}function l(){}var c,d,f=e.exports={};!function(){try{c=\"function\"==typeof setTimeout?setTimeout:n}catch(t){c=n}try{d=\"function\"==typeof clearTimeout?clearTimeout:i}catch(t){d=i}}();var p,v=[],y=!1,g=-1;f.nextTick=function(t){var e=new Array(arguments.length-1);if(arguments.length>1)for(var r=1;r<arguments.length;r++)e[r-1]=arguments[r];v.push(new h(t,e)),1!==v.length||y||o(u)},h.prototype.run=function(){this.fun.apply(null,this.array)},f.title=\"browser\",f.browser=!0,f.env={},f.argv=[],f.version=\"\",f.versions={},f.on=l,f.addListener=l,f.once=l,f.off=l,f.removeListener=l,f.removeAllListeners=l,f.emit=l,f.prependListener=l,f.prependOnceListener=l,f.listeners=function(t){return[]},f.binding=function(t){throw new Error(\"process.binding is not supported\")},f.cwd=function(){return\"/\"},f.chdir=function(t){throw new Error(\"process.chdir is not supported\")},f.umask=function(){return 0}},{}],27:[function(e,r,n){(function(e){!function(i){function o(t){throw new RangeError(L[t])}function s(t,e){for(var r=t.length,n=[];r--;)n[r]=e(t[r]);return n}function a(t,e){var r=t.split(\"@\"),n=\"\";return r.length>1&&(n=r[0]+\"@\",t=r[1]),t=t.replace(D,\".\"),n+s(t.split(\".\"),e).join(\".\")}function u(t){for(var e,r,n=[],i=0,o=t.length;i<o;)e=t.charCodeAt(i++),e>=55296&&e<=56319&&i<o?(r=t.charCodeAt(i++),56320==(64512&r)?n.push(((1023&e)<<10)+(1023&r)+65536):(n.push(e),i--)):n.push(e);return n}function h(t){return s(t,function(t){var e=\"\";return t>65535&&(t-=65536,e+=B(t>>>10&1023|55296),t=56320|1023&t),e+=B(t)}).join(\"\")}function l(t){return t-48<10?t-22:t-65<26?t-65:t-97<26?t-97:w}function c(t,e){return t+22+75*(t<26)-((0!=e)<<5)}function d(t,e,r){var n=0;for(t=r?F(t/M):t>>1,t+=F(t/e);t>N*S>>1;n+=w)t=F(t/N);return F(n+(N+1)*t/(t+O))}function f(t){var e,r,n,i,s,a,u,c,f,p,v=[],y=t.length,g=0,m=C,_=P;for(r=t.lastIndexOf(R),r<0&&(r=0),n=0;n<r;++n)t.charCodeAt(n)>=128&&o(\"not-basic\"),v.push(t.charCodeAt(n));for(i=r>0?r+1:0;i<y;){for(s=g,a=1,u=w;i>=y&&o(\"invalid-input\"),c=l(t.charCodeAt(i++)),(c>=w||c>F((T-g)/a))&&o(\"overflow\"),g+=c*a,f=u<=_?E:u>=_+S?S:u-_,!(c<f);u+=w)p=w-f,a>F(T/p)&&o(\"overflow\"),a*=p;e=v.length+1,_=d(g-s,e,0==s),F(g/e)>T-m&&o(\"overflow\"),m+=F(g/e),g%=e,v.splice(g++,0,m)}return h(v)}function p(t){var e,r,n,i,s,a,h,l,f,p,v,y,g,m,_,b=[];for(t=u(t),y=t.length,e=C,r=0,s=P,a=0;a<y;++a)(v=t[a])<128&&b.push(B(v));for(n=i=b.length,i&&b.push(R);n<y;){for(h=T,a=0;a<y;++a)(v=t[a])>=e&&v<h&&(h=v);for(g=n+1,h-e>F((T-r)/g)&&o(\"overflow\"),r+=(h-e)*g,e=h,a=0;a<y;++a)if(v=t[a],v<e&&++r>T&&o(\"overflow\"),v==e){for(l=r,f=w;p=f<=s?E:f>=s+S?S:f-s,!(l<p);f+=w)_=l-p,m=w-p,b.push(B(c(p+_%m,0))),l=F(_/m);b.push(B(c(l,0))),s=d(r,g,n==i),r=0,++n}++r,++e}return b.join(\"\")}function v(t){return a(t,function(t){return A.test(t)?f(t.slice(4).toLowerCase()):t})}function y(t){return a(t,function(t){return I.test(t)?\"xn--\"+p(t):t})}var g=\"object\"==typeof n&&n&&!n.nodeType&&n,m=\"object\"==typeof r&&r&&!r.nodeType&&r,_=\"object\"==typeof e&&e;_.global!==_&&_.window!==_&&_.self!==_||(i=_);var b,x,T=2147483647,w=36,E=1,S=26,O=38,M=700,P=72,C=128,R=\"-\",A=/^xn--/,I=/[^\\x20-\\x7E]/,D=/[\\x2E\\u3002\\uFF0E\\uFF61]/g,L={overflow:\"Overflow: input needs wider integers to process\",\"not-basic\":\"Illegal input >= 0x80 (not a basic code point)\",\"invalid-input\":\"Invalid input\"},N=w-E,F=Math.floor,B=String.fromCharCode;if(b={version:\"1.4.1\",ucs2:{decode:u,encode:h},decode:f,encode:p,toASCII:y,toUnicode:v},\"function\"==typeof t&&\"object\"==typeof t.amd&&t.amd)t(\"punycode\",function(){return b});else if(g&&m)if(r.exports==g)m.exports=b;else for(x in b)b.hasOwnProperty(x)&&(g[x]=b[x]);else i.punycode=b}(this)}).call(this,\"undefined\"!=typeof global?global:\"undefined\"!=typeof self?self:\"undefined\"!=typeof window?window:{})},{}],28:[function(t,e,r){\"use strict\";function n(t,e){return Object.prototype.hasOwnProperty.call(t,e)}e.exports=function(t,e,r,o){e=e||\"&\",r=r||\"=\";var s={};if(\"string\"!=typeof t||0===t.length)return s;var a=/\\+/g;t=t.split(e);var u=1e3;o&&\"number\"==typeof o.maxKeys&&(u=o.maxKeys);var h=t.length;u>0&&h>u&&(h=u);for(var l=0;l<h;++l){var c,d,f,p,v=t[l].replace(a,\"%20\"),y=v.indexOf(r);y>=0?(c=v.substr(0,y),d=v.substr(y+1)):(c=v,d=\"\"),f=decodeURIComponent(c),p=decodeURIComponent(d),n(s,f)?i(s[f])?s[f].push(p):s[f]=[s[f],p]:s[f]=p}return s};var i=Array.isArray||function(t){return\"[object Array]\"===Object.prototype.toString.call(t)}},{}],29:[function(t,e,r){\"use strict\";function n(t,e){if(t.map)return t.map(e);for(var r=[],n=0;n<t.length;n++)r.push(e(t[n],n));return r}var i=function(t){switch(typeof t){case\"string\":return t;case\"boolean\":return t?\"true\":\"false\";case\"number\":return isFinite(t)?t:\"\";default:return\"\"}};e.exports=function(t,e,r,a){return e=e||\"&\",r=r||\"=\",null===t&&(t=void 0),\"object\"==typeof t?n(s(t),function(s){var a=encodeURIComponent(i(s))+r;return o(t[s])?n(t[s],function(t){return a+encodeURIComponent(i(t))}).join(e):a+encodeURIComponent(i(t[s]))}).join(e):a?encodeURIComponent(i(a))+r+encodeURIComponent(i(t)):\"\"};var o=Array.isArray||function(t){return\"[object Array]\"===Object.prototype.toString.call(t)},s=Object.keys||function(t){var e=[];for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&e.push(r);return e}},{}],30:[function(t,e,r){\"use strict\";r.decode=r.parse=t(\"./decode\"),r.encode=r.stringify=t(\"./encode\")},{\"./decode\":28,\"./encode\":29}],31:[function(t,e,r){\"use strict\";e.exports=function(t,e,r){var n,i=t.length;if(!(e>=i||0===r)){r=e+r>i?i-e:r;var o=i-r;for(n=e;n<o;++n)t[n]=t[n+r];t.length=o}}},{}],32:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var o=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&\"function\"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?\"symbol\":typeof t},s=t(\"mini-signals\"),a=n(s),u=t(\"parse-uri\"),h=n(u),l=t(\"./async\"),c=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(l),d=t(\"./Resource\"),f=n(d),p=/(#[\\w-]+)?$/,v=function(){function t(){var e=this,r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:\"\",n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:10;i(this,t),this.baseUrl=r,this.progress=0,this.loading=!1,this.defaultQueryString=\"\",this._beforeMiddleware=[],this._afterMiddleware=[],this._resourcesParsing=[],this._boundLoadResource=function(t,r){return e._loadResource(t,r)},this._queue=c.queue(this._boundLoadResource,n),this._queue.pause(),this.resources={},this.onProgress=new a.default,this.onError=new a.default,this.onLoad=new a.default,this.onStart=new a.default,this.onComplete=new a.default}return t.prototype.add=function(t,e,r,n){if(Array.isArray(t)){for(var i=0;i<t.length;++i)this.add(t[i]);return this}if(\"object\"===(void 0===t?\"undefined\":o(t))&&(n=e||t.callback||t.onComplete,r=t,e=t.url,t=t.name||t.key||t.url),\"string\"!=typeof e&&(n=r,r=e,e=t),\"string\"!=typeof e)throw new Error(\"No url passed to add resource to loader.\");if(\"function\"==typeof r&&(n=r,r=null),this.loading&&(!r||!r.parentResource))throw new Error(\"Cannot add resources while the loader is running.\");if(this.resources[t])throw new Error('Resource named \"'+t+'\" already exists.');if(e=this._prepareUrl(e),this.resources[t]=new f.default(t,e,r),\"function\"==typeof n&&this.resources[t].onAfterMiddleware.once(n),this.loading){for(var s=r.parentResource,a=[],u=0;u<s.children.length;++u)s.children[u].isComplete||a.push(s.children[u]);var h=s.progressChunk*(a.length+1),l=h/(a.length+2);s.children.push(this.resources[t]),s.progressChunk=l;for(var c=0;c<a.length;++c)a[c].progressChunk=l;this.resources[t].progressChunk=l}return this._queue.push(this.resources[t]),this},t.prototype.pre=function(t){return this._beforeMiddleware.push(t),this},t.prototype.use=function(t){return this._afterMiddleware.push(t),this},t.prototype.reset=function(){this.progress=0,this.loading=!1,this._queue.kill(),this._queue.pause();for(var t in this.resources){var e=this.resources[t];e._onLoadBinding&&e._onLoadBinding.detach(),e.isLoading&&e.abort()}return this.resources={},this},t.prototype.load=function(t){if(\"function\"==typeof t&&this.onComplete.once(t),this.loading)return this;for(var e=100/this._queue._tasks.length,r=0;r<this._queue._tasks.length;++r)this._queue._tasks[r].data.progressChunk=e;return this.loading=!0,this.onStart.dispatch(this),this._queue.resume(),this},t.prototype._prepareUrl=function(t){var e=(0,h.default)(t,{strictMode:!0}),r=void 0;if(r=e.protocol||!e.path||0===t.indexOf(\"//\")?t:this.baseUrl.length&&this.baseUrl.lastIndexOf(\"/\")!==this.baseUrl.length-1&&\"/\"!==t.charAt(0)?this.baseUrl+\"/\"+t:this.baseUrl+t,this.defaultQueryString){var n=p.exec(r)[0];r=r.substr(0,r.length-n.length),-1!==r.indexOf(\"?\")?r+=\"&\"+this.defaultQueryString:r+=\"?\"+this.defaultQueryString,r+=n}return r},t.prototype._loadResource=function(t,e){var r=this;t._dequeue=e,c.eachSeries(this._beforeMiddleware,function(e,n){e.call(r,t,function(){n(t.isComplete?{}:null)})},function(){t.isComplete?r._onLoad(t):(t._onLoadBinding=t.onComplete.once(r._onLoad,r),t.load())},!0)},t.prototype._onComplete=function(){this.loading=!1,this.onComplete.dispatch(this,this.resources)},t.prototype._onLoad=function(t){var e=this;t._onLoadBinding=null,this._resourcesParsing.push(t),t._dequeue(),c.eachSeries(this._afterMiddleware,function(r,n){r.call(e,t,n)},function(){t.onAfterMiddleware.dispatch(t),e.progress+=t.progressChunk,e.onProgress.dispatch(e,t),t.error?e.onError.dispatch(t.error,e,t):e.onLoad.dispatch(e,t),e._resourcesParsing.splice(e._resourcesParsing.indexOf(t),1),e._queue.idle()&&0===e._resourcesParsing.length&&(e.progress=100,e._onComplete())},!0)},t}();r.default=v},{\"./Resource\":33,\"./async\":34,\"mini-signals\":5,\"parse-uri\":7}],33:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(){}function s(t,e,r){e&&0===e.indexOf(\".\")&&(e=e.substring(1)),e&&(t[e]=r)}function a(t){return t.toString().replace(\"object \",\"\")}r.__esModule=!0;var u=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),h=t(\"parse-uri\"),l=n(h),c=t(\"mini-signals\"),d=n(c),f=!(!window.XDomainRequest||\"withCredentials\"in new XMLHttpRequest),p=null,v=function(){function t(e,r,n){if(i(this,t),\"string\"!=typeof e||\"string\"!=typeof r)throw new Error(\"Both name and url are required for constructing a resource.\");n=n||{},this._flags=0,this._setFlag(t.STATUS_FLAGS.DATA_URL,0===r.indexOf(\"data:\")),this.name=e,this.url=r,this.extension=this._getExtension(),this.data=null,this.crossOrigin=!0===n.crossOrigin?\"anonymous\":n.crossOrigin,this.loadType=n.loadType||this._determineLoadType(),this.xhrType=n.xhrType,this.metadata=n.metadata||{},this.error=null,this.xhr=null,this.children=[],this.type=t.TYPE.UNKNOWN,this.progressChunk=0,this._dequeue=o,this._onLoadBinding=null,this._boundComplete=this.complete.bind(this),this._boundOnError=this._onError.bind(this),this._boundOnProgress=this._onProgress.bind(this),this._boundXhrOnError=this._xhrOnError.bind(this),this._boundXhrOnAbort=this._xhrOnAbort.bind(this),this._boundXhrOnLoad=this._xhrOnLoad.bind(this),this._boundXdrOnTimeout=this._xdrOnTimeout.bind(this),this.onStart=new d.default,this.onProgress=new d.default,this.onComplete=new d.default,this.onAfterMiddleware=new d.default}return t.setExtensionLoadType=function(e,r){s(t._loadTypeMap,e,r)},t.setExtensionXhrType=function(e,r){s(t._xhrTypeMap,e,r)},t.prototype.complete=function(){if(this.data&&this.data.removeEventListener&&(this.data.removeEventListener(\"error\",this._boundOnError,!1),this.data.removeEventListener(\"load\",this._boundComplete,!1),this.data.removeEventListener(\"progress\",this._boundOnProgress,!1),this.data.removeEventListener(\"canplaythrough\",this._boundComplete,!1)),this.xhr&&(this.xhr.removeEventListener?(this.xhr.removeEventListener(\"error\",this._boundXhrOnError,!1),this.xhr.removeEventListener(\"abort\",this._boundXhrOnAbort,!1),this.xhr.removeEventListener(\"progress\",this._boundOnProgress,!1),this.xhr.removeEventListener(\"load\",this._boundXhrOnLoad,!1)):(this.xhr.onerror=null,this.xhr.ontimeout=null,this.xhr.onprogress=null,this.xhr.onload=null)),this.isComplete)throw new Error(\"Complete called again for an already completed resource.\");this._setFlag(t.STATUS_FLAGS.COMPLETE,!0),this._setFlag(t.STATUS_FLAGS.LOADING,!1),this.onComplete.dispatch(this)},t.prototype.abort=function(e){if(!this.error){if(this.error=new Error(e),this.xhr)this.xhr.abort();else if(this.xdr)this.xdr.abort();else if(this.data)if(this.data.src)this.data.src=t.EMPTY_GIF;else for(;this.data.firstChild;)this.data.removeChild(this.data.firstChild);this.complete()}},t.prototype.load=function(e){var r=this;if(!this.isLoading){if(this.isComplete)return void(e&&setTimeout(function(){return e(r)},1));switch(e&&this.onComplete.once(e),this._setFlag(t.STATUS_FLAGS.LOADING,!0),this.onStart.dispatch(this),!1!==this.crossOrigin&&\"string\"==typeof this.crossOrigin||(this.crossOrigin=this._determineCrossOrigin(this.url)),this.loadType){case t.LOAD_TYPE.IMAGE:this.type=t.TYPE.IMAGE,this._loadElement(\"image\");break;case t.LOAD_TYPE.AUDIO:this.type=t.TYPE.AUDIO,this._loadSourceElement(\"audio\");break;case t.LOAD_TYPE.VIDEO:this.type=t.TYPE.VIDEO,this._loadSourceElement(\"video\");break;case t.LOAD_TYPE.XHR:default:f&&this.crossOrigin?this._loadXdr():this._loadXhr()}}},t.prototype._hasFlag=function(t){return!!(this._flags&t)},t.prototype._setFlag=function(t,e){this._flags=e?this._flags|t:this._flags&~t},t.prototype._loadElement=function(t){this.metadata.loadElement?this.data=this.metadata.loadElement:\"image\"===t&&void 0!==window.Image?this.data=new Image:this.data=document.createElement(t),this.crossOrigin&&(this.data.crossOrigin=this.crossOrigin),this.metadata.skipSource||(this.data.src=this.url),this.data.addEventListener(\"error\",this._boundOnError,!1),this.data.addEventListener(\"load\",this._boundComplete,!1),this.data.addEventListener(\"progress\",this._boundOnProgress,!1)},t.prototype._loadSourceElement=function(t){if(this.metadata.loadElement?this.data=this.metadata.loadElement:\"audio\"===t&&void 0!==window.Audio?this.data=new Audio:this.data=document.createElement(t),null===this.data)return void this.abort(\"Unsupported element: \"+t);if(!this.metadata.skipSource)if(navigator.isCocoonJS)this.data.src=Array.isArray(this.url)?this.url[0]:this.url;else if(Array.isArray(this.url))for(var e=this.metadata.mimeType,r=0;r<this.url.length;++r)this.data.appendChild(this._createSource(t,this.url[r],Array.isArray(e)?e[r]:e));else{var n=this.metadata.mimeType;this.data.appendChild(this._createSource(t,this.url,Array.isArray(n)?n[0]:n))}this.data.addEventListener(\"error\",this._boundOnError,!1),this.data.addEventListener(\"load\",this._boundComplete,!1),this.data.addEventListener(\"progress\",this._boundOnProgress,!1),this.data.addEventListener(\"canplaythrough\",this._boundComplete,!1),this.data.load()},t.prototype._loadXhr=function(){\"string\"!=typeof this.xhrType&&(this.xhrType=this._determineXhrType());var e=this.xhr=new XMLHttpRequest;e.open(\"GET\",this.url,!0),this.xhrType===t.XHR_RESPONSE_TYPE.JSON||this.xhrType===t.XHR_RESPONSE_TYPE.DOCUMENT?e.responseType=t.XHR_RESPONSE_TYPE.TEXT:e.responseType=this.xhrType,e.addEventListener(\"error\",this._boundXhrOnError,!1),e.addEventListener(\"abort\",this._boundXhrOnAbort,!1),e.addEventListener(\"progress\",this._boundOnProgress,!1),e.addEventListener(\"load\",this._boundXhrOnLoad,!1),e.send()},t.prototype._loadXdr=function(){\"string\"!=typeof this.xhrType&&(this.xhrType=this._determineXhrType());var t=this.xhr=new XDomainRequest;t.timeout=5e3,t.onerror=this._boundXhrOnError,t.ontimeout=this._boundXdrOnTimeout,t.onprogress=this._boundOnProgress,t.onload=this._boundXhrOnLoad,t.open(\"GET\",this.url,!0),setTimeout(function(){return t.send()},1)},t.prototype._createSource=function(t,e,r){r||(r=t+\"/\"+this._getExtension(e));var n=document.createElement(\"source\");return n.src=e,n.type=r,n},t.prototype._onError=function(t){this.abort(\"Failed to load element using: \"+t.target.nodeName)},t.prototype._onProgress=function(t){t&&t.lengthComputable&&this.onProgress.dispatch(this,t.loaded/t.total)},t.prototype._xhrOnError=function(){var t=this.xhr;this.abort(a(t)+\" Request failed. Status: \"+t.status+', text: \"'+t.statusText+'\"')},t.prototype._xhrOnAbort=function(){this.abort(a(this.xhr)+\" Request was aborted by the user.\")},t.prototype._xdrOnTimeout=function(){this.abort(a(this.xhr)+\" Request timed out.\")},t.prototype._xhrOnLoad=function(){var e=this.xhr,r=\"\",n=void 0===e.status?200:e.status;if(\"\"!==e.responseType&&\"text\"!==e.responseType&&void 0!==e.responseType||(r=e.responseText),0===n&&r.length>0?n=200:1223===n&&(n=204),2!=(n/100|0))return void this.abort(\"[\"+e.status+\"] \"+e.statusText+\": \"+e.responseURL);if(this.xhrType===t.XHR_RESPONSE_TYPE.TEXT)this.data=r,this.type=t.TYPE.TEXT;else if(this.xhrType===t.XHR_RESPONSE_TYPE.JSON)try{this.data=JSON.parse(r),this.type=t.TYPE.JSON}catch(t){return void this.abort(\"Error trying to parse loaded json: \"+t)}else if(this.xhrType===t.XHR_RESPONSE_TYPE.DOCUMENT)try{if(window.DOMParser){var i=new DOMParser;this.data=i.parseFromString(r,\"text/xml\")}else{var o=document.createElement(\"div\");o.innerHTML=r,this.data=o}this.type=t.TYPE.XML}catch(t){return void this.abort(\"Error trying to parse loaded xml: \"+t)}else this.data=e.response||r;this.complete()},t.prototype._determineCrossOrigin=function(t,e){if(0===t.indexOf(\"data:\"))return\"\";e=e||window.location,p||(p=document.createElement(\"a\")),p.href=t,t=(0,l.default)(p.href,{strictMode:!0});var r=!t.port&&\"\"===e.port||t.port===e.port,n=t.protocol?t.protocol+\":\":\"\";return t.host===e.hostname&&r&&n===e.protocol?\"\":\"anonymous\"},t.prototype._determineXhrType=function(){return t._xhrTypeMap[this.extension]||t.XHR_RESPONSE_TYPE.TEXT},t.prototype._determineLoadType=function(){return t._loadTypeMap[this.extension]||t.LOAD_TYPE.XHR},t.prototype._getExtension=function(){var t=this.url,e=\"\";if(this.isDataUrl){var r=t.indexOf(\"/\");e=t.substring(r+1,t.indexOf(\";\",r))}else{var n=t.indexOf(\"?\"),i=t.indexOf(\"#\"),o=Math.min(n>-1?n:t.length,i>-1?i:t.length);t=t.substring(0,o),e=t.substring(t.lastIndexOf(\".\")+1)}return e.toLowerCase()},t.prototype._getMimeFromXhrType=function(e){switch(e){case t.XHR_RESPONSE_TYPE.BUFFER:return\"application/octet-binary\";case t.XHR_RESPONSE_TYPE.BLOB:return\"application/blob\";case t.XHR_RESPONSE_TYPE.DOCUMENT:return\"application/xml\";case t.XHR_RESPONSE_TYPE.JSON:return\"application/json\";case t.XHR_RESPONSE_TYPE.DEFAULT:case t.XHR_RESPONSE_TYPE.TEXT:default:return\"text/plain\"}},u(t,[{key:\"isDataUrl\",get:function(){return this._hasFlag(t.STATUS_FLAGS.DATA_URL)}},{key:\"isComplete\",get:function(){return this._hasFlag(t.STATUS_FLAGS.COMPLETE)}},{key:\"isLoading\",get:function(){return this._hasFlag(t.STATUS_FLAGS.LOADING)}}]),t}();r.default=v,v.STATUS_FLAGS={NONE:0,DATA_URL:1,COMPLETE:2,LOADING:4},v.TYPE={UNKNOWN:0,JSON:1,XML:2,IMAGE:3,AUDIO:4,VIDEO:5,TEXT:6},v.LOAD_TYPE={XHR:1,IMAGE:2,AUDIO:3,VIDEO:4},v.XHR_RESPONSE_TYPE={DEFAULT:\"text\",BUFFER:\"arraybuffer\",BLOB:\"blob\",DOCUMENT:\"document\",JSON:\"json\",TEXT:\"text\"},v._loadTypeMap={gif:v.LOAD_TYPE.IMAGE,png:v.LOAD_TYPE.IMAGE,bmp:v.LOAD_TYPE.IMAGE,jpg:v.LOAD_TYPE.IMAGE,jpeg:v.LOAD_TYPE.IMAGE,tif:v.LOAD_TYPE.IMAGE,tiff:v.LOAD_TYPE.IMAGE,webp:v.LOAD_TYPE.IMAGE,tga:v.LOAD_TYPE.IMAGE,svg:v.LOAD_TYPE.IMAGE,\"svg+xml\":v.LOAD_TYPE.IMAGE,mp3:v.LOAD_TYPE.AUDIO,ogg:v.LOAD_TYPE.AUDIO,wav:v.LOAD_TYPE.AUDIO,mp4:v.LOAD_TYPE.VIDEO,webm:v.LOAD_TYPE.VIDEO},v._xhrTypeMap={xhtml:v.XHR_RESPONSE_TYPE.DOCUMENT,html:v.XHR_RESPONSE_TYPE.DOCUMENT,htm:v.XHR_RESPONSE_TYPE.DOCUMENT,xml:v.XHR_RESPONSE_TYPE.DOCUMENT,tmx:v.XHR_RESPONSE_TYPE.DOCUMENT,svg:v.XHR_RESPONSE_TYPE.DOCUMENT,tsx:v.XHR_RESPONSE_TYPE.DOCUMENT,gif:v.XHR_RESPONSE_TYPE.BLOB,png:v.XHR_RESPONSE_TYPE.BLOB,bmp:v.XHR_RESPONSE_TYPE.BLOB,jpg:v.XHR_RESPONSE_TYPE.BLOB,jpeg:v.XHR_RESPONSE_TYPE.BLOB,tif:v.XHR_RESPONSE_TYPE.BLOB,tiff:v.XHR_RESPONSE_TYPE.BLOB,webp:v.XHR_RESPONSE_TYPE.BLOB,tga:v.XHR_RESPONSE_TYPE.BLOB,json:v.XHR_RESPONSE_TYPE.JSON,text:v.XHR_RESPONSE_TYPE.TEXT,txt:v.XHR_RESPONSE_TYPE.TEXT,ttf:v.XHR_RESPONSE_TYPE.BUFFER,otf:v.XHR_RESPONSE_TYPE.BUFFER},v.EMPTY_GIF=\"data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==\"},{\"mini-signals\":5,\"parse-uri\":7}],34:[function(t,e,r){\"use strict\";function n(){}function i(t,e,r,n){var i=0,o=t.length;!function s(a){if(a||i===o)return void(r&&r(a));n?setTimeout(function(){e(t[i++],s)},1):e(t[i++],s)}()}function o(t){return function(){if(null===t)throw new Error(\"Callback was already called.\");var e=t;t=null,e.apply(this,arguments)}}function s(t,e){function r(t,e,r){if(null!=r&&\"function\"!=typeof r)throw new Error(\"task callback must be a function\");if(a.started=!0,null==t&&a.idle())return void setTimeout(function(){return a.drain()},1);var i={data:t,callback:\"function\"==typeof r?r:n};e?a._tasks.unshift(i):a._tasks.push(i),setTimeout(function(){return a.process()},1)}function i(t){return function(){s-=1,t.callback.apply(t,arguments),null!=arguments[0]&&a.error(arguments[0],t.data),s<=a.concurrency-a.buffer&&a.unsaturated(),a.idle()&&a.drain(),a.process()}}if(null==e)e=1;else if(0===e)throw new Error(\"Concurrency must not be zero\");var s=0,a={_tasks:[],concurrency:e,saturated:n,unsaturated:n,buffer:e/4,empty:n,drain:n,error:n,started:!1,paused:!1,push:function(t,e){r(t,!1,e)},kill:function(){s=0,a.drain=n,a.started=!1,a._tasks=[]},unshift:function(t,e){r(t,!0,e)},process:function(){for(;!a.paused&&s<a.concurrency&&a._tasks.length;){var e=a._tasks.shift();0===a._tasks.length&&a.empty(),s+=1,s===a.concurrency&&a.saturated(),t(e.data,o(i(e)))}},length:function(){return a._tasks.length},running:function(){return s},idle:function(){return a._tasks.length+s===0},pause:function(){!0!==a.paused&&(a.paused=!0)},resume:function(){if(!1!==a.paused){a.paused=!1;for(var t=1;t<=a.concurrency;t++)a.process()}}};return a}r.__esModule=!0,r.eachSeries=i,r.queue=s},{}],35:[function(t,e,r){\"use strict\";function n(t){for(var e=\"\",r=0;r<t.length;){for(var n=[0,0,0],o=[0,0,0,0],s=0;s<n.length;++s)r<t.length?n[s]=255&t.charCodeAt(r++):n[s]=0;o[0]=n[0]>>2,o[1]=(3&n[0])<<4|n[1]>>4,o[2]=(15&n[1])<<2|n[2]>>6,o[3]=63&n[2];switch(r-(t.length-1)){case 2:o[3]=64,o[2]=64;break;case 1:o[3]=64}for(var a=0;a<o.length;++a)e+=i.charAt(o[a])}return e}r.__esModule=!0,r.encodeBinary=n;var i=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\"},{}],36:[function(t,e,r){\"use strict\";var n=t(\"./Loader\").default,i=t(\"./Resource\").default,o=t(\"./async\"),s=t(\"./b64\");n.Resource=i,n.async=o,n.base64=s,e.exports=n,e.exports.default=n},{\"./Loader\":32,\"./Resource\":33,\"./async\":34,\"./b64\":35}],37:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(){return function(t,e){if(!t.data)return void e();if(t.xhr&&t.xhrType===a.default.XHR_RESPONSE_TYPE.BLOB)if(window.Blob&&\"string\"!=typeof t.data){if(0===t.data.type.indexOf(\"image\")){var r=function(){var r=l.createObjectURL(t.data);return t.blob=t.data,t.data=new Image,t.data.src=r,t.type=a.default.TYPE.IMAGE,t.data.onload=function(){l.revokeObjectURL(r),t.data.onload=null,e()},{v:void 0}}();if(\"object\"===(void 0===r?\"undefined\":o(r)))return r.v}}else{var n=t.xhr.getResponseHeader(\"content-type\");if(n&&0===n.indexOf(\"image\"))return t.data=new Image,t.data.src=\"data:\"+n+\";base64,\"+h.default.encodeBinary(t.xhr.responseText),t.type=a.default.TYPE.IMAGE,void(t.data.onload=function(){t.data.onload=null,e()})}e()}}r.__esModule=!0;var o=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&\"function\"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?\"symbol\":typeof t};r.blobMiddlewareFactory=i;var s=t(\"../../Resource\"),a=n(s),u=t(\"../../b64\"),h=n(u),l=window.URL||window.webkitURL},{\"../../Resource\":33,\"../../b64\":35}],38:[function(t,e,r){\"use strict\";function n(){this.protocol=null,this.slashes=null,this.auth=null,this.host=null,this.port=null,this.hostname=null,this.hash=null,this.search=null,this.query=null,this.pathname=null,this.path=null,this.href=null}function i(t,e,r){if(t&&h.isObject(t)&&t instanceof n)return t;var i=new n;return i.parse(t,e,r),i}function o(t){return h.isString(t)&&(t=i(t)),t instanceof n?t.format():n.prototype.format.call(t)}function s(t,e){return i(t,!1,!0).resolve(e)}function a(t,e){return t?i(t,!1,!0).resolveObject(e):e}var u=t(\"punycode\"),h=t(\"./util\");r.parse=i,r.resolve=s,r.resolveObject=a,r.format=o,r.Url=n;var l=/^([a-z0-9.+-]+:)/i,c=/:[0-9]*$/,d=/^(\\/\\/?(?!\\/)[^\\?\\s]*)(\\?[^\\s]*)?$/,f=[\"<\",\">\",'\"',\"`\",\" \",\"\\r\",\"\\n\",\"\\t\"],p=[\"{\",\"}\",\"|\",\"\\\\\",\"^\",\"`\"].concat(f),v=[\"'\"].concat(p),y=[\"%\",\"/\",\"?\",\";\",\"#\"].concat(v),g=[\"/\",\"?\",\"#\"],m=/^[+a-z0-9A-Z_-]{0,63}$/,_=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,b={javascript:!0,\"javascript:\":!0},x={javascript:!0,\"javascript:\":!0},T={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,\"http:\":!0,\"https:\":!0,\"ftp:\":!0,\"gopher:\":!0,\"file:\":!0},w=t(\"querystring\");n.prototype.parse=function(t,e,r){if(!h.isString(t))throw new TypeError(\"Parameter 'url' must be a string, not \"+typeof t);var n=t.indexOf(\"?\"),i=-1!==n&&n<t.indexOf(\"#\")?\"?\":\"#\",o=t.split(i),s=/\\\\/g;o[0]=o[0].replace(s,\"/\"),t=o.join(i);var a=t;if(a=a.trim(),!r&&1===t.split(\"#\").length){var c=d.exec(a);if(c)return this.path=a,this.href=a,this.pathname=c[1],c[2]?(this.search=c[2],this.query=e?w.parse(this.search.substr(1)):this.search.substr(1)):e&&(this.search=\"\",this.query={}),this}var f=l.exec(a);if(f){f=f[0];var p=f.toLowerCase();this.protocol=p,a=a.substr(f.length)}if(r||f||a.match(/^\\/\\/[^@\\/]+@[^@\\/]+/)){var E=\"//\"===a.substr(0,2);!E||f&&x[f]||(a=a.substr(2),this.slashes=!0)}if(!x[f]&&(E||f&&!T[f])){for(var S=-1,O=0;O<g.length;O++){var M=a.indexOf(g[O]);-1!==M&&(-1===S||M<S)&&(S=M)}var P,C;C=-1===S?a.lastIndexOf(\"@\"):a.lastIndexOf(\"@\",S),-1!==C&&(P=a.slice(0,C),a=a.slice(C+1),this.auth=decodeURIComponent(P)),S=-1;for(var O=0;O<y.length;O++){var M=a.indexOf(y[O]);-1!==M&&(-1===S||M<S)&&(S=M)}-1===S&&(S=a.length),this.host=a.slice(0,S),a=a.slice(S),this.parseHost(),this.hostname=this.hostname||\"\";var R=\"[\"===this.hostname[0]&&\"]\"===this.hostname[this.hostname.length-1];if(!R)for(var A=this.hostname.split(/\\./),O=0,I=A.length;O<I;O++){var D=A[O];if(D&&!D.match(m)){for(var L=\"\",N=0,F=D.length;N<F;N++)D.charCodeAt(N)>127?L+=\"x\":L+=D[N];if(!L.match(m)){var B=A.slice(0,O),k=A.slice(O+1),j=D.match(_);j&&(B.push(j[1]),k.unshift(j[2])),k.length&&(a=\"/\"+k.join(\".\")+a),this.hostname=B.join(\".\");break}}}this.hostname.length>255?this.hostname=\"\":this.hostname=this.hostname.toLowerCase(),R||(this.hostname=u.toASCII(this.hostname));var U=this.port?\":\"+this.port:\"\",X=this.hostname||\"\";this.host=X+U,this.href+=this.host,R&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),\"/\"!==a[0]&&(a=\"/\"+a))}if(!b[p])for(var O=0,I=v.length;O<I;O++){var G=v[O];if(-1!==a.indexOf(G)){var W=encodeURIComponent(G);W===G&&(W=escape(G)),a=a.split(G).join(W)}}var H=a.indexOf(\"#\");-1!==H&&(this.hash=a.substr(H),a=a.slice(0,H));var Y=a.indexOf(\"?\");if(-1!==Y?(this.search=a.substr(Y),this.query=a.substr(Y+1),e&&(this.query=w.parse(this.query)),a=a.slice(0,Y)):e&&(this.search=\"\",this.query={}),a&&(this.pathname=a),T[p]&&this.hostname&&!this.pathname&&(this.pathname=\"/\"),this.pathname||this.search){var U=this.pathname||\"\",V=this.search||\"\";this.path=U+V}return this.href=this.format(),this},n.prototype.format=function(){var t=this.auth||\"\";t&&(t=encodeURIComponent(t),t=t.replace(/%3A/i,\":\"),t+=\"@\");var e=this.protocol||\"\",r=this.pathname||\"\",n=this.hash||\"\",i=!1,o=\"\";this.host?i=t+this.host:this.hostname&&(i=t+(-1===this.hostname.indexOf(\":\")?this.hostname:\"[\"+this.hostname+\"]\"),this.port&&(i+=\":\"+this.port)),this.query&&h.isObject(this.query)&&Object.keys(this.query).length&&(o=w.stringify(this.query));var s=this.search||o&&\"?\"+o||\"\";return e&&\":\"!==e.substr(-1)&&(e+=\":\"),this.slashes||(!e||T[e])&&!1!==i?(i=\"//\"+(i||\"\"),r&&\"/\"!==r.charAt(0)&&(r=\"/\"+r)):i||(i=\"\"),n&&\"#\"!==n.charAt(0)&&(n=\"#\"+n),s&&\"?\"!==s.charAt(0)&&(s=\"?\"+s),r=r.replace(/[?#]/g,function(t){\nreturn encodeURIComponent(t)}),s=s.replace(\"#\",\"%23\"),e+i+r+s+n},n.prototype.resolve=function(t){return this.resolveObject(i(t,!1,!0)).format()},n.prototype.resolveObject=function(t){if(h.isString(t)){var e=new n;e.parse(t,!1,!0),t=e}for(var r=new n,i=Object.keys(this),o=0;o<i.length;o++){var s=i[o];r[s]=this[s]}if(r.hash=t.hash,\"\"===t.href)return r.href=r.format(),r;if(t.slashes&&!t.protocol){for(var a=Object.keys(t),u=0;u<a.length;u++){var l=a[u];\"protocol\"!==l&&(r[l]=t[l])}return T[r.protocol]&&r.hostname&&!r.pathname&&(r.path=r.pathname=\"/\"),r.href=r.format(),r}if(t.protocol&&t.protocol!==r.protocol){if(!T[t.protocol]){for(var c=Object.keys(t),d=0;d<c.length;d++){var f=c[d];r[f]=t[f]}return r.href=r.format(),r}if(r.protocol=t.protocol,t.host||x[t.protocol])r.pathname=t.pathname;else{for(var p=(t.pathname||\"\").split(\"/\");p.length&&!(t.host=p.shift()););t.host||(t.host=\"\"),t.hostname||(t.hostname=\"\"),\"\"!==p[0]&&p.unshift(\"\"),p.length<2&&p.unshift(\"\"),r.pathname=p.join(\"/\")}if(r.search=t.search,r.query=t.query,r.host=t.host||\"\",r.auth=t.auth,r.hostname=t.hostname||t.host,r.port=t.port,r.pathname||r.search){var v=r.pathname||\"\",y=r.search||\"\";r.path=v+y}return r.slashes=r.slashes||t.slashes,r.href=r.format(),r}var g=r.pathname&&\"/\"===r.pathname.charAt(0),m=t.host||t.pathname&&\"/\"===t.pathname.charAt(0),_=m||g||r.host&&t.pathname,b=_,w=r.pathname&&r.pathname.split(\"/\")||[],p=t.pathname&&t.pathname.split(\"/\")||[],E=r.protocol&&!T[r.protocol];if(E&&(r.hostname=\"\",r.port=null,r.host&&(\"\"===w[0]?w[0]=r.host:w.unshift(r.host)),r.host=\"\",t.protocol&&(t.hostname=null,t.port=null,t.host&&(\"\"===p[0]?p[0]=t.host:p.unshift(t.host)),t.host=null),_=_&&(\"\"===p[0]||\"\"===w[0])),m)r.host=t.host||\"\"===t.host?t.host:r.host,r.hostname=t.hostname||\"\"===t.hostname?t.hostname:r.hostname,r.search=t.search,r.query=t.query,w=p;else if(p.length)w||(w=[]),w.pop(),w=w.concat(p),r.search=t.search,r.query=t.query;else if(!h.isNullOrUndefined(t.search)){if(E){r.hostname=r.host=w.shift();var S=!!(r.host&&r.host.indexOf(\"@\")>0)&&r.host.split(\"@\");S&&(r.auth=S.shift(),r.host=r.hostname=S.shift())}return r.search=t.search,r.query=t.query,h.isNull(r.pathname)&&h.isNull(r.search)||(r.path=(r.pathname?r.pathname:\"\")+(r.search?r.search:\"\")),r.href=r.format(),r}if(!w.length)return r.pathname=null,r.search?r.path=\"/\"+r.search:r.path=null,r.href=r.format(),r;for(var O=w.slice(-1)[0],M=(r.host||t.host||w.length>1)&&(\".\"===O||\"..\"===O)||\"\"===O,P=0,C=w.length;C>=0;C--)O=w[C],\".\"===O?w.splice(C,1):\"..\"===O?(w.splice(C,1),P++):P&&(w.splice(C,1),P--);if(!_&&!b)for(;P--;P)w.unshift(\"..\");!_||\"\"===w[0]||w[0]&&\"/\"===w[0].charAt(0)||w.unshift(\"\"),M&&\"/\"!==w.join(\"/\").substr(-1)&&w.push(\"\");var R=\"\"===w[0]||w[0]&&\"/\"===w[0].charAt(0);if(E){r.hostname=r.host=R?\"\":w.length?w.shift():\"\";var S=!!(r.host&&r.host.indexOf(\"@\")>0)&&r.host.split(\"@\");S&&(r.auth=S.shift(),r.host=r.hostname=S.shift())}return _=_||r.host&&w.length,_&&!R&&w.unshift(\"\"),w.length?r.pathname=w.join(\"/\"):(r.pathname=null,r.path=null),h.isNull(r.pathname)&&h.isNull(r.search)||(r.path=(r.pathname?r.pathname:\"\")+(r.search?r.search:\"\")),r.auth=t.auth||r.auth,r.slashes=r.slashes||t.slashes,r.href=r.format(),r},n.prototype.parseHost=function(){var t=this.host,e=c.exec(t);e&&(e=e[0],\":\"!==e&&(this.port=e.substr(1)),t=t.substr(0,t.length-e.length)),t&&(this.hostname=t)}},{\"./util\":39,punycode:27,querystring:30}],39:[function(t,e,r){\"use strict\";e.exports={isString:function(t){return\"string\"==typeof t},isObject:function(t){return\"object\"==typeof t&&null!==t},isNull:function(t){return null===t},isNullOrUndefined:function(t){return null==t}}},{}],40:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var o=t(\"../core\"),s=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(o),a=t(\"ismobilejs\"),u=n(a),h=t(\"./accessibleTarget\"),l=n(h);s.utils.mixins.delayMixin(s.DisplayObject.prototype,l.default);var c=100,d=0,f=0,p=2,v=function(){function t(e){i(this,t),!u.default.tablet&&!u.default.phone||navigator.isCocoonJS||this.createTouchHook();var r=document.createElement(\"div\");r.style.width=c+\"px\",r.style.height=c+\"px\",r.style.position=\"absolute\",r.style.top=d+\"px\",r.style.left=f+\"px\",r.style.zIndex=p,this.div=r,this.pool=[],this.renderId=0,this.debug=!1,this.renderer=e,this.children=[],this._onKeyDown=this._onKeyDown.bind(this),this._onMouseMove=this._onMouseMove.bind(this),this.isActive=!1,this.isMobileAccessabillity=!1,window.addEventListener(\"keydown\",this._onKeyDown,!1)}return t.prototype.createTouchHook=function(){var t=this,e=document.createElement(\"button\");e.style.width=\"1px\",e.style.height=\"1px\",e.style.position=\"absolute\",e.style.top=\"-1000px\",e.style.left=\"-1000px\",e.style.zIndex=2,e.style.backgroundColor=\"#FF0000\",e.title=\"HOOK DIV\",e.addEventListener(\"focus\",function(){t.isMobileAccessabillity=!0,t.activate(),document.body.removeChild(e)}),document.body.appendChild(e)},t.prototype.activate=function(){this.isActive||(this.isActive=!0,window.document.addEventListener(\"mousemove\",this._onMouseMove,!0),window.removeEventListener(\"keydown\",this._onKeyDown,!1),this.renderer.on(\"postrender\",this.update,this),this.renderer.view.parentNode&&this.renderer.view.parentNode.appendChild(this.div))},t.prototype.deactivate=function(){this.isActive&&!this.isMobileAccessabillity&&(this.isActive=!1,window.document.removeEventListener(\"mousemove\",this._onMouseMove),window.addEventListener(\"keydown\",this._onKeyDown,!1),this.renderer.off(\"postrender\",this.update),this.div.parentNode&&this.div.parentNode.removeChild(this.div))},t.prototype.updateAccessibleObjects=function(t){if(t.visible){t.accessible&&t.interactive&&(t._accessibleActive||this.addChild(t),t.renderId=this.renderId);for(var e=t.children,r=e.length-1;r>=0;r--)this.updateAccessibleObjects(e[r])}},t.prototype.update=function(){if(this.renderer.renderingToScreen){this.updateAccessibleObjects(this.renderer._lastObjectRendered);var t=this.renderer.view.getBoundingClientRect(),e=t.width/this.renderer.width,r=t.height/this.renderer.height,n=this.div;n.style.left=t.left+\"px\",n.style.top=t.top+\"px\",n.style.width=this.renderer.width+\"px\",n.style.height=this.renderer.height+\"px\";for(var i=0;i<this.children.length;i++){var o=this.children[i];if(o.renderId!==this.renderId)o._accessibleActive=!1,s.utils.removeItems(this.children,i,1),this.div.removeChild(o._accessibleDiv),this.pool.push(o._accessibleDiv),o._accessibleDiv=null,i--,0===this.children.length&&this.deactivate();else{n=o._accessibleDiv;var a=o.hitArea,u=o.worldTransform;o.hitArea?(n.style.left=(u.tx+a.x*u.a)*e+\"px\",n.style.top=(u.ty+a.y*u.d)*r+\"px\",n.style.width=a.width*u.a*e+\"px\",n.style.height=a.height*u.d*r+\"px\"):(a=o.getBounds(),this.capHitArea(a),n.style.left=a.x*e+\"px\",n.style.top=a.y*r+\"px\",n.style.width=a.width*e+\"px\",n.style.height=a.height*r+\"px\")}}this.renderId++}},t.prototype.capHitArea=function(t){t.x<0&&(t.width+=t.x,t.x=0),t.y<0&&(t.height+=t.y,t.y=0),t.x+t.width>this.renderer.width&&(t.width=this.renderer.width-t.x),t.y+t.height>this.renderer.height&&(t.height=this.renderer.height-t.y)},t.prototype.addChild=function(t){var e=this.pool.pop();e||(e=document.createElement(\"button\"),e.style.width=c+\"px\",e.style.height=c+\"px\",e.style.backgroundColor=this.debug?\"rgba(255,0,0,0.5)\":\"transparent\",e.style.position=\"absolute\",e.style.zIndex=p,e.style.borderStyle=\"none\",e.addEventListener(\"click\",this._onClick.bind(this)),e.addEventListener(\"focus\",this._onFocus.bind(this)),e.addEventListener(\"focusout\",this._onFocusOut.bind(this))),t.accessibleTitle?e.title=t.accessibleTitle:t.accessibleTitle||t.accessibleHint||(e.title=\"displayObject \"+this.tabIndex),t.accessibleHint&&e.setAttribute(\"aria-label\",t.accessibleHint),t._accessibleActive=!0,t._accessibleDiv=e,e.displayObject=t,this.children.push(t),this.div.appendChild(t._accessibleDiv),t._accessibleDiv.tabIndex=t.tabIndex},t.prototype._onClick=function(t){var e=this.renderer.plugins.interaction;e.dispatchEvent(t.target.displayObject,\"click\",e.eventData)},t.prototype._onFocus=function(t){var e=this.renderer.plugins.interaction;e.dispatchEvent(t.target.displayObject,\"mouseover\",e.eventData)},t.prototype._onFocusOut=function(t){var e=this.renderer.plugins.interaction;e.dispatchEvent(t.target.displayObject,\"mouseout\",e.eventData)},t.prototype._onKeyDown=function(t){9===t.keyCode&&this.activate()},t.prototype._onMouseMove=function(){this.deactivate()},t.prototype.destroy=function(){this.div=null;for(var t=0;t<this.children.length;t++)this.children[t].div=null;window.document.removeEventListener(\"mousemove\",this._onMouseMove),window.removeEventListener(\"keydown\",this._onKeyDown),this.pool=null,this.children=null,this.renderer=null},t}();r.default=v,s.WebGLRenderer.registerPlugin(\"accessibility\",v),s.CanvasRenderer.registerPlugin(\"accessibility\",v)},{\"../core\":65,\"./accessibleTarget\":41,ismobilejs:4}],41:[function(t,e,r){\"use strict\";r.__esModule=!0,r.default={accessible:!1,accessibleTitle:null,accessibleHint:null,tabIndex:0,_accessibleActive:!1,_accessibleDiv:!1}},{}],42:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0;var i=t(\"./accessibleTarget\");Object.defineProperty(r,\"accessibleTarget\",{enumerable:!0,get:function(){return n(i).default}});var o=t(\"./AccessibilityManager\");Object.defineProperty(r,\"AccessibilityManager\",{enumerable:!0,get:function(){return n(o).default}})},{\"./AccessibilityManager\":40,\"./accessibleTarget\":41}],43:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var o=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),s=t(\"./autoDetectRenderer\"),a=t(\"./display/Container\"),u=n(a),h=t(\"./ticker\"),l=t(\"./settings\"),c=n(l),d=t(\"./const\"),f=function(){function t(e,r,n,o,a){i(this,t),\"number\"==typeof e&&(e=Object.assign({width:e,height:r||c.default.RENDER_OPTIONS.height,forceCanvas:!!o,sharedTicker:!!a},n)),this._options=e=Object.assign({autoStart:!0,sharedTicker:!1,forceCanvas:!1,sharedLoader:!1},e),this.renderer=(0,s.autoDetectRenderer)(e),this.stage=new u.default,this._ticker=null,this.ticker=e.sharedTicker?h.shared:new h.Ticker,e.autoStart&&this.start()}return t.prototype.render=function(){this.renderer.render(this.stage)},t.prototype.stop=function(){this._ticker.stop()},t.prototype.start=function(){this._ticker.start()},t.prototype.destroy=function(t){var e=this._ticker;this.ticker=null,e.destroy(),this.stage.destroy(),this.stage=null,this.renderer.destroy(t),this.renderer=null,this._options=null},o(t,[{key:\"ticker\",set:function(t){this._ticker&&this._ticker.remove(this.render,this),this._ticker=t,t&&t.add(this.render,this,d.UPDATE_PRIORITY.LOW)},get:function(){return this._ticker}},{key:\"view\",get:function(){return this.renderer.view}},{key:\"screen\",get:function(){return this.renderer.screen}}]),t}();r.default=f},{\"./autoDetectRenderer\":45,\"./const\":46,\"./display/Container\":48,\"./settings\":101,\"./ticker\":120}],44:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function s(t,e){if(t instanceof Array){if(\"precision\"!==t[0].substring(0,9)){var r=t.slice(0);return r.unshift(\"precision \"+e+\" float;\"),r}}else if(\"precision\"!==t.substring(0,9))return\"precision \"+e+\" float;\\n\"+t;return t}r.__esModule=!0;var a=t(\"pixi-gl-core\"),u=t(\"./settings\"),h=function(t){return t&&t.__esModule?t:{default:t}}(u),l=function(t){function e(r,o,a){return n(this,e),i(this,t.call(this,r,s(o,h.default.PRECISION_VERTEX),s(a,h.default.PRECISION_FRAGMENT)))}return o(e,t),e}(a.GLShader);r.default=l},{\"./settings\":101,\"pixi-gl-core\":15}],45:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e,r,n){var i=t&&t.forceCanvas;return void 0!==n&&(i=n),!i&&s.isWebGLSupported()?new l.default(t,e,r):new u.default(t,e,r)}r.__esModule=!0,r.autoDetectRenderer=i;var o=t(\"./utils\"),s=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(o),a=t(\"./renderers/canvas/CanvasRenderer\"),u=n(a),h=t(\"./renderers/webgl/WebGLRenderer\"),l=n(h)},{\"./renderers/canvas/CanvasRenderer\":77,\"./renderers/webgl/WebGLRenderer\":84,\"./utils\":124}],46:[function(t,e,r){\"use strict\";r.__esModule=!0;r.VERSION=\"4.5.6\",r.PI_2=2*Math.PI,r.RAD_TO_DEG=180/Math.PI,r.DEG_TO_RAD=Math.PI/180,r.RENDERER_TYPE={UNKNOWN:0,WEBGL:1,CANVAS:2},r.BLEND_MODES={NORMAL:0,ADD:1,MULTIPLY:2,SCREEN:3,OVERLAY:4,DARKEN:5,LIGHTEN:6,COLOR_DODGE:7,COLOR_BURN:8,HARD_LIGHT:9,SOFT_LIGHT:10,DIFFERENCE:11,EXCLUSION:12,HUE:13,SATURATION:14,COLOR:15,LUMINOSITY:16,NORMAL_NPM:17,ADD_NPM:18,SCREEN_NPM:19},r.DRAW_MODES={POINTS:0,LINES:1,LINE_LOOP:2,LINE_STRIP:3,TRIANGLES:4,TRIANGLE_STRIP:5,TRIANGLE_FAN:6},r.SCALE_MODES={LINEAR:0,NEAREST:1},r.WRAP_MODES={CLAMP:0,REPEAT:1,MIRRORED_REPEAT:2},r.GC_MODES={AUTO:0,MANUAL:1},r.URL_FILE_EXTENSION=/\\.(\\w{3,4})(?:$|\\?|#)/i,r.DATA_URI=/^\\s*data:(?:([\\w-]+)\\/([\\w+.-]+))?(?:;(charset=[\\w-]+|base64))?,(.*)/i,r.SVG_SIZE=/<svg[^>]*(?:\\s(width|height)=('|\")(\\d*(?:\\.\\d+)?)(?:px)?('|\"))[^>]*(?:\\s(width|height)=('|\")(\\d*(?:\\.\\d+)?)(?:px)?('|\"))[^>]*>/i,r.SHAPES={POLY:0,RECT:1,CIRC:2,ELIP:3,RREC:4},r.PRECISION={LOW:\"lowp\",MEDIUM:\"mediump\",HIGH:\"highp\"},r.TRANSFORM_MODE={STATIC:0,DYNAMIC:1},r.TEXT_GRADIENT={LINEAR_VERTICAL:0,LINEAR_HORIZONTAL:1},r.UPDATE_PRIORITY={INTERACTION:50,HIGH:25,NORMAL:0,LOW:-25,UTILITY:-50}},{}],47:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../math\"),o=function(){function t(){n(this,t),this.minX=1/0,this.minY=1/0,this.maxX=-1/0,this.maxY=-1/0,this.rect=null}return t.prototype.isEmpty=function(){return this.minX>this.maxX||this.minY>this.maxY},t.prototype.clear=function(){this.updateID++,this.minX=1/0,this.minY=1/0,this.maxX=-1/0,this.maxY=-1/0},t.prototype.getRectangle=function(t){return this.minX>this.maxX||this.minY>this.maxY?i.Rectangle.EMPTY:(t=t||new i.Rectangle(0,0,1,1),t.x=this.minX,t.y=this.minY,t.width=this.maxX-this.minX,t.height=this.maxY-this.minY,t)},t.prototype.addPoint=function(t){this.minX=Math.min(this.minX,t.x),this.maxX=Math.max(this.maxX,t.x),this.minY=Math.min(this.minY,t.y),this.maxY=Math.max(this.maxY,t.y)},t.prototype.addQuad=function(t){var e=this.minX,r=this.minY,n=this.maxX,i=this.maxY,o=t[0],s=t[1];e=o<e?o:e,r=s<r?s:r,n=o>n?o:n,i=s>i?s:i,o=t[2],s=t[3],e=o<e?o:e,r=s<r?s:r,n=o>n?o:n,i=s>i?s:i,o=t[4],s=t[5],e=o<e?o:e,r=s<r?s:r,n=o>n?o:n,i=s>i?s:i,o=t[6],s=t[7],e=o<e?o:e,r=s<r?s:r,n=o>n?o:n,i=s>i?s:i,this.minX=e,this.minY=r,this.maxX=n,this.maxY=i},t.prototype.addFrame=function(t,e,r,n,i){var o=t.worldTransform,s=o.a,a=o.b,u=o.c,h=o.d,l=o.tx,c=o.ty,d=this.minX,f=this.minY,p=this.maxX,v=this.maxY,y=s*e+u*r+l,g=a*e+h*r+c;d=y<d?y:d,f=g<f?g:f,p=y>p?y:p,v=g>v?g:v,y=s*n+u*r+l,g=a*n+h*r+c,d=y<d?y:d,f=g<f?g:f,p=y>p?y:p,v=g>v?g:v,y=s*e+u*i+l,g=a*e+h*i+c,d=y<d?y:d,f=g<f?g:f,p=y>p?y:p,v=g>v?g:v,y=s*n+u*i+l,g=a*n+h*i+c,d=y<d?y:d,f=g<f?g:f,p=y>p?y:p,v=g>v?g:v,this.minX=d,this.minY=f,this.maxX=p,this.maxY=v},t.prototype.addVertices=function(t,e,r,n){for(var i=t.worldTransform,o=i.a,s=i.b,a=i.c,u=i.d,h=i.tx,l=i.ty,c=this.minX,d=this.minY,f=this.maxX,p=this.maxY,v=r;v<n;v+=2){var y=e[v],g=e[v+1],m=o*y+a*g+h,_=u*g+s*y+l;c=m<c?m:c,d=_<d?_:d,f=m>f?m:f,p=_>p?_:p}this.minX=c,this.minY=d,this.maxX=f,this.maxY=p},t.prototype.addBounds=function(t){var e=this.minX,r=this.minY,n=this.maxX,i=this.maxY;this.minX=t.minX<e?t.minX:e,this.minY=t.minY<r?t.minY:r,this.maxX=t.maxX>n?t.maxX:n,this.maxY=t.maxY>i?t.maxY:i},t.prototype.addBoundsMask=function(t,e){var r=t.minX>e.minX?t.minX:e.minX,n=t.minY>e.minY?t.minY:e.minY,i=t.maxX<e.maxX?t.maxX:e.maxX,o=t.maxY<e.maxY?t.maxY:e.maxY;if(r<=i&&n<=o){var s=this.minX,a=this.minY,u=this.maxX,h=this.maxY;this.minX=r<s?r:s,this.minY=n<a?n:a,this.maxX=i>u?i:u,this.maxY=o>h?o:h}},t.prototype.addBoundsArea=function(t,e){var r=t.minX>e.x?t.minX:e.x,n=t.minY>e.y?t.minY:e.y,i=t.maxX<e.x+e.width?t.maxX:e.x+e.width,o=t.maxY<e.y+e.height?t.maxY:e.y+e.height;if(r<=i&&n<=o){var s=this.minX,a=this.minY,u=this.maxX,h=this.maxY;this.minX=r<s?r:s,this.minY=n<a?n:a,this.maxX=i>u?i:u,this.maxY=o>h?o:h}},t}();r.default=o},{\"../math\":70}],48:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"../utils\"),u=t(\"./DisplayObject\"),h=function(t){return t&&t.__esModule?t:{default:t}}(u),l=function(t){function e(){n(this,e);var r=i(this,t.call(this));return r.children=[],r}return o(e,t),e.prototype.onChildrenChange=function(){},e.prototype.addChild=function(t){var e=arguments.length;if(e>1)for(var r=0;r<e;r++)this.addChild(arguments[r]);else t.parent&&t.parent.removeChild(t),t.parent=this,t.transform._parentID=-1,this.children.push(t),this._boundsID++,this.onChildrenChange(this.children.length-1),t.emit(\"added\",this);return t},e.prototype.addChildAt=function(t,e){if(e<0||e>this.children.length)throw new Error(t+\"addChildAt: The index \"+e+\" supplied is out of bounds \"+this.children.length);return t.parent&&t.parent.removeChild(t),t.parent=this,t.transform._parentID=-1,this.children.splice(e,0,t),this._boundsID++,this.onChildrenChange(e),t.emit(\"added\",this),t},e.prototype.swapChildren=function(t,e){if(t!==e){var r=this.getChildIndex(t),n=this.getChildIndex(e);this.children[r]=e,this.children[n]=t,this.onChildrenChange(r<n?r:n)}},e.prototype.getChildIndex=function(t){var e=this.children.indexOf(t);if(-1===e)throw new Error(\"The supplied DisplayObject must be a child of the caller\");return e},e.prototype.setChildIndex=function(t,e){if(e<0||e>=this.children.length)throw new Error(\"The supplied index is out of bounds\");var r=this.getChildIndex(t);(0,a.removeItems)(this.children,r,1),this.children.splice(e,0,t),this.onChildrenChange(e)},e.prototype.getChildAt=function(t){if(t<0||t>=this.children.length)throw new Error(\"getChildAt: Index (\"+t+\") does not exist.\");return this.children[t]},e.prototype.removeChild=function(t){var e=arguments.length;if(e>1)for(var r=0;r<e;r++)this.removeChild(arguments[r]);else{var n=this.children.indexOf(t);if(-1===n)return null;t.parent=null,t.transform._parentID=-1,(0,a.removeItems)(this.children,n,1),this._boundsID++,this.onChildrenChange(n),t.emit(\"removed\",this)}return t},e.prototype.removeChildAt=function(t){var e=this.getChildAt(t);return e.parent=null,e.transform._parentID=-1,(0,a.removeItems)(this.children,t,1),this._boundsID++,this.onChildrenChange(t),e.emit(\"removed\",this),e},e.prototype.removeChildren=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments[1],r=t,n=\"number\"==typeof e?e:this.children.length,i=n-r,o=void 0;if(i>0&&i<=n){o=this.children.splice(r,i);for(var s=0;s<o.length;++s)o[s].parent=null,o[s].transform&&(o[s].transform._parentID=-1);this._boundsID++,this.onChildrenChange(t);for(var a=0;a<o.length;++a)o[a].emit(\"removed\",this);return o}if(0===i&&0===this.children.length)return[];throw new RangeError(\"removeChildren: numeric values are outside the acceptable range.\")},e.prototype.updateTransform=function(){this._boundsID++,this.transform.updateTransform(this.parent.transform),this.worldAlpha=this.alpha*this.parent.worldAlpha;for(var t=0,e=this.children.length;t<e;++t){var r=this.children[t];r.visible&&r.updateTransform()}},e.prototype.calculateBounds=function(){this._bounds.clear(),this._calculateBounds();for(var t=0;t<this.children.length;t++){var e=this.children[t];e.visible&&e.renderable&&(e.calculateBounds(),e._mask?(e._mask.calculateBounds(),this._bounds.addBoundsMask(e._bounds,e._mask._bounds)):e.filterArea?this._bounds.addBoundsArea(e._bounds,e.filterArea):this._bounds.addBounds(e._bounds))}this._lastBoundsID=this._boundsID},e.prototype._calculateBounds=function(){},e.prototype.renderWebGL=function(t){if(this.visible&&!(this.worldAlpha<=0)&&this.renderable)if(this._mask||this._filters)this.renderAdvancedWebGL(t);else{this._renderWebGL(t);for(var e=0,r=this.children.length;e<r;++e)this.children[e].renderWebGL(t)}},e.prototype.renderAdvancedWebGL=function(t){t.flush();var e=this._filters,r=this._mask;if(e){this._enabledFilters||(this._enabledFilters=[]),this._enabledFilters.length=0;for(var n=0;n<e.length;n++)e[n].enabled&&this._enabledFilters.push(e[n]);this._enabledFilters.length&&t.filterManager.pushFilter(this,this._enabledFilters)}r&&t.maskManager.pushMask(this,this._mask),this._renderWebGL(t);for(var i=0,o=this.children.length;i<o;i++)this.children[i].renderWebGL(t);t.flush(),r&&t.maskManager.popMask(this,this._mask),e&&this._enabledFilters&&this._enabledFilters.length&&t.filterManager.popFilter()},e.prototype._renderWebGL=function(t){},e.prototype._renderCanvas=function(t){},e.prototype.renderCanvas=function(t){if(this.visible&&!(this.worldAlpha<=0)&&this.renderable){this._mask&&t.maskManager.pushMask(this._mask),this._renderCanvas(t);for(var e=0,r=this.children.length;e<r;++e)this.children[e].renderCanvas(t);this._mask&&t.maskManager.popMask(t)}},e.prototype.destroy=function(e){t.prototype.destroy.call(this);var r=\"boolean\"==typeof e?e:e&&e.children,n=this.removeChildren(0,this.children.length);if(r)for(var i=0;i<n.length;++i)n[i].destroy(e)},s(e,[{key:\"width\",get:function(){return this.scale.x*this.getLocalBounds().width},set:function(t){var e=this.getLocalBounds().width;this.scale.x=0!==e?t/e:1,this._width=t}},{key:\"height\",get:function(){return this.scale.y*this.getLocalBounds().height},set:function(t){var e=this.getLocalBounds().height;this.scale.y=0!==e?t/e:1,this._height=t}}]),e}(h.default);r.default=l,l.prototype.containerUpdateTransform=l.prototype.updateTransform},{\"../utils\":124,\"./DisplayObject\":49}],49:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),u=t(\"eventemitter3\"),h=n(u),l=t(\"../const\"),c=t(\"../settings\"),d=n(c),f=t(\"./TransformStatic\"),p=n(f),v=t(\"./Transform\"),y=n(v),g=t(\"./Bounds\"),m=n(g),_=t(\"../math\"),b=function(t){function e(){i(this,e);var r=o(this,t.call(this)),n=d.default.TRANSFORM_MODE===l.TRANSFORM_MODE.STATIC?p.default:y.default;return r.tempDisplayObjectParent=null,r.transform=new n,r.alpha=1,r.visible=!0,r.renderable=!0,r.parent=null,r.worldAlpha=1,r.filterArea=null,r._filters=null,r._enabledFilters=null,r._bounds=new m.default,r._boundsID=0,r._lastBoundsID=-1,r._boundsRect=null,r._localBoundsRect=null,r._mask=null,r._destroyed=!1,r}return s(e,t),e.prototype.updateTransform=function(){this.transform.updateTransform(this.parent.transform),this.worldAlpha=this.alpha*this.parent.worldAlpha,this._bounds.updateID++},e.prototype._recursivePostUpdateTransform=function(){this.parent?(this.parent._recursivePostUpdateTransform(),this.transform.updateTransform(this.parent.transform)):this.transform.updateTransform(this._tempDisplayObjectParent.transform)},e.prototype.getBounds=function(t,e){return t||(this.parent?(this._recursivePostUpdateTransform(),this.updateTransform()):(this.parent=this._tempDisplayObjectParent,this.updateTransform(),this.parent=null)),this._boundsID!==this._lastBoundsID&&this.calculateBounds(),e||(this._boundsRect||(this._boundsRect=new _.Rectangle),e=this._boundsRect),this._bounds.getRectangle(e)},e.prototype.getLocalBounds=function(t){var e=this.transform,r=this.parent;this.parent=null,this.transform=this._tempDisplayObjectParent.transform,t||(this._localBoundsRect||(this._localBoundsRect=new _.Rectangle),t=this._localBoundsRect);var n=this.getBounds(!1,t);return this.parent=r,this.transform=e,n},e.prototype.toGlobal=function(t,e){return arguments.length>2&&void 0!==arguments[2]&&arguments[2]||(this._recursivePostUpdateTransform(),this.parent?this.displayObjectUpdateTransform():(this.parent=this._tempDisplayObjectParent,this.displayObjectUpdateTransform(),this.parent=null)),this.worldTransform.apply(t,e)},e.prototype.toLocal=function(t,e,r,n){return e&&(t=e.toGlobal(t,r,n)),n||(this._recursivePostUpdateTransform(),this.parent?this.displayObjectUpdateTransform():(this.parent=this._tempDisplayObjectParent,this.displayObjectUpdateTransform(),this.parent=null)),this.worldTransform.applyInverse(t,r)},e.prototype.renderWebGL=function(t){},e.prototype.renderCanvas=function(t){},e.prototype.setParent=function(t){if(!t||!t.addChild)throw new Error(\"setParent: Argument must be a Container\");return t.addChild(this),t},e.prototype.setTransform=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:1,i=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,o=arguments.length>5&&void 0!==arguments[5]?arguments[5]:0,s=arguments.length>6&&void 0!==arguments[6]?arguments[6]:0,a=arguments.length>7&&void 0!==arguments[7]?arguments[7]:0,u=arguments.length>8&&void 0!==arguments[8]?arguments[8]:0;return this.position.x=t,this.position.y=e,this.scale.x=r||1,this.scale.y=n||1,this.rotation=i,this.skew.x=o,this.skew.y=s,this.pivot.x=a,this.pivot.y=u,this},e.prototype.destroy=function(){this.removeAllListeners(),this.parent&&this.parent.removeChild(this),this.transform=null,this.parent=null,this._bounds=null,this._currentBounds=null,this._mask=null,this.filterArea=null,this.interactive=!1,this.interactiveChildren=!1,this._destroyed=!0},a(e,[{key:\"_tempDisplayObjectParent\",get:function(){return null===this.tempDisplayObjectParent&&(this.tempDisplayObjectParent=new e),this.tempDisplayObjectParent}},{key:\"x\",get:function(){return this.position.x},set:function(t){this.transform.position.x=t}},{key:\"y\",get:function(){return this.position.y},set:function(t){this.transform.position.y=t}},{key:\"worldTransform\",get:function(){return this.transform.worldTransform}},{key:\"localTransform\",get:function(){return this.transform.localTransform}},{key:\"position\",get:function(){return this.transform.position},set:function(t){this.transform.position.copy(t)}},{key:\"scale\",get:function(){return this.transform.scale},set:function(t){this.transform.scale.copy(t)}},{key:\"pivot\",get:function(){return this.transform.pivot},set:function(t){this.transform.pivot.copy(t)}},{key:\"skew\",get:function(){return this.transform.skew},set:function(t){this.transform.skew.copy(t)}},{key:\"rotation\",get:function(){return this.transform.rotation},set:function(t){this.transform.rotation=t}},{key:\"worldVisible\",get:function(){var t=this;do{if(!t.visible)return!1;t=t.parent}while(t);return!0}},{key:\"mask\",get:function(){return this._mask},set:function(t){this._mask&&(this._mask.renderable=!0),this._mask=t,this._mask&&(this._mask.renderable=!1)}},{key:\"filters\",get:function(){return this._filters&&this._filters.slice()},set:function(t){this._filters=t&&t.slice()}}]),e}(h.default);r.default=b,b.prototype.displayObjectUpdateTransform=b.prototype.updateTransform},{\"../const\":46,\"../math\":70,\"../settings\":101,\"./Bounds\":47,\"./Transform\":50,\"./TransformStatic\":52,eventemitter3:3}],50:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"../math\"),u=t(\"./TransformBase\"),h=function(t){return t&&t.__esModule?t:{default:t}}(u),l=function(t){function e(){n(this,e);var r=i(this,t.call(this));return r.position=new a.Point(0,0),r.scale=new a.Point(1,1),r.skew=new a.ObservablePoint(r.updateSkew,r,0,0),r.pivot=new a.Point(0,0),r._rotation=0,r._cx=1,r._sx=0,r._cy=0,r._sy=1,r}return o(e,t),e.prototype.updateSkew=function(){this._cx=Math.cos(this._rotation+this.skew._y),this._sx=Math.sin(this._rotation+this.skew._y),this._cy=-Math.sin(this._rotation-this.skew._x),this._sy=Math.cos(this._rotation-this.skew._x)},e.prototype.updateLocalTransform=function(){var t=this.localTransform;t.a=this._cx*this.scale.x,t.b=this._sx*this.scale.x,t.c=this._cy*this.scale.y,t.d=this._sy*this.scale.y,t.tx=this.position.x-(this.pivot.x*t.a+this.pivot.y*t.c),t.ty=this.position.y-(this.pivot.x*t.b+this.pivot.y*t.d)},e.prototype.updateTransform=function(t){var e=this.localTransform;e.a=this._cx*this.scale.x,e.b=this._sx*this.scale.x,e.c=this._cy*this.scale.y,e.d=this._sy*this.scale.y,e.tx=this.position.x-(this.pivot.x*e.a+this.pivot.y*e.c),e.ty=this.position.y-(this.pivot.x*e.b+this.pivot.y*e.d);var r=t.worldTransform,n=this.worldTransform;n.a=e.a*r.a+e.b*r.c,n.b=e.a*r.b+e.b*r.d,n.c=e.c*r.a+e.d*r.c,n.d=e.c*r.b+e.d*r.d,n.tx=e.tx*r.a+e.ty*r.c+r.tx,n.ty=e.tx*r.b+e.ty*r.d+r.ty,this._worldID++},e.prototype.setFromMatrix=function(t){t.decompose(this)},s(e,[{key:\"rotation\",get:function(){return this._rotation},set:function(t){this._rotation=t,this.updateSkew()}}]),e}(h.default);r.default=l},{\"../math\":70,\"./TransformBase\":51}],51:[function(t,e,r){\"use strict\";function n(t,e){\nif(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../math\"),o=function(){function t(){n(this,t),this.worldTransform=new i.Matrix,this.localTransform=new i.Matrix,this._worldID=0,this._parentID=0}return t.prototype.updateLocalTransform=function(){},t.prototype.updateTransform=function(t){var e=t.worldTransform,r=this.worldTransform,n=this.localTransform;r.a=n.a*e.a+n.b*e.c,r.b=n.a*e.b+n.b*e.d,r.c=n.c*e.a+n.d*e.c,r.d=n.c*e.b+n.d*e.d,r.tx=n.tx*e.a+n.ty*e.c+e.tx,r.ty=n.tx*e.b+n.ty*e.d+e.ty,this._worldID++},t}();r.default=o,o.prototype.updateWorldTransform=o.prototype.updateTransform,o.IDENTITY=new o},{\"../math\":70}],52:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"../math\"),u=t(\"./TransformBase\"),h=function(t){return t&&t.__esModule?t:{default:t}}(u),l=function(t){function e(){n(this,e);var r=i(this,t.call(this));return r.position=new a.ObservablePoint(r.onChange,r,0,0),r.scale=new a.ObservablePoint(r.onChange,r,1,1),r.pivot=new a.ObservablePoint(r.onChange,r,0,0),r.skew=new a.ObservablePoint(r.updateSkew,r,0,0),r._rotation=0,r._cx=1,r._sx=0,r._cy=0,r._sy=1,r._localID=0,r._currentLocalID=0,r}return o(e,t),e.prototype.onChange=function(){this._localID++},e.prototype.updateSkew=function(){this._cx=Math.cos(this._rotation+this.skew._y),this._sx=Math.sin(this._rotation+this.skew._y),this._cy=-Math.sin(this._rotation-this.skew._x),this._sy=Math.cos(this._rotation-this.skew._x),this._localID++},e.prototype.updateLocalTransform=function(){var t=this.localTransform;this._localID!==this._currentLocalID&&(t.a=this._cx*this.scale._x,t.b=this._sx*this.scale._x,t.c=this._cy*this.scale._y,t.d=this._sy*this.scale._y,t.tx=this.position._x-(this.pivot._x*t.a+this.pivot._y*t.c),t.ty=this.position._y-(this.pivot._x*t.b+this.pivot._y*t.d),this._currentLocalID=this._localID,this._parentID=-1)},e.prototype.updateTransform=function(t){var e=this.localTransform;if(this._localID!==this._currentLocalID&&(e.a=this._cx*this.scale._x,e.b=this._sx*this.scale._x,e.c=this._cy*this.scale._y,e.d=this._sy*this.scale._y,e.tx=this.position._x-(this.pivot._x*e.a+this.pivot._y*e.c),e.ty=this.position._y-(this.pivot._x*e.b+this.pivot._y*e.d),this._currentLocalID=this._localID,this._parentID=-1),this._parentID!==t._worldID){var r=t.worldTransform,n=this.worldTransform;n.a=e.a*r.a+e.b*r.c,n.b=e.a*r.b+e.b*r.d,n.c=e.c*r.a+e.d*r.c,n.d=e.c*r.b+e.d*r.d,n.tx=e.tx*r.a+e.ty*r.c+r.tx,n.ty=e.tx*r.b+e.ty*r.d+r.ty,this._parentID=t._worldID,this._worldID++}},e.prototype.setFromMatrix=function(t){t.decompose(this),this._localID++},s(e,[{key:\"rotation\",get:function(){return this._rotation},set:function(t){this._rotation=t,this.updateSkew()}}]),e}(h.default);r.default=l},{\"../math\":70,\"./TransformBase\":51}],53:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"../display/Container\"),u=n(a),h=t(\"../textures/RenderTexture\"),l=n(h),c=t(\"../textures/Texture\"),d=n(c),f=t(\"./GraphicsData\"),p=n(f),v=t(\"../sprites/Sprite\"),y=n(v),g=t(\"../math\"),m=t(\"../utils\"),_=t(\"../const\"),b=t(\"../display/Bounds\"),x=n(b),T=t(\"./utils/bezierCurveTo\"),w=n(T),E=t(\"../renderers/canvas/CanvasRenderer\"),S=n(E),O=void 0,M=new g.Matrix,P=new g.Point,C=new Float32Array(4),R=new Float32Array(4),A=function(t){function e(){var r=arguments.length>0&&void 0!==arguments[0]&&arguments[0];i(this,e);var n=o(this,t.call(this));return n.fillAlpha=1,n.lineWidth=0,n.nativeLines=r,n.lineColor=0,n.graphicsData=[],n.tint=16777215,n._prevTint=16777215,n.blendMode=_.BLEND_MODES.NORMAL,n.currentPath=null,n._webGL={},n.isMask=!1,n.boundsPadding=0,n._localBounds=new x.default,n.dirty=0,n.fastRectDirty=-1,n.clearDirty=0,n.boundsDirty=-1,n.cachedSpriteDirty=!1,n._spriteRect=null,n._fastRect=!1,n}return s(e,t),e.prototype.clone=function(){var t=new e;t.renderable=this.renderable,t.fillAlpha=this.fillAlpha,t.lineWidth=this.lineWidth,t.lineColor=this.lineColor,t.tint=this.tint,t.blendMode=this.blendMode,t.isMask=this.isMask,t.boundsPadding=this.boundsPadding,t.dirty=0,t.cachedSpriteDirty=this.cachedSpriteDirty;for(var r=0;r<this.graphicsData.length;++r)t.graphicsData.push(this.graphicsData[r].clone());return t.currentPath=t.graphicsData[t.graphicsData.length-1],t.updateLocalBounds(),t},e.prototype.lineStyle=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1;if(this.lineWidth=t,this.lineColor=e,this.lineAlpha=r,this.currentPath)if(this.currentPath.shape.points.length){var n=new g.Polygon(this.currentPath.shape.points.slice(-2));n.closed=!1,this.drawShape(n)}else this.currentPath.lineWidth=this.lineWidth,this.currentPath.lineColor=this.lineColor,this.currentPath.lineAlpha=this.lineAlpha;return this},e.prototype.moveTo=function(t,e){var r=new g.Polygon([t,e]);return r.closed=!1,this.drawShape(r),this},e.prototype.lineTo=function(t,e){return this.currentPath.shape.points.push(t,e),this.dirty++,this},e.prototype.quadraticCurveTo=function(t,e,r,n){this.currentPath?0===this.currentPath.shape.points.length&&(this.currentPath.shape.points=[0,0]):this.moveTo(0,0);var i=this.currentPath.shape.points,o=0,s=0;0===i.length&&this.moveTo(0,0);for(var a=i[i.length-2],u=i[i.length-1],h=1;h<=20;++h){var l=h/20;o=a+(t-a)*l,s=u+(e-u)*l,i.push(o+(t+(r-t)*l-o)*l,s+(e+(n-e)*l-s)*l)}return this.dirty++,this},e.prototype.bezierCurveTo=function(t,e,r,n,i,o){this.currentPath?0===this.currentPath.shape.points.length&&(this.currentPath.shape.points=[0,0]):this.moveTo(0,0);var s=this.currentPath.shape.points,a=s[s.length-2],u=s[s.length-1];return s.length-=2,(0,w.default)(a,u,t,e,r,n,i,o,s),this.dirty++,this},e.prototype.arcTo=function(t,e,r,n,i){this.currentPath?0===this.currentPath.shape.points.length&&this.currentPath.shape.points.push(t,e):this.moveTo(t,e);var o=this.currentPath.shape.points,s=o[o.length-2],a=o[o.length-1],u=a-e,h=s-t,l=n-e,c=r-t,d=Math.abs(u*c-h*l);if(d<1e-8||0===i)o[o.length-2]===t&&o[o.length-1]===e||o.push(t,e);else{var f=u*u+h*h,p=l*l+c*c,v=u*l+h*c,y=i*Math.sqrt(f)/d,g=i*Math.sqrt(p)/d,m=y*v/f,_=g*v/p,b=y*c+g*h,x=y*l+g*u,T=h*(g+m),w=u*(g+m),E=c*(y+_),S=l*(y+_),O=Math.atan2(w-x,T-b),M=Math.atan2(S-x,E-b);this.arc(b+t,x+e,i,O,M,h*l>c*u)}return this.dirty++,this},e.prototype.arc=function(t,e,r,n,i){var o=arguments.length>5&&void 0!==arguments[5]&&arguments[5];if(n===i)return this;!o&&i<=n?i+=2*Math.PI:o&&n<=i&&(n+=2*Math.PI);var s=i-n,a=40*Math.ceil(Math.abs(s)/(2*Math.PI));if(0===s)return this;var u=t+Math.cos(n)*r,h=e+Math.sin(n)*r,l=this.currentPath?this.currentPath.shape.points:null;l?l[l.length-2]===u&&l[l.length-1]===h||l.push(u,h):(this.moveTo(u,h),l=this.currentPath.shape.points);for(var c=s/(2*a),d=2*c,f=Math.cos(c),p=Math.sin(c),v=a-1,y=v%1/v,g=0;g<=v;++g){var m=g+y*g,_=c+n+d*m,b=Math.cos(_),x=-Math.sin(_);l.push((f*b+p*x)*r+t,(f*-x+p*b)*r+e)}return this.dirty++,this},e.prototype.beginFill=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;return this.filling=!0,this.fillColor=t,this.fillAlpha=e,this.currentPath&&this.currentPath.shape.points.length<=2&&(this.currentPath.fill=this.filling,this.currentPath.fillColor=this.fillColor,this.currentPath.fillAlpha=this.fillAlpha),this},e.prototype.endFill=function(){return this.filling=!1,this.fillColor=null,this.fillAlpha=1,this},e.prototype.drawRect=function(t,e,r,n){return this.drawShape(new g.Rectangle(t,e,r,n)),this},e.prototype.drawRoundedRect=function(t,e,r,n,i){return this.drawShape(new g.RoundedRectangle(t,e,r,n,i)),this},e.prototype.drawCircle=function(t,e,r){return this.drawShape(new g.Circle(t,e,r)),this},e.prototype.drawEllipse=function(t,e,r,n){return this.drawShape(new g.Ellipse(t,e,r,n)),this},e.prototype.drawPolygon=function(t){var e=t,r=!0;if(e instanceof g.Polygon&&(r=e.closed,e=e.points),!Array.isArray(e)){e=new Array(arguments.length);for(var n=0;n<e.length;++n)e[n]=arguments[n]}var i=new g.Polygon(e);return i.closed=r,this.drawShape(i),this},e.prototype.clear=function(){return(this.lineWidth||this.filling||this.graphicsData.length>0)&&(this.lineWidth=0,this.filling=!1,this.boundsDirty=-1,this.dirty++,this.clearDirty++,this.graphicsData.length=0),this.currentPath=null,this._spriteRect=null,this},e.prototype.isFastRect=function(){return 1===this.graphicsData.length&&this.graphicsData[0].shape.type===_.SHAPES.RECT&&!this.graphicsData[0].lineWidth},e.prototype._renderWebGL=function(t){this.dirty!==this.fastRectDirty&&(this.fastRectDirty=this.dirty,this._fastRect=this.isFastRect()),this._fastRect?this._renderSpriteRect(t):(t.setObjectRenderer(t.plugins.graphics),t.plugins.graphics.render(this))},e.prototype._renderSpriteRect=function(t){var e=this.graphicsData[0].shape;this._spriteRect||(this._spriteRect=new y.default(new d.default(d.default.WHITE)));var r=this._spriteRect;if(16777215===this.tint)r.tint=this.graphicsData[0].fillColor;else{var n=C,i=R;(0,m.hex2rgb)(this.graphicsData[0].fillColor,n),(0,m.hex2rgb)(this.tint,i),n[0]*=i[0],n[1]*=i[1],n[2]*=i[2],r.tint=(0,m.rgb2hex)(n)}r.alpha=this.graphicsData[0].fillAlpha,r.worldAlpha=this.worldAlpha*r.alpha,r.blendMode=this.blendMode,r._texture._frame.width=e.width,r._texture._frame.height=e.height,r.transform.worldTransform=this.transform.worldTransform,r.anchor.set(-e.x/e.width,-e.y/e.height),r._onAnchorUpdate(),r._renderWebGL(t)},e.prototype._renderCanvas=function(t){!0!==this.isMask&&t.plugins.graphics.render(this)},e.prototype._calculateBounds=function(){this.boundsDirty!==this.dirty&&(this.boundsDirty=this.dirty,this.updateLocalBounds(),this.cachedSpriteDirty=!0);var t=this._localBounds;this._bounds.addFrame(this.transform,t.minX,t.minY,t.maxX,t.maxY)},e.prototype.containsPoint=function(t){this.worldTransform.applyInverse(t,P);for(var e=this.graphicsData,r=0;r<e.length;++r){var n=e[r];if(n.fill&&(n.shape&&n.shape.contains(P.x,P.y))){if(n.holes)for(var i=0;i<n.holes.length;i++){var o=n.holes[i];if(o.contains(P.x,P.y))return!1}return!0}}return!1},e.prototype.updateLocalBounds=function(){var t=1/0,e=-1/0,r=1/0,n=-1/0;if(this.graphicsData.length)for(var i=0,o=0,s=0,a=0,u=0,h=0;h<this.graphicsData.length;h++){var l=this.graphicsData[h],c=l.type,d=l.lineWidth;if(i=l.shape,c===_.SHAPES.RECT||c===_.SHAPES.RREC)o=i.x-d/2,s=i.y-d/2,a=i.width+d,u=i.height+d,t=o<t?o:t,e=o+a>e?o+a:e,r=s<r?s:r,n=s+u>n?s+u:n;else if(c===_.SHAPES.CIRC)o=i.x,s=i.y,a=i.radius+d/2,u=i.radius+d/2,t=o-a<t?o-a:t,e=o+a>e?o+a:e,r=s-u<r?s-u:r,n=s+u>n?s+u:n;else if(c===_.SHAPES.ELIP)o=i.x,s=i.y,a=i.width+d/2,u=i.height+d/2,t=o-a<t?o-a:t,e=o+a>e?o+a:e,r=s-u<r?s-u:r,n=s+u>n?s+u:n;else for(var f=i.points,p=0,v=0,y=0,g=0,m=0,b=0,x=0,T=0,w=0;w+2<f.length;w+=2)o=f[w],s=f[w+1],p=f[w+2],v=f[w+3],y=Math.abs(p-o),g=Math.abs(v-s),u=d,(a=Math.sqrt(y*y+g*g))<1e-9||(m=(u/a*g+y)/2,b=(u/a*y+g)/2,x=(p+o)/2,T=(v+s)/2,t=x-m<t?x-m:t,e=x+m>e?x+m:e,r=T-b<r?T-b:r,n=T+b>n?T+b:n)}else t=0,e=0,r=0,n=0;var E=this.boundsPadding;this._localBounds.minX=t-E,this._localBounds.maxX=e+E,this._localBounds.minY=r-E,this._localBounds.maxY=n+E},e.prototype.drawShape=function(t){this.currentPath&&this.currentPath.shape.points.length<=2&&this.graphicsData.pop(),this.currentPath=null;var e=new p.default(this.lineWidth,this.lineColor,this.lineAlpha,this.fillColor,this.fillAlpha,this.filling,this.nativeLines,t);return this.graphicsData.push(e),e.type===_.SHAPES.POLY&&(e.shape.closed=e.shape.closed||this.filling,this.currentPath=e),this.dirty++,e},e.prototype.generateCanvasTexture=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,r=this.getLocalBounds(),n=l.default.create(r.width,r.height,t,e);O||(O=new S.default),this.transform.updateLocalTransform(),this.transform.localTransform.copy(M),M.invert(),M.tx-=r.x,M.ty-=r.y,O.render(this,n,!0,M);var i=d.default.fromCanvas(n.baseTexture._canvasRenderTarget.canvas,t,\"graphics\");return i.baseTexture.resolution=e,i.baseTexture.update(),i},e.prototype.closePath=function(){var t=this.currentPath;return t&&t.shape&&t.shape.close(),this},e.prototype.addHole=function(){var t=this.graphicsData.pop();return this.currentPath=this.graphicsData[this.graphicsData.length-1],this.currentPath.addHole(t.shape),this.currentPath=null,this},e.prototype.destroy=function(e){t.prototype.destroy.call(this,e);for(var r=0;r<this.graphicsData.length;++r)this.graphicsData[r].destroy();for(var n in this._webgl)for(var i=0;i<this._webgl[n].data.length;++i)this._webgl[n].data[i].destroy();this._spriteRect&&this._spriteRect.destroy(),this.graphicsData=null,this.currentPath=null,this._webgl=null,this._localBounds=null},e}(u.default);r.default=A,A._SPRITE_TEXTURE=null},{\"../const\":46,\"../display/Bounds\":47,\"../display/Container\":48,\"../math\":70,\"../renderers/canvas/CanvasRenderer\":77,\"../sprites/Sprite\":102,\"../textures/RenderTexture\":113,\"../textures/Texture\":115,\"../utils\":124,\"./GraphicsData\":54,\"./utils/bezierCurveTo\":56}],54:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(e,r,i,o,s,a,u,h){n(this,t),this.lineWidth=e,this.nativeLines=u,this.lineColor=r,this.lineAlpha=i,this._lineTint=r,this.fillColor=o,this.fillAlpha=s,this._fillTint=o,this.fill=a,this.holes=[],this.shape=h,this.type=h.type}return t.prototype.clone=function(){return new t(this.lineWidth,this.lineColor,this.lineAlpha,this.fillColor,this.fillAlpha,this.fill,this.nativeLines,this.shape)},t.prototype.addHole=function(t){this.holes.push(t)},t.prototype.destroy=function(){this.shape=null,this.holes=null},t}();r.default=i},{}],55:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../../renderers/canvas/CanvasRenderer\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=t(\"../../const\"),a=function(){function t(e){n(this,t),this.renderer=e}return t.prototype.render=function(t){var e=this.renderer,r=e.context,n=t.worldAlpha,i=t.transform.worldTransform,o=e.resolution;this._prevTint!==this.tint&&(this.dirty=!0),r.setTransform(i.a*o,i.b*o,i.c*o,i.d*o,i.tx*o,i.ty*o),t.dirty&&(this.updateGraphicsTint(t),t.dirty=!1),e.setBlendMode(t.blendMode);for(var a=0;a<t.graphicsData.length;a++){var u=t.graphicsData[a],h=u.shape,l=u._fillTint,c=u._lineTint;if(r.lineWidth=u.lineWidth,u.type===s.SHAPES.POLY){r.beginPath(),this.renderPolygon(h.points,h.closed,r);for(var d=0;d<u.holes.length;d++)this.renderPolygon(u.holes[d].points,!0,r);u.fill&&(r.globalAlpha=u.fillAlpha*n,r.fillStyle=\"#\"+(\"00000\"+(0|l).toString(16)).substr(-6),r.fill()),u.lineWidth&&(r.globalAlpha=u.lineAlpha*n,r.strokeStyle=\"#\"+(\"00000\"+(0|c).toString(16)).substr(-6),r.stroke())}else if(u.type===s.SHAPES.RECT)(u.fillColor||0===u.fillColor)&&(r.globalAlpha=u.fillAlpha*n,r.fillStyle=\"#\"+(\"00000\"+(0|l).toString(16)).substr(-6),r.fillRect(h.x,h.y,h.width,h.height)),u.lineWidth&&(r.globalAlpha=u.lineAlpha*n,r.strokeStyle=\"#\"+(\"00000\"+(0|c).toString(16)).substr(-6),r.strokeRect(h.x,h.y,h.width,h.height));else if(u.type===s.SHAPES.CIRC)r.beginPath(),r.arc(h.x,h.y,h.radius,0,2*Math.PI),r.closePath(),u.fill&&(r.globalAlpha=u.fillAlpha*n,r.fillStyle=\"#\"+(\"00000\"+(0|l).toString(16)).substr(-6),r.fill()),u.lineWidth&&(r.globalAlpha=u.lineAlpha*n,r.strokeStyle=\"#\"+(\"00000\"+(0|c).toString(16)).substr(-6),r.stroke());else if(u.type===s.SHAPES.ELIP){var f=2*h.width,p=2*h.height,v=h.x-f/2,y=h.y-p/2;r.beginPath();var g=f/2*.5522848,m=p/2*.5522848,_=v+f,b=y+p,x=v+f/2,T=y+p/2;r.moveTo(v,T),r.bezierCurveTo(v,T-m,x-g,y,x,y),r.bezierCurveTo(x+g,y,_,T-m,_,T),r.bezierCurveTo(_,T+m,x+g,b,x,b),r.bezierCurveTo(x-g,b,v,T+m,v,T),r.closePath(),u.fill&&(r.globalAlpha=u.fillAlpha*n,r.fillStyle=\"#\"+(\"00000\"+(0|l).toString(16)).substr(-6),r.fill()),u.lineWidth&&(r.globalAlpha=u.lineAlpha*n,r.strokeStyle=\"#\"+(\"00000\"+(0|c).toString(16)).substr(-6),r.stroke())}else if(u.type===s.SHAPES.RREC){var w=h.x,E=h.y,S=h.width,O=h.height,M=h.radius,P=Math.min(S,O)/2|0;M=M>P?P:M,r.beginPath(),r.moveTo(w,E+M),r.lineTo(w,E+O-M),r.quadraticCurveTo(w,E+O,w+M,E+O),r.lineTo(w+S-M,E+O),r.quadraticCurveTo(w+S,E+O,w+S,E+O-M),r.lineTo(w+S,E+M),r.quadraticCurveTo(w+S,E,w+S-M,E),r.lineTo(w+M,E),r.quadraticCurveTo(w,E,w,E+M),r.closePath(),(u.fillColor||0===u.fillColor)&&(r.globalAlpha=u.fillAlpha*n,r.fillStyle=\"#\"+(\"00000\"+(0|l).toString(16)).substr(-6),r.fill()),u.lineWidth&&(r.globalAlpha=u.lineAlpha*n,r.strokeStyle=\"#\"+(\"00000\"+(0|c).toString(16)).substr(-6),r.stroke())}}},t.prototype.updateGraphicsTint=function(t){t._prevTint=t.tint;for(var e=(t.tint>>16&255)/255,r=(t.tint>>8&255)/255,n=(255&t.tint)/255,i=0;i<t.graphicsData.length;++i){var o=t.graphicsData[i],s=0|o.fillColor,a=0|o.lineColor;o._fillTint=((s>>16&255)/255*e*255<<16)+((s>>8&255)/255*r*255<<8)+(255&s)/255*n*255,o._lineTint=((a>>16&255)/255*e*255<<16)+((a>>8&255)/255*r*255<<8)+(255&a)/255*n*255}},t.prototype.renderPolygon=function(t,e,r){r.moveTo(t[0],t[1]);for(var n=1;n<t.length/2;++n)r.lineTo(t[2*n],t[2*n+1]);e&&r.closePath()},t.prototype.destroy=function(){this.renderer=null},t}();r.default=a,o.default.registerPlugin(\"graphics\",a)},{\"../../const\":46,\"../../renderers/canvas/CanvasRenderer\":77}],56:[function(t,e,r){\"use strict\";function n(t,e,r,n,i,o,s,a){var u=arguments.length>8&&void 0!==arguments[8]?arguments[8]:[],h=0,l=0,c=0,d=0,f=0;u.push(t,e);for(var p=1,v=0;p<=20;++p)v=p/20,h=1-v,l=h*h,c=l*h,d=v*v,f=d*v,u.push(c*t+3*l*v*r+3*h*d*i+f*s,c*e+3*l*v*n+3*h*d*o+f*a);return u}r.__esModule=!0,r.default=n},{}],57:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"../../utils\"),u=t(\"../../const\"),h=t(\"../../renderers/webgl/utils/ObjectRenderer\"),l=n(h),c=t(\"../../renderers/webgl/WebGLRenderer\"),d=n(c),f=t(\"./WebGLGraphicsData\"),p=n(f),v=t(\"./shaders/PrimitiveShader\"),y=n(v),g=t(\"./utils/buildPoly\"),m=n(g),_=t(\"./utils/buildRectangle\"),b=n(_),x=t(\"./utils/buildRoundedRectangle\"),T=n(x),w=t(\"./utils/buildCircle\"),E=n(w),S=function(t){function e(r){i(this,e);var n=o(this,t.call(this,r));return n.graphicsDataPool=[],n.primitiveShader=null,n.gl=r.gl,n.CONTEXT_UID=0,n}return s(e,t),e.prototype.onContextChange=function(){this.gl=this.renderer.gl,this.CONTEXT_UID=this.renderer.CONTEXT_UID,this.primitiveShader=new y.default(this.gl)},e.prototype.destroy=function(){l.default.prototype.destroy.call(this);for(var t=0;t<this.graphicsDataPool.length;++t)this.graphicsDataPool[t].destroy();this.graphicsDataPool=null},e.prototype.render=function(t){var e=this.renderer,r=e.gl,n=void 0,i=t._webGL[this.CONTEXT_UID];i&&t.dirty===i.dirty||(this.updateGraphics(t),i=t._webGL[this.CONTEXT_UID]);var o=this.primitiveShader;e.bindShader(o),e.state.setBlendMode(t.blendMode);for(var s=0,u=i.data.length;s<u;s++){n=i.data[s];var h=n.shader;e.bindShader(h),h.uniforms.translationMatrix=t.transform.worldTransform.toArray(!0),h.uniforms.tint=(0,a.hex2rgb)(t.tint),h.uniforms.alpha=t.worldAlpha,e.bindVao(n.vao),n.nativeLines?r.drawArrays(r.LINES,0,n.points.length/6):n.vao.draw(r.TRIANGLE_STRIP,n.indices.length)}},e.prototype.updateGraphics=function(t){var e=this.renderer.gl,r=t._webGL[this.CONTEXT_UID];if(r||(r=t._webGL[this.CONTEXT_UID]={lastIndex:0,data:[],gl:e,clearDirty:-1,dirty:-1}),r.dirty=t.dirty,t.clearDirty!==r.clearDirty){r.clearDirty=t.clearDirty;for(var n=0;n<r.data.length;n++)this.graphicsDataPool.push(r.data[n]);r.data.length=0,r.lastIndex=0}for(var i=void 0,o=void 0,s=r.lastIndex;s<t.graphicsData.length;s++){var a=t.graphicsData[s];i=this.getWebGLData(r,0),a.nativeLines&&a.lineWidth&&(o=this.getWebGLData(r,0,!0),r.lastIndex++),a.type===u.SHAPES.POLY&&(0,m.default)(a,i,o),a.type===u.SHAPES.RECT?(0,b.default)(a,i,o):a.type===u.SHAPES.CIRC||a.type===u.SHAPES.ELIP?(0,E.default)(a,i,o):a.type===u.SHAPES.RREC&&(0,T.default)(a,i,o),r.lastIndex++}this.renderer.bindVao(null);for(var h=0;h<r.data.length;h++)i=r.data[h],i.dirty&&i.upload()},e.prototype.getWebGLData=function(t,e,r){var n=t.data[t.data.length-1];return(!n||n.nativeLines!==r||n.points.length>32e4)&&(n=this.graphicsDataPool.pop()||new p.default(this.renderer.gl,this.primitiveShader,this.renderer.state.attribsState),n.nativeLines=r,n.reset(e),t.data.push(n)),n.dirty=!0,n},e}(l.default);r.default=S,d.default.registerPlugin(\"graphics\",S)},{\"../../const\":46,\"../../renderers/webgl/WebGLRenderer\":84,\"../../renderers/webgl/utils/ObjectRenderer\":94,\"../../utils\":124,\"./WebGLGraphicsData\":58,\"./shaders/PrimitiveShader\":59,\"./utils/buildCircle\":60,\"./utils/buildPoly\":62,\"./utils/buildRectangle\":63,\"./utils/buildRoundedRectangle\":64}],58:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"pixi-gl-core\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=function(){function t(e,r,i){n(this,t),this.gl=e,this.color=[0,0,0],this.points=[],this.indices=[],this.buffer=o.default.GLBuffer.createVertexBuffer(e),this.indexBuffer=o.default.GLBuffer.createIndexBuffer(e),this.dirty=!0,this.nativeLines=!1,this.glPoints=null,this.glIndices=null,this.shader=r,this.vao=new o.default.VertexArrayObject(e,i).addIndex(this.indexBuffer).addAttribute(this.buffer,r.attributes.aVertexPosition,e.FLOAT,!1,24,0).addAttribute(this.buffer,r.attributes.aColor,e.FLOAT,!1,24,8)}return t.prototype.reset=function(){this.points.length=0,this.indices.length=0},t.prototype.upload=function(){this.glPoints=new Float32Array(this.points),this.buffer.upload(this.glPoints),this.glIndices=new Uint16Array(this.indices),this.indexBuffer.upload(this.glIndices),this.dirty=!1},t.prototype.destroy=function(){this.color=null,this.points=null,this.indices=null,this.vao.destroy(),this.buffer.destroy(),this.indexBuffer.destroy(),this.gl=null,this.buffer=null,this.indexBuffer=null,this.glPoints=null,this.glIndices=null},t}();r.default=s},{\"pixi-gl-core\":15}],59:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=t(\"../../../Shader\"),a=function(t){return t&&t.__esModule?t:{default:t}}(s),u=function(t){function e(r){return n(this,e),i(this,t.call(this,r,[\"attribute vec2 aVertexPosition;\",\"attribute vec4 aColor;\",\"uniform mat3 translationMatrix;\",\"uniform mat3 projectionMatrix;\",\"uniform float alpha;\",\"uniform vec3 tint;\",\"varying vec4 vColor;\",\"void main(void){\",\"   gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\",\"   vColor = aColor * vec4(tint * alpha, alpha);\",\"}\"].join(\"\\n\"),[\"varying vec4 vColor;\",\"void main(void){\",\"   gl_FragColor = vColor;\",\"}\"].join(\"\\n\")))}return o(e,t),e}(a.default);r.default=u},{\"../../../Shader\":44}],60:[function(t,e,r){\"use strict\";function n(t,e,r){var n=t.shape,i=n.x,u=n.y,h=void 0,l=void 0;if(t.type===s.SHAPES.CIRC?(h=n.radius,l=n.radius):(h=n.width,l=n.height),0!==h&&0!==l){var c=Math.floor(30*Math.sqrt(n.radius))||Math.floor(15*Math.sqrt(n.width+n.height)),d=2*Math.PI/c;if(t.fill){var f=(0,a.hex2rgb)(t.fillColor),p=t.fillAlpha,v=f[0]*p,y=f[1]*p,g=f[2]*p,m=e.points,_=e.indices,b=m.length/6;_.push(b);for(var x=0;x<c+1;x++)m.push(i,u,v,y,g,p),m.push(i+Math.sin(d*x)*h,u+Math.cos(d*x)*l,v,y,g,p),_.push(b++,b++);_.push(b-1)}if(t.lineWidth){var T=t.points;t.points=[];for(var w=0;w<c+1;w++)t.points.push(i+Math.sin(d*w)*h,u+Math.cos(d*w)*l);(0,o.default)(t,e,r),t.points=T}}}r.__esModule=!0,r.default=n;var i=t(\"./buildLine\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=t(\"../../../const\"),a=t(\"../../../utils\")},{\"../../../const\":46,\"../../../utils\":124,\"./buildLine\":61}],61:[function(t,e,r){\"use strict\";function n(t,e){var r=t.points;if(0!==r.length){var n=new o.Point(r[0],r[1]),i=new o.Point(r[r.length-2],r[r.length-1]);if(n.x===i.x&&n.y===i.y){r=r.slice(),r.pop(),r.pop(),i=new o.Point(r[r.length-2],r[r.length-1]);var a=i.x+.5*(n.x-i.x),u=i.y+.5*(n.y-i.y);r.unshift(a,u),r.push(a,u)}var h=e.points,l=e.indices,c=r.length/2,d=r.length,f=h.length/6,p=t.lineWidth/2,v=(0,s.hex2rgb)(t.lineColor),y=t.lineAlpha,g=v[0]*y,m=v[1]*y,_=v[2]*y,b=r[0],x=r[1],T=r[2],w=r[3],E=0,S=0,O=-(x-w),M=b-T,P=0,C=0,R=0,A=0,I=Math.sqrt(O*O+M*M);O/=I,M/=I,O*=p,M*=p,h.push(b-O,x-M,g,m,_,y),h.push(b+O,x+M,g,m,_,y);for(var D=1;D<c-1;++D){b=r[2*(D-1)],x=r[2*(D-1)+1],T=r[2*D],w=r[2*D+1],E=r[2*(D+1)],S=r[2*(D+1)+1],O=-(x-w),M=b-T,I=Math.sqrt(O*O+M*M),O/=I,M/=I,O*=p,M*=p,P=-(w-S),C=T-E,I=Math.sqrt(P*P+C*C),P/=I,C/=I,P*=p,C*=p;var L=-M+x-(-M+w),N=-O+T-(-O+b),F=(-O+b)*(-M+w)-(-O+T)*(-M+x),B=-C+S-(-C+w),k=-P+T-(-P+E),j=(-P+E)*(-C+w)-(-P+T)*(-C+S),U=L*k-B*N;if(Math.abs(U)<.1)U+=10.1,h.push(T-O,w-M,g,m,_,y),h.push(T+O,w+M,g,m,_,y);else{var X=(N*j-k*F)/U,G=(B*F-L*j)/U;(X-T)*(X-T)+(G-w)*(G-w)>196*p*p?(R=O-P,A=M-C,I=Math.sqrt(R*R+A*A),R/=I,A/=I,R*=p,A*=p,h.push(T-R,w-A),h.push(g,m,_,y),h.push(T+R,w+A),h.push(g,m,_,y),h.push(T-R,w-A),h.push(g,m,_,y),d++):(h.push(X,G),h.push(g,m,_,y),h.push(T-(X-T),w-(G-w)),h.push(g,m,_,y))}}b=r[2*(c-2)],x=r[2*(c-2)+1],T=r[2*(c-1)],w=r[2*(c-1)+1],O=-(x-w),M=b-T,I=Math.sqrt(O*O+M*M),O/=I,M/=I,O*=p,M*=p,h.push(T-O,w-M),h.push(g,m,_,y),h.push(T+O,w+M),h.push(g,m,_,y),l.push(f);for(var W=0;W<d;++W)l.push(f++);l.push(f-1)}}function i(t,e){var r=0,n=t.points;if(0!==n.length){var i=e.points,o=n.length/2,a=(0,s.hex2rgb)(t.lineColor),u=t.lineAlpha,h=a[0]*u,l=a[1]*u,c=a[2]*u;for(r=1;r<o;r++){var d=n[2*(r-1)],f=n[2*(r-1)+1],p=n[2*r],v=n[2*r+1];i.push(d,f),i.push(h,l,c,u),i.push(p,v),i.push(h,l,c,u)}}}r.__esModule=!0,r.default=function(t,e,r){t.nativeLines?i(t,r):n(t,e)};var o=t(\"../../../math\"),s=t(\"../../../utils\")},{\"../../../math\":70,\"../../../utils\":124}],62:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e,r){t.points=t.shape.points.slice();var n=t.points;if(t.fill&&n.length>=6){for(var i=[],o=t.holes,u=0;u<o.length;u++){var l=o[u];i.push(n.length/2),n=n.concat(l.points)}var c=e.points,d=e.indices,f=n.length/2,p=(0,a.hex2rgb)(t.fillColor),v=t.fillAlpha,y=p[0]*v,g=p[1]*v,m=p[2]*v,_=(0,h.default)(n,i,2);if(!_)return;for(var b=c.length/6,x=0;x<_.length;x+=3)d.push(_[x]+b),d.push(_[x]+b),d.push(_[x+1]+b),d.push(_[x+2]+b),d.push(_[x+2]+b);for(var T=0;T<f;T++)c.push(n[2*T],n[2*T+1],y,g,m,v)}t.lineWidth>0&&(0,s.default)(t,e,r)}r.__esModule=!0,r.default=i;var o=t(\"./buildLine\"),s=n(o),a=t(\"../../../utils\"),u=t(\"earcut\"),h=n(u)},{\"../../../utils\":124,\"./buildLine\":61,earcut:2}],63:[function(t,e,r){\"use strict\";function n(t,e,r){var n=t.shape,i=n.x,a=n.y,u=n.width,h=n.height;if(t.fill){var l=(0,s.hex2rgb)(t.fillColor),c=t.fillAlpha,d=l[0]*c,f=l[1]*c,p=l[2]*c,v=e.points,y=e.indices,g=v.length/6;v.push(i,a),v.push(d,f,p,c),v.push(i+u,a),v.push(d,f,p,c),v.push(i,a+h),v.push(d,f,p,c),v.push(i+u,a+h),v.push(d,f,p,c),y.push(g,g,g+1,g+2,g+3,g+3)}if(t.lineWidth){var m=t.points;t.points=[i,a,i+u,a,i+u,a+h,i,a+h,i,a],(0,o.default)(t,e,r),t.points=m}}r.__esModule=!0,r.default=n;var i=t(\"./buildLine\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=t(\"../../../utils\")},{\"../../../utils\":124,\"./buildLine\":61}],64:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e,r){var n=t.shape,i=n.x,o=n.y,a=n.width,h=n.height,d=n.radius,f=[];if(f.push(i,o+d),s(i,o+h-d,i,o+h,i+d,o+h,f),s(i+a-d,o+h,i+a,o+h,i+a,o+h-d,f),s(i+a,o+d,i+a,o,i+a-d,o,f),s(i+d,o,i,o,i,o+d+1e-10,f),t.fill){for(var p=(0,c.hex2rgb)(t.fillColor),v=t.fillAlpha,y=p[0]*v,g=p[1]*v,m=p[2]*v,_=e.points,b=e.indices,x=_.length/6,T=(0,u.default)(f,null,2),w=0,E=T.length;w<E;w+=3)b.push(T[w]+x),b.push(T[w]+x),b.push(T[w+1]+x),b.push(T[w+2]+x),b.push(T[w+2]+x);for(var S=0,O=f.length;S<O;S++)_.push(f[S],f[++S],y,g,m,v)}if(t.lineWidth){var M=t.points;t.points=f,(0,l.default)(t,e,r),t.points=M}}function o(t,e,r){return t+(e-t)*r}function s(t,e,r,n,i,s){for(var a=arguments.length>6&&void 0!==arguments[6]?arguments[6]:[],u=a,h=0,l=0,c=0,d=0,f=0,p=0,v=0,y=0;v<=20;++v)y=v/20,h=o(t,r,y),l=o(e,n,y),c=o(r,i,y),d=o(n,s,y),f=o(h,c,y),p=o(l,d,y),u.push(f,p);return u}r.__esModule=!0,r.default=i;var a=t(\"earcut\"),u=n(a),h=t(\"./buildLine\"),l=n(h),c=t(\"../../../utils\")},{\"../../../utils\":124,\"./buildLine\":61,earcut:2}],65:[function(t,e,r){\"use strict\";function n(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}function i(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0,r.autoDetectRenderer=r.Application=r.Filter=r.SpriteMaskFilter=r.Quad=r.RenderTarget=r.ObjectRenderer=r.WebGLManager=r.Shader=r.CanvasRenderTarget=r.TextureUvs=r.VideoBaseTexture=r.BaseRenderTexture=r.RenderTexture=r.BaseTexture=r.Texture=r.Spritesheet=r.CanvasGraphicsRenderer=r.GraphicsRenderer=r.GraphicsData=r.Graphics=r.TextMetrics=r.TextStyle=r.Text=r.SpriteRenderer=r.CanvasTinter=r.CanvasSpriteRenderer=r.Sprite=r.TransformBase=r.TransformStatic=r.Transform=r.Container=r.DisplayObject=r.Bounds=r.glCore=r.WebGLRenderer=r.CanvasRenderer=r.ticker=r.utils=r.settings=void 0;var o=t(\"./const\");Object.keys(o).forEach(function(t){\"default\"!==t&&\"__esModule\"!==t&&Object.defineProperty(r,t,{enumerable:!0,get:function(){return o[t]}})});var s=t(\"./math\");Object.keys(s).forEach(function(t){\"default\"!==t&&\"__esModule\"!==t&&Object.defineProperty(r,t,{enumerable:!0,get:function(){return s[t]}})});var a=t(\"pixi-gl-core\");Object.defineProperty(r,\"glCore\",{enumerable:!0,get:function(){return i(a).default}});var u=t(\"./display/Bounds\");Object.defineProperty(r,\"Bounds\",{enumerable:!0,get:function(){return i(u).default}})\n;var h=t(\"./display/DisplayObject\");Object.defineProperty(r,\"DisplayObject\",{enumerable:!0,get:function(){return i(h).default}});var l=t(\"./display/Container\");Object.defineProperty(r,\"Container\",{enumerable:!0,get:function(){return i(l).default}});var c=t(\"./display/Transform\");Object.defineProperty(r,\"Transform\",{enumerable:!0,get:function(){return i(c).default}});var d=t(\"./display/TransformStatic\");Object.defineProperty(r,\"TransformStatic\",{enumerable:!0,get:function(){return i(d).default}});var f=t(\"./display/TransformBase\");Object.defineProperty(r,\"TransformBase\",{enumerable:!0,get:function(){return i(f).default}});var p=t(\"./sprites/Sprite\");Object.defineProperty(r,\"Sprite\",{enumerable:!0,get:function(){return i(p).default}});var v=t(\"./sprites/canvas/CanvasSpriteRenderer\");Object.defineProperty(r,\"CanvasSpriteRenderer\",{enumerable:!0,get:function(){return i(v).default}});var y=t(\"./sprites/canvas/CanvasTinter\");Object.defineProperty(r,\"CanvasTinter\",{enumerable:!0,get:function(){return i(y).default}});var g=t(\"./sprites/webgl/SpriteRenderer\");Object.defineProperty(r,\"SpriteRenderer\",{enumerable:!0,get:function(){return i(g).default}});var m=t(\"./text/Text\");Object.defineProperty(r,\"Text\",{enumerable:!0,get:function(){return i(m).default}});var _=t(\"./text/TextStyle\");Object.defineProperty(r,\"TextStyle\",{enumerable:!0,get:function(){return i(_).default}});var b=t(\"./text/TextMetrics\");Object.defineProperty(r,\"TextMetrics\",{enumerable:!0,get:function(){return i(b).default}});var x=t(\"./graphics/Graphics\");Object.defineProperty(r,\"Graphics\",{enumerable:!0,get:function(){return i(x).default}});var T=t(\"./graphics/GraphicsData\");Object.defineProperty(r,\"GraphicsData\",{enumerable:!0,get:function(){return i(T).default}});var w=t(\"./graphics/webgl/GraphicsRenderer\");Object.defineProperty(r,\"GraphicsRenderer\",{enumerable:!0,get:function(){return i(w).default}});var E=t(\"./graphics/canvas/CanvasGraphicsRenderer\");Object.defineProperty(r,\"CanvasGraphicsRenderer\",{enumerable:!0,get:function(){return i(E).default}});var S=t(\"./textures/Spritesheet\");Object.defineProperty(r,\"Spritesheet\",{enumerable:!0,get:function(){return i(S).default}});var O=t(\"./textures/Texture\");Object.defineProperty(r,\"Texture\",{enumerable:!0,get:function(){return i(O).default}});var M=t(\"./textures/BaseTexture\");Object.defineProperty(r,\"BaseTexture\",{enumerable:!0,get:function(){return i(M).default}});var P=t(\"./textures/RenderTexture\");Object.defineProperty(r,\"RenderTexture\",{enumerable:!0,get:function(){return i(P).default}});var C=t(\"./textures/BaseRenderTexture\");Object.defineProperty(r,\"BaseRenderTexture\",{enumerable:!0,get:function(){return i(C).default}});var R=t(\"./textures/VideoBaseTexture\");Object.defineProperty(r,\"VideoBaseTexture\",{enumerable:!0,get:function(){return i(R).default}});var A=t(\"./textures/TextureUvs\");Object.defineProperty(r,\"TextureUvs\",{enumerable:!0,get:function(){return i(A).default}});var I=t(\"./renderers/canvas/utils/CanvasRenderTarget\");Object.defineProperty(r,\"CanvasRenderTarget\",{enumerable:!0,get:function(){return i(I).default}});var D=t(\"./Shader\");Object.defineProperty(r,\"Shader\",{enumerable:!0,get:function(){return i(D).default}});var L=t(\"./renderers/webgl/managers/WebGLManager\");Object.defineProperty(r,\"WebGLManager\",{enumerable:!0,get:function(){return i(L).default}});var N=t(\"./renderers/webgl/utils/ObjectRenderer\");Object.defineProperty(r,\"ObjectRenderer\",{enumerable:!0,get:function(){return i(N).default}});var F=t(\"./renderers/webgl/utils/RenderTarget\");Object.defineProperty(r,\"RenderTarget\",{enumerable:!0,get:function(){return i(F).default}});var B=t(\"./renderers/webgl/utils/Quad\");Object.defineProperty(r,\"Quad\",{enumerable:!0,get:function(){return i(B).default}});var k=t(\"./renderers/webgl/filters/spriteMask/SpriteMaskFilter\");Object.defineProperty(r,\"SpriteMaskFilter\",{enumerable:!0,get:function(){return i(k).default}});var j=t(\"./renderers/webgl/filters/Filter\");Object.defineProperty(r,\"Filter\",{enumerable:!0,get:function(){return i(j).default}});var U=t(\"./Application\");Object.defineProperty(r,\"Application\",{enumerable:!0,get:function(){return i(U).default}});var X=t(\"./autoDetectRenderer\");Object.defineProperty(r,\"autoDetectRenderer\",{enumerable:!0,get:function(){return X.autoDetectRenderer}});var G=t(\"./utils\"),W=n(G),H=t(\"./ticker\"),Y=n(H),V=t(\"./settings\"),z=i(V),q=t(\"./renderers/canvas/CanvasRenderer\"),K=i(q),Z=t(\"./renderers/webgl/WebGLRenderer\"),J=i(Z);r.settings=z.default,r.utils=W,r.ticker=Y,r.CanvasRenderer=K.default,r.WebGLRenderer=J.default},{\"./Application\":43,\"./Shader\":44,\"./autoDetectRenderer\":45,\"./const\":46,\"./display/Bounds\":47,\"./display/Container\":48,\"./display/DisplayObject\":49,\"./display/Transform\":50,\"./display/TransformBase\":51,\"./display/TransformStatic\":52,\"./graphics/Graphics\":53,\"./graphics/GraphicsData\":54,\"./graphics/canvas/CanvasGraphicsRenderer\":55,\"./graphics/webgl/GraphicsRenderer\":57,\"./math\":70,\"./renderers/canvas/CanvasRenderer\":77,\"./renderers/canvas/utils/CanvasRenderTarget\":79,\"./renderers/webgl/WebGLRenderer\":84,\"./renderers/webgl/filters/Filter\":86,\"./renderers/webgl/filters/spriteMask/SpriteMaskFilter\":89,\"./renderers/webgl/managers/WebGLManager\":93,\"./renderers/webgl/utils/ObjectRenderer\":94,\"./renderers/webgl/utils/Quad\":95,\"./renderers/webgl/utils/RenderTarget\":96,\"./settings\":101,\"./sprites/Sprite\":102,\"./sprites/canvas/CanvasSpriteRenderer\":103,\"./sprites/canvas/CanvasTinter\":104,\"./sprites/webgl/SpriteRenderer\":106,\"./text/Text\":108,\"./text/TextMetrics\":109,\"./text/TextStyle\":110,\"./textures/BaseRenderTexture\":111,\"./textures/BaseTexture\":112,\"./textures/RenderTexture\":113,\"./textures/Spritesheet\":114,\"./textures/Texture\":115,\"./textures/TextureUvs\":116,\"./textures/VideoBaseTexture\":117,\"./ticker\":120,\"./utils\":124,\"pixi-gl-core\":15}],66:[function(t,e,r){\"use strict\";function n(t){return t<0?-1:t>0?1:0}r.__esModule=!0;var i=t(\"./Matrix\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=[1,1,0,-1,-1,-1,0,1,1,1,0,-1,-1,-1,0,1],a=[0,1,1,1,0,-1,-1,-1,0,1,1,1,0,-1,-1,-1],u=[0,-1,-1,-1,0,1,1,1,0,1,1,1,0,-1,-1,-1],h=[1,1,0,-1,-1,-1,0,1,-1,-1,0,1,1,1,0,-1],l=[],c=[];!function(){for(var t=0;t<16;t++){var e=[];c.push(e);for(var r=0;r<16;r++)for(var i=n(s[t]*s[r]+u[t]*a[r]),d=n(a[t]*s[r]+h[t]*a[r]),f=n(s[t]*u[r]+u[t]*h[r]),p=n(a[t]*u[r]+h[t]*h[r]),v=0;v<16;v++)if(s[v]===i&&a[v]===d&&u[v]===f&&h[v]===p){e.push(v);break}}for(var y=0;y<16;y++){var g=new o.default;g.set(s[y],a[y],u[y],h[y],0,0),l.push(g)}}();var d={E:0,SE:1,S:2,SW:3,W:4,NW:5,N:6,NE:7,MIRROR_VERTICAL:8,MIRROR_HORIZONTAL:12,uX:function(t){return s[t]},uY:function(t){return a[t]},vX:function(t){return u[t]},vY:function(t){return h[t]},inv:function(t){return 8&t?15&t:7&-t},add:function(t,e){return c[t][e]},sub:function(t,e){return c[t][d.inv(e)]},rotate180:function(t){return 4^t},isSwapWidthHeight:function(t){return 2==(3&t)},byDirection:function(t,e){return 2*Math.abs(t)<=Math.abs(e)?e>=0?d.S:d.N:2*Math.abs(e)<=Math.abs(t)?t>0?d.E:d.W:e>0?t>0?d.SE:d.SW:t>0?d.NE:d.NW},matrixAppendRotationInv:function(t,e){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,i=l[d.inv(e)];i.tx=r,i.ty=n,t.append(i)}};r.default=d},{\"./Matrix\":67}],67:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),o=t(\"./Point\"),s=function(t){return t&&t.__esModule?t:{default:t}}(o),a=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:1,s=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,a=arguments.length>5&&void 0!==arguments[5]?arguments[5]:0;n(this,t),this.a=e,this.b=r,this.c=i,this.d=o,this.tx=s,this.ty=a,this.array=null}return t.prototype.fromArray=function(t){this.a=t[0],this.b=t[1],this.c=t[3],this.d=t[4],this.tx=t[2],this.ty=t[5]},t.prototype.set=function(t,e,r,n,i,o){return this.a=t,this.b=e,this.c=r,this.d=n,this.tx=i,this.ty=o,this},t.prototype.toArray=function(t,e){this.array||(this.array=new Float32Array(9));var r=e||this.array;return t?(r[0]=this.a,r[1]=this.b,r[2]=0,r[3]=this.c,r[4]=this.d,r[5]=0,r[6]=this.tx,r[7]=this.ty,r[8]=1):(r[0]=this.a,r[1]=this.c,r[2]=this.tx,r[3]=this.b,r[4]=this.d,r[5]=this.ty,r[6]=0,r[7]=0,r[8]=1),r},t.prototype.apply=function(t,e){e=e||new s.default;var r=t.x,n=t.y;return e.x=this.a*r+this.c*n+this.tx,e.y=this.b*r+this.d*n+this.ty,e},t.prototype.applyInverse=function(t,e){e=e||new s.default;var r=1/(this.a*this.d+this.c*-this.b),n=t.x,i=t.y;return e.x=this.d*r*n+-this.c*r*i+(this.ty*this.c-this.tx*this.d)*r,e.y=this.a*r*i+-this.b*r*n+(-this.ty*this.a+this.tx*this.b)*r,e},t.prototype.translate=function(t,e){return this.tx+=t,this.ty+=e,this},t.prototype.scale=function(t,e){return this.a*=t,this.d*=e,this.c*=t,this.b*=e,this.tx*=t,this.ty*=e,this},t.prototype.rotate=function(t){var e=Math.cos(t),r=Math.sin(t),n=this.a,i=this.c,o=this.tx;return this.a=n*e-this.b*r,this.b=n*r+this.b*e,this.c=i*e-this.d*r,this.d=i*r+this.d*e,this.tx=o*e-this.ty*r,this.ty=o*r+this.ty*e,this},t.prototype.append=function(t){var e=this.a,r=this.b,n=this.c,i=this.d;return this.a=t.a*e+t.b*n,this.b=t.a*r+t.b*i,this.c=t.c*e+t.d*n,this.d=t.c*r+t.d*i,this.tx=t.tx*e+t.ty*n+this.tx,this.ty=t.tx*r+t.ty*i+this.ty,this},t.prototype.setTransform=function(t,e,r,n,i,o,s,a,u){var h=Math.sin(s),l=Math.cos(s),c=Math.cos(u),d=Math.sin(u),f=-Math.sin(a),p=Math.cos(a),v=l*i,y=h*i,g=-h*o,m=l*o;return this.a=c*v+d*g,this.b=c*y+d*m,this.c=f*v+p*g,this.d=f*y+p*m,this.tx=t+(r*v+n*g),this.ty=e+(r*y+n*m),this},t.prototype.prepend=function(t){var e=this.tx;if(1!==t.a||0!==t.b||0!==t.c||1!==t.d){var r=this.a,n=this.c;this.a=r*t.a+this.b*t.c,this.b=r*t.b+this.b*t.d,this.c=n*t.a+this.d*t.c,this.d=n*t.b+this.d*t.d}return this.tx=e*t.a+this.ty*t.c+t.tx,this.ty=e*t.b+this.ty*t.d+t.ty,this},t.prototype.decompose=function(t){var e=this.a,r=this.b,n=this.c,i=this.d,o=-Math.atan2(-n,i),s=Math.atan2(r,e);return Math.abs(o+s)<1e-5?(t.rotation=s,e<0&&i>=0&&(t.rotation+=t.rotation<=0?Math.PI:-Math.PI),t.skew.x=t.skew.y=0):(t.skew.x=o,t.skew.y=s),t.scale.x=Math.sqrt(e*e+r*r),t.scale.y=Math.sqrt(n*n+i*i),t.position.x=this.tx,t.position.y=this.ty,t},t.prototype.invert=function(){var t=this.a,e=this.b,r=this.c,n=this.d,i=this.tx,o=t*n-e*r;return this.a=n/o,this.b=-e/o,this.c=-r/o,this.d=t/o,this.tx=(r*this.ty-n*i)/o,this.ty=-(t*this.ty-e*i)/o,this},t.prototype.identity=function(){return this.a=1,this.b=0,this.c=0,this.d=1,this.tx=0,this.ty=0,this},t.prototype.clone=function(){var e=new t;return e.a=this.a,e.b=this.b,e.c=this.c,e.d=this.d,e.tx=this.tx,e.ty=this.ty,e},t.prototype.copy=function(t){return t.a=this.a,t.b=this.b,t.c=this.c,t.d=this.d,t.tx=this.tx,t.ty=this.ty,t},i(t,null,[{key:\"IDENTITY\",get:function(){return new t}},{key:\"TEMP_MATRIX\",get:function(){return new t}}]),t}();r.default=a},{\"./Point\":69}],68:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),o=function(){function t(e,r){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0;n(this,t),this._x=i,this._y=o,this.cb=e,this.scope=r}return t.prototype.set=function(t,e){var r=t||0,n=e||(0!==e?r:0);this._x===r&&this._y===n||(this._x=r,this._y=n,this.cb.call(this.scope))},t.prototype.copy=function(t){this._x===t.x&&this._y===t.y||(this._x=t.x,this._y=t.y,this.cb.call(this.scope))},i(t,[{key:\"x\",get:function(){return this._x},set:function(t){this._x!==t&&(this._x=t,this.cb.call(this.scope))}},{key:\"y\",get:function(){return this._y},set:function(t){this._y!==t&&(this._y=t,this.cb.call(this.scope))}}]),t}();r.default=o},{}],69:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;n(this,t),this.x=e,this.y=r}return t.prototype.clone=function(){return new t(this.x,this.y)},t.prototype.copy=function(t){this.set(t.x,t.y)},t.prototype.equals=function(t){return t.x===this.x&&t.y===this.y},t.prototype.set=function(t,e){this.x=t||0,this.y=e||(0!==e?this.x:0)},t}();r.default=i},{}],70:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0;var i=t(\"./Point\");Object.defineProperty(r,\"Point\",{enumerable:!0,get:function(){return n(i).default}});var o=t(\"./ObservablePoint\");Object.defineProperty(r,\"ObservablePoint\",{enumerable:!0,get:function(){return n(o).default}});var s=t(\"./Matrix\");Object.defineProperty(r,\"Matrix\",{enumerable:!0,get:function(){return n(s).default}});var a=t(\"./GroupD8\");Object.defineProperty(r,\"GroupD8\",{enumerable:!0,get:function(){return n(a).default}});var u=t(\"./shapes/Circle\");Object.defineProperty(r,\"Circle\",{enumerable:!0,get:function(){return n(u).default}});var h=t(\"./shapes/Ellipse\");Object.defineProperty(r,\"Ellipse\",{enumerable:!0,get:function(){return n(h).default}});var l=t(\"./shapes/Polygon\");Object.defineProperty(r,\"Polygon\",{enumerable:!0,get:function(){return n(l).default}});var c=t(\"./shapes/Rectangle\");Object.defineProperty(r,\"Rectangle\",{enumerable:!0,get:function(){return n(c).default}});var d=t(\"./shapes/RoundedRectangle\");Object.defineProperty(r,\"RoundedRectangle\",{enumerable:!0,get:function(){return n(d).default}})},{\"./GroupD8\":66,\"./Matrix\":67,\"./ObservablePoint\":68,\"./Point\":69,\"./shapes/Circle\":71,\"./shapes/Ellipse\":72,\"./shapes/Polygon\":73,\"./shapes/Rectangle\":74,\"./shapes/RoundedRectangle\":75}],71:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"./Rectangle\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=t(\"../../const\"),a=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;n(this,t),this.x=e,this.y=r,this.radius=i,this.type=s.SHAPES.CIRC}return t.prototype.clone=function(){return new t(this.x,this.y,this.radius)},t.prototype.contains=function(t,e){if(this.radius<=0)return!1;var r=this.radius*this.radius,n=this.x-t,i=this.y-e;return n*=n,i*=i,n+i<=r},t.prototype.getBounds=function(){return new o.default(this.x-this.radius,this.y-this.radius,2*this.radius,2*this.radius)},t}();r.default=a},{\"../../const\":46,\"./Rectangle\":74}],72:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"./Rectangle\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=t(\"../../const\"),a=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0;n(this,t),this.x=e,this.y=r,this.width=i,this.height=o,this.type=s.SHAPES.ELIP}return t.prototype.clone=function(){return new t(this.x,this.y,this.width,this.height)},t.prototype.contains=function(t,e){if(this.width<=0||this.height<=0)return!1;var r=(t-this.x)/this.width,n=(e-this.y)/this.height;return r*=r,n*=n,r+n<=1},t.prototype.getBounds=function(){return new o.default(this.x-this.width,this.y-this.height,this.width,this.height)},t}();r.default=a},{\"../../const\":46,\"./Rectangle\":74}],73:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../Point\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=t(\"../../const\"),a=function(){function t(){for(var e=arguments.length,r=Array(e),i=0;i<e;i++)r[i]=arguments[i];if(n(this,t),Array.isArray(r[0])&&(r=r[0]),r[0]instanceof o.default){for(var a=[],u=0,h=r.length;u<h;u++)a.push(r[u].x,r[u].y);r=a}this.closed=!0,this.points=r,this.type=s.SHAPES.POLY}return t.prototype.clone=function(){return new t(this.points.slice())},t.prototype.close=function(){var t=this.points;t[0]===t[t.length-2]&&t[1]===t[t.length-1]||t.push(t[0],t[1])},t.prototype.contains=function(t,e){for(var r=!1,n=this.points.length/2,i=0,o=n-1;i<n;o=i++){var s=this.points[2*i],a=this.points[2*i+1],u=this.points[2*o],h=this.points[2*o+1];a>e!=h>e&&t<(e-a)/(h-a)*(u-s)+s&&(r=!r)}return r},t}();r.default=a},{\"../../const\":46,\"../Point\":69}],74:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),o=t(\"../../const\"),s=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,s=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0;n(this,t),this.x=Number(e),this.y=Number(r),this.width=Number(i),this.height=Number(s),this.type=o.SHAPES.RECT}return t.prototype.clone=function(){return new t(this.x,this.y,this.width,this.height)},t.prototype.copy=function(t){return this.x=t.x,this.y=t.y,this.width=t.width,this.height=t.height,this},t.prototype.contains=function(t,e){return!(this.width<=0||this.height<=0)&&(t>=this.x&&t<this.x+this.width&&e>=this.y&&e<this.y+this.height)},t.prototype.pad=function(t,e){t=t||0,e=e||(0!==e?t:0),this.x-=t,this.y-=e,this.width+=2*t,this.height+=2*e},t.prototype.fit=function(t){this.x<t.x&&(this.width+=this.x,this.width<0&&(this.width=0),this.x=t.x),this.y<t.y&&(this.height+=this.y,this.height<0&&(this.height=0),this.y=t.y),this.x+this.width>t.x+t.width&&(this.width=t.width-this.x,this.width<0&&(this.width=0)),this.y+this.height>t.y+t.height&&(this.height=t.height-this.y,this.height<0&&(this.height=0))},t.prototype.enlarge=function(t){var e=Math.min(this.x,t.x),r=Math.max(this.x+this.width,t.x+t.width),n=Math.min(this.y,t.y),i=Math.max(this.y+this.height,t.y+t.height);this.x=e,this.width=r-e,this.y=n,this.height=i-n},i(t,[{key:\"left\",get:function(){return this.x}},{key:\"right\",get:function(){return this.x+this.width}},{key:\"top\",get:function(){return this.y}},{key:\"bottom\",get:function(){return this.y+this.height}}],[{key:\"EMPTY\",get:function(){return new t(0,0,0,0)}}]),t}();r.default=s},{\"../../const\":46}],75:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../../const\"),o=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,s=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,a=arguments.length>4&&void 0!==arguments[4]?arguments[4]:20;n(this,t),this.x=e,this.y=r,this.width=o,this.height=s,this.radius=a,this.type=i.SHAPES.RREC}return t.prototype.clone=function(){return new t(this.x,this.y,this.width,this.height,this.radius)},t.prototype.contains=function(t,e){if(this.width<=0||this.height<=0)return!1;if(t>=this.x&&t<=this.x+this.width&&e>=this.y&&e<=this.y+this.height){if(e>=this.y+this.radius&&e<=this.y+this.height-this.radius||t>=this.x+this.radius&&t<=this.x+this.width-this.radius)return!0;var r=t-(this.x+this.radius),n=e-(this.y+this.radius),i=this.radius*this.radius;if(r*r+n*n<=i)return!0;if((r=t-(this.x+this.width-this.radius))*r+n*n<=i)return!0;if(n=e-(this.y+this.height-this.radius),r*r+n*n<=i)return!0;if((r=t-(this.x+this.radius))*r+n*n<=i)return!0}return!1},t}();r.default=o},{\"../../const\":46}],76:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),u=t(\"../utils\"),h=t(\"../math\"),l=t(\"../const\"),c=t(\"../settings\"),d=n(c),f=t(\"../display/Container\"),p=n(f),v=t(\"../textures/RenderTexture\"),y=n(v),g=t(\"eventemitter3\"),m=n(g),_=new h.Matrix,b=function(t){function e(r,n,s,a){i(this,e);var c=o(this,t.call(this));return(0,u.sayHello)(r),\"number\"==typeof n&&(n=Object.assign({width:n,height:s||d.default.RENDER_OPTIONS.height},a)),n=Object.assign({},d.default.RENDER_OPTIONS,n),c.options=n,c.type=l.RENDERER_TYPE.UNKNOWN,c.screen=new h.Rectangle(0,0,n.width,n.height),c.view=n.view||document.createElement(\"canvas\"),c.resolution=n.resolution||d.default.RESOLUTION,c.transparent=n.transparent,c.autoResize=n.autoResize||!1,c.blendModes=null,c.preserveDrawingBuffer=n.preserveDrawingBuffer,c.clearBeforeRender=n.clearBeforeRender,c.roundPixels=n.roundPixels,c._backgroundColor=0,c._backgroundColorRgba=[0,0,0,0],c._backgroundColorString=\"#000000\",c.backgroundColor=n.backgroundColor||c._backgroundColor,c._tempDisplayObjectParent=new p.default,c._lastObjectRendered=c._tempDisplayObjectParent,c}return s(e,t),e.prototype.resize=function(t,e){this.screen.width=t,this.screen.height=e,this.view.width=t*this.resolution,this.view.height=e*this.resolution,this.autoResize&&(this.view.style.width=t+\"px\",this.view.style.height=e+\"px\")},e.prototype.generateTexture=function(t,e,r){var n=t.getLocalBounds(),i=y.default.create(0|n.width,0|n.height,e,r);return _.tx=-n.x,_.ty=-n.y,this.render(t,i,!1,_,!0),i},e.prototype.destroy=function(t){t&&this.view.parentNode&&this.view.parentNode.removeChild(this.view),this.type=l.RENDERER_TYPE.UNKNOWN,this.view=null,this.screen=null,this.resolution=0,this.transparent=!1,this.autoResize=!1,this.blendModes=null,this.options=null,this.preserveDrawingBuffer=!1,this.clearBeforeRender=!1,this.roundPixels=!1,this._backgroundColor=0,this._backgroundColorRgba=null,this._backgroundColorString=null,this._tempDisplayObjectParent=null,this._lastObjectRendered=null},a(e,[{key:\"width\",get:function(){return this.view.width}},{key:\"height\",get:function(){return this.view.height}},{key:\"backgroundColor\",get:function(){return this._backgroundColor},set:function(t){this._backgroundColor=t,this._backgroundColorString=(0,u.hex2string)(t),(0,u.hex2rgb)(t,this._backgroundColorRgba)}}]),e}(m.default);r.default=b},{\"../const\":46,\"../display/Container\":48,\"../math\":70,\"../settings\":101,\"../textures/RenderTexture\":113,\"../utils\":124,eventemitter3:3}],77:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"../SystemRenderer\"),u=n(a),h=t(\"./utils/CanvasMaskManager\"),l=n(h),c=t(\"./utils/CanvasRenderTarget\"),d=n(c),f=t(\"./utils/mapCanvasBlendModesToPixi\"),p=n(f),v=t(\"../../utils\"),y=t(\"../../const\"),g=t(\"../../settings\"),m=n(g),_=function(t){function e(r,n,s){i(this,e);var a=o(this,t.call(this,\"Canvas\",r,n,s));return a.type=y.RENDERER_TYPE.CANVAS,a.rootContext=a.view.getContext(\"2d\",{alpha:a.transparent}),a.context=a.rootContext,a.refresh=!0,a.maskManager=new l.default(a),a.smoothProperty=\"imageSmoothingEnabled\",a.rootContext.imageSmoothingEnabled||(a.rootContext.webkitImageSmoothingEnabled?a.smoothProperty=\"webkitImageSmoothingEnabled\":a.rootContext.mozImageSmoothingEnabled?a.smoothProperty=\"mozImageSmoothingEnabled\":a.rootContext.oImageSmoothingEnabled?a.smoothProperty=\"oImageSmoothingEnabled\":a.rootContext.msImageSmoothingEnabled&&(a.smoothProperty=\"msImageSmoothingEnabled\")),a.initPlugins(),a.blendModes=(0,p.default)(),a._activeBlendMode=null,a.renderingToScreen=!1,a.resize(a.options.width,a.options.height),a}return s(e,t),e.prototype.render=function(t,e,r,n,i){if(this.view){this.renderingToScreen=!e,this.emit(\"prerender\");var o=this.resolution;e?(e=e.baseTexture||e,e._canvasRenderTarget||(e._canvasRenderTarget=new d.default(e.width,e.height,e.resolution),e.source=e._canvasRenderTarget.canvas,e.valid=!0),this.context=e._canvasRenderTarget.context,this.resolution=e._canvasRenderTarget.resolution):this.context=this.rootContext;var s=this.context;if(e||(this._lastObjectRendered=t),!i){var a=t.parent,u=this._tempDisplayObjectParent.transform.worldTransform;n?(n.copy(u),this._tempDisplayObjectParent.transform._worldID=-1):u.identity(),t.parent=this._tempDisplayObjectParent,t.updateTransform(),t.parent=a}s.setTransform(1,0,0,1,0,0),s.globalAlpha=1,this._activeBlendMode=y.BLEND_MODES.NORMAL,s.globalCompositeOperation=this.blendModes[y.BLEND_MODES.NORMAL],navigator.isCocoonJS&&this.view.screencanvas&&(s.fillStyle=\"black\",s.clear()),(void 0!==r?r:this.clearBeforeRender)&&this.renderingToScreen&&(this.transparent?s.clearRect(0,0,this.width,this.height):(s.fillStyle=this._backgroundColorString,s.fillRect(0,0,this.width,this.height)));var h=this.context;this.context=s,t.renderCanvas(this),this.context=h,this.resolution=o,this.emit(\"postrender\")}},e.prototype.clear=function(t){var e=this.context;t=t||this._backgroundColorString,!this.transparent&&t?(e.fillStyle=t,e.fillRect(0,0,this.width,this.height)):e.clearRect(0,0,this.width,this.height)},e.prototype.setBlendMode=function(t){this._activeBlendMode!==t&&(this._activeBlendMode=t,this.context.globalCompositeOperation=this.blendModes[t])},e.prototype.destroy=function(e){this.destroyPlugins(),t.prototype.destroy.call(this,e),this.context=null,this.refresh=!0,this.maskManager.destroy(),this.maskManager=null,this.smoothProperty=null},e.prototype.resize=function(e,r){t.prototype.resize.call(this,e,r),this.smoothProperty&&(this.rootContext[this.smoothProperty]=m.default.SCALE_MODE===y.SCALE_MODES.LINEAR)},e.prototype.invalidateBlendMode=function(){this._activeBlendMode=this.blendModes.indexOf(this.context.globalCompositeOperation)},e}(u.default);r.default=_,v.pluginTarget.mixin(_)},{\"../../const\":46,\"../../settings\":101,\"../../utils\":124,\"../SystemRenderer\":76,\"./utils/CanvasMaskManager\":78,\"./utils/CanvasRenderTarget\":79,\"./utils/mapCanvasBlendModesToPixi\":81}],78:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../../../const\"),o=function(){function t(e){n(this,t),this.renderer=e}return t.prototype.pushMask=function(t){var e=this.renderer;e.context.save();var r=t.alpha,n=t.transform.worldTransform,i=e.resolution;e.context.setTransform(n.a*i,n.b*i,n.c*i,n.d*i,n.tx*i,n.ty*i),t._texture||(this.renderGraphicsShape(t),e.context.clip()),t.worldAlpha=r},t.prototype.renderGraphicsShape=function(t){var e=this.renderer.context,r=t.graphicsData.length;if(0!==r){e.beginPath();for(var n=0;n<r;n++){var o=t.graphicsData[n],s=o.shape;if(o.type===i.SHAPES.POLY){var a=s.points;e.moveTo(a[0],a[1]);for(var u=1;u<a.length/2;u++)e.lineTo(a[2*u],a[2*u+1]);a[0]===a[a.length-2]&&a[1]===a[a.length-1]&&e.closePath()}else if(o.type===i.SHAPES.RECT)e.rect(s.x,s.y,s.width,s.height),e.closePath();else if(o.type===i.SHAPES.CIRC)e.arc(s.x,s.y,s.radius,0,2*Math.PI),e.closePath();else if(o.type===i.SHAPES.ELIP){var h=2*s.width,l=2*s.height,c=s.x-h/2,d=s.y-l/2,f=h/2*.5522848,p=l/2*.5522848,v=c+h,y=d+l,g=c+h/2,m=d+l/2;e.moveTo(c,m),e.bezierCurveTo(c,m-p,g-f,d,g,d),e.bezierCurveTo(g+f,d,v,m-p,v,m),e.bezierCurveTo(v,m+p,g+f,y,g,y),e.bezierCurveTo(g-f,y,c,m+p,c,m),e.closePath()}else if(o.type===i.SHAPES.RREC){var _=s.x,b=s.y,x=s.width,T=s.height,w=s.radius,E=Math.min(x,T)/2|0;w=w>E?E:w,e.moveTo(_,b+w),e.lineTo(_,b+T-w),e.quadraticCurveTo(_,b+T,_+w,b+T),e.lineTo(_+x-w,b+T),e.quadraticCurveTo(_+x,b+T,_+x,b+T-w),e.lineTo(_+x,b+w),e.quadraticCurveTo(_+x,b,_+x-w,b),e.lineTo(_+w,b),e.quadraticCurveTo(_,b,_,b+w),e.closePath()}}}},t.prototype.popMask=function(t){t.context.restore(),t.invalidateBlendMode()},t.prototype.destroy=function(){},t}();r.default=o},{\"../../../const\":46}],79:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),o=t(\"../../../settings\"),s=function(t){return t&&t.__esModule?t:{default:t}}(o),a=function(){function t(e,r,i){n(this,t),this.canvas=document.createElement(\"canvas\"),this.context=this.canvas.getContext(\"2d\"),this.resolution=i||s.default.RESOLUTION,this.resize(e,r)}return t.prototype.clear=function(){this.context.setTransform(1,0,0,1,0,0),this.context.clearRect(0,0,this.canvas.width,this.canvas.height)},t.prototype.resize=function(t,e){this.canvas.width=t*this.resolution,this.canvas.height=e*this.resolution},t.prototype.destroy=function(){this.context=null,this.canvas=null},i(t,[{key:\"width\",get:function(){return this.canvas.width},set:function(t){this.canvas.width=t}},{key:\"height\",get:function(){return this.canvas.height},set:function(t){this.canvas.height=t}}]),t}();r.default=a},{\"../../../settings\":101}],80:[function(t,e,r){\"use strict\";function n(t){var e=document.createElement(\"canvas\");e.width=6,e.height=1;var r=e.getContext(\"2d\");return r.fillStyle=t,r.fillRect(0,0,6,1),e}function i(){if(\"undefined\"==typeof document)return!1;var t=n(\"#ff00ff\"),e=n(\"#ffff00\"),r=document.createElement(\"canvas\");r.width=6,r.height=1;var i=r.getContext(\"2d\");i.globalCompositeOperation=\"multiply\",i.drawImage(t,0,0),i.drawImage(e,2,0);var o=i.getImageData(2,0,1,1);if(!o)return!1;var s=o.data;return 255===s[0]&&0===s[1]&&0===s[2]}r.__esModule=!0,r.default=i},{}],81:[function(t,e,r){\"use strict\";function n(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];return(0,s.default)()?(t[i.BLEND_MODES.NORMAL]=\"source-over\",t[i.BLEND_MODES.ADD]=\"lighter\",t[i.BLEND_MODES.MULTIPLY]=\"multiply\",t[i.BLEND_MODES.SCREEN]=\"screen\",t[i.BLEND_MODES.OVERLAY]=\"overlay\",t[i.BLEND_MODES.DARKEN]=\"darken\",t[i.BLEND_MODES.LIGHTEN]=\"lighten\",t[i.BLEND_MODES.COLOR_DODGE]=\"color-dodge\",t[i.BLEND_MODES.COLOR_BURN]=\"color-burn\",\nt[i.BLEND_MODES.HARD_LIGHT]=\"hard-light\",t[i.BLEND_MODES.SOFT_LIGHT]=\"soft-light\",t[i.BLEND_MODES.DIFFERENCE]=\"difference\",t[i.BLEND_MODES.EXCLUSION]=\"exclusion\",t[i.BLEND_MODES.HUE]=\"hue\",t[i.BLEND_MODES.SATURATION]=\"saturate\",t[i.BLEND_MODES.COLOR]=\"color\",t[i.BLEND_MODES.LUMINOSITY]=\"luminosity\"):(t[i.BLEND_MODES.NORMAL]=\"source-over\",t[i.BLEND_MODES.ADD]=\"lighter\",t[i.BLEND_MODES.MULTIPLY]=\"source-over\",t[i.BLEND_MODES.SCREEN]=\"source-over\",t[i.BLEND_MODES.OVERLAY]=\"source-over\",t[i.BLEND_MODES.DARKEN]=\"source-over\",t[i.BLEND_MODES.LIGHTEN]=\"source-over\",t[i.BLEND_MODES.COLOR_DODGE]=\"source-over\",t[i.BLEND_MODES.COLOR_BURN]=\"source-over\",t[i.BLEND_MODES.HARD_LIGHT]=\"source-over\",t[i.BLEND_MODES.SOFT_LIGHT]=\"source-over\",t[i.BLEND_MODES.DIFFERENCE]=\"source-over\",t[i.BLEND_MODES.EXCLUSION]=\"source-over\",t[i.BLEND_MODES.HUE]=\"source-over\",t[i.BLEND_MODES.SATURATION]=\"source-over\",t[i.BLEND_MODES.COLOR]=\"source-over\",t[i.BLEND_MODES.LUMINOSITY]=\"source-over\"),t[i.BLEND_MODES.NORMAL_NPM]=t[i.BLEND_MODES.NORMAL],t[i.BLEND_MODES.ADD_NPM]=t[i.BLEND_MODES.ADD],t[i.BLEND_MODES.SCREEN_NPM]=t[i.BLEND_MODES.SCREEN],t}r.__esModule=!0,r.default=n;var i=t(\"../../../const\"),o=t(\"./canUseNewCanvasBlendModes\"),s=function(t){return t&&t.__esModule?t:{default:t}}(o)},{\"../../../const\":46,\"./canUseNewCanvasBlendModes\":80}],82:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../../const\"),o=t(\"../../settings\"),s=function(t){return t&&t.__esModule?t:{default:t}}(o),a=function(){function t(e){n(this,t),this.renderer=e,this.count=0,this.checkCount=0,this.maxIdle=s.default.GC_MAX_IDLE,this.checkCountMax=s.default.GC_MAX_CHECK_COUNT,this.mode=s.default.GC_MODE}return t.prototype.update=function(){this.count++,this.mode!==i.GC_MODES.MANUAL&&++this.checkCount>this.checkCountMax&&(this.checkCount=0,this.run())},t.prototype.run=function(){for(var t=this.renderer.textureManager,e=t._managedTextures,r=!1,n=0;n<e.length;n++){var i=e[n];!i._glRenderTargets&&this.count-i.touched>this.maxIdle&&(t.destroyTexture(i,!0),e[n]=null,r=!0)}if(r){for(var o=0,s=0;s<e.length;s++)null!==e[s]&&(e[o++]=e[s]);e.length=o}},t.prototype.unload=function(t){var e=this.renderer.textureManager;t._texture&&t._texture._glRenderTargets&&e.destroyTexture(t._texture,!0);for(var r=t.children.length-1;r>=0;r--)this.unload(t.children[r])},t}();r.default=a},{\"../../const\":46,\"../../settings\":101}],83:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"pixi-gl-core\"),o=t(\"../../const\"),s=t(\"./utils/RenderTarget\"),a=function(t){return t&&t.__esModule?t:{default:t}}(s),u=t(\"../../utils\"),h=function(){function t(e){n(this,t),this.renderer=e,this.gl=e.gl,this._managedTextures=[]}return t.prototype.bindTexture=function(){},t.prototype.getTexture=function(){},t.prototype.updateTexture=function(t,e){var r=this.gl,n=!!t._glRenderTargets;if(!t.hasLoaded)return null;var s=this.renderer.boundTextures;if(void 0===e){e=0;for(var u=0;u<s.length;++u)if(s[u]===t){e=u;break}}s[e]=t,r.activeTexture(r.TEXTURE0+e);var h=t._glTextures[this.renderer.CONTEXT_UID];if(h)n?t._glRenderTargets[this.renderer.CONTEXT_UID].resize(t.width,t.height):h.upload(t.source);else{if(n){var l=new a.default(this.gl,t.width,t.height,t.scaleMode,t.resolution);l.resize(t.width,t.height),t._glRenderTargets[this.renderer.CONTEXT_UID]=l,h=l.texture}else h=new i.GLTexture(this.gl,null,null,null,null),h.bind(e),h.premultiplyAlpha=!0,h.upload(t.source);t._glTextures[this.renderer.CONTEXT_UID]=h,t.on(\"update\",this.updateTexture,this),t.on(\"dispose\",this.destroyTexture,this),this._managedTextures.push(t),t.isPowerOfTwo?(t.mipmap&&h.enableMipmap(),t.wrapMode===o.WRAP_MODES.CLAMP?h.enableWrapClamp():t.wrapMode===o.WRAP_MODES.REPEAT?h.enableWrapRepeat():h.enableWrapMirrorRepeat()):h.enableWrapClamp(),t.scaleMode===o.SCALE_MODES.NEAREST?h.enableNearestScaling():h.enableLinearScaling()}return h},t.prototype.destroyTexture=function(t,e){if(t=t.baseTexture||t,t.hasLoaded){var r=this.renderer.CONTEXT_UID,n=t._glTextures,i=t._glRenderTargets;if(n[r]&&(this.renderer.unbindTexture(t),n[r].destroy(),t.off(\"update\",this.updateTexture,this),t.off(\"dispose\",this.destroyTexture,this),delete n[r],!e)){var o=this._managedTextures.indexOf(t);-1!==o&&(0,u.removeItems)(this._managedTextures,o,1)}i&&i[r]&&(i[r].destroy(),delete i[r])}},t.prototype.removeAll=function(){for(var t=0;t<this._managedTextures.length;++t){var e=this._managedTextures[t];e._glTextures[this.renderer.CONTEXT_UID]&&delete e._glTextures[this.renderer.CONTEXT_UID]}},t.prototype.destroy=function(){for(var t=0;t<this._managedTextures.length;++t){var e=this._managedTextures[t];this.destroyTexture(e,!0),e.off(\"update\",this.updateTexture,this),e.off(\"dispose\",this.destroyTexture,this)}this._managedTextures=null},t}();r.default=h},{\"../../const\":46,\"../../utils\":124,\"./utils/RenderTarget\":96,\"pixi-gl-core\":15}],84:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"../SystemRenderer\"),u=n(a),h=t(\"./managers/MaskManager\"),l=n(h),c=t(\"./managers/StencilManager\"),d=n(c),f=t(\"./managers/FilterManager\"),p=n(f),v=t(\"./utils/RenderTarget\"),y=n(v),g=t(\"./utils/ObjectRenderer\"),m=n(g),_=t(\"./TextureManager\"),b=n(_),x=t(\"../../textures/BaseTexture\"),T=n(x),w=t(\"./TextureGarbageCollector\"),E=n(w),S=t(\"./WebGLState\"),O=n(S),M=t(\"./utils/mapWebGLDrawModesToPixi\"),P=n(M),C=t(\"./utils/validateContext\"),R=n(C),A=t(\"../../utils\"),I=t(\"pixi-gl-core\"),D=n(I),L=t(\"../../const\"),N=0,F=function(t){function e(r,n,s){i(this,e);var a=o(this,t.call(this,\"WebGL\",r,n,s));return a.legacy=a.options.legacy,a.legacy&&(D.default.VertexArrayObject.FORCE_NATIVE=!0),a.type=L.RENDERER_TYPE.WEBGL,a.handleContextLost=a.handleContextLost.bind(a),a.handleContextRestored=a.handleContextRestored.bind(a),a.view.addEventListener(\"webglcontextlost\",a.handleContextLost,!1),a.view.addEventListener(\"webglcontextrestored\",a.handleContextRestored,!1),a._contextOptions={alpha:a.transparent,antialias:a.options.antialias,premultipliedAlpha:a.transparent&&\"notMultiplied\"!==a.transparent,stencil:!0,preserveDrawingBuffer:a.options.preserveDrawingBuffer,powerPreference:a.options.powerPreference},a._backgroundColorRgba[3]=a.transparent?0:1,a.maskManager=new l.default(a),a.stencilManager=new d.default(a),a.emptyRenderer=new m.default(a),a.currentRenderer=a.emptyRenderer,a.textureManager=null,a.filterManager=null,a.initPlugins(),a.options.context&&(0,R.default)(a.options.context),a.gl=a.options.context||D.default.createContext(a.view,a._contextOptions),a.CONTEXT_UID=N++,a.state=new O.default(a.gl),a.renderingToScreen=!0,a.boundTextures=null,a._activeShader=null,a._activeVao=null,a._activeRenderTarget=null,a._initContext(),a.drawModes=(0,P.default)(a.gl),a._nextTextureLocation=0,a.setBlendMode(0),a}return s(e,t),e.prototype._initContext=function(){var t=this.gl;t.isContextLost()&&t.getExtension(\"WEBGL_lose_context\")&&t.getExtension(\"WEBGL_lose_context\").restoreContext();var e=t.getParameter(t.MAX_TEXTURE_IMAGE_UNITS);this._activeShader=null,this._activeVao=null,this.boundTextures=new Array(e),this.emptyTextures=new Array(e),this.textureManager=new b.default(this),this.filterManager=new p.default(this),this.textureGC=new E.default(this),this.state.resetToDefault(),this.rootRenderTarget=new y.default(t,this.width,this.height,null,this.resolution,!0),this.rootRenderTarget.clearColor=this._backgroundColorRgba,this.bindRenderTarget(this.rootRenderTarget);var r=new D.default.GLTexture.fromData(t,null,1,1),n={_glTextures:{}};n._glTextures[this.CONTEXT_UID]={};for(var i=0;i<e;i++){var o=new T.default;o._glTextures[this.CONTEXT_UID]=r,this.boundTextures[i]=n,this.emptyTextures[i]=o,this.bindTexture(null,i)}this.emit(\"context\",t),this.resize(this.screen.width,this.screen.height)},e.prototype.render=function(t,e,r,n,i){if(this.renderingToScreen=!e,this.emit(\"prerender\"),this.gl&&!this.gl.isContextLost()){if(this._nextTextureLocation=0,e||(this._lastObjectRendered=t),!i){var o=t.parent;t.parent=this._tempDisplayObjectParent,t.updateTransform(),t.parent=o}this.bindRenderTexture(e,n),this.currentRenderer.start(),(void 0!==r?r:this.clearBeforeRender)&&this._activeRenderTarget.clear(),t.renderWebGL(this),this.currentRenderer.flush(),this.textureGC.update(),this.emit(\"postrender\")}},e.prototype.setObjectRenderer=function(t){this.currentRenderer!==t&&(this.currentRenderer.stop(),this.currentRenderer=t,this.currentRenderer.start())},e.prototype.flush=function(){this.setObjectRenderer(this.emptyRenderer)},e.prototype.resize=function(t,e){u.default.prototype.resize.call(this,t,e),this.rootRenderTarget.resize(t,e),this._activeRenderTarget===this.rootRenderTarget&&(this.rootRenderTarget.activate(),this._activeShader&&(this._activeShader.uniforms.projectionMatrix=this.rootRenderTarget.projectionMatrix.toArray(!0)))},e.prototype.setBlendMode=function(t){this.state.setBlendMode(t)},e.prototype.clear=function(t){this._activeRenderTarget.clear(t)},e.prototype.setTransform=function(t){this._activeRenderTarget.transform=t},e.prototype.clearRenderTexture=function(t,e){var r=t.baseTexture,n=r._glRenderTargets[this.CONTEXT_UID];return n&&n.clear(e),this},e.prototype.bindRenderTexture=function(t,e){var r=void 0;if(t){var n=t.baseTexture;n._glRenderTargets[this.CONTEXT_UID]||this.textureManager.updateTexture(n,0),this.unbindTexture(n),r=n._glRenderTargets[this.CONTEXT_UID],r.setFrame(t.frame)}else r=this.rootRenderTarget;return r.transform=e,this.bindRenderTarget(r),this},e.prototype.bindRenderTarget=function(t){return t!==this._activeRenderTarget&&(this._activeRenderTarget=t,t.activate(),this._activeShader&&(this._activeShader.uniforms.projectionMatrix=t.projectionMatrix.toArray(!0)),this.stencilManager.setMaskStack(t.stencilMaskStack)),this},e.prototype.bindShader=function(t,e){return this._activeShader!==t&&(this._activeShader=t,t.bind(),!1!==e&&(t.uniforms.projectionMatrix=this._activeRenderTarget.projectionMatrix.toArray(!0))),this},e.prototype.bindTexture=function(t,e,r){if(t=t||this.emptyTextures[e],t=t.baseTexture||t,t.touched=this.textureGC.count,r)e=e||0;else{for(var n=0;n<this.boundTextures.length;n++)if(this.boundTextures[n]===t)return n;void 0===e&&(this._nextTextureLocation++,this._nextTextureLocation%=this.boundTextures.length,e=this.boundTextures.length-this._nextTextureLocation-1)}var i=this.gl,o=t._glTextures[this.CONTEXT_UID];return o?(this.boundTextures[e]=t,i.activeTexture(i.TEXTURE0+e),i.bindTexture(i.TEXTURE_2D,o.texture)):this.textureManager.updateTexture(t,e),e},e.prototype.unbindTexture=function(t){var e=this.gl;t=t.baseTexture||t;for(var r=0;r<this.boundTextures.length;r++)this.boundTextures[r]===t&&(this.boundTextures[r]=this.emptyTextures[r],e.activeTexture(e.TEXTURE0+r),e.bindTexture(e.TEXTURE_2D,this.emptyTextures[r]._glTextures[this.CONTEXT_UID].texture));return this},e.prototype.createVao=function(){return new D.default.VertexArrayObject(this.gl,this.state.attribState)},e.prototype.bindVao=function(t){return this._activeVao===t?this:(t?t.bind():this._activeVao&&this._activeVao.unbind(),this._activeVao=t,this)},e.prototype.reset=function(){return this.setObjectRenderer(this.emptyRenderer),this._activeShader=null,this._activeRenderTarget=this.rootRenderTarget,this.rootRenderTarget.activate(),this.state.resetToDefault(),this},e.prototype.handleContextLost=function(t){t.preventDefault()},e.prototype.handleContextRestored=function(){this.textureManager.removeAll(),this.filterManager.destroy(!0),this._initContext()},e.prototype.destroy=function(e){this.destroyPlugins(),this.view.removeEventListener(\"webglcontextlost\",this.handleContextLost),this.view.removeEventListener(\"webglcontextrestored\",this.handleContextRestored),this.textureManager.destroy(),t.prototype.destroy.call(this,e),this.uid=0,this.maskManager.destroy(),this.stencilManager.destroy(),this.filterManager.destroy(),this.maskManager=null,this.filterManager=null,this.textureManager=null,this.currentRenderer=null,this.handleContextLost=null,this.handleContextRestored=null,this._contextOptions=null,this.gl.useProgram(null),this.gl.getExtension(\"WEBGL_lose_context\")&&this.gl.getExtension(\"WEBGL_lose_context\").loseContext(),this.gl=null},e}(u.default);r.default=F,A.pluginTarget.mixin(F)},{\"../../const\":46,\"../../textures/BaseTexture\":112,\"../../utils\":124,\"../SystemRenderer\":76,\"./TextureGarbageCollector\":82,\"./TextureManager\":83,\"./WebGLState\":85,\"./managers/FilterManager\":90,\"./managers/MaskManager\":91,\"./managers/StencilManager\":92,\"./utils/ObjectRenderer\":94,\"./utils/RenderTarget\":96,\"./utils/mapWebGLDrawModesToPixi\":99,\"./utils/validateContext\":100,\"pixi-gl-core\":15}],85:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"./utils/mapWebGLBlendModesToPixi\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=function(){function t(e){n(this,t),this.activeState=new Uint8Array(16),this.defaultState=new Uint8Array(16),this.defaultState[0]=1,this.stackIndex=0,this.stack=[],this.gl=e,this.maxAttribs=e.getParameter(e.MAX_VERTEX_ATTRIBS),this.attribState={tempAttribState:new Array(this.maxAttribs),attribState:new Array(this.maxAttribs)},this.blendModes=(0,o.default)(e),this.nativeVaoExtension=e.getExtension(\"OES_vertex_array_object\")||e.getExtension(\"MOZ_OES_vertex_array_object\")||e.getExtension(\"WEBKIT_OES_vertex_array_object\")}return t.prototype.push=function(){var t=this.stack[this.stackIndex];t||(t=this.stack[this.stackIndex]=new Uint8Array(16)),++this.stackIndex;for(var e=0;e<this.activeState.length;e++)t[e]=this.activeState[e]},t.prototype.pop=function(){var t=this.stack[--this.stackIndex];this.setState(t)},t.prototype.setState=function(t){this.setBlend(t[0]),this.setDepthTest(t[1]),this.setFrontFace(t[2]),this.setCullFace(t[3]),this.setBlendMode(t[4])},t.prototype.setBlend=function(t){t=t?1:0,this.activeState[0]!==t&&(this.activeState[0]=t,this.gl[t?\"enable\":\"disable\"](this.gl.BLEND))},t.prototype.setBlendMode=function(t){if(t!==this.activeState[4]){this.activeState[4]=t;var e=this.blendModes[t];2===e.length?this.gl.blendFunc(e[0],e[1]):this.gl.blendFuncSeparate(e[0],e[1],e[2],e[3])}},t.prototype.setDepthTest=function(t){t=t?1:0,this.activeState[1]!==t&&(this.activeState[1]=t,this.gl[t?\"enable\":\"disable\"](this.gl.DEPTH_TEST))},t.prototype.setCullFace=function(t){t=t?1:0,this.activeState[3]!==t&&(this.activeState[3]=t,this.gl[t?\"enable\":\"disable\"](this.gl.CULL_FACE))},t.prototype.setFrontFace=function(t){t=t?1:0,this.activeState[2]!==t&&(this.activeState[2]=t,this.gl.frontFace(this.gl[t?\"CW\":\"CCW\"]))},t.prototype.resetAttributes=function(){for(var t=0;t<this.attribState.tempAttribState.length;t++)this.attribState.tempAttribState[t]=0;for(var e=0;e<this.attribState.attribState.length;e++)this.attribState.attribState[e]=0;for(var r=1;r<this.maxAttribs;r++)this.gl.disableVertexAttribArray(r)},t.prototype.resetToDefault=function(){this.nativeVaoExtension&&this.nativeVaoExtension.bindVertexArrayOES(null),this.resetAttributes();for(var t=0;t<this.activeState.length;++t)this.activeState[t]=32;this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL,!1),this.setState(this.defaultState)},t}();r.default=s},{\"./utils/mapWebGLBlendModesToPixi\":98}],86:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var o=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),s=t(\"./extractUniformsFromSrc\"),a=n(s),u=t(\"../../../utils\"),h=t(\"../../../const\"),l=t(\"../../../settings\"),c=n(l),d={},f=function(){function t(e,r,n){i(this,t),this.vertexSrc=e||t.defaultVertexSrc,this.fragmentSrc=r||t.defaultFragmentSrc,this._blendMode=h.BLEND_MODES.NORMAL,this.uniformData=n||(0,a.default)(this.vertexSrc,this.fragmentSrc,\"projectionMatrix|uSampler\"),this.uniforms={};for(var o in this.uniformData)this.uniforms[o]=this.uniformData[o].value,this.uniformData[o].type&&(this.uniformData[o].type=this.uniformData[o].type.toLowerCase());this.glShaders={},d[this.vertexSrc+this.fragmentSrc]||(d[this.vertexSrc+this.fragmentSrc]=(0,u.uid)()),this.glShaderKey=d[this.vertexSrc+this.fragmentSrc],this.padding=4,this.resolution=c.default.RESOLUTION,this.enabled=!0,this.autoFit=!0}return t.prototype.apply=function(t,e,r,n,i){t.applyFilter(this,e,r,n)},o(t,[{key:\"blendMode\",get:function(){return this._blendMode},set:function(t){this._blendMode=t}}],[{key:\"defaultVertexSrc\",get:function(){return[\"attribute vec2 aVertexPosition;\",\"attribute vec2 aTextureCoord;\",\"uniform mat3 projectionMatrix;\",\"uniform mat3 filterMatrix;\",\"varying vec2 vTextureCoord;\",\"varying vec2 vFilterCoord;\",\"void main(void){\",\"   gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\",\"   vFilterCoord = ( filterMatrix * vec3( aTextureCoord, 1.0)  ).xy;\",\"   vTextureCoord = aTextureCoord ;\",\"}\"].join(\"\\n\")}},{key:\"defaultFragmentSrc\",get:function(){return[\"varying vec2 vTextureCoord;\",\"varying vec2 vFilterCoord;\",\"uniform sampler2D uSampler;\",\"uniform sampler2D filterSampler;\",\"void main(void){\",\"   vec4 masky = texture2D(filterSampler, vFilterCoord);\",\"   vec4 sample = texture2D(uSampler, vTextureCoord);\",\"   vec4 color;\",\"   if(mod(vFilterCoord.x, 1.0) > 0.5)\",\"   {\",\"     color = vec4(1.0, 0.0, 0.0, 1.0);\",\"   }\",\"   else\",\"   {\",\"     color = vec4(0.0, 1.0, 0.0, 1.0);\",\"   }\",\"   gl_FragColor = mix(sample, masky, 0.5);\",\"   gl_FragColor *= sample.a;\",\"}\"].join(\"\\n\")}}]),t}();r.default=f},{\"../../../const\":46,\"../../../settings\":101,\"../../../utils\":124,\"./extractUniformsFromSrc\":87}],87:[function(t,e,r){\"use strict\";function n(t,e,r){var n=i(t),o=i(e);return Object.assign(n,o)}function i(t){for(var e=new RegExp(\"^(projectionMatrix|uSampler|filterArea|filterClamp)$\"),r={},n=void 0,i=t.replace(/\\s+/g,\" \").split(/\\s*;\\s*/),o=0;o<i.length;o++){var s=i[o].trim();if(s.indexOf(\"uniform\")>-1){var u=s.split(\" \"),h=u[1],l=u[2],c=1;l.indexOf(\"[\")>-1&&(n=l.split(/\\[|]/),l=n[0],c*=Number(n[1])),l.match(e)||(r[l]={value:a(h,c),name:l,type:h})}}return r}r.__esModule=!0,r.default=n;var o=t(\"pixi-gl-core\"),s=function(t){return t&&t.__esModule?t:{default:t}}(o),a=s.default.shader.defaultValue},{\"pixi-gl-core\":15}],88:[function(t,e,r){\"use strict\";function n(t,e,r){var n=t.identity();return n.translate(e.x/r.width,e.y/r.height),n.scale(r.width,r.height),n}function i(t,e,r){var n=t.identity();n.translate(e.x/r.width,e.y/r.height);var i=r.width/e.width,o=r.height/e.height;return n.scale(i,o),n}function o(t,e,r,n){var i=n._texture.baseTexture,o=t.set(r.width,0,0,r.height,e.x,e.y),a=n.worldTransform.copy(s.Matrix.TEMP_MATRIX);return a.invert(),o.prepend(a),o.scale(1/i.width,1/i.height),o.translate(n.anchor.x,n.anchor.y),o}r.__esModule=!0,r.calculateScreenSpaceMatrix=n,r.calculateNormalizedScreenSpaceMatrix=i,r.calculateSpriteMatrix=o;var s=t(\"../../../math\")},{\"../../../math\":70}],89:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=t(\"../Filter\"),a=function(t){return t&&t.__esModule?t:{default:t}}(s),u=t(\"../../../../math\"),h=(t(\"path\"),function(t){function e(r){n(this,e);var o=new u.Matrix,s=i(this,t.call(this,\"attribute vec2 aVertexPosition;\\nattribute vec2 aTextureCoord;\\n\\nuniform mat3 projectionMatrix;\\nuniform mat3 otherMatrix;\\n\\nvarying vec2 vMaskCoord;\\nvarying vec2 vTextureCoord;\\n\\nvoid main(void)\\n{\\n    gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\\n\\n    vTextureCoord = aTextureCoord;\\n    vMaskCoord = ( otherMatrix * vec3( aTextureCoord, 1.0)  ).xy;\\n}\\n\",\"varying vec2 vMaskCoord;\\nvarying vec2 vTextureCoord;\\n\\nuniform sampler2D uSampler;\\nuniform float alpha;\\nuniform sampler2D mask;\\n\\nvoid main(void)\\n{\\n    // check clip! this will stop the mask bleeding out from the edges\\n    vec2 text = abs( vMaskCoord - 0.5 );\\n    text = step(0.5, text);\\n\\n    float clip = 1.0 - max(text.y, text.x);\\n    vec4 original = texture2D(uSampler, vTextureCoord);\\n    vec4 masky = texture2D(mask, vMaskCoord);\\n\\n    original *= (masky.r * masky.a * alpha * clip);\\n\\n    gl_FragColor = original;\\n}\\n\"));return r.renderable=!1,s.maskSprite=r,s.maskMatrix=o,s}return o(e,t),e.prototype.apply=function(t,e,r){var n=this.maskSprite;this.uniforms.mask=n._texture,this.uniforms.otherMatrix=t.calculateSpriteMatrix(this.maskMatrix,n),this.uniforms.alpha=n.worldAlpha,t.applyFilter(this,e,r)},e}(a.default));r.default=h},{\"../../../../math\":70,\"../Filter\":86,path:8}],90:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function s(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var a=t(\"./WebGLManager\"),u=n(a),h=t(\"../utils/RenderTarget\"),l=n(h),c=t(\"../utils/Quad\"),d=n(c),f=t(\"../../../math\"),p=t(\"../../../Shader\"),v=n(p),y=t(\"../filters/filterTransforms\"),g=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(y),m=t(\"bit-twiddle\"),_=n(m),b=function t(){s(this,t),this.renderTarget=null,this.sourceFrame=new f.Rectangle,this.destinationFrame=new f.Rectangle,this.filters=[],this.target=null,this.resolution=1},x=function(t){function e(r){s(this,e);var n=i(this,t.call(this,r));return n.gl=n.renderer.gl,n.quad=new d.default(n.gl,r.state.attribState),n.shaderCache={},n.pool={},n.filterData=null,n.managedFilters=[],n}return o(e,t),e.prototype.pushFilter=function(t,e){var r=this.renderer,n=this.filterData;if(!n){n=this.renderer._activeRenderTarget.filterStack;var i=new b;i.sourceFrame=i.destinationFrame=this.renderer._activeRenderTarget.size,i.renderTarget=r._activeRenderTarget,this.renderer._activeRenderTarget.filterData=n={index:0,stack:[i]},this.filterData=n}var o=n.stack[++n.index];o||(o=n.stack[n.index]=new b);var s=e[0].resolution,a=0|e[0].padding,u=t.filterArea||t.getBounds(!0),h=o.sourceFrame,l=o.destinationFrame;h.x=(u.x*s|0)/s,h.y=(u.y*s|0)/s,h.width=(u.width*s|0)/s,h.height=(u.height*s|0)/s,n.stack[0].renderTarget.transform||e[0].autoFit&&h.fit(n.stack[0].destinationFrame),h.pad(a),l.width=h.width,l.height=h.height;var c=this.getPotRenderTarget(r.gl,h.width,h.height,s);o.target=t,o.filters=e,o.resolution=s,o.renderTarget=c,c.setFrame(l,h),r.bindRenderTarget(c),c.clear()},e.prototype.popFilter=function(){var t=this.filterData,e=t.stack[t.index-1],r=t.stack[t.index];this.quad.map(r.renderTarget.size,r.sourceFrame).upload();var n=r.filters;if(1===n.length)n[0].apply(this,r.renderTarget,e.renderTarget,!1,r),this.freePotRenderTarget(r.renderTarget);else{var i=r.renderTarget,o=this.getPotRenderTarget(this.renderer.gl,r.sourceFrame.width,r.sourceFrame.height,r.resolution);o.setFrame(r.destinationFrame,r.sourceFrame),o.clear();var s=0;for(s=0;s<n.length-1;++s){n[s].apply(this,i,o,!0,r);var a=i;i=o,o=a}n[s].apply(this,i,e.renderTarget,!1,r),this.freePotRenderTarget(i),this.freePotRenderTarget(o)}0===--t.index&&(this.filterData=null)},e.prototype.applyFilter=function(t,e,r,n){var i=this.renderer,o=i.gl,s=t.glShaders[i.CONTEXT_UID];s||(t.glShaderKey?(s=this.shaderCache[t.glShaderKey])||(s=new v.default(this.gl,t.vertexSrc,t.fragmentSrc),t.glShaders[i.CONTEXT_UID]=this.shaderCache[t.glShaderKey]=s):s=t.glShaders[i.CONTEXT_UID]=new v.default(this.gl,t.vertexSrc,t.fragmentSrc),this.managedFilters.push(t),i.bindVao(null),this.quad.initVao(s)),i.bindVao(this.quad.vao),i.bindRenderTarget(r),n&&(o.disable(o.SCISSOR_TEST),i.clear(),o.enable(o.SCISSOR_TEST)),r===i.maskManager.scissorRenderTarget&&i.maskManager.pushScissorMask(null,i.maskManager.scissorData),i.bindShader(s);var a=this.renderer.emptyTextures[0];this.renderer.boundTextures[0]=a,this.syncUniforms(s,t),i.state.setBlendMode(t.blendMode),o.activeTexture(o.TEXTURE0),o.bindTexture(o.TEXTURE_2D,e.texture.texture),this.quad.vao.draw(this.renderer.gl.TRIANGLES,6,0),o.bindTexture(o.TEXTURE_2D,a._glTextures[this.renderer.CONTEXT_UID].texture)},e.prototype.syncUniforms=function(t,e){var r=e.uniformData,n=e.uniforms,i=1,o=void 0;if(t.uniforms.filterArea){o=this.filterData.stack[this.filterData.index];var s=t.uniforms.filterArea;s[0]=o.renderTarget.size.width,s[1]=o.renderTarget.size.height,s[2]=o.sourceFrame.x,s[3]=o.sourceFrame.y,t.uniforms.filterArea=s}if(t.uniforms.filterClamp){o=o||this.filterData.stack[this.filterData.index];var a=t.uniforms.filterClamp;a[0]=0,a[1]=0,a[2]=(o.sourceFrame.width-1)/o.renderTarget.size.width,a[3]=(o.sourceFrame.height-1)/o.renderTarget.size.height,t.uniforms.filterClamp=a}for(var u in r){var h=r[u].type;if(\"sampler2d\"===h&&0!==n[u]){if(n[u].baseTexture)t.uniforms[u]=this.renderer.bindTexture(n[u].baseTexture,i);else{t.uniforms[u]=i;var l=this.renderer.gl;this.renderer.boundTextures[i]=this.renderer.emptyTextures[i],l.activeTexture(l.TEXTURE0+i),n[u].texture.bind()}i++}else if(\"mat3\"===h)void 0!==n[u].a?t.uniforms[u]=n[u].toArray(!0):t.uniforms[u]=n[u];else if(\"vec2\"===h)if(void 0!==n[u].x){var c=t.uniforms[u]||new Float32Array(2);c[0]=n[u].x,c[1]=n[u].y,t.uniforms[u]=c}else t.uniforms[u]=n[u];else\"float\"===h?t.uniforms.data[u].value!==r[u]&&(t.uniforms[u]=n[u]):t.uniforms[u]=n[u]}},e.prototype.getRenderTarget=function(t,e){var r=this.filterData.stack[this.filterData.index],n=this.getPotRenderTarget(this.renderer.gl,r.sourceFrame.width,r.sourceFrame.height,e||r.resolution);return n.setFrame(r.destinationFrame,r.sourceFrame),n},e.prototype.returnRenderTarget=function(t){this.freePotRenderTarget(t)},e.prototype.calculateScreenSpaceMatrix=function(t){var e=this.filterData.stack[this.filterData.index];return g.calculateScreenSpaceMatrix(t,e.sourceFrame,e.renderTarget.size)},e.prototype.calculateNormalizedScreenSpaceMatrix=function(t){var e=this.filterData.stack[this.filterData.index];return g.calculateNormalizedScreenSpaceMatrix(t,e.sourceFrame,e.renderTarget.size,e.destinationFrame)},e.prototype.calculateSpriteMatrix=function(t,e){var r=this.filterData.stack[this.filterData.index];return g.calculateSpriteMatrix(t,r.sourceFrame,r.renderTarget.size,e)},e.prototype.destroy=function(){for(var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0],e=this.renderer,r=this.managedFilters,n=0;n<r.length;n++)t||r[n].glShaders[e.CONTEXT_UID].destroy(),delete r[n].glShaders[e.CONTEXT_UID];this.shaderCache={},t?this.pool={}:this.emptyPool()},e.prototype.getPotRenderTarget=function(t,e,r,n){e=_.default.nextPow2(e*n),r=_.default.nextPow2(r*n);var i=(65535&e)<<16|65535&r;this.pool[i]||(this.pool[i]=[]);var o=this.pool[i].pop();if(!o){var s=this.renderer.boundTextures[0];t.activeTexture(t.TEXTURE0),o=new l.default(t,e,r,null,1),t.bindTexture(t.TEXTURE_2D,s._glTextures[this.renderer.CONTEXT_UID].texture)}return o.resolution=n,o.defaultFrame.width=o.size.width=e/n,o.defaultFrame.height=o.size.height=r/n,o},e.prototype.emptyPool=function(){for(var t in this.pool){var e=this.pool[t];if(e)for(var r=0;r<e.length;r++)e[r].destroy(!0)}this.pool={}},e.prototype.freePotRenderTarget=function(t){var e=t.size.width*t.resolution,r=t.size.height*t.resolution,n=(65535&e)<<16|65535&r;this.pool[n].push(t)},e}(u.default);r.default=x},{\"../../../Shader\":44,\"../../../math\":70,\"../filters/filterTransforms\":88,\"../utils/Quad\":95,\"../utils/RenderTarget\":96,\"./WebGLManager\":93,\"bit-twiddle\":1}],91:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"./WebGLManager\"),u=n(a),h=t(\"../filters/spriteMask/SpriteMaskFilter\"),l=n(h),c=function(t){function e(r){i(this,e);var n=o(this,t.call(this,r));return n.scissor=!1,n.scissorData=null,n.scissorRenderTarget=null,n.enableScissor=!0,n.alphaMaskPool=[],n.alphaMaskIndex=0,n}return s(e,t),e.prototype.pushMask=function(t,e){if(e.texture)this.pushSpriteMask(t,e);else if(this.enableScissor&&!this.scissor&&this.renderer._activeRenderTarget.root&&!this.renderer.stencilManager.stencilMaskStack.length&&e.isFastRect()){var r=e.worldTransform,n=Math.atan2(r.b,r.a);n=Math.round(n*(180/Math.PI)),n%90?this.pushStencilMask(e):this.pushScissorMask(t,e)}else this.pushStencilMask(e)},e.prototype.popMask=function(t,e){e.texture?this.popSpriteMask(t,e):this.enableScissor&&!this.renderer.stencilManager.stencilMaskStack.length?this.popScissorMask(t,e):this.popStencilMask(t,e)},e.prototype.pushSpriteMask=function(t,e){var r=this.alphaMaskPool[this.alphaMaskIndex];r||(r=this.alphaMaskPool[this.alphaMaskIndex]=[new l.default(e)]),r[0].resolution=this.renderer.resolution,r[0].maskSprite=e,t.filterArea=e.getBounds(!0),this.renderer.filterManager.pushFilter(t,r),this.alphaMaskIndex++},e.prototype.popSpriteMask=function(){this.renderer.filterManager.popFilter(),this.alphaMaskIndex--},e.prototype.pushStencilMask=function(t){this.renderer.currentRenderer.stop(),this.renderer.stencilManager.pushStencil(t)},e.prototype.popStencilMask=function(){this.renderer.currentRenderer.stop(),this.renderer.stencilManager.popStencil()},e.prototype.pushScissorMask=function(t,e){e.renderable=!0;var r=this.renderer._activeRenderTarget,n=e.getBounds();n.fit(r.size),e.renderable=!1,this.renderer.gl.enable(this.renderer.gl.SCISSOR_TEST);var i=this.renderer.resolution;this.renderer.gl.scissor(n.x*i,(r.root?r.size.height-n.y-n.height:n.y)*i,n.width*i,n.height*i),this.scissorRenderTarget=r,this.scissorData=e,this.scissor=!0},e.prototype.popScissorMask=function(){this.scissorRenderTarget=null,this.scissorData=null,this.scissor=!1;var t=this.renderer.gl;t.disable(t.SCISSOR_TEST)},e}(u.default);r.default=c},{\"../filters/spriteMask/SpriteMaskFilter\":89,\n\"./WebGLManager\":93}],92:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=t(\"./WebGLManager\"),a=function(t){return t&&t.__esModule?t:{default:t}}(s),u=function(t){function e(r){n(this,e);var o=i(this,t.call(this,r));return o.stencilMaskStack=null,o}return o(e,t),e.prototype.setMaskStack=function(t){this.stencilMaskStack=t;var e=this.renderer.gl;0===t.length?e.disable(e.STENCIL_TEST):e.enable(e.STENCIL_TEST)},e.prototype.pushStencil=function(t){this.renderer.setObjectRenderer(this.renderer.plugins.graphics),this.renderer._activeRenderTarget.attachStencilBuffer();var e=this.renderer.gl,r=this.stencilMaskStack.length;0===r&&e.enable(e.STENCIL_TEST),this.stencilMaskStack.push(t),e.colorMask(!1,!1,!1,!1),e.stencilFunc(e.EQUAL,r,this._getBitwiseMask()),e.stencilOp(e.KEEP,e.KEEP,e.INCR),this.renderer.plugins.graphics.render(t),this._useCurrent()},e.prototype.popStencil=function(){this.renderer.setObjectRenderer(this.renderer.plugins.graphics);var t=this.renderer.gl,e=this.stencilMaskStack.pop();0===this.stencilMaskStack.length?(t.disable(t.STENCIL_TEST),t.clear(t.STENCIL_BUFFER_BIT),t.clearStencil(0)):(t.colorMask(!1,!1,!1,!1),t.stencilOp(t.KEEP,t.KEEP,t.DECR),this.renderer.plugins.graphics.render(e),this._useCurrent())},e.prototype._useCurrent=function(){var t=this.renderer.gl;t.colorMask(!0,!0,!0,!0),t.stencilFunc(t.EQUAL,this.stencilMaskStack.length,this._getBitwiseMask()),t.stencilOp(t.KEEP,t.KEEP,t.KEEP)},e.prototype._getBitwiseMask=function(){return(1<<this.stencilMaskStack.length)-1},e.prototype.destroy=function(){a.default.prototype.destroy.call(this),this.stencilMaskStack.stencilStack=null},e}(a.default);r.default=u},{\"./WebGLManager\":93}],93:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(e){n(this,t),this.renderer=e,this.renderer.on(\"context\",this.onContextChange,this)}return t.prototype.onContextChange=function(){},t.prototype.destroy=function(){this.renderer.off(\"context\",this.onContextChange,this),this.renderer=null},t}();r.default=i},{}],94:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=t(\"../managers/WebGLManager\"),a=function(t){return t&&t.__esModule?t:{default:t}}(s),u=function(t){function e(){return n(this,e),i(this,t.apply(this,arguments))}return o(e,t),e.prototype.start=function(){},e.prototype.stop=function(){this.flush()},e.prototype.flush=function(){},e.prototype.render=function(t){},e}(a.default);r.default=u},{\"../managers/WebGLManager\":93}],95:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var o=t(\"pixi-gl-core\"),s=n(o),a=t(\"../../../utils/createIndicesForQuads\"),u=n(a),h=function(){function t(e,r){i(this,t),this.gl=e,this.vertices=new Float32Array([-1,-1,1,-1,1,1,-1,1]),this.uvs=new Float32Array([0,0,1,0,1,1,0,1]),this.interleaved=new Float32Array(16);for(var n=0;n<4;n++)this.interleaved[4*n]=this.vertices[2*n],this.interleaved[4*n+1]=this.vertices[2*n+1],this.interleaved[4*n+2]=this.uvs[2*n],this.interleaved[4*n+3]=this.uvs[2*n+1];this.indices=(0,u.default)(1),this.vertexBuffer=s.default.GLBuffer.createVertexBuffer(e,this.interleaved,e.STATIC_DRAW),this.indexBuffer=s.default.GLBuffer.createIndexBuffer(e,this.indices,e.STATIC_DRAW),this.vao=new s.default.VertexArrayObject(e,r)}return t.prototype.initVao=function(t){this.vao.clear().addIndex(this.indexBuffer).addAttribute(this.vertexBuffer,t.attributes.aVertexPosition,this.gl.FLOAT,!1,16,0).addAttribute(this.vertexBuffer,t.attributes.aTextureCoord,this.gl.FLOAT,!1,16,8)},t.prototype.map=function(t,e){var r=0,n=0;return this.uvs[0]=r,this.uvs[1]=n,this.uvs[2]=r+e.width/t.width,this.uvs[3]=n,this.uvs[4]=r+e.width/t.width,this.uvs[5]=n+e.height/t.height,this.uvs[6]=r,this.uvs[7]=n+e.height/t.height,r=e.x,n=e.y,this.vertices[0]=r,this.vertices[1]=n,this.vertices[2]=r+e.width,this.vertices[3]=n,this.vertices[4]=r+e.width,this.vertices[5]=n+e.height,this.vertices[6]=r,this.vertices[7]=n+e.height,this},t.prototype.upload=function(){for(var t=0;t<4;t++)this.interleaved[4*t]=this.vertices[2*t],this.interleaved[4*t+1]=this.vertices[2*t+1],this.interleaved[4*t+2]=this.uvs[2*t],this.interleaved[4*t+3]=this.uvs[2*t+1];return this.vertexBuffer.upload(this.interleaved),this},t.prototype.destroy=function(){var t=this.gl;t.deleteBuffer(this.vertexBuffer),t.deleteBuffer(this.indexBuffer)},t}();r.default=h},{\"../../../utils/createIndicesForQuads\":122,\"pixi-gl-core\":15}],96:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../../../math\"),o=t(\"../../../const\"),s=t(\"../../../settings\"),a=function(t){return t&&t.__esModule?t:{default:t}}(s),u=t(\"pixi-gl-core\"),h=function(){function t(e,r,s,h,l,c){n(this,t),this.gl=e,this.frameBuffer=null,this.texture=null,this.clearColor=[0,0,0,0],this.size=new i.Rectangle(0,0,1,1),this.resolution=l||a.default.RESOLUTION,this.projectionMatrix=new i.Matrix,this.transform=null,this.frame=null,this.defaultFrame=new i.Rectangle,this.destinationFrame=null,this.sourceFrame=null,this.stencilBuffer=null,this.stencilMaskStack=[],this.filterData=null,this.scaleMode=void 0!==h?h:a.default.SCALE_MODE,this.root=c,this.root?(this.frameBuffer=new u.GLFramebuffer(e,100,100),this.frameBuffer.framebuffer=null):(this.frameBuffer=u.GLFramebuffer.createRGBA(e,100,100),this.scaleMode===o.SCALE_MODES.NEAREST?this.frameBuffer.texture.enableNearestScaling():this.frameBuffer.texture.enableLinearScaling(),this.texture=this.frameBuffer.texture),this.setFrame(),this.resize(r,s)}return t.prototype.clear=function(t){var e=t||this.clearColor;this.frameBuffer.clear(e[0],e[1],e[2],e[3])},t.prototype.attachStencilBuffer=function(){this.root||this.frameBuffer.enableStencil()},t.prototype.setFrame=function(t,e){this.destinationFrame=t||this.destinationFrame||this.defaultFrame,this.sourceFrame=e||this.sourceFrame||this.destinationFrame},t.prototype.activate=function(){var t=this.gl;this.frameBuffer.bind(),this.calculateProjection(this.destinationFrame,this.sourceFrame),this.transform&&this.projectionMatrix.append(this.transform),this.destinationFrame!==this.sourceFrame?(t.enable(t.SCISSOR_TEST),t.scissor(0|this.destinationFrame.x,0|this.destinationFrame.y,this.destinationFrame.width*this.resolution|0,this.destinationFrame.height*this.resolution|0)):t.disable(t.SCISSOR_TEST),t.viewport(0|this.destinationFrame.x,0|this.destinationFrame.y,this.destinationFrame.width*this.resolution|0,this.destinationFrame.height*this.resolution|0)},t.prototype.calculateProjection=function(t,e){var r=this.projectionMatrix;e=e||t,r.identity(),this.root?(r.a=1/t.width*2,r.d=-1/t.height*2,r.tx=-1-e.x*r.a,r.ty=1-e.y*r.d):(r.a=1/t.width*2,r.d=1/t.height*2,r.tx=-1-e.x*r.a,r.ty=-1-e.y*r.d)},t.prototype.resize=function(t,e){if(t|=0,e|=0,this.size.width!==t||this.size.height!==e){this.size.width=t,this.size.height=e,this.defaultFrame.width=t,this.defaultFrame.height=e,this.frameBuffer.resize(t*this.resolution,e*this.resolution);var r=this.frame||this.size;this.calculateProjection(r)}},t.prototype.destroy=function(){this.frameBuffer.destroy(),this.frameBuffer=null,this.texture=null},t}();r.default=h},{\"../../../const\":46,\"../../../math\":70,\"../../../settings\":101,\"pixi-gl-core\":15}],97:[function(t,e,r){\"use strict\";function n(t,e){var r=!e;if(r){var n=document.createElement(\"canvas\");n.width=1,n.height=1,e=s.default.createContext(n)}for(var o=e.createShader(e.FRAGMENT_SHADER);;){var u=a.replace(/%forloop%/gi,i(t));if(e.shaderSource(o,u),e.compileShader(o),e.getShaderParameter(o,e.COMPILE_STATUS))break;t=t/2|0}return r&&e.getExtension(\"WEBGL_lose_context\")&&e.getExtension(\"WEBGL_lose_context\").loseContext(),t}function i(t){for(var e=\"\",r=0;r<t;++r)r>0&&(e+=\"\\nelse \"),r<t-1&&(e+=\"if(test == \"+r+\".0){}\");return e}r.__esModule=!0,r.default=n;var o=t(\"pixi-gl-core\"),s=function(t){return t&&t.__esModule?t:{default:t}}(o),a=[\"precision mediump float;\",\"void main(void){\",\"float test = 0.1;\",\"%forloop%\",\"gl_FragColor = vec4(0.0);\",\"}\"].join(\"\\n\")},{\"pixi-gl-core\":15}],98:[function(t,e,r){\"use strict\";function n(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[];return e[i.BLEND_MODES.NORMAL]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.ADD]=[t.ONE,t.DST_ALPHA],e[i.BLEND_MODES.MULTIPLY]=[t.DST_COLOR,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.SCREEN]=[t.ONE,t.ONE_MINUS_SRC_COLOR],e[i.BLEND_MODES.OVERLAY]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.DARKEN]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.LIGHTEN]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.COLOR_DODGE]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.COLOR_BURN]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.HARD_LIGHT]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.SOFT_LIGHT]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.DIFFERENCE]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.EXCLUSION]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.HUE]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.SATURATION]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.COLOR]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.LUMINOSITY]=[t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.NORMAL_NPM]=[t.SRC_ALPHA,t.ONE_MINUS_SRC_ALPHA,t.ONE,t.ONE_MINUS_SRC_ALPHA],e[i.BLEND_MODES.ADD_NPM]=[t.SRC_ALPHA,t.DST_ALPHA,t.ONE,t.DST_ALPHA],e[i.BLEND_MODES.SCREEN_NPM]=[t.SRC_ALPHA,t.ONE_MINUS_SRC_COLOR,t.ONE,t.ONE_MINUS_SRC_COLOR],e}r.__esModule=!0,r.default=n;var i=t(\"../../../const\")},{\"../../../const\":46}],99:[function(t,e,r){\"use strict\";function n(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return e[i.DRAW_MODES.POINTS]=t.POINTS,e[i.DRAW_MODES.LINES]=t.LINES,e[i.DRAW_MODES.LINE_LOOP]=t.LINE_LOOP,e[i.DRAW_MODES.LINE_STRIP]=t.LINE_STRIP,e[i.DRAW_MODES.TRIANGLES]=t.TRIANGLES,e[i.DRAW_MODES.TRIANGLE_STRIP]=t.TRIANGLE_STRIP,e[i.DRAW_MODES.TRIANGLE_FAN]=t.TRIANGLE_FAN,e}r.__esModule=!0,r.default=n;var i=t(\"../../../const\")},{\"../../../const\":46}],100:[function(t,e,r){\"use strict\";function n(t){t.getContextAttributes().stencil||console.warn(\"Provided WebGL context does not have a stencil buffer, masks may not render correctly\")}r.__esModule=!0,r.default=n},{}],101:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0;var i=t(\"./utils/maxRecommendedTextures\"),o=n(i),s=t(\"./utils/canUploadSameBuffer\"),a=n(s);r.default={TARGET_FPMS:.06,MIPMAP_TEXTURES:!0,RESOLUTION:1,FILTER_RESOLUTION:1,SPRITE_MAX_TEXTURES:(0,o.default)(32),SPRITE_BATCH_SIZE:4096,RETINA_PREFIX:/@([0-9\\.]+)x/,RENDER_OPTIONS:{view:null,antialias:!1,forceFXAA:!1,autoResize:!1,transparent:!1,backgroundColor:0,clearBeforeRender:!0,preserveDrawingBuffer:!1,roundPixels:!1,width:800,height:600,legacy:!1},TRANSFORM_MODE:0,GC_MODE:0,GC_MAX_IDLE:3600,GC_MAX_CHECK_COUNT:600,WRAP_MODE:0,SCALE_MODE:0,PRECISION_VERTEX:\"highp\",PRECISION_FRAGMENT:\"mediump\",CAN_UPLOAD_SAME_BUFFER:(0,a.default)()}},{\"./utils/canUploadSameBuffer\":121,\"./utils/maxRecommendedTextures\":126}],102:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),u=t(\"../math\"),h=t(\"../utils\"),l=t(\"../const\"),c=t(\"../textures/Texture\"),d=n(c),f=t(\"../display/Container\"),p=n(f),v=new u.Point,y=function(t){function e(r){i(this,e);var n=o(this,t.call(this));return n._anchor=new u.ObservablePoint(n._onAnchorUpdate,n),n._texture=null,n._width=0,n._height=0,n._tint=null,n._tintRGB=null,n.tint=16777215,n.blendMode=l.BLEND_MODES.NORMAL,n.shader=null,n.cachedTint=16777215,n.texture=r||d.default.EMPTY,n.vertexData=new Float32Array(8),n.vertexTrimmedData=null,n._transformID=-1,n._textureID=-1,n._transformTrimmedID=-1,n._textureTrimmedID=-1,n.pluginName=\"sprite\",n}return s(e,t),e.prototype._onTextureUpdate=function(){this._textureID=-1,this._textureTrimmedID=-1,this.cachedTint=16777215,this._width&&(this.scale.x=(0,h.sign)(this.scale.x)*this._width/this._texture.orig.width),this._height&&(this.scale.y=(0,h.sign)(this.scale.y)*this._height/this._texture.orig.height)},e.prototype._onAnchorUpdate=function(){this._transformID=-1,this._transformTrimmedID=-1},e.prototype.calculateVertices=function(){if(this._transformID!==this.transform._worldID||this._textureID!==this._texture._updateID){this._transformID=this.transform._worldID,this._textureID=this._texture._updateID;var t=this._texture,e=this.transform.worldTransform,r=e.a,n=e.b,i=e.c,o=e.d,s=e.tx,a=e.ty,u=this.vertexData,h=t.trim,l=t.orig,c=this._anchor,d=0,f=0,p=0,v=0;h?(f=h.x-c._x*l.width,d=f+h.width,v=h.y-c._y*l.height,p=v+h.height):(f=-c._x*l.width,d=f+l.width,v=-c._y*l.height,p=v+l.height),u[0]=r*f+i*v+s,u[1]=o*v+n*f+a,u[2]=r*d+i*v+s,u[3]=o*v+n*d+a,u[4]=r*d+i*p+s,u[5]=o*p+n*d+a,u[6]=r*f+i*p+s,u[7]=o*p+n*f+a}},e.prototype.calculateTrimmedVertices=function(){if(this.vertexTrimmedData){if(this._transformTrimmedID===this.transform._worldID&&this._textureTrimmedID===this._texture._updateID)return}else this.vertexTrimmedData=new Float32Array(8);this._transformTrimmedID=this.transform._worldID,this._textureTrimmedID=this._texture._updateID;var t=this._texture,e=this.vertexTrimmedData,r=t.orig,n=this._anchor,i=this.transform.worldTransform,o=i.a,s=i.b,a=i.c,u=i.d,h=i.tx,l=i.ty,c=-n._x*r.width,d=c+r.width,f=-n._y*r.height,p=f+r.height;e[0]=o*c+a*f+h,e[1]=u*f+s*c+l,e[2]=o*d+a*f+h,e[3]=u*f+s*d+l,e[4]=o*d+a*p+h,e[5]=u*p+s*d+l,e[6]=o*c+a*p+h,e[7]=u*p+s*c+l},e.prototype._renderWebGL=function(t){this.calculateVertices(),t.setObjectRenderer(t.plugins[this.pluginName]),t.plugins[this.pluginName].render(this)},e.prototype._renderCanvas=function(t){t.plugins[this.pluginName].render(this)},e.prototype._calculateBounds=function(){var t=this._texture.trim,e=this._texture.orig;!t||t.width===e.width&&t.height===e.height?(this.calculateVertices(),this._bounds.addQuad(this.vertexData)):(this.calculateTrimmedVertices(),this._bounds.addQuad(this.vertexTrimmedData))},e.prototype.getLocalBounds=function(e){return 0===this.children.length?(this._bounds.minX=this._texture.orig.width*-this._anchor._x,this._bounds.minY=this._texture.orig.height*-this._anchor._y,this._bounds.maxX=this._texture.orig.width*(1-this._anchor._x),this._bounds.maxY=this._texture.orig.height*(1-this._anchor._y),e||(this._localBoundsRect||(this._localBoundsRect=new u.Rectangle),e=this._localBoundsRect),this._bounds.getRectangle(e)):t.prototype.getLocalBounds.call(this,e)},e.prototype.containsPoint=function(t){this.worldTransform.applyInverse(t,v);var e=this._texture.orig.width,r=this._texture.orig.height,n=-e*this.anchor.x,i=0;return v.x>=n&&v.x<n+e&&(i=-r*this.anchor.y,v.y>=i&&v.y<i+r)},e.prototype.destroy=function(e){if(t.prototype.destroy.call(this,e),this._anchor=null,\"boolean\"==typeof e?e:e&&e.texture){var r=\"boolean\"==typeof e?e:e&&e.baseTexture;this._texture.destroy(!!r)}this._texture=null,this.shader=null},e.from=function(t){return new e(d.default.from(t))},e.fromFrame=function(t){var r=h.TextureCache[t];if(!r)throw new Error('The frameId \"'+t+'\" does not exist in the texture cache');return new e(r)},e.fromImage=function(t,r,n){return new e(d.default.fromImage(t,r,n))},a(e,[{key:\"width\",get:function(){return Math.abs(this.scale.x)*this._texture.orig.width},set:function(t){var e=(0,h.sign)(this.scale.x)||1;this.scale.x=e*t/this._texture.orig.width,this._width=t}},{key:\"height\",get:function(){return Math.abs(this.scale.y)*this._texture.orig.height},set:function(t){var e=(0,h.sign)(this.scale.y)||1;this.scale.y=e*t/this._texture.orig.height,this._height=t}},{key:\"anchor\",get:function(){return this._anchor},set:function(t){this._anchor.copy(t)}},{key:\"tint\",get:function(){return this._tint},set:function(t){this._tint=t,this._tintRGB=(t>>16)+(65280&t)+((255&t)<<16)}},{key:\"texture\",get:function(){return this._texture},set:function(t){this._texture!==t&&(this._texture=t,this.cachedTint=16777215,this._textureID=-1,this._textureTrimmedID=-1,t&&(t.baseTexture.hasLoaded?this._onTextureUpdate():t.once(\"update\",this._onTextureUpdate,this)))}}]),e}(p.default);r.default=y},{\"../const\":46,\"../display/Container\":48,\"../math\":70,\"../textures/Texture\":115,\"../utils\":124}],103:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var o=t(\"../../renderers/canvas/CanvasRenderer\"),s=n(o),a=t(\"../../const\"),u=t(\"../../math\"),h=t(\"./CanvasTinter\"),l=n(h),c=new u.Matrix,d=function(){function t(e){i(this,t),this.renderer=e}return t.prototype.render=function(t){var e=t._texture,r=this.renderer,n=e._frame.width,i=e._frame.height,o=t.transform.worldTransform,s=0,h=0;if(!(e.orig.width<=0||e.orig.height<=0)&&e.baseTexture.source&&(r.setBlendMode(t.blendMode),e.valid)){r.context.globalAlpha=t.worldAlpha;var d=e.baseTexture.scaleMode===a.SCALE_MODES.LINEAR;r.smoothProperty&&r.context[r.smoothProperty]!==d&&(r.context[r.smoothProperty]=d),e.trim?(s=e.trim.width/2+e.trim.x-t.anchor.x*e.orig.width,h=e.trim.height/2+e.trim.y-t.anchor.y*e.orig.height):(s=(.5-t.anchor.x)*e.orig.width,h=(.5-t.anchor.y)*e.orig.height),e.rotate&&(o.copy(c),o=c,u.GroupD8.matrixAppendRotationInv(o,e.rotate,s,h),s=0,h=0),s-=n/2,h-=i/2,r.roundPixels?(r.context.setTransform(o.a,o.b,o.c,o.d,o.tx*r.resolution|0,o.ty*r.resolution|0),s|=0,h|=0):r.context.setTransform(o.a,o.b,o.c,o.d,o.tx*r.resolution,o.ty*r.resolution);var f=e.baseTexture.resolution;16777215!==t.tint?(t.cachedTint===t.tint&&t.tintedTexture.tintId===t._texture._updateID||(t.cachedTint=t.tint,t.tintedTexture=l.default.getTintedTexture(t,t.tint)),r.context.drawImage(t.tintedTexture,0,0,n*f,i*f,s*r.resolution,h*r.resolution,n*r.resolution,i*r.resolution)):r.context.drawImage(e.baseTexture.source,e._frame.x*f,e._frame.y*f,n*f,i*f,s*r.resolution,h*r.resolution,n*r.resolution,i*r.resolution)}},t.prototype.destroy=function(){this.renderer=null},t}();r.default=d,s.default.registerPlugin(\"sprite\",d)},{\"../../const\":46,\"../../math\":70,\"../../renderers/canvas/CanvasRenderer\":77,\"./CanvasTinter\":104}],104:[function(t,e,r){\"use strict\";r.__esModule=!0;var n=t(\"../../utils\"),i=t(\"../../renderers/canvas/utils/canUseNewCanvasBlendModes\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s={getTintedTexture:function(t,e){var r=t._texture;e=s.roundColor(e);var n=\"#\"+(\"00000\"+(0|e).toString(16)).substr(-6);r.tintCache=r.tintCache||{};var i=r.tintCache[n],o=void 0;if(i){if(i.tintId===r._updateID)return r.tintCache[n];o=r.tintCache[n]}else o=s.canvas||document.createElement(\"canvas\");if(s.tintMethod(r,e,o),o.tintId=r._updateID,s.convertTintToImage){var a=new Image;a.src=o.toDataURL(),r.tintCache[n]=a}else r.tintCache[n]=o,s.canvas=null;return o},tintWithMultiply:function(t,e,r){var n=r.getContext(\"2d\"),i=t._frame.clone(),o=t.baseTexture.resolution;i.x*=o,i.y*=o,i.width*=o,i.height*=o,r.width=Math.ceil(i.width),r.height=Math.ceil(i.height),n.save(),n.fillStyle=\"#\"+(\"00000\"+(0|e).toString(16)).substr(-6),n.fillRect(0,0,i.width,i.height),n.globalCompositeOperation=\"multiply\",n.drawImage(t.baseTexture.source,i.x,i.y,i.width,i.height,0,0,i.width,i.height),n.globalCompositeOperation=\"destination-atop\",n.drawImage(t.baseTexture.source,i.x,i.y,i.width,i.height,0,0,i.width,i.height),n.restore()},tintWithOverlay:function(t,e,r){var n=r.getContext(\"2d\"),i=t._frame.clone(),o=t.baseTexture.resolution;i.x*=o,i.y*=o,i.width*=o,i.height*=o,r.width=Math.ceil(i.width),r.height=Math.ceil(i.height),n.save(),n.globalCompositeOperation=\"copy\",n.fillStyle=\"#\"+(\"00000\"+(0|e).toString(16)).substr(-6),n.fillRect(0,0,i.width,i.height),n.globalCompositeOperation=\"destination-atop\",n.drawImage(t.baseTexture.source,i.x,i.y,i.width,i.height,0,0,i.width,i.height),n.restore()},tintWithPerPixel:function(t,e,r){var i=r.getContext(\"2d\"),o=t._frame.clone(),s=t.baseTexture.resolution;o.x*=s,o.y*=s,o.width*=s,o.height*=s,r.width=Math.ceil(o.width),r.height=Math.ceil(o.height),i.save(),i.globalCompositeOperation=\"copy\",i.drawImage(t.baseTexture.source,o.x,o.y,o.width,o.height,0,0,o.width,o.height),i.restore();for(var a=(0,n.hex2rgb)(e),u=a[0],h=a[1],l=a[2],c=i.getImageData(0,0,o.width,o.height),d=c.data,f=0;f<d.length;f+=4)d[f+0]*=u,d[f+1]*=h,d[f+2]*=l;i.putImageData(c,0,0)},roundColor:function(t){var e=s.cacheStepsPerColorChannel,r=(0,n.hex2rgb)(t);return r[0]=Math.min(255,r[0]/e*e),r[1]=Math.min(255,r[1]/e*e),r[2]=Math.min(255,r[2]/e*e),(0,n.rgb2hex)(r)},cacheStepsPerColorChannel:8,convertTintToImage:!1,canUseMultiply:(0,o.default)(),tintMethod:0};s.tintMethod=s.canUseMultiply?s.tintWithMultiply:s.tintWithPerPixel,r.default=s},{\"../../renderers/canvas/utils/canUseNewCanvasBlendModes\":80,\"../../utils\":124}],105:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(e){n(this,t),this.vertices=new ArrayBuffer(e),this.float32View=new Float32Array(this.vertices),this.uint32View=new Uint32Array(this.vertices)}return t.prototype.destroy=function(){this.vertices=null,this.positions=null,this.uvs=null,this.colors=null},t}();r.default=i},{}],106:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"../../renderers/webgl/utils/ObjectRenderer\"),u=n(a),h=t(\"../../renderers/webgl/WebGLRenderer\"),l=n(h),c=t(\"../../utils/createIndicesForQuads\"),d=n(c),f=t(\"./generateMultiTextureShader\"),p=n(f),v=t(\"../../renderers/webgl/utils/checkMaxIfStatmentsInShader\"),y=n(v),g=t(\"./BatchBuffer\"),m=n(g),_=t(\"../../settings\"),b=n(_),x=t(\"../../utils\"),T=t(\"pixi-gl-core\"),w=n(T),E=t(\"bit-twiddle\"),S=n(E),O=0,M=0,P=function(t){function e(r){i(this,e);var n=o(this,t.call(this,r));n.vertSize=5,n.vertByteSize=4*n.vertSize,n.size=b.default.SPRITE_BATCH_SIZE,n.buffers=[];for(var s=1;s<=S.default.nextPow2(n.size);s*=2)n.buffers.push(new m.default(4*s*n.vertByteSize));n.indices=(0,d.default)(n.size),n.shader=null,n.currentIndex=0,n.groups=[];for(var a=0;a<n.size;a++)n.groups[a]={textures:[],textureCount:0,ids:[],size:0,start:0,blend:0};return n.sprites=[],n.vertexBuffers=[],n.vaos=[],n.vaoMax=2,n.vertexCount=0,n.renderer.on(\"prerender\",n.onPrerender,n),n}return s(e,t),e.prototype.onContextChange=function(){var t=this.renderer.gl;this.renderer.legacy?this.MAX_TEXTURES=1:(this.MAX_TEXTURES=Math.min(t.getParameter(t.MAX_TEXTURE_IMAGE_UNITS),b.default.SPRITE_MAX_TEXTURES),this.MAX_TEXTURES=(0,y.default)(this.MAX_TEXTURES,t)),this.shader=(0,p.default)(t,this.MAX_TEXTURES),this.indexBuffer=w.default.GLBuffer.createIndexBuffer(t,this.indices,t.STATIC_DRAW),this.renderer.bindVao(null);for(var e=this.shader.attributes,r=0;r<this.vaoMax;r++){var n=this.vertexBuffers[r]=w.default.GLBuffer.createVertexBuffer(t,null,t.STREAM_DRAW),i=this.renderer.createVao().addIndex(this.indexBuffer).addAttribute(n,e.aVertexPosition,t.FLOAT,!1,this.vertByteSize,0).addAttribute(n,e.aTextureCoord,t.UNSIGNED_SHORT,!0,this.vertByteSize,8).addAttribute(n,e.aColor,t.UNSIGNED_BYTE,!0,this.vertByteSize,12);e.aTextureId&&i.addAttribute(n,e.aTextureId,t.FLOAT,!1,this.vertByteSize,16),this.vaos[r]=i}this.vao=this.vaos[0],this.currentBlendMode=99999,this.boundTextures=new Array(this.MAX_TEXTURES)},e.prototype.onPrerender=function(){this.vertexCount=0},e.prototype.render=function(t){this.currentIndex>=this.size&&this.flush(),t._texture._uvs&&(this.sprites[this.currentIndex++]=t)},e.prototype.flush=function(){if(0!==this.currentIndex){var t=this.renderer.gl,e=this.MAX_TEXTURES,r=S.default.nextPow2(this.currentIndex),n=S.default.log2(r),i=this.buffers[n],o=this.sprites,s=this.groups,a=i.float32View,u=i.uint32View,h=this.boundTextures,l=this.renderer.boundTextures,c=this.renderer.textureGC.count,d=0,f=void 0,p=void 0,v=1,y=0,g=s[0],m=void 0,_=void 0,T=x.premultiplyBlendMode[o[0]._texture.baseTexture.premultipliedAlpha?1:0][o[0].blendMode];g.textureCount=0,g.start=0,g.blend=T,O++;var E=void 0;for(E=0;E<e;++E)h[E]=l[E],h[E]._virtalBoundId=E;for(E=0;E<this.currentIndex;++E){var P=o[E];f=P._texture.baseTexture;var C=x.premultiplyBlendMode[Number(f.premultipliedAlpha)][P.blendMode];if(T!==C&&(T=C,p=null,y=e,O++),p!==f&&(p=f,f._enabled!==O)){if(y===e&&(O++,g.size=E-g.start,y=0,g=s[v++],g.blend=T,g.textureCount=0,g.start=E),f.touched=c,-1===f._virtalBoundId)for(var R=0;R<e;++R){var A=(R+M)%e,I=h[A];if(I._enabled!==O){M++,I._virtalBoundId=-1,f._virtalBoundId=A,h[A]=f;break}}f._enabled=O,g.textureCount++,g.ids[y]=f._virtalBoundId,g.textures[y++]=f}if(m=P.vertexData,_=P._texture._uvs.uvsUint32,this.renderer.roundPixels){var D=this.renderer.resolution;a[d]=(m[0]*D|0)/D,a[d+1]=(m[1]*D|0)/D,a[d+5]=(m[2]*D|0)/D,a[d+6]=(m[3]*D|0)/D,a[d+10]=(m[4]*D|0)/D,a[d+11]=(m[5]*D|0)/D,a[d+15]=(m[6]*D|0)/D,a[d+16]=(m[7]*D|0)/D}else a[d]=m[0],a[d+1]=m[1],a[d+5]=m[2],a[d+6]=m[3],a[d+10]=m[4],a[d+11]=m[5],a[d+15]=m[6],a[d+16]=m[7];u[d+2]=_[0],u[d+7]=_[1],u[d+12]=_[2],u[d+17]=_[3];var L=Math.min(P.worldAlpha,1),N=L<1&&f.premultipliedAlpha?(0,x.premultiplyTint)(P._tintRGB,L):P._tintRGB+(255*L<<24);u[d+3]=u[d+8]=u[d+13]=u[d+18]=N,a[d+4]=a[d+9]=a[d+14]=a[d+19]=f._virtalBoundId,d+=20}if(g.size=E-g.start,b.default.CAN_UPLOAD_SAME_BUFFER)this.vertexBuffers[this.vertexCount].upload(i.vertices,0,!0);else{if(this.vaoMax<=this.vertexCount){this.vaoMax++;var F=this.shader.attributes,B=this.vertexBuffers[this.vertexCount]=w.default.GLBuffer.createVertexBuffer(t,null,t.STREAM_DRAW),k=this.renderer.createVao().addIndex(this.indexBuffer).addAttribute(B,F.aVertexPosition,t.FLOAT,!1,this.vertByteSize,0).addAttribute(B,F.aTextureCoord,t.UNSIGNED_SHORT,!0,this.vertByteSize,8).addAttribute(B,F.aColor,t.UNSIGNED_BYTE,!0,this.vertByteSize,12);F.aTextureId&&k.addAttribute(B,F.aTextureId,t.FLOAT,!1,this.vertByteSize,16),this.vaos[this.vertexCount]=k}this.renderer.bindVao(this.vaos[this.vertexCount]),this.vertexBuffers[this.vertexCount].upload(i.vertices,0,!1),this.vertexCount++}for(E=0;E<e;++E)l[E]._virtalBoundId=-1;for(E=0;E<v;++E){for(var j=s[E],U=j.textureCount,X=0;X<U;X++)p=j.textures[X],l[j.ids[X]]!==p&&this.renderer.bindTexture(p,j.ids[X],!0),p._virtalBoundId=-1;this.renderer.state.setBlendMode(j.blend),t.drawElements(t.TRIANGLES,6*j.size,t.UNSIGNED_SHORT,6*j.start*2)}this.currentIndex=0}},e.prototype.start=function(){this.renderer.bindShader(this.shader),b.default.CAN_UPLOAD_SAME_BUFFER&&(this.renderer.bindVao(this.vaos[this.vertexCount]),this.vertexBuffers[this.vertexCount].bind())},e.prototype.stop=function(){this.flush()},e.prototype.destroy=function(){for(var e=0;e<this.vaoMax;e++)this.vertexBuffers[e]&&this.vertexBuffers[e].destroy(),this.vaos[e]&&this.vaos[e].destroy();this.indexBuffer&&this.indexBuffer.destroy(),this.renderer.off(\"prerender\",this.onPrerender,this),t.prototype.destroy.call(this),this.shader&&(this.shader.destroy(),this.shader=null),this.vertexBuffers=null,this.vaos=null,this.indexBuffer=null,this.indices=null,this.sprites=null;for(var r=0;r<this.buffers.length;++r)this.buffers[r].destroy()},e}(u.default);r.default=P,l.default.registerPlugin(\"sprite\",P)},{\"../../renderers/webgl/WebGLRenderer\":84,\"../../renderers/webgl/utils/ObjectRenderer\":94,\"../../renderers/webgl/utils/checkMaxIfStatmentsInShader\":97,\"../../settings\":101,\"../../utils\":124,\"../../utils/createIndicesForQuads\":122,\"./BatchBuffer\":105,\"./generateMultiTextureShader\":107,\"bit-twiddle\":1,\"pixi-gl-core\":15}],107:[function(t,e,r){\"use strict\";function n(t,e){var r=a;r=r.replace(/%count%/gi,e),r=r.replace(/%forloop%/gi,i(e));for(var n=new s.default(t,\"precision highp float;\\nattribute vec2 aVertexPosition;\\nattribute vec2 aTextureCoord;\\nattribute vec4 aColor;\\nattribute float aTextureId;\\n\\nuniform mat3 projectionMatrix;\\n\\nvarying vec2 vTextureCoord;\\nvarying vec4 vColor;\\nvarying float vTextureId;\\n\\nvoid main(void){\\n    gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\\n\\n    vTextureCoord = aTextureCoord;\\n    vTextureId = aTextureId;\\n    vColor = aColor;\\n}\\n\",r),o=[],u=0;u<e;u++)o[u]=u;return n.bind(),n.uniforms.uSamplers=o,n}function i(t){var e=\"\";e+=\"\\n\",e+=\"\\n\";for(var r=0;r<t;r++)r>0&&(e+=\"\\nelse \"),r<t-1&&(e+=\"if(textureId == \"+r+\".0)\"),e+=\"\\n{\",e+=\"\\n\\tcolor = texture2D(uSamplers[\"+r+\"], vTextureCoord);\",e+=\"\\n}\";return e+=\"\\n\",e+=\"\\n\"}r.__esModule=!0,r.default=n;var o=t(\"../../Shader\"),s=function(t){return t&&t.__esModule?t:{default:t}}(o),a=(t(\"path\"),[\"varying vec2 vTextureCoord;\",\"varying vec4 vColor;\",\"varying float vTextureId;\",\"uniform sampler2D uSamplers[%count%];\",\"void main(void){\",\"vec4 color;\",\"float textureId = floor(vTextureId+0.5);\",\"%forloop%\",\"gl_FragColor = color * vColor;\",\"}\"].join(\"\\n\"))},{\"../../Shader\":44,path:8}],108:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),\nObject.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),u=t(\"../sprites/Sprite\"),h=n(u),l=t(\"../textures/Texture\"),c=n(l),d=t(\"../math\"),f=t(\"../utils\"),p=t(\"../const\"),v=t(\"../settings\"),y=n(v),g=t(\"./TextStyle\"),m=n(g),_=t(\"./TextMetrics\"),b=n(_),x=t(\"../utils/trimCanvas\"),T=n(x),w={texture:!0,children:!1,baseTexture:!0},E=function(t){function e(r,n,s){i(this,e),s=s||document.createElement(\"canvas\"),s.width=3,s.height=3;var a=c.default.fromCanvas(s,y.default.SCALE_MODE,\"text\");a.orig=new d.Rectangle,a.trim=new d.Rectangle;var u=o(this,t.call(this,a));return c.default.addToCache(u._texture,u._texture.baseTexture.textureCacheIds[0]),u.canvas=s,u.context=u.canvas.getContext(\"2d\"),u.resolution=y.default.RESOLUTION,u._text=null,u._style=null,u._styleListener=null,u._font=\"\",u.text=r,u.style=n,u.localStyleID=-1,u}return s(e,t),e.prototype.updateText=function(t){var e=this._style;if(this.localStyleID!==e.styleID&&(this.dirty=!0,this.localStyleID=e.styleID),this.dirty||!t){this._font=this._style.toFontString();var r=this.context,n=b.default.measureText(this._text,this._style,this._style.wordWrap,this.canvas),i=n.width,o=n.height,s=n.lines,a=n.lineHeight,u=n.lineWidths,h=n.maxLineWidth,l=n.fontProperties;this.canvas.width=Math.ceil((i+2*e.padding)*this.resolution),this.canvas.height=Math.ceil((o+2*e.padding)*this.resolution),r.scale(this.resolution,this.resolution),r.clearRect(0,0,this.canvas.width,this.canvas.height),r.font=this._font,r.strokeStyle=e.stroke,r.lineWidth=e.strokeThickness,r.textBaseline=e.textBaseline,r.lineJoin=e.lineJoin,r.miterLimit=e.miterLimit;var c=void 0,d=void 0;if(e.dropShadow){r.fillStyle=e.dropShadowColor,r.globalAlpha=e.dropShadowAlpha,r.shadowBlur=e.dropShadowBlur,e.dropShadowBlur>0&&(r.shadowColor=e.dropShadowColor);for(var f=Math.cos(e.dropShadowAngle)*e.dropShadowDistance,p=Math.sin(e.dropShadowAngle)*e.dropShadowDistance,v=0;v<s.length;v++)c=e.strokeThickness/2,d=e.strokeThickness/2+v*a+l.ascent,\"right\"===e.align?c+=h-u[v]:\"center\"===e.align&&(c+=(h-u[v])/2),e.fill&&(this.drawLetterSpacing(s[v],c+f+e.padding,d+p+e.padding),e.stroke&&e.strokeThickness&&(r.strokeStyle=e.dropShadowColor,this.drawLetterSpacing(s[v],c+f+e.padding,d+p+e.padding,!0),r.strokeStyle=e.stroke))}r.shadowBlur=0,r.globalAlpha=1,r.fillStyle=this._generateFillStyle(e,s);for(var y=0;y<s.length;y++)c=e.strokeThickness/2,d=e.strokeThickness/2+y*a+l.ascent,\"right\"===e.align?c+=h-u[y]:\"center\"===e.align&&(c+=(h-u[y])/2),e.stroke&&e.strokeThickness&&this.drawLetterSpacing(s[y],c+e.padding,d+e.padding,!0),e.fill&&this.drawLetterSpacing(s[y],c+e.padding,d+e.padding);this.updateTexture()}},e.prototype.drawLetterSpacing=function(t,e,r){var n=arguments.length>3&&void 0!==arguments[3]&&arguments[3],i=this._style,o=i.letterSpacing;if(0===o)return void(n?this.context.strokeText(t,e,r):this.context.fillText(t,e,r));for(var s=String.prototype.split.call(t,\"\"),a=e,u=0,h=\"\";u<t.length;)h=s[u++],n?this.context.strokeText(h,a,r):this.context.fillText(h,a,r),a+=this.context.measureText(h).width+o},e.prototype.updateTexture=function(){var t=this.canvas;if(this._style.trim){var e=(0,T.default)(t);t.width=e.width,t.height=e.height,this.context.putImageData(e.data,0,0)}var r=this._texture,n=this._style,i=n.trim?0:n.padding,o=r.baseTexture;o.hasLoaded=!0,o.resolution=this.resolution,o.realWidth=t.width,o.realHeight=t.height,o.width=t.width/this.resolution,o.height=t.height/this.resolution,r.trim.width=r._frame.width=t.width/this.resolution,r.trim.height=r._frame.height=t.height/this.resolution,r.trim.x=-i,r.trim.y=-i,r.orig.width=r._frame.width-2*i,r.orig.height=r._frame.height-2*i,this._onTextureUpdate(),o.emit(\"update\",o),this.dirty=!1},e.prototype.renderWebGL=function(e){this.resolution!==e.resolution&&(this.resolution=e.resolution,this.dirty=!0),this.updateText(!0),t.prototype.renderWebGL.call(this,e)},e.prototype._renderCanvas=function(e){this.resolution!==e.resolution&&(this.resolution=e.resolution,this.dirty=!0),this.updateText(!0),t.prototype._renderCanvas.call(this,e)},e.prototype.getLocalBounds=function(e){return this.updateText(!0),t.prototype.getLocalBounds.call(this,e)},e.prototype._calculateBounds=function(){this.updateText(!0),this.calculateVertices(),this._bounds.addQuad(this.vertexData)},e.prototype._onStyleChange=function(){this.dirty=!0},e.prototype._generateFillStyle=function(t,e){if(!Array.isArray(t.fill))return t.fill;if(navigator.isCocoonJS)return t.fill[0];var r=void 0,n=void 0,i=void 0,o=void 0,s=this.canvas.width/this.resolution,a=this.canvas.height/this.resolution,u=t.fill.slice(),h=t.fillGradientStops.slice();if(!h.length)for(var l=u.length+1,c=1;c<l;++c)h.push(c/l);if(u.unshift(t.fill[0]),h.unshift(0),u.push(t.fill[t.fill.length-1]),h.push(1),t.fillGradientType===p.TEXT_GRADIENT.LINEAR_VERTICAL){r=this.context.createLinearGradient(s/2,0,s/2,a),n=(u.length+1)*e.length,i=0;for(var d=0;d<e.length;d++){i+=1;for(var f=0;f<u.length;f++)o=\"number\"==typeof h[f]?h[f]/e.length+d/e.length:i/n,r.addColorStop(o,u[f]),i++}}else{r=this.context.createLinearGradient(0,a/2,s,a/2),n=u.length+1,i=1;for(var v=0;v<u.length;v++)o=\"number\"==typeof h[v]?h[v]:i/n,r.addColorStop(o,u[v]),i++}return r},e.prototype.destroy=function(e){\"boolean\"==typeof e&&(e={children:e}),e=Object.assign({},w,e),t.prototype.destroy.call(this,e),this.context=null,this.canvas=null,this._style=null},a(e,[{key:\"width\",get:function(){return this.updateText(!0),Math.abs(this.scale.x)*this._texture.orig.width},set:function(t){this.updateText(!0);var e=(0,f.sign)(this.scale.x)||1;this.scale.x=e*t/this._texture.orig.width,this._width=t}},{key:\"height\",get:function(){return this.updateText(!0),Math.abs(this.scale.y)*this._texture.orig.height},set:function(t){this.updateText(!0);var e=(0,f.sign)(this.scale.y)||1;this.scale.y=e*t/this._texture.orig.height,this._height=t}},{key:\"style\",get:function(){return this._style},set:function(t){t=t||{},t instanceof m.default?this._style=t:this._style=new m.default(t),this.localStyleID=-1,this.dirty=!0}},{key:\"text\",get:function(){return this._text},set:function(t){t=String(\"\"===t||null===t||void 0===t?\" \":t),this._text!==t&&(this._text=t,this.dirty=!0)}}]),e}(h.default);r.default=E},{\"../const\":46,\"../math\":70,\"../settings\":101,\"../sprites/Sprite\":102,\"../textures/Texture\":115,\"../utils\":124,\"../utils/trimCanvas\":129,\"./TextMetrics\":109,\"./TextStyle\":110}],109:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(e,r,i,o,s,a,u,h,l){n(this,t),this.text=e,this.style=r,this.width=i,this.height=o,this.lines=s,this.lineWidths=a,this.lineHeight=u,this.maxLineWidth=h,this.fontProperties=l}return t.measureText=function(e,r,n){var i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:t._canvas;n=n||r.wordWrap;var o=r.toFontString(),s=t.measureFont(o),a=i.getContext(\"2d\");a.font=o;for(var u=n?t.wordWrap(e,r,i):e,h=u.split(/(?:\\r\\n|\\r|\\n)/),l=new Array(h.length),c=0,d=0;d<h.length;d++){var f=a.measureText(h[d]).width+(h[d].length-1)*r.letterSpacing;l[d]=f,c=Math.max(c,f)}var p=c+r.strokeThickness;r.dropShadow&&(p+=r.dropShadowDistance);var v=r.lineHeight||s.fontSize+r.strokeThickness,y=Math.max(v,s.fontSize+r.strokeThickness)+(h.length-1)*(v+r.leading);return r.dropShadow&&(y+=r.dropShadowDistance),new t(e,r,p,y,h,l,v+r.leading,c,s)},t.wordWrap=function(e,r){for(var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t._canvas,i=n.getContext(\"2d\"),o=\"\",s=e.split(\"\\n\"),a=r.wordWrapWidth,u={},h=0;h<s.length;h++){for(var l=a,c=s[h].split(\" \"),d=0;d<c.length;d++){var f=i.measureText(c[d]).width;if(r.breakWords&&f>a)for(var p=c[d].split(\"\"),v=0;v<p.length;v++){var y=p[v],g=u[y];void 0===g&&(g=i.measureText(y).width,u[y]=g),g>l?(o+=\"\\n\"+y,l=a-g):(0===v&&(o+=\" \"),o+=y,l-=g)}else{var m=f+i.measureText(\" \").width;0===d||m>l?(d>0&&(o+=\"\\n\"),o+=c[d],l=a-f):(l-=m,o+=\" \"+c[d])}}h<s.length-1&&(o+=\"\\n\")}return o},t.measureFont=function(e){if(t._fonts[e])return t._fonts[e];var r={},n=t._canvas,i=t._context;i.font=e;var o=Math.ceil(i.measureText(\"|MÉq\").width),s=Math.ceil(i.measureText(\"M\").width),a=2*s;s=1.4*s|0,n.width=o,n.height=a,i.fillStyle=\"#f00\",i.fillRect(0,0,o,a),i.font=e,i.textBaseline=\"alphabetic\",i.fillStyle=\"#000\",i.fillText(\"|MÉq\",0,s);var u=i.getImageData(0,0,o,a).data,h=u.length,l=4*o,c=0,d=0,f=!1;for(c=0;c<s;++c){for(var p=0;p<l;p+=4)if(255!==u[d+p]){f=!0;break}if(f)break;d+=l}for(r.ascent=s-c,d=h-l,f=!1,c=a;c>s;--c){for(var v=0;v<l;v+=4)if(255!==u[d+v]){f=!0;break}if(f)break;d-=l}return r.descent=c-s,r.fontSize=r.ascent+r.descent,t._fonts[e]=r,r},t}();r.default=i;var o=document.createElement(\"canvas\");o.width=o.height=10,i._canvas=o,i._context=o.getContext(\"2d\"),i._fonts={}},{}],110:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t){return\"number\"==typeof t?(0,h.hex2string)(t):(\"string\"==typeof t&&0===t.indexOf(\"0x\")&&(t=t.replace(\"0x\",\"#\")),t)}function o(t){if(Array.isArray(t)){for(var e=0;e<t.length;++e)t[e]=i(t[e]);return t}return i(t)}function s(t,e){if(!Array.isArray(t)||!Array.isArray(e))return!1;if(t.length!==e.length)return!1;for(var r=0;r<t.length;++r)if(t[r]!==e[r])return!1;return!0}r.__esModule=!0;var a=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),u=t(\"../const\"),h=t(\"../utils\"),l={align:\"left\",breakWords:!1,dropShadow:!1,dropShadowAlpha:1,dropShadowAngle:Math.PI/6,dropShadowBlur:0,dropShadowColor:\"black\",dropShadowDistance:5,fill:\"black\",fillGradientType:u.TEXT_GRADIENT.LINEAR_VERTICAL,fillGradientStops:[],fontFamily:\"Arial\",fontSize:26,fontStyle:\"normal\",fontVariant:\"normal\",fontWeight:\"normal\",letterSpacing:0,lineHeight:0,lineJoin:\"miter\",miterLimit:10,padding:0,stroke:\"black\",strokeThickness:0,textBaseline:\"alphabetic\",trim:!1,wordWrap:!1,wordWrapWidth:100,leading:0},c=function(){function t(e){n(this,t),this.styleID=0,Object.assign(this,l,e)}return t.prototype.clone=function(){var e={};for(var r in l)e[r]=this[r];return new t(e)},t.prototype.reset=function(){Object.assign(this,l)},t.prototype.toFontString=function(){var t=\"number\"==typeof this.fontSize?this.fontSize+\"px\":this.fontSize,e=this.fontFamily;Array.isArray(this.fontFamily)||(e=this.fontFamily.split(\",\"));for(var r=e.length-1;r>=0;r--){var n=e[r].trim();/([\\\"\\'])[^\\'\\\"]+\\1/.test(n)||(n='\"'+n+'\"'),e[r]=n}return this.fontStyle+\" \"+this.fontVariant+\" \"+this.fontWeight+\" \"+t+\" \"+e.join(\",\")},a(t,[{key:\"align\",get:function(){return this._align},set:function(t){this._align!==t&&(this._align=t,this.styleID++)}},{key:\"breakWords\",get:function(){return this._breakWords},set:function(t){this._breakWords!==t&&(this._breakWords=t,this.styleID++)}},{key:\"dropShadow\",get:function(){return this._dropShadow},set:function(t){this._dropShadow!==t&&(this._dropShadow=t,this.styleID++)}},{key:\"dropShadowAlpha\",get:function(){return this._dropShadowAlpha},set:function(t){this._dropShadowAlpha!==t&&(this._dropShadowAlpha=t,this.styleID++)}},{key:\"dropShadowAngle\",get:function(){return this._dropShadowAngle},set:function(t){this._dropShadowAngle!==t&&(this._dropShadowAngle=t,this.styleID++)}},{key:\"dropShadowBlur\",get:function(){return this._dropShadowBlur},set:function(t){this._dropShadowBlur!==t&&(this._dropShadowBlur=t,this.styleID++)}},{key:\"dropShadowColor\",get:function(){return this._dropShadowColor},set:function(t){var e=o(t);this._dropShadowColor!==e&&(this._dropShadowColor=e,this.styleID++)}},{key:\"dropShadowDistance\",get:function(){return this._dropShadowDistance},set:function(t){this._dropShadowDistance!==t&&(this._dropShadowDistance=t,this.styleID++)}},{key:\"fill\",get:function(){return this._fill},set:function(t){var e=o(t);this._fill!==e&&(this._fill=e,this.styleID++)}},{key:\"fillGradientType\",get:function(){return this._fillGradientType},set:function(t){this._fillGradientType!==t&&(this._fillGradientType=t,this.styleID++)}},{key:\"fillGradientStops\",get:function(){return this._fillGradientStops},set:function(t){s(this._fillGradientStops,t)||(this._fillGradientStops=t,this.styleID++)}},{key:\"fontFamily\",get:function(){return this._fontFamily},set:function(t){this.fontFamily!==t&&(this._fontFamily=t,this.styleID++)}},{key:\"fontSize\",get:function(){return this._fontSize},set:function(t){this._fontSize!==t&&(this._fontSize=t,this.styleID++)}},{key:\"fontStyle\",get:function(){return this._fontStyle},set:function(t){this._fontStyle!==t&&(this._fontStyle=t,this.styleID++)}},{key:\"fontVariant\",get:function(){return this._fontVariant},set:function(t){this._fontVariant!==t&&(this._fontVariant=t,this.styleID++)}},{key:\"fontWeight\",get:function(){return this._fontWeight},set:function(t){this._fontWeight!==t&&(this._fontWeight=t,this.styleID++)}},{key:\"letterSpacing\",get:function(){return this._letterSpacing},set:function(t){this._letterSpacing!==t&&(this._letterSpacing=t,this.styleID++)}},{key:\"lineHeight\",get:function(){return this._lineHeight},set:function(t){this._lineHeight!==t&&(this._lineHeight=t,this.styleID++)}},{key:\"leading\",get:function(){return this._leading},set:function(t){this._leading!==t&&(this._leading=t,this.styleID++)}},{key:\"lineJoin\",get:function(){return this._lineJoin},set:function(t){this._lineJoin!==t&&(this._lineJoin=t,this.styleID++)}},{key:\"miterLimit\",get:function(){return this._miterLimit},set:function(t){this._miterLimit!==t&&(this._miterLimit=t,this.styleID++)}},{key:\"padding\",get:function(){return this._padding},set:function(t){this._padding!==t&&(this._padding=t,this.styleID++)}},{key:\"stroke\",get:function(){return this._stroke},set:function(t){var e=o(t);this._stroke!==e&&(this._stroke=e,this.styleID++)}},{key:\"strokeThickness\",get:function(){return this._strokeThickness},set:function(t){this._strokeThickness!==t&&(this._strokeThickness=t,this.styleID++)}},{key:\"textBaseline\",get:function(){return this._textBaseline},set:function(t){this._textBaseline!==t&&(this._textBaseline=t,this.styleID++)}},{key:\"trim\",get:function(){return this._trim},set:function(t){this._trim!==t&&(this._trim=t,this.styleID++)}},{key:\"wordWrap\",get:function(){return this._wordWrap},set:function(t){this._wordWrap!==t&&(this._wordWrap=t,this.styleID++)}},{key:\"wordWrapWidth\",get:function(){return this._wordWrapWidth},set:function(t){this._wordWrapWidth!==t&&(this._wordWrapWidth=t,this.styleID++)}}]),t}();r.default=c},{\"../const\":46,\"../utils\":124}],111:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"./BaseTexture\"),u=n(a),h=t(\"../settings\"),l=n(h),c=function(t){function e(){var r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:100,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:100,s=arguments[2],a=arguments[3];i(this,e);var u=o(this,t.call(this,null,s));return u.resolution=a||l.default.RESOLUTION,u.width=r,u.height=n,u.realWidth=u.width*u.resolution,u.realHeight=u.height*u.resolution,u.scaleMode=void 0!==s?s:l.default.SCALE_MODE,u.hasLoaded=!0,u._glRenderTargets={},u._canvasRenderTarget=null,u.valid=!1,u}return s(e,t),e.prototype.resize=function(t,e){t===this.width&&e===this.height||(this.valid=t>0&&e>0,this.width=t,this.height=e,this.realWidth=this.width*this.resolution,this.realHeight=this.height*this.resolution,this.valid&&this.emit(\"update\",this))},e.prototype.destroy=function(){t.prototype.destroy.call(this,!0),this.renderer=null},e}(u.default);r.default=c},{\"../settings\":101,\"./BaseTexture\":112}],112:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"../utils\"),u=t(\"../settings\"),h=n(u),l=t(\"eventemitter3\"),c=n(l),d=t(\"../utils/determineCrossOrigin\"),f=n(d),p=t(\"bit-twiddle\"),v=n(p),y=function(t){function e(r,n,s){i(this,e);var u=o(this,t.call(this));return u.uid=(0,a.uid)(),u.touched=0,u.resolution=s||h.default.RESOLUTION,u.width=100,u.height=100,u.realWidth=100,u.realHeight=100,u.scaleMode=void 0!==n?n:h.default.SCALE_MODE,u.hasLoaded=!1,u.isLoading=!1,u.source=null,u.origSource=null,u.imageType=null,u.sourceScale=1,u.premultipliedAlpha=!0,u.imageUrl=null,u.isPowerOfTwo=!1,u.mipmap=h.default.MIPMAP_TEXTURES,u.wrapMode=h.default.WRAP_MODE,u._glTextures={},u._enabled=0,u._virtalBoundId=-1,u._destroyed=!1,u.textureCacheIds=[],r&&u.loadSource(r),u}return s(e,t),e.prototype.update=function(){\"svg\"!==this.imageType&&(this.realWidth=this.source.naturalWidth||this.source.videoWidth||this.source.width,this.realHeight=this.source.naturalHeight||this.source.videoHeight||this.source.height,this._updateDimensions()),this.emit(\"update\",this)},e.prototype._updateDimensions=function(){this.width=this.realWidth/this.resolution,this.height=this.realHeight/this.resolution,this.isPowerOfTwo=v.default.isPow2(this.realWidth)&&v.default.isPow2(this.realHeight)},e.prototype.loadSource=function(t){var e=this.isLoading;this.hasLoaded=!1,this.isLoading=!1,e&&this.source&&(this.source.onload=null,this.source.onerror=null);var r=!this.source;if(this.source=t,(t.src&&t.complete||t.getContext)&&t.width&&t.height)this._updateImageType(),\"svg\"===this.imageType?this._loadSvgSource():this._sourceLoaded(),r&&this.emit(\"loaded\",this);else if(!t.getContext){this.isLoading=!0;var n=this;if(t.onload=function(){if(n._updateImageType(),t.onload=null,t.onerror=null,n.isLoading){if(n.isLoading=!1,n._sourceLoaded(),\"svg\"===n.imageType)return void n._loadSvgSource();n.emit(\"loaded\",n)}},t.onerror=function(){t.onload=null,t.onerror=null,n.isLoading&&(n.isLoading=!1,n.emit(\"error\",n))},t.complete&&t.src){if(t.onload=null,t.onerror=null,\"svg\"===n.imageType)return void n._loadSvgSource();this.isLoading=!1,t.width&&t.height?(this._sourceLoaded(),e&&this.emit(\"loaded\",this)):e&&this.emit(\"error\",this)}}},e.prototype._updateImageType=function(){if(this.imageUrl){var t=(0,a.decomposeDataUri)(this.imageUrl),e=void 0;if(t&&\"image\"===t.mediaType){var r=t.subType.split(\"+\")[0];if(!(e=(0,a.getUrlFileExtension)(\".\"+r)))throw new Error(\"Invalid image type in data URI.\")}else(e=(0,a.getUrlFileExtension)(this.imageUrl))||(e=\"png\");this.imageType=e}},e.prototype._loadSvgSource=function(){if(\"svg\"===this.imageType){var t=(0,a.decomposeDataUri)(this.imageUrl);t?this._loadSvgSourceUsingDataUri(t):this._loadSvgSourceUsingXhr()}},e.prototype._loadSvgSourceUsingDataUri=function(t){var e=void 0;if(\"base64\"===t.encoding){if(!atob)throw new Error(\"Your browser doesn't support base64 conversions.\");e=atob(t.data)}else e=t.data;this._loadSvgSourceUsingString(e)},e.prototype._loadSvgSourceUsingXhr=function(){var t=this,e=new XMLHttpRequest;e.onload=function(){if(e.readyState!==e.DONE||200!==e.status)throw new Error(\"Failed to load SVG using XHR.\");t._loadSvgSourceUsingString(e.response)},e.onerror=function(){return t.emit(\"error\",t)},e.open(\"GET\",this.imageUrl,!0),e.send()},e.prototype._loadSvgSourceUsingString=function(t){var r=(0,a.getSvgSize)(t),n=r.width,i=r.height;if(!n||!i)throw new Error(\"The SVG image must have width and height defined (in pixels), canvas API needs them.\");this.realWidth=Math.round(n*this.sourceScale),this.realHeight=Math.round(i*this.sourceScale),this._updateDimensions();var o=document.createElement(\"canvas\");o.width=this.realWidth,o.height=this.realHeight,o._pixiId=\"canvas_\"+(0,a.uid)(),o.getContext(\"2d\").drawImage(this.source,0,0,n,i,0,0,this.realWidth,this.realHeight),this.origSource=this.source,this.source=o,e.addToCache(this,o._pixiId),this.isLoading=!1,this._sourceLoaded(),this.emit(\"loaded\",this)},e.prototype._sourceLoaded=function(){this.hasLoaded=!0,this.update()},e.prototype.destroy=function(){this.imageUrl&&(delete a.TextureCache[this.imageUrl],this.imageUrl=null,navigator.isCocoonJS||(this.source.src=\"\")),this.source=null,this.dispose(),e.removeFromCache(this),this.textureCacheIds=null,this._destroyed=!0},e.prototype.dispose=function(){this.emit(\"dispose\",this)},e.prototype.updateSourceImage=function(t){this.source.src=t,this.loadSource(this.source)},e.fromImage=function(t,r,n,i){var o=a.BaseTextureCache[t];if(!o){var s=new Image;void 0===r&&0!==t.indexOf(\"data:\")?s.crossOrigin=(0,f.default)(t):r&&(s.crossOrigin=\"string\"==typeof r?r:\"anonymous\"),o=new e(s,n),o.imageUrl=t,i&&(o.sourceScale=i),o.resolution=(0,a.getResolutionOfUrl)(t),s.src=t,e.addToCache(o,t)}return o},e.fromCanvas=function(t,r){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:\"canvas\";t._pixiId||(t._pixiId=n+\"_\"+(0,a.uid)());var i=a.BaseTextureCache[t._pixiId];return i||(i=new e(t,r),e.addToCache(i,t._pixiId)),i},e.from=function(t,r,n){if(\"string\"==typeof t)return e.fromImage(t,void 0,r,n);if(t instanceof HTMLImageElement){var i=t.src,o=a.BaseTextureCache[i];return o||(o=new e(t,r),o.imageUrl=i,n&&(o.sourceScale=n),o.resolution=(0,a.getResolutionOfUrl)(i),e.addToCache(o,i)),o}return t instanceof HTMLCanvasElement?e.fromCanvas(t,r):t},e.addToCache=function(t,e){e&&(-1===t.textureCacheIds.indexOf(e)&&t.textureCacheIds.push(e),a.BaseTextureCache[e]=t)},e.removeFromCache=function(t){if(\"string\"==typeof t){var e=a.BaseTextureCache[t];if(e){var r=e.textureCacheIds.indexOf(t);return r>-1&&e.textureCacheIds.splice(r,1),delete a.BaseTextureCache[t],e}}else if(t&&t.textureCacheIds){for(var n=0;n<t.textureCacheIds.length;++n)delete a.BaseTextureCache[t.textureCacheIds[n]];return t.textureCacheIds.length=0,t}return null},e}(c.default);r.default=y},{\"../settings\":101,\"../utils\":124,\"../utils/determineCrossOrigin\":123,\"bit-twiddle\":1,eventemitter3:3}],113:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"./BaseRenderTexture\"),u=n(a),h=t(\"./Texture\"),l=n(h),c=function(t){function e(r,n){i(this,e);var s=null;if(!(r instanceof u.default)){var a=arguments[1],h=arguments[2],l=arguments[3],c=arguments[4];console.warn(\"Please use RenderTexture.create(\"+a+\", \"+h+\") instead of the ctor directly.\"),s=arguments[0],n=null,r=new u.default(a,h,l,c)}var d=o(this,t.call(this,r,n));return d.legacyRenderer=s,d.valid=!0,d._updateUvs(),d}return s(e,t),e.prototype.resize=function(t,e,r){this.valid=t>0&&e>0,this._frame.width=this.orig.width=t,this._frame.height=this.orig.height=e,r||this.baseTexture.resize(t,e),this._updateUvs()},e.create=function(t,r,n,i){return new e(new u.default(t,r,n,i))},e}(l.default);r.default=c},{\"./BaseRenderTexture\":111,\"./Texture\":115}],114:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),o=t(\"../\"),s=t(\"../utils\"),a=function(){function t(e,r){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;n(this,t),this.baseTexture=e,this.textures={},this.data=r,this.resolution=this._updateResolution(i||this.baseTexture.imageUrl),this._frames=this.data.frames,this._frameKeys=Object.keys(this._frames),this._batchIndex=0,this._callback=null}return i(t,null,[{key:\"BATCH_SIZE\",get:function(){return 1e3}}]),t.prototype._updateResolution=function(t){var e=this.data.meta.scale,r=(0,s.getResolutionOfUrl)(t,null);return null===r&&(r=void 0!==e?parseFloat(e):1),1!==r&&(this.baseTexture.resolution=r,this.baseTexture.update()),r},t.prototype.parse=function(e){this._batchIndex=0,this._callback=e,this._frameKeys.length<=t.BATCH_SIZE?(this._processFrames(0),this._parseComplete()):this._nextBatch()},t.prototype._processFrames=function(e){for(var r=e,n=t.BATCH_SIZE,i=this.baseTexture.sourceScale;r-e<n&&r<this._frameKeys.length;){var s=this._frameKeys[r],a=this._frames[s].frame;if(a){var u=null,h=null,l=new o.Rectangle(0,0,Math.floor(this._frames[s].sourceSize.w*i)/this.resolution,Math.floor(this._frames[s].sourceSize.h*i)/this.resolution);u=this._frames[s].rotated?new o.Rectangle(Math.floor(a.x*i)/this.resolution,Math.floor(a.y*i)/this.resolution,Math.floor(a.h*i)/this.resolution,Math.floor(a.w*i)/this.resolution):new o.Rectangle(Math.floor(a.x*i)/this.resolution,Math.floor(a.y*i)/this.resolution,Math.floor(a.w*i)/this.resolution,Math.floor(a.h*i)/this.resolution),this._frames[s].trimmed&&(h=new o.Rectangle(Math.floor(this._frames[s].spriteSourceSize.x*i)/this.resolution,Math.floor(this._frames[s].spriteSourceSize.y*i)/this.resolution,Math.floor(a.w*i)/this.resolution,Math.floor(a.h*i)/this.resolution)),this.textures[s]=new o.Texture(this.baseTexture,u,l,h,this._frames[s].rotated?2:0),o.Texture.addToCache(this.textures[s],s)}r++}},t.prototype._parseComplete=function(){var t=this._callback;this._callback=null,this._batchIndex=0,t.call(this,this.textures)},t.prototype._nextBatch=function(){var e=this;this._processFrames(this._batchIndex*t.BATCH_SIZE),this._batchIndex++,setTimeout(function(){e._batchIndex*t.BATCH_SIZE<e._frameKeys.length?e._nextBatch():e._parseComplete()},0)},t.prototype.destroy=function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];for(var e in this.textures)this.textures[e].destroy();this._frames=null,this._frameKeys=null,this.data=null,this.textures=null,t&&this.baseTexture.destroy(),this.baseTexture=null},t}();r.default=a},{\"../\":65,\"../utils\":124}],115:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function a(t){t.destroy=function(){},t.on=function(){},t.once=function(){},t.emit=function(){}}r.__esModule=!0;var u=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),h=t(\"./BaseTexture\"),l=n(h),c=t(\"./VideoBaseTexture\"),d=n(c),f=t(\"./TextureUvs\"),p=n(f),v=t(\"eventemitter3\"),y=n(v),g=t(\"../math\"),m=t(\"../utils\"),_=t(\"../settings\"),b=n(_),x=function(t){function e(r,n,s,a,u){i(this,e);var h=o(this,t.call(this));if(h.noFrame=!1,n||(h.noFrame=!0,n=new g.Rectangle(0,0,1,1)),r instanceof e&&(r=r.baseTexture),h.baseTexture=r,h._frame=n,h.trim=a,h.valid=!1,h.requiresUpdate=!1,h._uvs=null,h.orig=s||n,h._rotate=Number(u||0),!0===u)h._rotate=2;else if(h._rotate%2!=0)throw new Error(\"attempt to use diamond-shaped UVs. If you are sure, set rotation manually\");return r.hasLoaded?(h.noFrame&&(n=new g.Rectangle(0,0,r.width,r.height),r.on(\"update\",h.onBaseTextureUpdated,h)),h.frame=n):r.once(\"loaded\",h.onBaseTextureLoaded,h),h._updateID=0,h.transform=null,h.textureCacheIds=[],h}return s(e,t),e.prototype.update=function(){this.baseTexture.update()},e.prototype.onBaseTextureLoaded=function(t){this._updateID++,this.noFrame?this.frame=new g.Rectangle(0,0,t.width,t.height):this.frame=this._frame,this.baseTexture.on(\"update\",this.onBaseTextureUpdated,this),this.emit(\"update\",this)},e.prototype.onBaseTextureUpdated=function(t){this._updateID++,this._frame.width=t.width,this._frame.height=t.height,this.emit(\"update\",this)},e.prototype.destroy=function(t){this.baseTexture&&(t&&(m.TextureCache[this.baseTexture.imageUrl]&&e.removeFromCache(this.baseTexture.imageUrl),this.baseTexture.destroy()),this.baseTexture.off(\"update\",this.onBaseTextureUpdated,this),this.baseTexture.off(\"loaded\",this.onBaseTextureLoaded,this),this.baseTexture=null),this._frame=null,this._uvs=null,this.trim=null,this.orig=null,this.valid=!1,e.removeFromCache(this),this.textureCacheIds=null},e.prototype.clone=function(){return new e(this.baseTexture,this.frame,this.orig,this.trim,this.rotate)},e.prototype._updateUvs=function(){this._uvs||(this._uvs=new p.default),this._uvs.set(this._frame,this.baseTexture,this.rotate),this._updateID++},e.fromImage=function(t,r,n,i){var o=m.TextureCache[t];return o||(o=new e(l.default.fromImage(t,r,n,i)),e.addToCache(o,t)),o},e.fromFrame=function(t){var e=m.TextureCache[t];if(!e)throw new Error('The frameId \"'+t+'\" does not exist in the texture cache');return e},e.fromCanvas=function(t,r){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:\"canvas\";return new e(l.default.fromCanvas(t,r,n))},e.fromVideo=function(t,r){return\"string\"==typeof t?e.fromVideoUrl(t,r):new e(d.default.fromVideo(t,r))},e.fromVideoUrl=function(t,r){return new e(d.default.fromUrl(t,r))},e.from=function(t){if(\"string\"==typeof t){var r=m.TextureCache[t];if(!r){return null!==t.match(/\\.(mp4|webm|ogg|h264|avi|mov)$/)?e.fromVideoUrl(t):e.fromImage(t)}return r}return t instanceof HTMLImageElement?new e(l.default.from(t)):t instanceof HTMLCanvasElement?e.fromCanvas(t,b.default.SCALE_MODE,\"HTMLCanvasElement\"):t instanceof HTMLVideoElement?e.fromVideo(t):t instanceof l.default?new e(t):t},e.fromLoader=function(t,r,n){var i=new l.default(t,void 0,(0,m.getResolutionOfUrl)(r)),o=new e(i);return i.imageUrl=r,n||(n=r),l.default.addToCache(o.baseTexture,n),e.addToCache(o,n),n!==r&&(l.default.addToCache(o.baseTexture,r),e.addToCache(o,r)),o},e.addToCache=function(t,e){e&&(-1===t.textureCacheIds.indexOf(e)&&t.textureCacheIds.push(e),m.TextureCache[e]=t)},e.removeFromCache=function(t){if(\"string\"==typeof t){var e=m.TextureCache[t];if(e){var r=e.textureCacheIds.indexOf(t);return r>-1&&e.textureCacheIds.splice(r,1),delete m.TextureCache[t],e}}else if(t&&t.textureCacheIds){for(var n=0;n<t.textureCacheIds.length;++n)m.TextureCache[t.textureCacheIds[n]]===t&&delete m.TextureCache[t.textureCacheIds[n]];return t.textureCacheIds.length=0,t}return null},u(e,[{key:\"frame\",get:function(){return this._frame},set:function(t){this._frame=t,this.noFrame=!1\n;var e=t.x,r=t.y,n=t.width,i=t.height,o=e+n>this.baseTexture.width,s=r+i>this.baseTexture.height;if(o||s){var a=o&&s?\"and\":\"or\",u=\"X: \"+e+\" + \"+n+\" = \"+(e+n)+\" > \"+this.baseTexture.width,h=\"Y: \"+r+\" + \"+i+\" = \"+(r+i)+\" > \"+this.baseTexture.height;throw new Error(\"Texture Error: frame does not fit inside the base Texture dimensions: \"+u+\" \"+a+\" \"+h)}this.valid=n&&i&&this.baseTexture.hasLoaded,this.trim||this.rotate||(this.orig=t),this.valid&&this._updateUvs()}},{key:\"rotate\",get:function(){return this._rotate},set:function(t){this._rotate=t,this.valid&&this._updateUvs()}},{key:\"width\",get:function(){return this.orig.width}},{key:\"height\",get:function(){return this.orig.height}}]),e}(y.default);r.default=x,x.EMPTY=new x(new l.default),a(x.EMPTY),a(x.EMPTY.baseTexture),x.WHITE=function(){var t=document.createElement(\"canvas\");t.width=10,t.height=10;var e=t.getContext(\"2d\");return e.fillStyle=\"white\",e.fillRect(0,0,10,10),new x(new l.default(t))}(),a(x.WHITE),a(x.WHITE.baseTexture)},{\"../math\":70,\"../settings\":101,\"../utils\":124,\"./BaseTexture\":112,\"./TextureUvs\":116,\"./VideoBaseTexture\":117,eventemitter3:3}],116:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../math/GroupD8\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=function(){function t(){n(this,t),this.x0=0,this.y0=0,this.x1=1,this.y1=0,this.x2=1,this.y2=1,this.x3=0,this.y3=1,this.uvsUint32=new Uint32Array(4)}return t.prototype.set=function(t,e,r){var n=e.width,i=e.height;if(r){var s=t.width/2/n,a=t.height/2/i,u=t.x/n+s,h=t.y/i+a;r=o.default.add(r,o.default.NW),this.x0=u+s*o.default.uX(r),this.y0=h+a*o.default.uY(r),r=o.default.add(r,2),this.x1=u+s*o.default.uX(r),this.y1=h+a*o.default.uY(r),r=o.default.add(r,2),this.x2=u+s*o.default.uX(r),this.y2=h+a*o.default.uY(r),r=o.default.add(r,2),this.x3=u+s*o.default.uX(r),this.y3=h+a*o.default.uY(r)}else this.x0=t.x/n,this.y0=t.y/i,this.x1=(t.x+t.width)/n,this.y1=t.y/i,this.x2=(t.x+t.width)/n,this.y2=(t.y+t.height)/i,this.x3=t.x/n,this.y3=(t.y+t.height)/i;this.uvsUint32[0]=(65535*this.y0&65535)<<16|65535*this.x0&65535,this.uvsUint32[1]=(65535*this.y1&65535)<<16|65535*this.x1&65535,this.uvsUint32[2]=(65535*this.y2&65535)<<16|65535*this.x2&65535,this.uvsUint32[3]=(65535*this.y3&65535)<<16|65535*this.x3&65535},t}();r.default=s},{\"../math/GroupD8\":66}],117:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function s(t,e){e||(e=\"video/\"+t.substr(t.lastIndexOf(\".\")+1));var r=document.createElement(\"source\");return r.src=t,r.type=e,r}r.__esModule=!0;var a=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),u=t(\"./BaseTexture\"),h=function(t){return t&&t.__esModule?t:{default:t}}(u),l=t(\"../utils\"),c=t(\"../ticker\"),d=t(\"../const\"),f=function(t){function e(r,o){if(n(this,e),!r)throw new Error(\"No video source element specified.\");(r.readyState===r.HAVE_ENOUGH_DATA||r.readyState===r.HAVE_FUTURE_DATA)&&r.width&&r.height&&(r.complete=!0);var s=i(this,t.call(this,r,o));return s.width=r.videoWidth,s.height=r.videoHeight,s._autoUpdate=!0,s._isAutoUpdating=!1,s.autoPlay=!0,s.update=s.update.bind(s),s._onCanPlay=s._onCanPlay.bind(s),r.addEventListener(\"play\",s._onPlayStart.bind(s)),r.addEventListener(\"pause\",s._onPlayStop.bind(s)),s.hasLoaded=!1,s.__loaded=!1,s._isSourceReady()?s._onCanPlay():(r.addEventListener(\"canplay\",s._onCanPlay),r.addEventListener(\"canplaythrough\",s._onCanPlay)),s}return o(e,t),e.prototype._isSourcePlaying=function(){var t=this.source;return t.currentTime>0&&!1===t.paused&&!1===t.ended&&t.readyState>2},e.prototype._isSourceReady=function(){return 3===this.source.readyState||4===this.source.readyState},e.prototype._onPlayStart=function(){this.hasLoaded||this._onCanPlay(),!this._isAutoUpdating&&this.autoUpdate&&(c.shared.add(this.update,this,d.UPDATE_PRIORITY.HIGH),this._isAutoUpdating=!0)},e.prototype._onPlayStop=function(){this._isAutoUpdating&&(c.shared.remove(this.update,this),this._isAutoUpdating=!1)},e.prototype._onCanPlay=function(){this.hasLoaded=!0,this.source&&(this.source.removeEventListener(\"canplay\",this._onCanPlay),this.source.removeEventListener(\"canplaythrough\",this._onCanPlay),this.width=this.source.videoWidth,this.height=this.source.videoHeight,this.__loaded||(this.__loaded=!0,this.emit(\"loaded\",this)),this._isSourcePlaying()?this._onPlayStart():this.autoPlay&&this.source.play())},e.prototype.destroy=function(){this._isAutoUpdating&&c.shared.remove(this.update,this),this.source&&this.source._pixiId&&(h.default.removeFromCache(this.source._pixiId),delete this.source._pixiId),t.prototype.destroy.call(this)},e.fromVideo=function(t,r){t._pixiId||(t._pixiId=\"video_\"+(0,l.uid)());var n=l.BaseTextureCache[t._pixiId];return n||(n=new e(t,r),h.default.addToCache(n,t._pixiId)),n},e.fromUrl=function(t,r){var n=document.createElement(\"video\");if(n.setAttribute(\"webkit-playsinline\",\"\"),n.setAttribute(\"playsinline\",\"\"),Array.isArray(t))for(var i=0;i<t.length;++i)n.appendChild(s(t[i].src||t[i],t[i].mime));else n.appendChild(s(t.src||t,t.mime));return n.load(),e.fromVideo(n,r)},a(e,[{key:\"autoUpdate\",get:function(){return this._autoUpdate},set:function(t){t!==this._autoUpdate&&(this._autoUpdate=t,!this._autoUpdate&&this._isAutoUpdating?(c.shared.remove(this.update,this),this._isAutoUpdating=!1):this._autoUpdate&&!this._isAutoUpdating&&(c.shared.add(this.update,this,d.UPDATE_PRIORITY.HIGH),this._isAutoUpdating=!0))}}]),e}(h.default);r.default=f,f.fromUrls=f.fromUrl},{\"../const\":46,\"../ticker\":120,\"../utils\":124,\"./BaseTexture\":112}],118:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var o=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),s=t(\"../settings\"),a=n(s),u=t(\"../const\"),h=t(\"./TickerListener\"),l=n(h),c=function(){function t(){var e=this;i(this,t),this._head=new l.default(null,null,1/0),this._requestId=null,this._maxElapsedMS=100,this.autoStart=!1,this.deltaTime=1,this.elapsedMS=1/a.default.TARGET_FPMS,this.lastTime=-1,this.speed=1,this.started=!1,this._tick=function(t){e._requestId=null,e.started&&(e.update(t),e.started&&null===e._requestId&&e._head.next&&(e._requestId=requestAnimationFrame(e._tick)))}}return t.prototype._requestIfNeeded=function(){null===this._requestId&&this._head.next&&(this.lastTime=performance.now(),this._requestId=requestAnimationFrame(this._tick))},t.prototype._cancelIfNeeded=function(){null!==this._requestId&&(cancelAnimationFrame(this._requestId),this._requestId=null)},t.prototype._startIfPossible=function(){this.started?this._requestIfNeeded():this.autoStart&&this.start()},t.prototype.add=function(t,e){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:u.UPDATE_PRIORITY.NORMAL;return this._addListener(new l.default(t,e,r))},t.prototype.addOnce=function(t,e){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:u.UPDATE_PRIORITY.NORMAL;return this._addListener(new l.default(t,e,r,!0))},t.prototype._addListener=function(t){var e=this._head.next,r=this._head;if(e){for(;e;){if(t.priority>e.priority){t.connect(r);break}r=e,e=e.next}t.previous||t.connect(r)}else t.connect(r);return this._startIfPossible(),this},t.prototype.remove=function(t,e){for(var r=this._head.next;r;)r=r.match(t,e)?r.destroy():r.next;return this._head.next||this._cancelIfNeeded(),this},t.prototype.start=function(){this.started||(this.started=!0,this._requestIfNeeded())},t.prototype.stop=function(){this.started&&(this.started=!1,this._cancelIfNeeded())},t.prototype.destroy=function(){this.stop();for(var t=this._head.next;t;)t=t.destroy(!0);this._head.destroy(),this._head=null},t.prototype.update=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:performance.now(),e=void 0;if(t>this.lastTime){e=this.elapsedMS=t-this.lastTime,e>this._maxElapsedMS&&(e=this._maxElapsedMS),this.deltaTime=e*a.default.TARGET_FPMS*this.speed;for(var r=this._head,n=r.next;n;)n=n.emit(this.deltaTime);r.next||this._cancelIfNeeded()}else this.deltaTime=this.elapsedMS=0;this.lastTime=t},o(t,[{key:\"FPS\",get:function(){return 1e3/this.elapsedMS}},{key:\"minFPS\",get:function(){return 1e3/this._maxElapsedMS},set:function(t){var e=Math.min(Math.max(0,t)/1e3,a.default.TARGET_FPMS);this._maxElapsedMS=1/e}}]),t}();r.default=c},{\"../const\":46,\"../settings\":101,\"./TickerListener\":119}],119:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(e){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=arguments.length>3&&void 0!==arguments[3]&&arguments[3];n(this,t),this.fn=e,this.context=r,this.priority=i,this.once=o,this.next=null,this.previous=null,this._destroyed=!1}return t.prototype.match=function(t,e){return e=e||null,this.fn===t&&this.context===e},t.prototype.emit=function(t){this.fn&&(this.context?this.fn.call(this.context,t):this.fn(t));var e=this.next;return this.once&&this.destroy(!0),this._destroyed&&(this.next=null),e},t.prototype.connect=function(t){this.previous=t,t.next&&(t.next.previous=this),this.next=t.next,t.next=this},t.prototype.destroy=function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0];this._destroyed=!0,this.fn=null,this.context=null,this.previous&&(this.previous.next=this.next),this.next&&(this.next.previous=this.previous);var e=this.previous;return this.next=t?null:e,this.previous=null,e},t}();r.default=i},{}],120:[function(t,e,r){\"use strict\";r.__esModule=!0,r.Ticker=r.shared=void 0;var n=t(\"./Ticker\"),i=function(t){return t&&t.__esModule?t:{default:t}}(n),o=new i.default;o.autoStart=!0,o.destroy=function(){},r.shared=o,r.Ticker=i.default},{\"./Ticker\":118}],121:[function(t,e,r){\"use strict\";function n(){return!(!!navigator.platform&&/iPad|iPhone|iPod/.test(navigator.platform))}r.__esModule=!0,r.default=n},{}],122:[function(t,e,r){\"use strict\";function n(t){for(var e=6*t,r=new Uint16Array(e),n=0,i=0;n<e;n+=6,i+=4)r[n+0]=i+0,r[n+1]=i+1,r[n+2]=i+2,r[n+3]=i+0,r[n+4]=i+2,r[n+5]=i+3;return r}r.__esModule=!0,r.default=n},{}],123:[function(t,e,r){\"use strict\";function n(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:window.location;if(0===t.indexOf(\"data:\"))return\"\";e=e||window.location,s||(s=document.createElement(\"a\")),s.href=t,t=o.default.parse(s.href);var r=!t.port&&\"\"===e.port||t.port===e.port;return t.hostname===e.hostname&&r&&t.protocol===e.protocol?\"\":\"anonymous\"}r.__esModule=!0,r.default=n;var i=t(\"url\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i),s=void 0},{url:38}],124:[function(t,e,r){\"use strict\";function n(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}function i(t){return t&&t.__esModule?t:{default:t}}function o(){return++k}function s(t,e){return e=e||[],e[0]=(t>>16&255)/255,e[1]=(t>>8&255)/255,e[2]=(255&t)/255,e}function a(t){return t=t.toString(16),\"#\"+(t=\"000000\".substr(0,6-t.length)+t)}function u(t){return(255*t[0]<<16)+(255*t[1]<<8)+(255*t[2]|0)}function h(t,e){var r=S.default.RETINA_PREFIX.exec(t);return r?parseFloat(r[1]):void 0!==e?e:1}function l(t){var e=w.DATA_URI.exec(t);if(e)return{mediaType:e[1]?e[1].toLowerCase():void 0,subType:e[2]?e[2].toLowerCase():void 0,encoding:e[3]?e[3].toLowerCase():void 0,data:e[4]}}function c(t){var e=w.URL_FILE_EXTENSION.exec(t);if(e)return e[1].toLowerCase()}function d(t){var e=w.SVG_SIZE.exec(t),r={};return e&&(r[e[1]]=Math.round(parseFloat(e[3])),r[e[5]]=Math.round(parseFloat(e[7]))),r}function f(){j=!0}function p(t){if(!j){if(navigator.userAgent.toLowerCase().indexOf(\"chrome\")>-1){var e=[\"\\n %c %c %c PixiJS \"+w.VERSION+\" - ✰ \"+t+\" ✰  %c  %c  http://www.pixijs.com/  %c %c ♥%c♥%c♥ \\n\\n\",\"background: #ff66a5; padding:5px 0;\",\"background: #ff66a5; padding:5px 0;\",\"color: #ff66a5; background: #030307; padding:5px 0;\",\"background: #ff66a5; padding:5px 0;\",\"background: #ffc3dc; padding:5px 0;\",\"background: #ff66a5; padding:5px 0;\",\"color: #ff2424; background: #fff; padding:5px 0;\",\"color: #ff2424; background: #fff; padding:5px 0;\",\"color: #ff2424; background: #fff; padding:5px 0;\"];window.console.log.apply(console,e)}else window.console&&window.console.log(\"PixiJS \"+w.VERSION+\" - \"+t+\" - http://www.pixijs.com/\");j=!0}}function v(){var t={stencil:!0,failIfMajorPerformanceCaveat:!0};try{if(!window.WebGLRenderingContext)return!1;var e=document.createElement(\"canvas\"),r=e.getContext(\"webgl\",t)||e.getContext(\"experimental-webgl\",t),n=!(!r||!r.getContextAttributes().stencil);if(r){var i=r.getExtension(\"WEBGL_lose_context\");i&&i.loseContext()}return r=null,n}catch(t){return!1}}function y(t){return 0===t?0:t<0?-1:1}function g(){var t=void 0;for(t in U)U[t].destroy();for(t in X)X[t].destroy()}function m(){var t=void 0;for(t in U)delete U[t];for(t in X)delete X[t]}function _(t,e){return G[e?1:0][t]}function b(t,e){if(1===e)return(255*e<<24)+t;if(0===e)return 0;var r=t>>16&255,n=t>>8&255,i=255&t;return r=r*e+.5|0,n=n*e+.5|0,i=i*e+.5|0,(255*e<<24)+(r<<16)+(n<<8)+i}function x(t,e,r,n){return r=r||new Float32Array(4),n||void 0===n?(r[0]=t[0]*e,r[1]=t[1]*e,r[2]=t[2]*e):(r[0]=t[0],r[1]=t[1],r[2]=t[2]),r[3]=e,r}function T(t,e,r,n){return r=r||new Float32Array(4),r[0]=(t>>16&255)/255,r[1]=(t>>8&255)/255,r[2]=(255&t)/255,(n||void 0===n)&&(r[0]*=e,r[1]*=e,r[2]*=e),r[3]=e,r}r.__esModule=!0,r.premultiplyBlendMode=r.BaseTextureCache=r.TextureCache=r.mixins=r.pluginTarget=r.EventEmitter=r.removeItems=r.isMobile=void 0,r.uid=o,r.hex2rgb=s,r.hex2string=a,r.rgb2hex=u,r.getResolutionOfUrl=h,r.decomposeDataUri=l,r.getUrlFileExtension=c,r.getSvgSize=d,r.skipHello=f,r.sayHello=p,r.isWebGLSupported=v,r.sign=y,r.destroyTextureCache=g,r.clearTextureCache=m,r.correctBlendMode=_,r.premultiplyTint=b,r.premultiplyRgba=x,r.premultiplyTintToRgba=T;var w=t(\"../const\"),E=t(\"../settings\"),S=i(E),O=t(\"eventemitter3\"),M=i(O),P=t(\"./pluginTarget\"),C=i(P),R=t(\"./mixin\"),A=n(R),I=t(\"ismobilejs\"),D=n(I),L=t(\"remove-array-items\"),N=i(L),F=t(\"./mapPremultipliedBlendModes\"),B=i(F),k=0,j=!1;r.isMobile=D,r.removeItems=N.default,r.EventEmitter=M.default,r.pluginTarget=C.default,r.mixins=A;var U=r.TextureCache=Object.create(null),X=r.BaseTextureCache=Object.create(null),G=r.premultiplyBlendMode=(0,B.default)()},{\"../const\":46,\"../settings\":101,\"./mapPremultipliedBlendModes\":125,\"./mixin\":127,\"./pluginTarget\":128,eventemitter3:3,ismobilejs:4,\"remove-array-items\":31}],125:[function(t,e,r){\"use strict\";function n(){for(var t=[],e=[],r=0;r<32;r++)t[r]=r,e[r]=r;t[i.BLEND_MODES.NORMAL_NPM]=i.BLEND_MODES.NORMAL,t[i.BLEND_MODES.ADD_NPM]=i.BLEND_MODES.ADD,t[i.BLEND_MODES.SCREEN_NPM]=i.BLEND_MODES.SCREEN,e[i.BLEND_MODES.NORMAL]=i.BLEND_MODES.NORMAL_NPM,e[i.BLEND_MODES.ADD]=i.BLEND_MODES.ADD_NPM,e[i.BLEND_MODES.SCREEN]=i.BLEND_MODES.SCREEN_NPM;var n=[];return n.push(e),n.push(t),n}r.__esModule=!0,r.default=n;var i=t(\"../const\")},{\"../const\":46}],126:[function(t,e,r){\"use strict\";function n(t){return o.default.tablet||o.default.phone?4:t}r.__esModule=!0,r.default=n;var i=t(\"ismobilejs\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i)},{ismobilejs:4}],127:[function(t,e,r){\"use strict\";function n(t,e){if(t&&e)for(var r=Object.keys(e),n=0;n<r.length;++n){var i=r[n];Object.defineProperty(t,i,Object.getOwnPropertyDescriptor(e,i))}}function i(t,e){s.push(t,e)}function o(){for(var t=0;t<s.length;t+=2)n(s[t],s[t+1]);s.length=0}r.__esModule=!0,r.mixin=n,r.delayMixin=i,r.performMixins=o;var s=[]},{}],128:[function(t,e,r){\"use strict\";function n(t){t.__plugins={},t.registerPlugin=function(e,r){t.__plugins[e]=r},t.prototype.initPlugins=function(){this.plugins=this.plugins||{};for(var e in t.__plugins)this.plugins[e]=new t.__plugins[e](this)},t.prototype.destroyPlugins=function(){for(var t in this.plugins)this.plugins[t].destroy(),this.plugins[t]=null;this.plugins=null}}r.__esModule=!0,r.default={mixin:function(t){n(t)}}},{}],129:[function(t,e,r){\"use strict\";function n(t){var e=t.width,r=t.height,n=t.getContext(\"2d\"),i=n.getImageData(0,0,e,r),o=i.data,s=o.length,a={top:null,left:null,right:null,bottom:null},u=void 0,h=void 0,l=void 0;for(u=0;u<s;u+=4)0!==o[u+3]&&(h=u/4%e,l=~~(u/4/e),null===a.top&&(a.top=l),null===a.left?a.left=h:h<a.left&&(a.left=h),null===a.right?a.right=h+1:a.right<h&&(a.right=h+1),null===a.bottom?a.bottom=l:a.bottom<l&&(a.bottom=l));return e=a.right-a.left,r=a.bottom-a.top+1,{height:r,width:e,data:n.getImageData(a.left,a.top,e,r)}}r.__esModule=!0,r.default=n},{}],130:[function(t,e,r){\"use strict\";function n(t){}function i(t){var e=t.mesh,r=t.particles,i=t.extras,o=t.filters,s=t.prepare,a=t.loaders,u=t.interaction;Object.defineProperties(t,{SpriteBatch:{get:function(){throw new ReferenceError(\"SpriteBatch does not exist any more, please use the new ParticleContainer instead.\")}},AssetLoader:{get:function(){throw new ReferenceError(\"The loader system was overhauled in PixiJS v3, please see the new PIXI.loaders.Loader class.\")}},Stage:{get:function(){return n(\"You do not need to use a PIXI Stage any more, you can simply render any container.\"),t.Container}},DisplayObjectContainer:{get:function(){return n(\"DisplayObjectContainer has been shortened to Container, please use Container from now on.\"),t.Container}},Strip:{get:function(){return n(\"The Strip class has been renamed to Mesh and moved to mesh.Mesh, please use mesh.Mesh from now on.\"),e.Mesh}},Rope:{get:function(){return n(\"The Rope class has been moved to mesh.Rope, please use mesh.Rope from now on.\"),e.Rope}},ParticleContainer:{get:function(){return n(\"The ParticleContainer class has been moved to particles.ParticleContainer, please use particles.ParticleContainer from now on.\"),r.ParticleContainer}},MovieClip:{get:function(){return n(\"The MovieClip class has been moved to extras.AnimatedSprite, please use extras.AnimatedSprite.\"),i.AnimatedSprite}},TilingSprite:{get:function(){return n(\"The TilingSprite class has been moved to extras.TilingSprite, please use extras.TilingSprite from now on.\"),i.TilingSprite}},BitmapText:{get:function(){return n(\"The BitmapText class has been moved to extras.BitmapText, please use extras.BitmapText from now on.\"),i.BitmapText}},blendModes:{get:function(){return n(\"The blendModes has been moved to BLEND_MODES, please use BLEND_MODES from now on.\"),t.BLEND_MODES}},scaleModes:{get:function(){return n(\"The scaleModes has been moved to SCALE_MODES, please use SCALE_MODES from now on.\"),t.SCALE_MODES}},BaseTextureCache:{get:function(){return n(\"The BaseTextureCache class has been moved to utils.BaseTextureCache, please use utils.BaseTextureCache from now on.\"),t.utils.BaseTextureCache}},TextureCache:{get:function(){return n(\"The TextureCache class has been moved to utils.TextureCache, please use utils.TextureCache from now on.\"),t.utils.TextureCache}},math:{get:function(){return n(\"The math namespace is deprecated, please access members already accessible on PIXI.\"),t}},AbstractFilter:{get:function(){return n(\"AstractFilter has been renamed to Filter, please use PIXI.Filter\"),t.Filter}},TransformManual:{get:function(){return n(\"TransformManual has been renamed to TransformBase, please update your pixi-spine\"),t.TransformBase}},TARGET_FPMS:{get:function(){return n(\"PIXI.TARGET_FPMS has been deprecated, please use PIXI.settings.TARGET_FPMS\"),t.settings.TARGET_FPMS},set:function(e){n(\"PIXI.TARGET_FPMS has been deprecated, please use PIXI.settings.TARGET_FPMS\"),t.settings.TARGET_FPMS=e}},FILTER_RESOLUTION:{get:function(){return n(\"PIXI.FILTER_RESOLUTION has been deprecated, please use PIXI.settings.FILTER_RESOLUTION\"),t.settings.FILTER_RESOLUTION},set:function(e){n(\"PIXI.FILTER_RESOLUTION has been deprecated, please use PIXI.settings.FILTER_RESOLUTION\"),t.settings.FILTER_RESOLUTION=e}},RESOLUTION:{get:function(){return n(\"PIXI.RESOLUTION has been deprecated, please use PIXI.settings.RESOLUTION\"),t.settings.RESOLUTION},set:function(e){n(\"PIXI.RESOLUTION has been deprecated, please use PIXI.settings.RESOLUTION\"),t.settings.RESOLUTION=e}},MIPMAP_TEXTURES:{get:function(){return n(\"PIXI.MIPMAP_TEXTURES has been deprecated, please use PIXI.settings.MIPMAP_TEXTURES\"),t.settings.MIPMAP_TEXTURES},set:function(e){n(\"PIXI.MIPMAP_TEXTURES has been deprecated, please use PIXI.settings.MIPMAP_TEXTURES\"),t.settings.MIPMAP_TEXTURES=e}},SPRITE_BATCH_SIZE:{get:function(){return n(\"PIXI.SPRITE_BATCH_SIZE has been deprecated, please use PIXI.settings.SPRITE_BATCH_SIZE\"),t.settings.SPRITE_BATCH_SIZE},set:function(e){n(\"PIXI.SPRITE_BATCH_SIZE has been deprecated, please use PIXI.settings.SPRITE_BATCH_SIZE\"),t.settings.SPRITE_BATCH_SIZE=e}},SPRITE_MAX_TEXTURES:{get:function(){return n(\"PIXI.SPRITE_MAX_TEXTURES has been deprecated, please use PIXI.settings.SPRITE_MAX_TEXTURES\"),t.settings.SPRITE_MAX_TEXTURES},set:function(e){n(\"PIXI.SPRITE_MAX_TEXTURES has been deprecated, please use PIXI.settings.SPRITE_MAX_TEXTURES\"),t.settings.SPRITE_MAX_TEXTURES=e}},RETINA_PREFIX:{get:function(){return n(\"PIXI.RETINA_PREFIX has been deprecated, please use PIXI.settings.RETINA_PREFIX\"),t.settings.RETINA_PREFIX},set:function(e){n(\"PIXI.RETINA_PREFIX has been deprecated, please use PIXI.settings.RETINA_PREFIX\"),t.settings.RETINA_PREFIX=e}},DEFAULT_RENDER_OPTIONS:{get:function(){return n(\"PIXI.DEFAULT_RENDER_OPTIONS has been deprecated, please use PIXI.settings.DEFAULT_RENDER_OPTIONS\"),t.settings.RENDER_OPTIONS}}});for(var h=[{parent:\"TRANSFORM_MODE\",target:\"TRANSFORM_MODE\"},{parent:\"GC_MODES\",target:\"GC_MODE\"},{parent:\"WRAP_MODES\",target:\"WRAP_MODE\"},{parent:\"SCALE_MODES\",target:\"SCALE_MODE\"},{parent:\"PRECISION\",target:\"PRECISION_FRAGMENT\"}],l=0;l<h.length;l++)!function(e){var r=h[e];Object.defineProperty(t[r.parent],\"DEFAULT\",{get:function(){return n(\"PIXI.\"+r.parent+\".DEFAULT has been deprecated, please use PIXI.settings.\"+r.target),t.settings[r.target]},set:function(e){n(\"PIXI.\"+r.parent+\".DEFAULT has been deprecated, please use PIXI.settings.\"+r.target),t.settings[r.target]=e}})}(l);Object.defineProperties(t.settings,{PRECISION:{get:function(){return n(\"PIXI.settings.PRECISION has been deprecated, please use PIXI.settings.PRECISION_FRAGMENT\"),t.settings.PRECISION_FRAGMENT},set:function(e){n(\"PIXI.settings.PRECISION has been deprecated, please use PIXI.settings.PRECISION_FRAGMENT\"),t.settings.PRECISION_FRAGMENT=e}}}),i.AnimatedSprite&&Object.defineProperties(i,{MovieClip:{get:function(){return n(\"The MovieClip class has been renamed to AnimatedSprite, please use AnimatedSprite from now on.\"),i.AnimatedSprite}}}),t.DisplayObject.prototype.generateTexture=function(t,e,r){return n(\"generateTexture has moved to the renderer, please use renderer.generateTexture(displayObject)\"),t.generateTexture(this,e,r)},t.Graphics.prototype.generateTexture=function(t,e){return n(\"graphics generate texture has moved to the renderer. Or to render a graphics to a texture using canvas please use generateCanvasTexture\"),this.generateCanvasTexture(t,e)},t.RenderTexture.prototype.render=function(t,e,r,i){this.legacyRenderer.render(t,this,r,e,!i),n(\"RenderTexture.render is now deprecated, please use renderer.render(displayObject, renderTexture)\")},t.RenderTexture.prototype.getImage=function(t){return n(\"RenderTexture.getImage is now deprecated, please use renderer.extract.image(target)\"),this.legacyRenderer.extract.image(t)},t.RenderTexture.prototype.getBase64=function(t){return n(\"RenderTexture.getBase64 is now deprecated, please use renderer.extract.base64(target)\"),this.legacyRenderer.extract.base64(t)},t.RenderTexture.prototype.getCanvas=function(t){return n(\"RenderTexture.getCanvas is now deprecated, please use renderer.extract.canvas(target)\"),this.legacyRenderer.extract.canvas(t)},t.RenderTexture.prototype.getPixels=function(t){return n(\"RenderTexture.getPixels is now deprecated, please use renderer.extract.pixels(target)\"),this.legacyRenderer.pixels(t)},t.Sprite.prototype.setTexture=function(t){this.texture=t,n(\"setTexture is now deprecated, please use the texture property, e.g : sprite.texture = texture;\")},i.BitmapText&&(i.BitmapText.prototype.setText=function(t){this.text=t,n(\"setText is now deprecated, please use the text property, e.g : myBitmapText.text = 'my text';\")}),t.Text.prototype.setText=function(t){this.text=t,n(\"setText is now deprecated, please use the text property, e.g : myText.text = 'my text';\")},t.Text.calculateFontProperties=function(e){return n(\"Text.calculateFontProperties is now deprecated, please use the TextMetrics.measureFont\"),t.TextMetrics.measureFont(e)},Object.defineProperties(t.Text,{fontPropertiesCache:{get:function(){return n(\"Text.fontPropertiesCache is deprecated\"),t.TextMetrics._fonts}},fontPropertiesCanvas:{get:function(){return n(\"Text.fontPropertiesCanvas is deprecated\"),t.TextMetrics._canvas}},fontPropertiesContext:{get:function(){return n(\"Text.fontPropertiesContext is deprecated\"),t.TextMetrics._context}}}),t.Text.prototype.setStyle=function(t){this.style=t,n(\"setStyle is now deprecated, please use the style property, e.g : myText.style = style;\")},t.Text.prototype.determineFontProperties=function(e){return n(\"determineFontProperties is now deprecated, please use TextMetrics.measureFont method\"),t.TextMetrics.measureFont(e)},t.Text.getFontStyle=function(e){return n(\"getFontStyle is now deprecated, please use TextStyle.toFontString() instead\"),e=e||{},e instanceof t.TextStyle||(e=new t.TextStyle(e)),e.toFontString()},Object.defineProperties(t.TextStyle.prototype,{font:{get:function(){n(\"text style property 'font' is now deprecated, please use the 'fontFamily', 'fontSize', 'fontStyle', 'fontVariant' and 'fontWeight' properties from now on\");var t=\"number\"==typeof this._fontSize?this._fontSize+\"px\":this._fontSize;return this._fontStyle+\" \"+this._fontVariant+\" \"+this._fontWeight+\" \"+t+\" \"+this._fontFamily},set:function(t){n(\"text style property 'font' is now deprecated, please use the 'fontFamily','fontSize',fontStyle','fontVariant' and 'fontWeight' properties from now on\"),t.indexOf(\"italic\")>1?this._fontStyle=\"italic\":t.indexOf(\"oblique\")>-1?this._fontStyle=\"oblique\":this._fontStyle=\"normal\",t.indexOf(\"small-caps\")>-1?this._fontVariant=\"small-caps\":this._fontVariant=\"normal\";var e=t.split(\" \"),r=-1;this._fontSize=26;for(var i=0;i<e.length;++i)if(e[i].match(/(px|pt|em|%)/)){r=i,this._fontSize=e[i];break}this._fontWeight=\"normal\";for(var o=0;o<r;++o)if(e[o].match(/(bold|bolder|lighter|100|200|300|400|500|600|700|800|900)/)){this._fontWeight=e[o];break}if(r>-1&&r<e.length-1){this._fontFamily=\"\";for(var s=r+1;s<e.length;++s)this._fontFamily+=e[s]+\" \";this._fontFamily=this._fontFamily.slice(0,-1)}else this._fontFamily=\"Arial\";this.styleID++}}}),t.Texture.prototype.setFrame=function(t){this.frame=t,n(\"setFrame is now deprecated, please use the frame property, e.g: myTexture.frame = frame;\")},t.Texture.addTextureToCache=function(e,r){t.Texture.addToCache(e,r),n(\"Texture.addTextureToCache is deprecated, please use Texture.addToCache from now on.\")},t.Texture.removeTextureFromCache=function(e){return n(\"Texture.removeTextureFromCache is deprecated, please use Texture.removeFromCache from now on. Be aware that Texture.removeFromCache does not automatically its BaseTexture from the BaseTextureCache. For that, use BaseTexture.removeFromCache\"),t.BaseTexture.removeFromCache(e),t.Texture.removeFromCache(e)},Object.defineProperties(o,{AbstractFilter:{get:function(){return n(\"AstractFilter has been renamed to Filter, please use PIXI.Filter\"),t.AbstractFilter}},SpriteMaskFilter:{get:function(){return n(\"filters.SpriteMaskFilter is an undocumented alias, please use SpriteMaskFilter from now on.\"),t.SpriteMaskFilter}}}),t.utils.uuid=function(){return n(\"utils.uuid() is deprecated, please use utils.uid() from now on.\"),t.utils.uid()},t.utils.canUseNewCanvasBlendModes=function(){return n(\"utils.canUseNewCanvasBlendModes() is deprecated, please use CanvasTinter.canUseMultiply from now on\"),t.CanvasTinter.canUseMultiply};var c=!0;if(Object.defineProperty(t.utils,\"_saidHello\",{set:function(t){t&&(n(\"PIXI.utils._saidHello is deprecated, please use PIXI.utils.skipHello()\"),this.skipHello()),c=t},get:function(){return c}}),s.BasePrepare&&(s.BasePrepare.prototype.register=function(t,e){return n(\"renderer.plugins.prepare.register is now deprecated, please use renderer.plugins.prepare.registerFindHook & renderer.plugins.prepare.registerUploadHook\"),t&&this.registerFindHook(t),e&&this.registerUploadHook(e),this}),s.canvas&&Object.defineProperty(s.canvas,\"UPLOADS_PER_FRAME\",{set:function(){n(\"PIXI.CanvasPrepare.UPLOADS_PER_FRAME has been removed. Please set renderer.plugins.prepare.limiter.maxItemsPerFrame on your renderer\")},get:function(){return n(\"PIXI.CanvasPrepare.UPLOADS_PER_FRAME has been removed. Please use renderer.plugins.prepare.limiter\"),NaN}}),s.webgl&&Object.defineProperty(s.webgl,\"UPLOADS_PER_FRAME\",{set:function(){n(\"PIXI.WebGLPrepare.UPLOADS_PER_FRAME has been removed. Please set renderer.plugins.prepare.limiter.maxItemsPerFrame on your renderer\")},get:function(){return n(\"PIXI.WebGLPrepare.UPLOADS_PER_FRAME has been removed. Please use renderer.plugins.prepare.limiter\"),NaN}}),a.Loader){var d=a.Resource,f=a.Loader;Object.defineProperties(d.prototype,{isJson:{get:function(){return n(\"The isJson property is deprecated, please use `resource.type === Resource.TYPE.JSON`.\"),this.type===d.TYPE.JSON}},isXml:{get:function(){return n(\"The isXml property is deprecated, please use `resource.type === Resource.TYPE.XML`.\"),this.type===d.TYPE.XML}},isImage:{get:function(){return n(\"The isImage property is deprecated, please use `resource.type === Resource.TYPE.IMAGE`.\"),this.type===d.TYPE.IMAGE}},isAudio:{get:function(){return n(\"The isAudio property is deprecated, please use `resource.type === Resource.TYPE.AUDIO`.\"),this.type===d.TYPE.AUDIO}},isVideo:{get:function(){return n(\"The isVideo property is deprecated, please use `resource.type === Resource.TYPE.VIDEO`.\"),this.type===d.TYPE.VIDEO}}}),Object.defineProperties(f.prototype,{before:{get:function(){return n(\"The before() method is deprecated, please use pre().\"),this.pre}},after:{get:function(){return n(\"The after() method is deprecated, please use use().\"),this.use}}})}u.interactiveTarget&&Object.defineProperty(u.interactiveTarget,\"defaultCursor\",{set:function(t){n(\"Property defaultCursor has been replaced with 'cursor'. \"),this.cursor=t},get:function(){return n(\"Property defaultCursor has been replaced with 'cursor'. \"),this.cursor}}),u.InteractionManager&&(Object.defineProperty(u.InteractionManager,\"defaultCursorStyle\",{set:function(t){n(\"Property defaultCursorStyle has been replaced with 'cursorStyles.default'. \"),this.cursorStyles.default=t},get:function(){return n(\"Property defaultCursorStyle has been replaced with 'cursorStyles.default'. \"),this.cursorStyles.default}}),Object.defineProperty(u.InteractionManager,\"currentCursorStyle\",{set:function(t){n(\"Property currentCursorStyle has been removed.See the currentCursorMode property, which works differently.\"),\nthis.currentCursorMode=t},get:function(){return n(\"Property currentCursorStyle has been removed.See the currentCursorMode property, which works differently.\"),this.currentCursorMode}}))}r.__esModule=!0,r.default=i},{}],131:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../../core\"),o=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(i),s=new o.Rectangle,a=function(){function t(e){n(this,t),this.renderer=e,e.extract=this}return t.prototype.image=function(t){var e=new Image;return e.src=this.base64(t),e},t.prototype.base64=function(t){return this.canvas(t).toDataURL()},t.prototype.canvas=function(t){var e=this.renderer,r=void 0,n=void 0,i=void 0,a=void 0;t&&(a=t instanceof o.RenderTexture?t:e.generateTexture(t)),a?(r=a.baseTexture._canvasRenderTarget.context,n=a.baseTexture._canvasRenderTarget.resolution,i=a.frame):(r=e.rootContext,i=s,i.width=this.renderer.width,i.height=this.renderer.height);var u=i.width*n,h=i.height*n,l=new o.CanvasRenderTarget(u,h),c=r.getImageData(i.x*n,i.y*n,u,h);return l.context.putImageData(c,0,0),l.canvas},t.prototype.pixels=function(t){var e=this.renderer,r=void 0,n=void 0,i=void 0,a=void 0;return t&&(a=t instanceof o.RenderTexture?t:e.generateTexture(t)),a?(r=a.baseTexture._canvasRenderTarget.context,n=a.baseTexture._canvasRenderTarget.resolution,i=a.frame):(r=e.rootContext,i=s,i.width=e.width,i.height=e.height),r.getImageData(0,0,i.width*n,i.height*n).data},t.prototype.destroy=function(){this.renderer.extract=null,this.renderer=null},t}();r.default=a,o.CanvasRenderer.registerPlugin(\"extract\",a)},{\"../../core\":65}],132:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0;var i=t(\"./webgl/WebGLExtract\");Object.defineProperty(r,\"webgl\",{enumerable:!0,get:function(){return n(i).default}});var o=t(\"./canvas/CanvasExtract\");Object.defineProperty(r,\"canvas\",{enumerable:!0,get:function(){return n(o).default}})},{\"./canvas/CanvasExtract\":131,\"./webgl/WebGLExtract\":133}],133:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../../core\"),o=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(i),s=new o.Rectangle,a=function(){function t(e){n(this,t),this.renderer=e,e.extract=this}return t.prototype.image=function(t){var e=new Image;return e.src=this.base64(t),e},t.prototype.base64=function(t){return this.canvas(t).toDataURL()},t.prototype.canvas=function(t){var e=this.renderer,r=void 0,n=void 0,i=void 0,a=!1,u=void 0;t&&(u=t instanceof o.RenderTexture?t:this.renderer.generateTexture(t)),u?(r=u.baseTexture._glRenderTargets[this.renderer.CONTEXT_UID],n=r.resolution,i=u.frame,a=!1):(r=this.renderer.rootRenderTarget,n=r.resolution,a=!0,i=s,i.width=r.size.width,i.height=r.size.height);var h=i.width*n,l=i.height*n,c=new o.CanvasRenderTarget(h,l);if(r){e.bindRenderTarget(r);var d=new Uint8Array(4*h*l),f=e.gl;f.readPixels(i.x*n,i.y*n,h,l,f.RGBA,f.UNSIGNED_BYTE,d);var p=c.context.getImageData(0,0,h,l);p.data.set(d),c.context.putImageData(p,0,0),a&&(c.context.scale(1,-1),c.context.drawImage(c.canvas,0,-l))}return c.canvas},t.prototype.pixels=function(t){var e=this.renderer,r=void 0,n=void 0,i=void 0,a=void 0;t&&(a=t instanceof o.RenderTexture?t:this.renderer.generateTexture(t)),a?(r=a.baseTexture._glRenderTargets[this.renderer.CONTEXT_UID],n=r.resolution,i=a.frame):(r=this.renderer.rootRenderTarget,n=r.resolution,i=s,i.width=r.size.width,i.height=r.size.height);var u=i.width*n,h=i.height*n,l=new Uint8Array(4*u*h);if(r){e.bindRenderTarget(r);var c=e.gl;c.readPixels(i.x*n,i.y*n,u,h,c.RGBA,c.UNSIGNED_BYTE,l)}return l},t.prototype.destroy=function(){this.renderer.extract=null,this.renderer=null},t}();r.default=a,o.WebGLRenderer.registerPlugin(\"extract\",a)},{\"../../core\":65}],134:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"../core\"),u=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(a),h=function(t){function e(r,o){n(this,e);var s=i(this,t.call(this,r[0]instanceof u.Texture?r[0]:r[0].texture));return s._textures=null,s._durations=null,s.textures=r,s._autoUpdate=!1!==o,s.animationSpeed=1,s.loop=!0,s.onComplete=null,s.onFrameChange=null,s.onLoop=null,s._currentTime=0,s.playing=!1,s}return o(e,t),e.prototype.stop=function(){this.playing&&(this.playing=!1,this._autoUpdate&&u.ticker.shared.remove(this.update,this))},e.prototype.play=function(){this.playing||(this.playing=!0,this._autoUpdate&&u.ticker.shared.add(this.update,this,u.UPDATE_PRIORITY.HIGH))},e.prototype.gotoAndStop=function(t){this.stop();var e=this.currentFrame;this._currentTime=t,e!==this.currentFrame&&this.updateTexture()},e.prototype.gotoAndPlay=function(t){var e=this.currentFrame;this._currentTime=t,e!==this.currentFrame&&this.updateTexture(),this.play()},e.prototype.update=function(t){var e=this.animationSpeed*t,r=this.currentFrame;if(null!==this._durations){var n=this._currentTime%1*this._durations[this.currentFrame];for(n+=e/60*1e3;n<0;)this._currentTime--,n+=this._durations[this.currentFrame];var i=Math.sign(this.animationSpeed*t);for(this._currentTime=Math.floor(this._currentTime);n>=this._durations[this.currentFrame];)n-=this._durations[this.currentFrame]*i,this._currentTime+=i;this._currentTime+=n/this._durations[this.currentFrame]}else this._currentTime+=e;this._currentTime<0&&!this.loop?(this.gotoAndStop(0),this.onComplete&&this.onComplete()):this._currentTime>=this._textures.length&&!this.loop?(this.gotoAndStop(this._textures.length-1),this.onComplete&&this.onComplete()):r!==this.currentFrame&&(this.loop&&this.onLoop&&(this.animationSpeed>0&&this.currentFrame<r?this.onLoop():this.animationSpeed<0&&this.currentFrame>r&&this.onLoop()),this.updateTexture())},e.prototype.updateTexture=function(){this._texture=this._textures[this.currentFrame],this._textureID=-1,this.cachedTint=16777215,this.onFrameChange&&this.onFrameChange(this.currentFrame)},e.prototype.destroy=function(e){this.stop(),t.prototype.destroy.call(this,e)},e.fromFrames=function(t){for(var r=[],n=0;n<t.length;++n)r.push(u.Texture.fromFrame(t[n]));return new e(r)},e.fromImages=function(t){for(var r=[],n=0;n<t.length;++n)r.push(u.Texture.fromImage(t[n]));return new e(r)},s(e,[{key:\"totalFrames\",get:function(){return this._textures.length}},{key:\"textures\",get:function(){return this._textures},set:function(t){if(t[0]instanceof u.Texture)this._textures=t,this._durations=null;else{this._textures=[],this._durations=[];for(var e=0;e<t.length;e++)this._textures.push(t[e].texture),this._durations.push(t[e].time)}this.gotoAndStop(0),this.updateTexture()}},{key:\"currentFrame\",get:function(){var t=Math.floor(this._currentTime)%this._textures.length;return t<0&&(t+=this._textures.length),t}}]),e}(u.Sprite);r.default=h},{\"../core\":65}],135:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),u=t(\"../core\"),h=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(u),l=t(\"../core/math/ObservablePoint\"),c=n(l),d=t(\"../core/settings\"),f=n(d),p=function(t){function e(r){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};i(this,e);var s=o(this,t.call(this));return s._textWidth=0,s._textHeight=0,s._glyphs=[],s._font={tint:void 0!==n.tint?n.tint:16777215,align:n.align||\"left\",name:null,size:0},s.font=n.font,s._text=r,s._maxWidth=0,s._maxLineHeight=0,s._anchor=new c.default(function(){s.dirty=!0},s,0,0),s.dirty=!1,s.updateText(),s}return s(e,t),e.prototype.updateText=function(){for(var t=e.fonts[this._font.name],r=this._font.size/t.size,n=new h.Point,i=[],o=[],s=null,a=0,u=0,l=0,c=-1,d=0,f=0,p=0,v=0;v<this.text.length;v++){var y=this.text.charCodeAt(v);if(/(\\s)/.test(this.text.charAt(v))&&(c=v,d=a),/(?:\\r\\n|\\r|\\n)/.test(this.text.charAt(v)))o.push(a),u=Math.max(u,a),l++,n.x=0,n.y+=t.lineHeight,s=null;else if(-1!==c&&this._maxWidth>0&&n.x*r>this._maxWidth)h.utils.removeItems(i,c-f,v-c),v=c,c=-1,++f,o.push(d),u=Math.max(u,d),l++,n.x=0,n.y+=t.lineHeight,s=null;else{var g=t.chars[y];g&&(s&&g.kerning[s]&&(n.x+=g.kerning[s]),i.push({texture:g.texture,line:l,charCode:y,position:new h.Point(n.x+g.xOffset,n.y+g.yOffset)}),a=n.x+(g.texture.width+g.xOffset),n.x+=g.xAdvance,p=Math.max(p,g.yOffset+g.texture.height),s=y)}}o.push(a),u=Math.max(u,a);for(var m=[],_=0;_<=l;_++){var b=0;\"right\"===this._font.align?b=u-o[_]:\"center\"===this._font.align&&(b=(u-o[_])/2),m.push(b)}for(var x=i.length,T=this.tint,w=0;w<x;w++){var E=this._glyphs[w];E?E.texture=i[w].texture:(E=new h.Sprite(i[w].texture),this._glyphs.push(E)),E.position.x=(i[w].position.x+m[i[w].line])*r,E.position.y=i[w].position.y*r,E.scale.x=E.scale.y=r,E.tint=T,E.parent||this.addChild(E)}for(var S=x;S<this._glyphs.length;++S)this.removeChild(this._glyphs[S]);if(this._textWidth=u*r,this._textHeight=(n.y+t.lineHeight)*r,0!==this.anchor.x||0!==this.anchor.y)for(var O=0;O<x;O++)this._glyphs[O].x-=this._textWidth*this.anchor.x,this._glyphs[O].y-=this._textHeight*this.anchor.y;this._maxLineHeight=p*r},e.prototype.updateTransform=function(){this.validate(),this.containerUpdateTransform()},e.prototype.getLocalBounds=function(){return this.validate(),t.prototype.getLocalBounds.call(this)},e.prototype.validate=function(){this.dirty&&(this.updateText(),this.dirty=!1)},e.registerFont=function(t,r){var n={},i=t.getElementsByTagName(\"info\")[0],o=t.getElementsByTagName(\"common\")[0],s=r.baseTexture.resolution||f.default.RESOLUTION;n.font=i.getAttribute(\"face\"),n.size=parseInt(i.getAttribute(\"size\"),10),n.lineHeight=parseInt(o.getAttribute(\"lineHeight\"),10)/s,n.chars={};for(var a=t.getElementsByTagName(\"char\"),u=0;u<a.length;u++){var l=a[u],c=parseInt(l.getAttribute(\"id\"),10),d=new h.Rectangle(parseInt(l.getAttribute(\"x\"),10)/s+r.frame.x/s,parseInt(l.getAttribute(\"y\"),10)/s+r.frame.y/s,parseInt(l.getAttribute(\"width\"),10)/s,parseInt(l.getAttribute(\"height\"),10)/s);n.chars[c]={xOffset:parseInt(l.getAttribute(\"xoffset\"),10)/s,yOffset:parseInt(l.getAttribute(\"yoffset\"),10)/s,xAdvance:parseInt(l.getAttribute(\"xadvance\"),10)/s,kerning:{},texture:new h.Texture(r.baseTexture,d)}}for(var p=t.getElementsByTagName(\"kerning\"),v=0;v<p.length;v++){var y=p[v],g=parseInt(y.getAttribute(\"first\"),10)/s,m=parseInt(y.getAttribute(\"second\"),10)/s,_=parseInt(y.getAttribute(\"amount\"),10)/s;n.chars[m]&&(n.chars[m].kerning[g]=_)}return e.fonts[n.font]=n,n},a(e,[{key:\"tint\",get:function(){return this._font.tint},set:function(t){this._font.tint=\"number\"==typeof t&&t>=0?t:16777215,this.dirty=!0}},{key:\"align\",get:function(){return this._font.align},set:function(t){this._font.align=t||\"left\",this.dirty=!0}},{key:\"anchor\",get:function(){return this._anchor},set:function(t){\"number\"==typeof t?this._anchor.set(t):this._anchor.copy(t)}},{key:\"font\",get:function(){return this._font},set:function(t){t&&(\"string\"==typeof t?(t=t.split(\" \"),this._font.name=1===t.length?t[0]:t.slice(1).join(\" \"),this._font.size=t.length>=2?parseInt(t[0],10):e.fonts[this._font.name].size):(this._font.name=t.name,this._font.size=\"number\"==typeof t.size?t.size:parseInt(t.size,10)),this.dirty=!0)}},{key:\"text\",get:function(){return this._text},set:function(t){t=t.toString()||\" \",this._text!==t&&(this._text=t,this.dirty=!0)}},{key:\"maxWidth\",get:function(){return this._maxWidth},set:function(t){this._maxWidth!==t&&(this._maxWidth=t,this.dirty=!0)}},{key:\"maxLineHeight\",get:function(){return this.validate(),this._maxLineHeight}},{key:\"textWidth\",get:function(){return this.validate(),this._textWidth}},{key:\"textHeight\",get:function(){return this.validate(),this._textHeight}}]),e}(h.Container);r.default=p,p.fonts={}},{\"../core\":65,\"../core/math/ObservablePoint\":68,\"../core/settings\":101}],136:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),o=t(\"../core/math/Matrix\"),s=function(t){return t&&t.__esModule?t:{default:t}}(o),a=new s.default,u=function(){function t(e,r){n(this,t),this._texture=e,this.mapCoord=new s.default,this.uClampFrame=new Float32Array(4),this.uClampOffset=new Float32Array(2),this._lastTextureID=-1,this.clampOffset=0,this.clampMargin=void 0===r?.5:r}return t.prototype.multiplyUvs=function(t,e){void 0===e&&(e=t);for(var r=this.mapCoord,n=0;n<t.length;n+=2){var i=t[n],o=t[n+1];e[n]=i*r.a+o*r.c+r.tx,e[n+1]=i*r.b+o*r.d+r.ty}return e},t.prototype.update=function(t){var e=this._texture;if(!e||!e.valid)return!1;if(!t&&this._lastTextureID===e._updateID)return!1;this._lastTextureID=e._updateID;var r=e._uvs;this.mapCoord.set(r.x1-r.x0,r.y1-r.y0,r.x3-r.x0,r.y3-r.y0,r.x0,r.y0);var n=e.orig,i=e.trim;i&&(a.set(n.width/i.width,0,0,n.height/i.height,-i.x/i.width,-i.y/i.height),this.mapCoord.append(a));var o=e.baseTexture,s=this.uClampFrame,u=this.clampMargin/o.resolution,h=this.clampOffset;return s[0]=(e._frame.x+u+h)/o.width,s[1]=(e._frame.y+u+h)/o.height,s[2]=(e._frame.x+e._frame.width-u+h)/o.width,s[3]=(e._frame.y+e._frame.height-u+h)/o.height,this.uClampOffset[0]=h/o.realWidth,this.uClampOffset[1]=h/o.realHeight,!0},i(t,[{key:\"texture\",get:function(){return this._texture},set:function(t){this._texture=t,this._lastTextureID=-1}}]),t}();r.default=u},{\"../core/math/Matrix\":67}],137:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),u=t(\"../core\"),h=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(u),l=t(\"../core/sprites/canvas/CanvasTinter\"),c=n(l),d=t(\"./TextureTransform\"),f=n(d),p=new h.Point,v=function(t){function e(r){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:100,s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:100;i(this,e);var a=o(this,t.call(this,r));return a.tileTransform=new h.TransformStatic,a._width=n,a._height=s,a._canvasPattern=null,a.uvTransform=r.transform||new f.default(r),a.pluginName=\"tilingSprite\",a.uvRespectAnchor=!1,a}return s(e,t),e.prototype._onTextureUpdate=function(){this.uvTransform&&(this.uvTransform.texture=this._texture),this.cachedTint=16777215},e.prototype._renderWebGL=function(t){var e=this._texture;e&&e.valid&&(this.tileTransform.updateLocalTransform(),this.uvTransform.update(),t.setObjectRenderer(t.plugins[this.pluginName]),t.plugins[this.pluginName].render(this))},e.prototype._renderCanvas=function(t){var e=this._texture;if(e.baseTexture.hasLoaded){var r=t.context,n=this.worldTransform,i=t.resolution,o=e.baseTexture,s=o.resolution,a=this.tilePosition.x/this.tileScale.x%e._frame.width*s,u=this.tilePosition.y/this.tileScale.y%e._frame.height*s;if(this._textureID!==this._texture._updateID||this.cachedTint!==this.tint){this._textureID=this._texture._updateID;var l=new h.CanvasRenderTarget(e._frame.width,e._frame.height,s);16777215!==this.tint?(this.tintedTexture=c.default.getTintedTexture(this,this.tint),l.context.drawImage(this.tintedTexture,0,0)):l.context.drawImage(o.source,-e._frame.x*s,-e._frame.y*s),this.cachedTint=this.tint,this._canvasPattern=l.context.createPattern(l.canvas,\"repeat\")}r.globalAlpha=this.worldAlpha,r.setTransform(n.a*i,n.b*i,n.c*i,n.d*i,n.tx*i,n.ty*i),t.setBlendMode(this.blendMode),r.fillStyle=this._canvasPattern,r.scale(this.tileScale.x/s,this.tileScale.y/s);var d=this.anchor.x*-this._width,f=this.anchor.y*-this._height;this.uvRespectAnchor?(r.translate(a,u),r.fillRect(-a+d,-u+f,this._width/this.tileScale.x*s,this._height/this.tileScale.y*s)):(r.translate(a+d,u+f),r.fillRect(-a,-u,this._width/this.tileScale.x*s,this._height/this.tileScale.y*s))}},e.prototype._calculateBounds=function(){var t=this._width*-this._anchor._x,e=this._height*-this._anchor._y,r=this._width*(1-this._anchor._x),n=this._height*(1-this._anchor._y);this._bounds.addFrame(this.transform,t,e,r,n)},e.prototype.getLocalBounds=function(e){return 0===this.children.length?(this._bounds.minX=this._width*-this._anchor._x,this._bounds.minY=this._height*-this._anchor._y,this._bounds.maxX=this._width*(1-this._anchor._x),this._bounds.maxY=this._height*(1-this._anchor._x),e||(this._localBoundsRect||(this._localBoundsRect=new h.Rectangle),e=this._localBoundsRect),this._bounds.getRectangle(e)):t.prototype.getLocalBounds.call(this,e)},e.prototype.containsPoint=function(t){this.worldTransform.applyInverse(t,p);var e=this._width,r=this._height,n=-e*this.anchor._x;if(p.x>=n&&p.x<n+e){var i=-r*this.anchor._y;if(p.y>=i&&p.y<i+r)return!0}return!1},e.prototype.destroy=function(e){t.prototype.destroy.call(this,e),this.tileTransform=null,this.uvTransform=null},e.from=function(t,r,n){return new e(h.Texture.from(t),r,n)},e.fromFrame=function(t,r,n){var i=h.utils.TextureCache[t];if(!i)throw new Error('The frameId \"'+t+'\" does not exist in the texture cache '+this);return new e(i,r,n)},e.fromImage=function(t,r,n,i,o){return new e(h.Texture.fromImage(t,i,o),r,n)},a(e,[{key:\"clampMargin\",get:function(){return this.uvTransform.clampMargin},set:function(t){this.uvTransform.clampMargin=t,this.uvTransform.update(!0)}},{key:\"tileScale\",get:function(){return this.tileTransform.scale},set:function(t){this.tileTransform.scale.copy(t)}},{key:\"tilePosition\",get:function(){return this.tileTransform.position},set:function(t){this.tileTransform.position.copy(t)}},{key:\"width\",get:function(){return this._width},set:function(t){this._width=t}},{key:\"height\",get:function(){return this._height},set:function(t){this._height=t}}]),e}(h.Sprite);r.default=v},{\"../core\":65,\"../core/sprites/canvas/CanvasTinter\":104,\"./TextureTransform\":136}],138:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}var o=t(\"../core\"),s=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(o),a=t(\"../core/textures/Texture\"),u=n(a),h=t(\"../core/textures/BaseTexture\"),l=n(h),c=t(\"../core/utils\"),d=s.DisplayObject,f=new s.Matrix;d.prototype._cacheAsBitmap=!1,d.prototype._cacheData=!1;var p=function t(){i(this,t),this.textureCacheId=null,this.originalRenderWebGL=null,this.originalRenderCanvas=null,this.originalCalculateBounds=null,this.originalGetLocalBounds=null,this.originalUpdateTransform=null,this.originalHitTest=null,this.originalDestroy=null,this.originalMask=null,this.originalFilterArea=null,this.sprite=null};Object.defineProperties(d.prototype,{cacheAsBitmap:{get:function(){return this._cacheAsBitmap},set:function(t){if(this._cacheAsBitmap!==t){this._cacheAsBitmap=t;var e=void 0;t?(this._cacheData||(this._cacheData=new p),e=this._cacheData,e.originalRenderWebGL=this.renderWebGL,e.originalRenderCanvas=this.renderCanvas,e.originalUpdateTransform=this.updateTransform,e.originalCalculateBounds=this._calculateBounds,e.originalGetLocalBounds=this.getLocalBounds,e.originalDestroy=this.destroy,e.originalContainsPoint=this.containsPoint,e.originalMask=this._mask,e.originalFilterArea=this.filterArea,this.renderWebGL=this._renderCachedWebGL,this.renderCanvas=this._renderCachedCanvas,this.destroy=this._cacheAsBitmapDestroy):(e=this._cacheData,e.sprite&&this._destroyCachedDisplayObject(),this.renderWebGL=e.originalRenderWebGL,this.renderCanvas=e.originalRenderCanvas,this._calculateBounds=e.originalCalculateBounds,this.getLocalBounds=e.originalGetLocalBounds,this.destroy=e.originalDestroy,this.updateTransform=e.originalUpdateTransform,this.containsPoint=e.originalContainsPoint,this._mask=e.originalMask,this.filterArea=e.originalFilterArea)}}}}),d.prototype._renderCachedWebGL=function(t){!this.visible||this.worldAlpha<=0||!this.renderable||(this._initCachedDisplayObject(t),this._cacheData.sprite._transformID=-1,this._cacheData.sprite.worldAlpha=this.worldAlpha,this._cacheData.sprite._renderWebGL(t))},d.prototype._initCachedDisplayObject=function(t){if(!this._cacheData||!this._cacheData.sprite){var e=this.alpha;this.alpha=1,t.currentRenderer.flush();var r=this.getLocalBounds().clone();if(this._filters){var n=this._filters[0].padding;r.pad(n)}var i=t._activeRenderTarget,o=t.filterManager.filterStack,a=s.RenderTexture.create(0|r.width,0|r.height),h=\"cacheAsBitmap_\"+(0,c.uid)();this._cacheData.textureCacheId=h,l.default.addToCache(a.baseTexture,h),u.default.addToCache(a,h);var d=f;d.tx=-r.x,d.ty=-r.y,this.transform.worldTransform.identity(),this.renderWebGL=this._cacheData.originalRenderWebGL,t.render(this,a,!0,d,!0),t.bindRenderTarget(i),t.filterManager.filterStack=o,this.renderWebGL=this._renderCachedWebGL,this.updateTransform=this.displayObjectUpdateTransform,this._mask=null,this.filterArea=null;var p=new s.Sprite(a);p.transform.worldTransform=this.transform.worldTransform,p.anchor.x=-r.x/r.width,p.anchor.y=-r.y/r.height,p.alpha=e,p._bounds=this._bounds,this._calculateBounds=this._calculateCachedBounds,this.getLocalBounds=this._getCachedLocalBounds,this._cacheData.sprite=p,this.transform._parentID=-1,this.parent?this.updateTransform():(this.parent=t._tempDisplayObjectParent,this.updateTransform(),this.parent=null),this.containsPoint=p.containsPoint.bind(p)}},d.prototype._renderCachedCanvas=function(t){!this.visible||this.worldAlpha<=0||!this.renderable||(this._initCachedDisplayObjectCanvas(t),this._cacheData.sprite.worldAlpha=this.worldAlpha,this._cacheData.sprite.renderCanvas(t))},d.prototype._initCachedDisplayObjectCanvas=function(t){if(!this._cacheData||!this._cacheData.sprite){var e=this.getLocalBounds(),r=this.alpha;this.alpha=1;var n=t.context,i=s.RenderTexture.create(0|e.width,0|e.height),o=\"cacheAsBitmap_\"+(0,c.uid)();this._cacheData.textureCacheId=o,l.default.addToCache(i.baseTexture,o),u.default.addToCache(i,o);var a=f;this.transform.localTransform.copy(a),a.invert(),a.tx-=e.x,a.ty-=e.y,this.renderCanvas=this._cacheData.originalRenderCanvas,t.render(this,i,!0,a,!1),t.context=n,this.renderCanvas=this._renderCachedCanvas,this._calculateBounds=this._calculateCachedBounds,this._mask=null,this.filterArea=null;var h=new s.Sprite(i);h.transform.worldTransform=this.transform.worldTransform,h.anchor.x=-e.x/e.width,h.anchor.y=-e.y/e.height,h._bounds=this._bounds,h.alpha=r,this.parent?this.updateTransform():(this.parent=t._tempDisplayObjectParent,this.updateTransform(),this.parent=null),this.updateTransform=this.displayObjectUpdateTransform,this._cacheData.sprite=h,this.containsPoint=h.containsPoint.bind(h)}},d.prototype._calculateCachedBounds=function(){this._cacheData.sprite._calculateBounds()},d.prototype._getCachedLocalBounds=function(){return this._cacheData.sprite.getLocalBounds()},d.prototype._destroyCachedDisplayObject=function(){this._cacheData.sprite._texture.destroy(!0),this._cacheData.sprite=null,l.default.removeFromCache(this._cacheData.textureCacheId),u.default.removeFromCache(this._cacheData.textureCacheId),this._cacheData.textureCacheId=null},d.prototype._cacheAsBitmapDestroy=function(t){this.cacheAsBitmap=!1,this.destroy(t)}},{\"../core\":65,\"../core/textures/BaseTexture\":112,\"../core/textures/Texture\":115,\"../core/utils\":124}],139:[function(t,e,r){\"use strict\";var n=t(\"../core\"),i=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(n);i.DisplayObject.prototype.name=null,i.Container.prototype.getChildByName=function(t){for(var e=0;e<this.children.length;e++)if(this.children[e].name===t)return this.children[e];return null}},{\"../core\":65}],140:[function(t,e,r){\"use strict\";var n=t(\"../core\"),i=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(n);i.DisplayObject.prototype.getGlobalPosition=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:new i.Point,e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return this.parent?this.parent.toGlobal(this.position,t,e):(t.x=this.position.x,t.y=this.position.y),t}},{\"../core\":65}],141:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0,r.BitmapText=r.TilingSpriteRenderer=r.TilingSprite=r.TextureTransform=r.AnimatedSprite=void 0;var i=t(\"./AnimatedSprite\");Object.defineProperty(r,\"AnimatedSprite\",{enumerable:!0,get:function(){return n(i).default}});var o=t(\"./TextureTransform\");Object.defineProperty(r,\"TextureTransform\",{enumerable:!0,get:function(){return n(o).default}});var s=t(\"./TilingSprite\");Object.defineProperty(r,\"TilingSprite\",{enumerable:!0,get:function(){return n(s).default}});var a=t(\"./webgl/TilingSpriteRenderer\");Object.defineProperty(r,\"TilingSpriteRenderer\",{enumerable:!0,get:function(){return n(a).default}});var u=t(\"./BitmapText\");Object.defineProperty(r,\"BitmapText\",{enumerable:!0,get:function(){return n(u).default}}),t(\"./cacheAsBitmap\"),t(\"./getChildByName\"),t(\"./getGlobalPosition\")},{\"./AnimatedSprite\":134,\"./BitmapText\":135,\"./TextureTransform\":136,\"./TilingSprite\":137,\"./cacheAsBitmap\":138,\"./getChildByName\":139,\"./getGlobalPosition\":140,\"./webgl/TilingSpriteRenderer\":142}],142:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=t(\"../../core\"),a=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(s),u=t(\"../../core/const\"),h=(t(\"path\"),new a.Matrix),l=function(t){function e(r){n(this,e);var o=i(this,t.call(this,r));return o.shader=null,o.simpleShader=null,o.quad=null,o}return o(e,t),e.prototype.onContextChange=function(){var t=this.renderer.gl;this.shader=new a.Shader(t,\"attribute vec2 aVertexPosition;\\nattribute vec2 aTextureCoord;\\n\\nuniform mat3 projectionMatrix;\\nuniform mat3 translationMatrix;\\nuniform mat3 uTransform;\\n\\nvarying vec2 vTextureCoord;\\n\\nvoid main(void)\\n{\\n    gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\\n\\n    vTextureCoord = (uTransform * vec3(aTextureCoord, 1.0)).xy;\\n}\\n\",\"varying vec2 vTextureCoord;\\n\\nuniform sampler2D uSampler;\\nuniform vec4 uColor;\\nuniform mat3 uMapCoord;\\nuniform vec4 uClampFrame;\\nuniform vec2 uClampOffset;\\n\\nvoid main(void)\\n{\\n    vec2 coord = mod(vTextureCoord - uClampOffset, vec2(1.0, 1.0)) + uClampOffset;\\n    coord = (uMapCoord * vec3(coord, 1.0)).xy;\\n    coord = clamp(coord, uClampFrame.xy, uClampFrame.zw);\\n\\n    vec4 sample = texture2D(uSampler, coord);\\n    gl_FragColor = sample * uColor;\\n}\\n\"),this.simpleShader=new a.Shader(t,\"attribute vec2 aVertexPosition;\\nattribute vec2 aTextureCoord;\\n\\nuniform mat3 projectionMatrix;\\nuniform mat3 translationMatrix;\\nuniform mat3 uTransform;\\n\\nvarying vec2 vTextureCoord;\\n\\nvoid main(void)\\n{\\n    gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\\n\\n    vTextureCoord = (uTransform * vec3(aTextureCoord, 1.0)).xy;\\n}\\n\",\"varying vec2 vTextureCoord;\\n\\nuniform sampler2D uSampler;\\nuniform vec4 uColor;\\n\\nvoid main(void)\\n{\\n    vec4 sample = texture2D(uSampler, vTextureCoord);\\n    gl_FragColor = sample * uColor;\\n}\\n\"),this.renderer.bindVao(null),this.quad=new a.Quad(t,this.renderer.state.attribState),this.quad.initVao(this.shader)},e.prototype.render=function(t){var e=this.renderer,r=this.quad;e.bindVao(r.vao);var n=r.vertices;n[0]=n[6]=t._width*-t.anchor.x,n[1]=n[3]=t._height*-t.anchor.y,n[2]=n[4]=t._width*(1-t.anchor.x),n[5]=n[7]=t._height*(1-t.anchor.y),t.uvRespectAnchor&&(n=r.uvs,n[0]=n[6]=-t.anchor.x,n[1]=n[3]=-t.anchor.y,n[2]=n[4]=1-t.anchor.x,n[5]=n[7]=1-t.anchor.y),r.upload();var i=t._texture,o=i.baseTexture,s=t.tileTransform.localTransform,l=t.uvTransform,c=o.isPowerOfTwo&&i.frame.width===o.width&&i.frame.height===o.height;c&&(o._glTextures[e.CONTEXT_UID]?c=o.wrapMode!==u.WRAP_MODES.CLAMP:o.wrapMode===u.WRAP_MODES.CLAMP&&(o.wrapMode=u.WRAP_MODES.REPEAT));var d=c?this.simpleShader:this.shader;e.bindShader(d);var f=i.width,p=i.height,v=t._width,y=t._height;h.set(s.a*f/v,s.b*f/y,s.c*p/v,s.d*p/y,s.tx/v,s.ty/y),h.invert(),c?h.prepend(l.mapCoord):(d.uniforms.uMapCoord=l.mapCoord.toArray(!0),d.uniforms.uClampFrame=l.uClampFrame,d.uniforms.uClampOffset=l.uClampOffset),d.uniforms.uTransform=h.toArray(!0),d.uniforms.uColor=a.utils.premultiplyTintToRgba(t.tint,t.worldAlpha,d.uniforms.uColor,o.premultipliedAlpha),d.uniforms.translationMatrix=t.transform.worldTransform.toArray(!0),d.uniforms.uSampler=e.bindTexture(i),\ne.setBlendMode(a.utils.correctBlendMode(t.blendMode,o.premultipliedAlpha)),r.vao.draw(this.renderer.gl.TRIANGLES,6,0)},e}(a.ObjectRenderer);r.default=l,a.WebGLRenderer.registerPlugin(\"tilingSprite\",l)},{\"../../core\":65,\"../../core/const\":46,path:8}],143:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),u=t(\"../../core\"),h=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(u),l=t(\"./BlurXFilter\"),c=n(l),d=t(\"./BlurYFilter\"),f=n(d),p=function(t){function e(r,n,s,a){i(this,e);var u=o(this,t.call(this));return u.blurXFilter=new c.default(r,n,s,a),u.blurYFilter=new f.default(r,n,s,a),u.padding=0,u.resolution=s||h.settings.RESOLUTION,u.quality=n||4,u.blur=r||8,u}return s(e,t),e.prototype.apply=function(t,e,r){var n=t.getRenderTarget(!0);this.blurXFilter.apply(t,e,n,!0),this.blurYFilter.apply(t,n,r,!1),t.returnRenderTarget(n)},a(e,[{key:\"blur\",get:function(){return this.blurXFilter.blur},set:function(t){this.blurXFilter.blur=this.blurYFilter.blur=t,this.padding=2*Math.max(Math.abs(this.blurXFilter.strength),Math.abs(this.blurYFilter.strength))}},{key:\"quality\",get:function(){return this.blurXFilter.quality},set:function(t){this.blurXFilter.quality=this.blurYFilter.quality=t}},{key:\"blurX\",get:function(){return this.blurXFilter.blur},set:function(t){this.blurXFilter.blur=t,this.padding=2*Math.max(Math.abs(this.blurXFilter.strength),Math.abs(this.blurYFilter.strength))}},{key:\"blurY\",get:function(){return this.blurYFilter.blur},set:function(t){this.blurYFilter.blur=t,this.padding=2*Math.max(Math.abs(this.blurXFilter.strength),Math.abs(this.blurYFilter.strength))}},{key:\"blendMode\",get:function(){return this.blurYFilter._blendMode},set:function(t){this.blurYFilter._blendMode=t}}]),e}(h.Filter);r.default=p},{\"../../core\":65,\"./BlurXFilter\":144,\"./BlurYFilter\":145}],144:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),u=t(\"../../core\"),h=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(u),l=t(\"./generateBlurVertSource\"),c=n(l),d=t(\"./generateBlurFragSource\"),f=n(d),p=t(\"./getMaxBlurKernelSize\"),v=n(p),y=function(t){function e(r,n,s,a){i(this,e),a=a||5;var u=(0,c.default)(a,!0),l=(0,f.default)(a),d=o(this,t.call(this,u,l));return d.resolution=s||h.settings.RESOLUTION,d._quality=0,d.quality=n||4,d.strength=r||8,d.firstRun=!0,d}return s(e,t),e.prototype.apply=function(t,e,r,n){if(this.firstRun){var i=t.renderer.gl,o=(0,v.default)(i);this.vertexSrc=(0,c.default)(o,!0),this.fragmentSrc=(0,f.default)(o),this.firstRun=!1}if(this.uniforms.strength=1/r.size.width*(r.size.width/e.size.width),this.uniforms.strength*=this.strength,this.uniforms.strength/=this.passes,1===this.passes)t.applyFilter(this,e,r,n);else{for(var s=t.getRenderTarget(!0),a=e,u=s,h=0;h<this.passes-1;h++){t.applyFilter(this,a,u,!0);var l=u;u=a,a=l}t.applyFilter(this,a,r,n),t.returnRenderTarget(s)}},a(e,[{key:\"blur\",get:function(){return this.strength},set:function(t){this.padding=2*Math.abs(t),this.strength=t}},{key:\"quality\",get:function(){return this._quality},set:function(t){this._quality=t,this.passes=t}}]),e}(h.Filter);r.default=y},{\"../../core\":65,\"./generateBlurFragSource\":146,\"./generateBlurVertSource\":147,\"./getMaxBlurKernelSize\":148}],145:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),u=t(\"../../core\"),h=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(u),l=t(\"./generateBlurVertSource\"),c=n(l),d=t(\"./generateBlurFragSource\"),f=n(d),p=t(\"./getMaxBlurKernelSize\"),v=n(p),y=function(t){function e(r,n,s,a){i(this,e),a=a||5;var u=(0,c.default)(a,!1),l=(0,f.default)(a),d=o(this,t.call(this,u,l));return d.resolution=s||h.settings.RESOLUTION,d._quality=0,d.quality=n||4,d.strength=r||8,d.firstRun=!0,d}return s(e,t),e.prototype.apply=function(t,e,r,n){if(this.firstRun){var i=t.renderer.gl,o=(0,v.default)(i);this.vertexSrc=(0,c.default)(o,!1),this.fragmentSrc=(0,f.default)(o),this.firstRun=!1}if(this.uniforms.strength=1/r.size.height*(r.size.height/e.size.height),this.uniforms.strength*=this.strength,this.uniforms.strength/=this.passes,1===this.passes)t.applyFilter(this,e,r,n);else{for(var s=t.getRenderTarget(!0),a=e,u=s,h=0;h<this.passes-1;h++){t.applyFilter(this,a,u,!0);var l=u;u=a,a=l}t.applyFilter(this,a,r,n),t.returnRenderTarget(s)}},a(e,[{key:\"blur\",get:function(){return this.strength},set:function(t){this.padding=2*Math.abs(t),this.strength=t}},{key:\"quality\",get:function(){return this._quality},set:function(t){this._quality=t,this.passes=t}}]),e}(h.Filter);r.default=y},{\"../../core\":65,\"./generateBlurFragSource\":146,\"./generateBlurVertSource\":147,\"./getMaxBlurKernelSize\":148}],146:[function(t,e,r){\"use strict\";function n(t){for(var e=i[t],r=e.length,n=o,s=\"\",a=\"gl_FragColor += texture2D(uSampler, vBlurTexCoords[%index%]) * %value%;\",u=void 0,h=0;h<t;h++){var l=a.replace(\"%index%\",h);u=h,h>=r&&(u=t-h-1),l=l.replace(\"%value%\",e[u]),s+=l,s+=\"\\n\"}return n=n.replace(\"%blur%\",s),n=n.replace(\"%size%\",t)}r.__esModule=!0,r.default=n;var i={5:[.153388,.221461,.250301],7:[.071303,.131514,.189879,.214607],9:[.028532,.067234,.124009,.179044,.20236],11:[.0093,.028002,.065984,.121703,.175713,.198596],13:[.002406,.009255,.027867,.065666,.121117,.174868,.197641],15:[489e-6,.002403,.009246,.02784,.065602,.120999,.174697,.197448]},o=[\"varying vec2 vBlurTexCoords[%size%];\",\"uniform sampler2D uSampler;\",\"void main(void)\",\"{\",\"    gl_FragColor = vec4(0.0);\",\"    %blur%\",\"}\"].join(\"\\n\")},{}],147:[function(t,e,r){\"use strict\";function n(t,e){var r=Math.ceil(t/2),n=i,o=\"\",s=void 0;s=e?\"vBlurTexCoords[%index%] = aTextureCoord + vec2(%sampleIndex% * strength, 0.0);\":\"vBlurTexCoords[%index%] = aTextureCoord + vec2(0.0, %sampleIndex% * strength);\";for(var a=0;a<t;a++){var u=s.replace(\"%index%\",a);u=u.replace(\"%sampleIndex%\",a-(r-1)+\".0\"),o+=u,o+=\"\\n\"}return n=n.replace(\"%blur%\",o),n=n.replace(\"%size%\",t)}r.__esModule=!0,r.default=n;var i=[\"attribute vec2 aVertexPosition;\",\"attribute vec2 aTextureCoord;\",\"uniform float strength;\",\"uniform mat3 projectionMatrix;\",\"varying vec2 vBlurTexCoords[%size%];\",\"void main(void)\",\"{\",\"gl_Position = vec4((projectionMatrix * vec3((aVertexPosition), 1.0)).xy, 0.0, 1.0);\",\"%blur%\",\"}\"].join(\"\\n\")},{}],148:[function(t,e,r){\"use strict\";function n(t){for(var e=t.getParameter(t.MAX_VARYING_VECTORS),r=15;r>e;)r-=2;return r}r.__esModule=!0,r.default=n},{}],149:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"../../core\"),u=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(a),h=(t(\"path\"),function(t){function e(){n(this,e);var r=i(this,t.call(this,\"attribute vec2 aVertexPosition;\\nattribute vec2 aTextureCoord;\\n\\nuniform mat3 projectionMatrix;\\n\\nvarying vec2 vTextureCoord;\\n\\nvoid main(void)\\n{\\n    gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\\n    vTextureCoord = aTextureCoord;\\n}\",\"varying vec2 vTextureCoord;\\nuniform sampler2D uSampler;\\nuniform float m[20];\\nuniform float uAlpha;\\n\\nvoid main(void)\\n{\\n    vec4 c = texture2D(uSampler, vTextureCoord);\\n\\n    if (uAlpha == 0.0) {\\n        gl_FragColor = c;\\n        return;\\n    }\\n\\n    // Un-premultiply alpha before applying the color matrix. See issue #3539.\\n    if (c.a > 0.0) {\\n      c.rgb /= c.a;\\n    }\\n\\n    vec4 result;\\n\\n    result.r = (m[0] * c.r);\\n        result.r += (m[1] * c.g);\\n        result.r += (m[2] * c.b);\\n        result.r += (m[3] * c.a);\\n        result.r += m[4];\\n\\n    result.g = (m[5] * c.r);\\n        result.g += (m[6] * c.g);\\n        result.g += (m[7] * c.b);\\n        result.g += (m[8] * c.a);\\n        result.g += m[9];\\n\\n    result.b = (m[10] * c.r);\\n       result.b += (m[11] * c.g);\\n       result.b += (m[12] * c.b);\\n       result.b += (m[13] * c.a);\\n       result.b += m[14];\\n\\n    result.a = (m[15] * c.r);\\n       result.a += (m[16] * c.g);\\n       result.a += (m[17] * c.b);\\n       result.a += (m[18] * c.a);\\n       result.a += m[19];\\n\\n    vec3 rgb = mix(c.rgb, result.rgb, uAlpha);\\n\\n    // Premultiply alpha again.\\n    rgb *= result.a;\\n\\n    gl_FragColor = vec4(rgb, result.a);\\n}\\n\"));return r.uniforms.m=[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0],r.alpha=1,r}return o(e,t),e.prototype._loadMatrix=function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=t;e&&(this._multiply(r,this.uniforms.m,t),r=this._colorMatrix(r)),this.uniforms.m=r},e.prototype._multiply=function(t,e,r){return t[0]=e[0]*r[0]+e[1]*r[5]+e[2]*r[10]+e[3]*r[15],t[1]=e[0]*r[1]+e[1]*r[6]+e[2]*r[11]+e[3]*r[16],t[2]=e[0]*r[2]+e[1]*r[7]+e[2]*r[12]+e[3]*r[17],t[3]=e[0]*r[3]+e[1]*r[8]+e[2]*r[13]+e[3]*r[18],t[4]=e[0]*r[4]+e[1]*r[9]+e[2]*r[14]+e[3]*r[19]+e[4],t[5]=e[5]*r[0]+e[6]*r[5]+e[7]*r[10]+e[8]*r[15],t[6]=e[5]*r[1]+e[6]*r[6]+e[7]*r[11]+e[8]*r[16],t[7]=e[5]*r[2]+e[6]*r[7]+e[7]*r[12]+e[8]*r[17],t[8]=e[5]*r[3]+e[6]*r[8]+e[7]*r[13]+e[8]*r[18],t[9]=e[5]*r[4]+e[6]*r[9]+e[7]*r[14]+e[8]*r[19]+e[9],t[10]=e[10]*r[0]+e[11]*r[5]+e[12]*r[10]+e[13]*r[15],t[11]=e[10]*r[1]+e[11]*r[6]+e[12]*r[11]+e[13]*r[16],t[12]=e[10]*r[2]+e[11]*r[7]+e[12]*r[12]+e[13]*r[17],t[13]=e[10]*r[3]+e[11]*r[8]+e[12]*r[13]+e[13]*r[18],t[14]=e[10]*r[4]+e[11]*r[9]+e[12]*r[14]+e[13]*r[19]+e[14],t[15]=e[15]*r[0]+e[16]*r[5]+e[17]*r[10]+e[18]*r[15],t[16]=e[15]*r[1]+e[16]*r[6]+e[17]*r[11]+e[18]*r[16],t[17]=e[15]*r[2]+e[16]*r[7]+e[17]*r[12]+e[18]*r[17],t[18]=e[15]*r[3]+e[16]*r[8]+e[17]*r[13]+e[18]*r[18],t[19]=e[15]*r[4]+e[16]*r[9]+e[17]*r[14]+e[18]*r[19]+e[19],t},e.prototype._colorMatrix=function(t){var e=new Float32Array(t);return e[4]/=255,e[9]/=255,e[14]/=255,e[19]/=255,e},e.prototype.brightness=function(t,e){var r=[t,0,0,0,0,0,t,0,0,0,0,0,t,0,0,0,0,0,1,0];this._loadMatrix(r,e)},e.prototype.greyscale=function(t,e){var r=[t,t,t,0,0,t,t,t,0,0,t,t,t,0,0,0,0,0,1,0];this._loadMatrix(r,e)},e.prototype.blackAndWhite=function(t){var e=[.3,.6,.1,0,0,.3,.6,.1,0,0,.3,.6,.1,0,0,0,0,0,1,0];this._loadMatrix(e,t)},e.prototype.hue=function(t,e){t=(t||0)/180*Math.PI;var r=Math.cos(t),n=Math.sin(t),i=Math.sqrt,o=1/3,s=i(o),a=r+(1-r)*o,u=o*(1-r)-s*n,h=o*(1-r)+s*n,l=o*(1-r)+s*n,c=r+o*(1-r),d=o*(1-r)-s*n,f=o*(1-r)-s*n,p=o*(1-r)+s*n,v=r+o*(1-r),y=[a,u,h,0,0,l,c,d,0,0,f,p,v,0,0,0,0,0,1,0];this._loadMatrix(y,e)},e.prototype.contrast=function(t,e){var r=(t||0)+1,n=-.5*(r-1),i=[r,0,0,0,n,0,r,0,0,n,0,0,r,0,n,0,0,0,1,0];this._loadMatrix(i,e)},e.prototype.saturate=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments[1],r=2*t/3+1,n=-.5*(r-1),i=[r,n,n,0,0,n,r,n,0,0,n,n,r,0,0,0,0,0,1,0];this._loadMatrix(i,e)},e.prototype.desaturate=function(){this.saturate(-1)},e.prototype.negative=function(t){var e=[0,1,1,0,0,1,0,1,0,0,1,1,0,0,0,0,0,0,1,0];this._loadMatrix(e,t)},e.prototype.sepia=function(t){var e=[.393,.7689999,.18899999,0,0,.349,.6859999,.16799999,0,0,.272,.5339999,.13099999,0,0,0,0,0,1,0];this._loadMatrix(e,t)},e.prototype.technicolor=function(t){var e=[1.9125277891456083,-.8545344976951645,-.09155508482755585,0,11.793603434377337,-.3087833385928097,1.7658908555458428,-.10601743074722245,0,-70.35205161461398,-.231103377548616,-.7501899197440212,1.847597816108189,0,30.950940869491138,0,0,0,1,0];this._loadMatrix(e,t)},e.prototype.polaroid=function(t){var e=[1.438,-.062,-.062,0,0,-.122,1.378,-.122,0,0,-.016,-.016,1.483,0,0,0,0,0,1,0];this._loadMatrix(e,t)},e.prototype.toBGR=function(t){var e=[0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0];this._loadMatrix(e,t)},e.prototype.kodachrome=function(t){var e=[1.1285582396593525,-.3967382283601348,-.03992559172921793,0,63.72958762196502,-.16404339962244616,1.0835251566291304,-.05498805115633132,0,24.732407896706203,-.16786010706155763,-.5603416277695248,1.6014850761964943,0,35.62982807460946,0,0,0,1,0];this._loadMatrix(e,t)},e.prototype.browni=function(t){var e=[.5997023498159715,.34553243048391263,-.2708298674538042,0,47.43192855600873,-.037703249837783157,.8609577587992641,.15059552388459913,0,-36.96841498319127,.24113635128153335,-.07441037908422492,.44972182064877153,0,-7.562075277591283,0,0,0,1,0];this._loadMatrix(e,t)},e.prototype.vintage=function(t){var e=[.6279345635605994,.3202183420819367,-.03965408211312453,0,9.651285835294123,.02578397704808868,.6441188644374771,.03259127616149294,0,7.462829176470591,.0466055556782719,-.0851232987247891,.5241648018700465,0,5.159190588235296,0,0,0,1,0];this._loadMatrix(e,t)},e.prototype.colorTone=function(t,e,r,n,i){t=t||.2,e=e||.15,r=r||16770432,n=n||3375104;var o=(r>>16&255)/255,s=(r>>8&255)/255,a=(255&r)/255,u=(n>>16&255)/255,h=(n>>8&255)/255,l=(255&n)/255,c=[.3,.59,.11,0,0,o,s,a,t,0,u,h,l,e,0,o-u,s-h,a-l,0,0];this._loadMatrix(c,i)},e.prototype.night=function(t,e){t=t||.1;var r=[-2*t,-t,0,0,0,-t,0,t,0,0,0,t,2*t,0,0,0,0,0,1,0];this._loadMatrix(r,e)},e.prototype.predator=function(t,e){var r=[11.224130630493164*t,-4.794486999511719*t,-2.8746118545532227*t,0*t,.40342438220977783*t,-3.6330697536468506*t,9.193157196044922*t,-2.951810836791992*t,0*t,-1.316135048866272*t,-3.2184197902679443*t,-4.2375030517578125*t,7.476448059082031*t,0*t,.8044459223747253*t,0,0,0,1,0];this._loadMatrix(r,e)},e.prototype.lsd=function(t){var e=[2,-.4,.5,0,0,-.5,2,-.4,0,0,-.4,-.5,3,0,0,0,0,0,1,0];this._loadMatrix(e,t)},e.prototype.reset=function(){var t=[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0];this._loadMatrix(t,!1)},s(e,[{key:\"matrix\",get:function(){return this.uniforms.m},set:function(t){this.uniforms.m=t}},{key:\"alpha\",get:function(){return this.uniforms.uAlpha},set:function(t){this.uniforms.uAlpha=t}}]),e}(u.Filter));r.default=h,h.prototype.grayscale=h.prototype.greyscale},{\"../../core\":65,path:8}],150:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"../../core\"),u=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(a),h=(t(\"path\"),function(t){function e(r,o){n(this,e);var s=new u.Matrix;r.renderable=!1;var a=i(this,t.call(this,\"attribute vec2 aVertexPosition;\\nattribute vec2 aTextureCoord;\\n\\nuniform mat3 projectionMatrix;\\nuniform mat3 filterMatrix;\\n\\nvarying vec2 vTextureCoord;\\nvarying vec2 vFilterCoord;\\n\\nvoid main(void)\\n{\\n   gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\\n   vFilterCoord = ( filterMatrix * vec3( aTextureCoord, 1.0)  ).xy;\\n   vTextureCoord = aTextureCoord;\\n}\",\"varying vec2 vFilterCoord;\\nvarying vec2 vTextureCoord;\\n\\nuniform vec2 scale;\\n\\nuniform sampler2D uSampler;\\nuniform sampler2D mapSampler;\\n\\nuniform vec4 filterClamp;\\n\\nvoid main(void)\\n{\\n   vec4 map =  texture2D(mapSampler, vFilterCoord);\\n\\n   map -= 0.5;\\n   map.xy *= scale;\\n\\n   gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw));\\n}\\n\"));return a.maskSprite=r,a.maskMatrix=s,a.uniforms.mapSampler=r._texture,a.uniforms.filterMatrix=s,a.uniforms.scale={x:1,y:1},null!==o&&void 0!==o||(o=20),a.scale=new u.Point(o,o),a}return o(e,t),e.prototype.apply=function(t,e,r){var n=1/r.destinationFrame.width*(r.size.width/e.size.width);this.uniforms.filterMatrix=t.calculateSpriteMatrix(this.maskMatrix,this.maskSprite),this.uniforms.scale.x=this.scale.x*n,this.uniforms.scale.y=this.scale.y*n,t.applyFilter(this,e,r)},s(e,[{key:\"map\",get:function(){return this.uniforms.mapSampler},set:function(t){this.uniforms.mapSampler=t}}]),e}(u.Filter));r.default=h},{\"../../core\":65,path:8}],151:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=t(\"../../core\"),a=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(s),u=(t(\"path\"),function(t){function e(){return n(this,e),i(this,t.call(this,\"\\nattribute vec2 aVertexPosition;\\nattribute vec2 aTextureCoord;\\n\\nuniform mat3 projectionMatrix;\\n\\nvarying vec2 v_rgbNW;\\nvarying vec2 v_rgbNE;\\nvarying vec2 v_rgbSW;\\nvarying vec2 v_rgbSE;\\nvarying vec2 v_rgbM;\\n\\nuniform vec4 filterArea;\\n\\nvarying vec2 vTextureCoord;\\n\\nvec2 mapCoord( vec2 coord )\\n{\\n    coord *= filterArea.xy;\\n    coord += filterArea.zw;\\n\\n    return coord;\\n}\\n\\nvec2 unmapCoord( vec2 coord )\\n{\\n    coord -= filterArea.zw;\\n    coord /= filterArea.xy;\\n\\n    return coord;\\n}\\n\\nvoid texcoords(vec2 fragCoord, vec2 resolution,\\n               out vec2 v_rgbNW, out vec2 v_rgbNE,\\n               out vec2 v_rgbSW, out vec2 v_rgbSE,\\n               out vec2 v_rgbM) {\\n    vec2 inverseVP = 1.0 / resolution.xy;\\n    v_rgbNW = (fragCoord + vec2(-1.0, -1.0)) * inverseVP;\\n    v_rgbNE = (fragCoord + vec2(1.0, -1.0)) * inverseVP;\\n    v_rgbSW = (fragCoord + vec2(-1.0, 1.0)) * inverseVP;\\n    v_rgbSE = (fragCoord + vec2(1.0, 1.0)) * inverseVP;\\n    v_rgbM = vec2(fragCoord * inverseVP);\\n}\\n\\nvoid main(void) {\\n\\n   gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\\n\\n   vTextureCoord = aTextureCoord;\\n\\n   vec2 fragCoord = vTextureCoord * filterArea.xy;\\n\\n   texcoords(fragCoord, filterArea.xy, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM);\\n}\",'varying vec2 v_rgbNW;\\nvarying vec2 v_rgbNE;\\nvarying vec2 v_rgbSW;\\nvarying vec2 v_rgbSE;\\nvarying vec2 v_rgbM;\\n\\nvarying vec2 vTextureCoord;\\nuniform sampler2D uSampler;\\nuniform vec4 filterArea;\\n\\n/**\\n Basic FXAA implementation based on the code on geeks3d.com with the\\n modification that the texture2DLod stuff was removed since it\\'s\\n unsupported by WebGL.\\n \\n --\\n \\n From:\\n https://github.com/mitsuhiko/webgl-meincraft\\n \\n Copyright (c) 2011 by Armin Ronacher.\\n \\n Some rights reserved.\\n \\n Redistribution and use in source and binary forms, with or without\\n modification, are permitted provided that the following conditions are\\n met:\\n \\n * Redistributions of source code must retain the above copyright\\n notice, this list of conditions and the following disclaimer.\\n \\n * Redistributions in binary form must reproduce the above\\n copyright notice, this list of conditions and the following\\n disclaimer in the documentation and/or other materials provided\\n with the distribution.\\n \\n * The names of the contributors may not be used to endorse or\\n promote products derived from this software without specific\\n prior written permission.\\n \\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\\n \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\\n LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\\n A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\\n OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\\n SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\\n DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\\n */\\n\\n#ifndef FXAA_REDUCE_MIN\\n#define FXAA_REDUCE_MIN   (1.0/ 128.0)\\n#endif\\n#ifndef FXAA_REDUCE_MUL\\n#define FXAA_REDUCE_MUL   (1.0 / 8.0)\\n#endif\\n#ifndef FXAA_SPAN_MAX\\n#define FXAA_SPAN_MAX     8.0\\n#endif\\n\\n//optimized version for mobile, where dependent\\n//texture reads can be a bottleneck\\nvec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 resolution,\\n          vec2 v_rgbNW, vec2 v_rgbNE,\\n          vec2 v_rgbSW, vec2 v_rgbSE,\\n          vec2 v_rgbM) {\\n    vec4 color;\\n    mediump vec2 inverseVP = vec2(1.0 / resolution.x, 1.0 / resolution.y);\\n    vec3 rgbNW = texture2D(tex, v_rgbNW).xyz;\\n    vec3 rgbNE = texture2D(tex, v_rgbNE).xyz;\\n    vec3 rgbSW = texture2D(tex, v_rgbSW).xyz;\\n    vec3 rgbSE = texture2D(tex, v_rgbSE).xyz;\\n    vec4 texColor = texture2D(tex, v_rgbM);\\n    vec3 rgbM  = texColor.xyz;\\n    vec3 luma = vec3(0.299, 0.587, 0.114);\\n    float lumaNW = dot(rgbNW, luma);\\n    float lumaNE = dot(rgbNE, luma);\\n    float lumaSW = dot(rgbSW, luma);\\n    float lumaSE = dot(rgbSE, luma);\\n    float lumaM  = dot(rgbM,  luma);\\n    float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));\\n    float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));\\n    \\n    mediump vec2 dir;\\n    dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\\n    dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));\\n    \\n    float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *\\n                          (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);\\n    \\n    float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);\\n    dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),\\n              max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),\\n                  dir * rcpDirMin)) * inverseVP;\\n    \\n    vec3 rgbA = 0.5 * (\\n                       texture2D(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz +\\n                       texture2D(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz);\\n    vec3 rgbB = rgbA * 0.5 + 0.25 * (\\n                                     texture2D(tex, fragCoord * inverseVP + dir * -0.5).xyz +\\n                                     texture2D(tex, fragCoord * inverseVP + dir * 0.5).xyz);\\n    \\n    float lumaB = dot(rgbB, luma);\\n    if ((lumaB < lumaMin) || (lumaB > lumaMax))\\n        color = vec4(rgbA, texColor.a);\\n    else\\n        color = vec4(rgbB, texColor.a);\\n    return color;\\n}\\n\\nvoid main() {\\n\\n      vec2 fragCoord = vTextureCoord * filterArea.xy;\\n\\n      vec4 color;\\n\\n    color = fxaa(uSampler, fragCoord, filterArea.xy, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM);\\n\\n      gl_FragColor = color;\\n}\\n'))}return o(e,t),e}(a.Filter));r.default=u},{\"../../core\":65,path:8}],152:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0;var i=t(\"./fxaa/FXAAFilter\");Object.defineProperty(r,\"FXAAFilter\",{enumerable:!0,get:function(){return n(i).default}});var o=t(\"./noise/NoiseFilter\");Object.defineProperty(r,\"NoiseFilter\",{enumerable:!0,get:function(){return n(o).default}});var s=t(\"./displacement/DisplacementFilter\");Object.defineProperty(r,\"DisplacementFilter\",{enumerable:!0,get:function(){return n(s).default}});var a=t(\"./blur/BlurFilter\");Object.defineProperty(r,\"BlurFilter\",{enumerable:!0,get:function(){return n(a).default}});var u=t(\"./blur/BlurXFilter\");Object.defineProperty(r,\"BlurXFilter\",{enumerable:!0,get:function(){return n(u).default}});var h=t(\"./blur/BlurYFilter\");Object.defineProperty(r,\"BlurYFilter\",{enumerable:!0,get:function(){return n(h).default}});var l=t(\"./colormatrix/ColorMatrixFilter\");Object.defineProperty(r,\"ColorMatrixFilter\",{enumerable:!0,get:function(){return n(l).default}});var c=t(\"./void/VoidFilter\");Object.defineProperty(r,\"VoidFilter\",{enumerable:!0,get:function(){return n(c).default}})},{\"./blur/BlurFilter\":143,\"./blur/BlurXFilter\":144,\"./blur/BlurYFilter\":145,\"./colormatrix/ColorMatrixFilter\":149,\"./displacement/DisplacementFilter\":150,\"./fxaa/FXAAFilter\":151,\"./noise/NoiseFilter\":153,\"./void/VoidFilter\":154}],153:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"../../core\"),u=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(a),h=(t(\"path\"),function(t){function e(){var r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:.5,o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:Math.random();n(this,e);var s=i(this,t.call(this,\"attribute vec2 aVertexPosition;\\nattribute vec2 aTextureCoord;\\n\\nuniform mat3 projectionMatrix;\\n\\nvarying vec2 vTextureCoord;\\n\\nvoid main(void)\\n{\\n    gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\\n    vTextureCoord = aTextureCoord;\\n}\",\"precision highp float;\\n\\nvarying vec2 vTextureCoord;\\nvarying vec4 vColor;\\n\\nuniform float uNoise;\\nuniform float uSeed;\\nuniform sampler2D uSampler;\\n\\nfloat rand(vec2 co)\\n{\\n    return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);\\n}\\n\\nvoid main()\\n{\\n    vec4 color = texture2D(uSampler, vTextureCoord);\\n    float randomValue = rand(gl_FragCoord.xy * uSeed);\\n    float diff = (randomValue - 0.5) * uNoise;\\n\\n    // Un-premultiply alpha before applying the color matrix. See issue #3539.\\n    if (color.a > 0.0) {\\n        color.rgb /= color.a;\\n    }\\n\\n    color.r += diff;\\n    color.g += diff;\\n    color.b += diff;\\n\\n    // Premultiply alpha again.\\n    color.rgb *= color.a;\\n\\n    gl_FragColor = color;\\n}\\n\"));return s.noise=r,s.seed=o,s}return o(e,t),s(e,[{key:\"noise\",get:function(){return this.uniforms.uNoise},set:function(t){this.uniforms.uNoise=t}},{key:\"seed\",get:function(){return this.uniforms.uSeed},set:function(t){this.uniforms.uSeed=t}}]),e}(u.Filter));r.default=h},{\"../../core\":65,path:8}],154:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=t(\"../../core\"),a=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(s),u=(t(\"path\"),function(t){function e(){n(this,e);var r=i(this,t.call(this,\"attribute vec2 aVertexPosition;\\nattribute vec2 aTextureCoord;\\n\\nuniform mat3 projectionMatrix;\\n\\nvarying vec2 vTextureCoord;\\n\\nvoid main(void)\\n{\\n    gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\\n    vTextureCoord = aTextureCoord;\\n}\",\"varying vec2 vTextureCoord;\\n\\nuniform sampler2D uSampler;\\n\\nvoid main(void)\\n{\\n   gl_FragColor = texture2D(uSampler, vTextureCoord);\\n}\\n\"));return r.glShaderKey=\"void\",r}return o(e,t),e}(a.Filter));r.default=u},{\"../../core\":65,path:8}],155:[function(t,e,r){\"use strict\";function n(t,e){\nif(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),o=t(\"../core\"),s=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(o),a=function(){function t(){n(this,t),this.global=new s.Point,this.target=null,this.originalEvent=null,this.identifier=null,this.isPrimary=!1,this.button=0,this.buttons=0,this.width=0,this.height=0,this.tiltX=0,this.tiltY=0,this.pointerType=null,this.pressure=0,this.rotationAngle=0,this.twist=0,this.tangentialPressure=0}return t.prototype.getLocalPosition=function(t,e,r){return t.worldTransform.applyInverse(r||this.global,e)},t.prototype._copyEvent=function(t){t.isPrimary&&(this.isPrimary=!0),this.button=t.button,this.buttons=t.buttons,this.width=t.width,this.height=t.height,this.tiltX=t.tiltX,this.tiltY=t.tiltY,this.pointerType=t.pointerType,this.pressure=t.pressure,this.rotationAngle=t.rotationAngle,this.twist=t.twist||0,this.tangentialPressure=t.tangentialPressure||0},t.prototype._reset=function(){this.isPrimary=!1},i(t,[{key:\"pointerId\",get:function(){return this.identifier}}]),t}();r.default=a},{\"../core\":65}],156:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(){n(this,t),this.stopped=!1,this.target=null,this.currentTarget=null,this.type=null,this.data=null}return t.prototype.stopPropagation=function(){this.stopped=!0},t.prototype._reset=function(){this.stopped=!1,this.currentTarget=null,this.target=null},t}();r.default=i},{}],157:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&\"function\"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?\"symbol\":typeof t},u=t(\"../core\"),h=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(u),l=t(\"./InteractionData\"),c=n(l),d=t(\"./InteractionEvent\"),f=n(d),p=t(\"./InteractionTrackingData\"),v=n(p),y=t(\"eventemitter3\"),g=n(y),m=t(\"./interactiveTarget\"),_=n(m);h.utils.mixins.delayMixin(h.DisplayObject.prototype,_.default);var b=\"MOUSE\",x={target:null,data:{global:null}},T=function(t){function e(r,n){i(this,e);var s=o(this,t.call(this));return n=n||{},s.renderer=r,s.autoPreventDefault=void 0===n.autoPreventDefault||n.autoPreventDefault,s.interactionFrequency=n.interactionFrequency||10,s.mouse=new c.default,s.mouse.identifier=b,s.mouse.global.set(-999999),s.activeInteractionData={},s.activeInteractionData[b]=s.mouse,s.interactionDataPool=[],s.eventData=new f.default,s.interactionDOMElement=null,s.moveWhenInside=!1,s.eventsAdded=!1,s.mouseOverRenderer=!1,s.supportsTouchEvents=\"ontouchstart\"in window,s.supportsPointerEvents=!!window.PointerEvent,s.onPointerUp=s.onPointerUp.bind(s),s.processPointerUp=s.processPointerUp.bind(s),s.onPointerCancel=s.onPointerCancel.bind(s),s.processPointerCancel=s.processPointerCancel.bind(s),s.onPointerDown=s.onPointerDown.bind(s),s.processPointerDown=s.processPointerDown.bind(s),s.onPointerMove=s.onPointerMove.bind(s),s.processPointerMove=s.processPointerMove.bind(s),s.onPointerOut=s.onPointerOut.bind(s),s.processPointerOverOut=s.processPointerOverOut.bind(s),s.onPointerOver=s.onPointerOver.bind(s),s.cursorStyles={default:\"inherit\",pointer:\"pointer\"},s.currentCursorMode=null,s.cursor=null,s._tempPoint=new h.Point,s.resolution=1,s.setTargetElement(s.renderer.view,s.renderer.resolution),s}return s(e,t),e.prototype.hitTest=function(t,e){return x.target=null,x.data.global=t,e||(e=this.renderer._lastObjectRendered),this.processInteractive(x,e,null,!0),x.target},e.prototype.setTargetElement=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;this.removeEvents(),this.interactionDOMElement=t,this.resolution=e,this.addEvents()},e.prototype.addEvents=function(){this.interactionDOMElement&&(h.ticker.shared.add(this.update,this,h.UPDATE_PRIORITY.INTERACTION),window.navigator.msPointerEnabled?(this.interactionDOMElement.style[\"-ms-content-zooming\"]=\"none\",this.interactionDOMElement.style[\"-ms-touch-action\"]=\"none\"):this.supportsPointerEvents&&(this.interactionDOMElement.style[\"touch-action\"]=\"none\"),this.supportsPointerEvents?(window.document.addEventListener(\"pointermove\",this.onPointerMove,!0),this.interactionDOMElement.addEventListener(\"pointerdown\",this.onPointerDown,!0),this.interactionDOMElement.addEventListener(\"pointerleave\",this.onPointerOut,!0),this.interactionDOMElement.addEventListener(\"pointerover\",this.onPointerOver,!0),window.addEventListener(\"pointercancel\",this.onPointerCancel,!0),window.addEventListener(\"pointerup\",this.onPointerUp,!0)):(window.document.addEventListener(\"mousemove\",this.onPointerMove,!0),this.interactionDOMElement.addEventListener(\"mousedown\",this.onPointerDown,!0),this.interactionDOMElement.addEventListener(\"mouseout\",this.onPointerOut,!0),this.interactionDOMElement.addEventListener(\"mouseover\",this.onPointerOver,!0),window.addEventListener(\"mouseup\",this.onPointerUp,!0)),this.supportsTouchEvents&&(this.interactionDOMElement.addEventListener(\"touchstart\",this.onPointerDown,!0),this.interactionDOMElement.addEventListener(\"touchcancel\",this.onPointerCancel,!0),this.interactionDOMElement.addEventListener(\"touchend\",this.onPointerUp,!0),this.interactionDOMElement.addEventListener(\"touchmove\",this.onPointerMove,!0)),this.eventsAdded=!0)},e.prototype.removeEvents=function(){this.interactionDOMElement&&(h.ticker.shared.remove(this.update,this),window.navigator.msPointerEnabled?(this.interactionDOMElement.style[\"-ms-content-zooming\"]=\"\",this.interactionDOMElement.style[\"-ms-touch-action\"]=\"\"):this.supportsPointerEvents&&(this.interactionDOMElement.style[\"touch-action\"]=\"\"),this.supportsPointerEvents?(window.document.removeEventListener(\"pointermove\",this.onPointerMove,!0),this.interactionDOMElement.removeEventListener(\"pointerdown\",this.onPointerDown,!0),this.interactionDOMElement.removeEventListener(\"pointerleave\",this.onPointerOut,!0),this.interactionDOMElement.removeEventListener(\"pointerover\",this.onPointerOver,!0),window.removeEventListener(\"pointercancel\",this.onPointerCancel,!0),window.removeEventListener(\"pointerup\",this.onPointerUp,!0)):(window.document.removeEventListener(\"mousemove\",this.onPointerMove,!0),this.interactionDOMElement.removeEventListener(\"mousedown\",this.onPointerDown,!0),this.interactionDOMElement.removeEventListener(\"mouseout\",this.onPointerOut,!0),this.interactionDOMElement.removeEventListener(\"mouseover\",this.onPointerOver,!0),window.removeEventListener(\"mouseup\",this.onPointerUp,!0)),this.supportsTouchEvents&&(this.interactionDOMElement.removeEventListener(\"touchstart\",this.onPointerDown,!0),this.interactionDOMElement.removeEventListener(\"touchcancel\",this.onPointerCancel,!0),this.interactionDOMElement.removeEventListener(\"touchend\",this.onPointerUp,!0),this.interactionDOMElement.removeEventListener(\"touchmove\",this.onPointerMove,!0)),this.interactionDOMElement=null,this.eventsAdded=!1)},e.prototype.update=function(t){if(this._deltaTime+=t,!(this._deltaTime<this.interactionFrequency)&&(this._deltaTime=0,this.interactionDOMElement)){if(this.didMove)return void(this.didMove=!1);this.cursor=null;for(var e in this.activeInteractionData)if(this.activeInteractionData.hasOwnProperty(e)){var r=this.activeInteractionData[e];if(r.originalEvent&&\"touch\"!==r.pointerType){var n=this.configureInteractionEventForDOMEvent(this.eventData,r.originalEvent,r);this.processInteractive(n,this.renderer._lastObjectRendered,this.processPointerOverOut,!0)}}this.setCursorMode(this.cursor)}},e.prototype.setCursorMode=function(t){if(t=t||\"default\",this.currentCursorMode!==t){this.currentCursorMode=t;var e=this.cursorStyles[t];if(e)switch(void 0===e?\"undefined\":a(e)){case\"string\":this.interactionDOMElement.style.cursor=e;break;case\"function\":e(t);break;case\"object\":Object.assign(this.interactionDOMElement.style,e)}else\"string\"!=typeof t||Object.prototype.hasOwnProperty.call(this.cursorStyles,t)||(this.interactionDOMElement.style.cursor=t)}},e.prototype.dispatchEvent=function(t,e,r){r.stopped||(r.currentTarget=t,r.type=e,t.emit(e,r),t[e]&&t[e](r))},e.prototype.mapPositionToPoint=function(t,e,r){var n=void 0;n=this.interactionDOMElement.parentElement?this.interactionDOMElement.getBoundingClientRect():{x:0,y:0,width:0,height:0};var i=navigator.isCocoonJS?this.resolution:1/this.resolution;t.x=(e-n.left)*(this.interactionDOMElement.width/n.width)*i,t.y=(r-n.top)*(this.interactionDOMElement.height/n.height)*i},e.prototype.processInteractive=function(t,e,r,n,i){if(!e||!e.visible)return!1;var o=t.data.global;i=e.interactive||i;var s=!1,a=i;if(e.hitArea?a=!1:n&&e._mask&&(e._mask.containsPoint(o)||(n=!1)),e.interactiveChildren&&e.children)for(var u=e.children,h=u.length-1;h>=0;h--){var l=u[h],c=this.processInteractive(t,l,r,n,a);if(c){if(!l.parent)continue;a=!1,c&&(t.target&&(n=!1),s=!0)}}return i&&(n&&!t.target&&(e.hitArea?(e.worldTransform.applyInverse(o,this._tempPoint),e.hitArea.contains(this._tempPoint.x,this._tempPoint.y)&&(s=!0)):e.containsPoint&&e.containsPoint(o)&&(s=!0)),e.interactive&&(s&&!t.target&&(t.target=e),r&&r(t,e,!!s))),s},e.prototype.onPointerDown=function(t){if(!this.supportsTouchEvents||\"touch\"!==t.pointerType){var e=this.normalizeToPointerData(t);this.autoPreventDefault&&e[0].isNormalized&&t.preventDefault();for(var r=e.length,n=0;n<r;n++){var i=e[n],o=this.getInteractionDataForPointerId(i),s=this.configureInteractionEventForDOMEvent(this.eventData,i,o);if(s.data.originalEvent=t,this.processInteractive(s,this.renderer._lastObjectRendered,this.processPointerDown,!0),this.emit(\"pointerdown\",s),\"touch\"===i.pointerType)this.emit(\"touchstart\",s);else if(\"mouse\"===i.pointerType||\"pen\"===i.pointerType){var a=2===i.button;this.emit(a?\"rightdown\":\"mousedown\",this.eventData)}}}},e.prototype.processPointerDown=function(t,e,r){var n=t.data,i=t.data.identifier;if(r)if(e.trackedPointers[i]||(e.trackedPointers[i]=new v.default(i)),this.dispatchEvent(e,\"pointerdown\",t),\"touch\"===n.pointerType)this.dispatchEvent(e,\"touchstart\",t);else if(\"mouse\"===n.pointerType||\"pen\"===n.pointerType){var o=2===n.button;o?e.trackedPointers[i].rightDown=!0:e.trackedPointers[i].leftDown=!0,this.dispatchEvent(e,o?\"rightdown\":\"mousedown\",t)}},e.prototype.onPointerComplete=function(t,e,r){for(var n=this.normalizeToPointerData(t),i=n.length,o=t.target!==this.interactionDOMElement?\"outside\":\"\",s=0;s<i;s++){var a=n[s],u=this.getInteractionDataForPointerId(a),h=this.configureInteractionEventForDOMEvent(this.eventData,a,u);if(h.data.originalEvent=t,this.processInteractive(h,this.renderer._lastObjectRendered,r,e||!o),this.emit(e?\"pointercancel\":\"pointerup\"+o,h),\"mouse\"===a.pointerType||\"pen\"===a.pointerType){var l=2===a.button;this.emit(l?\"rightup\"+o:\"mouseup\"+o,h)}else\"touch\"===a.pointerType&&(this.emit(e?\"touchcancel\":\"touchend\"+o,h),this.releaseInteractionDataForPointerId(a.pointerId,u))}},e.prototype.onPointerCancel=function(t){this.supportsTouchEvents&&\"touch\"===t.pointerType||this.onPointerComplete(t,!0,this.processPointerCancel)},e.prototype.processPointerCancel=function(t,e){var r=t.data,n=t.data.identifier;void 0!==e.trackedPointers[n]&&(delete e.trackedPointers[n],this.dispatchEvent(e,\"pointercancel\",t),\"touch\"===r.pointerType&&this.dispatchEvent(e,\"touchcancel\",t))},e.prototype.onPointerUp=function(t){this.supportsTouchEvents&&\"touch\"===t.pointerType||this.onPointerComplete(t,!1,this.processPointerUp)},e.prototype.processPointerUp=function(t,e,r){var n=t.data,i=t.data.identifier,o=e.trackedPointers[i],s=\"touch\"===n.pointerType;if(\"mouse\"===n.pointerType||\"pen\"===n.pointerType){var a=2===n.button,u=v.default.FLAGS,h=a?u.RIGHT_DOWN:u.LEFT_DOWN,l=void 0!==o&&o.flags&h;r?(this.dispatchEvent(e,a?\"rightup\":\"mouseup\",t),l&&this.dispatchEvent(e,a?\"rightclick\":\"click\",t)):l&&this.dispatchEvent(e,a?\"rightupoutside\":\"mouseupoutside\",t),o&&(a?o.rightDown=!1:o.leftDown=!1)}r?(this.dispatchEvent(e,\"pointerup\",t),s&&this.dispatchEvent(e,\"touchend\",t),o&&(this.dispatchEvent(e,\"pointertap\",t),s&&(this.dispatchEvent(e,\"tap\",t),o.over=!1))):o&&(this.dispatchEvent(e,\"pointerupoutside\",t),s&&this.dispatchEvent(e,\"touchendoutside\",t)),o&&o.none&&delete e.trackedPointers[i]},e.prototype.onPointerMove=function(t){if(!this.supportsTouchEvents||\"touch\"!==t.pointerType){var e=this.normalizeToPointerData(t);\"mouse\"===e[0].pointerType&&(this.didMove=!0,this.cursor=null);for(var r=e.length,n=0;n<r;n++){var i=e[n],o=this.getInteractionDataForPointerId(i),s=this.configureInteractionEventForDOMEvent(this.eventData,i,o);s.data.originalEvent=t;var a=\"touch\"!==i.pointerType||this.moveWhenInside;this.processInteractive(s,this.renderer._lastObjectRendered,this.processPointerMove,a),this.emit(\"pointermove\",s),\"touch\"===i.pointerType&&this.emit(\"touchmove\",s),\"mouse\"!==i.pointerType&&\"pen\"!==i.pointerType||this.emit(\"mousemove\",s)}\"mouse\"===e[0].pointerType&&this.setCursorMode(this.cursor)}},e.prototype.processPointerMove=function(t,e,r){var n=t.data,i=\"touch\"===n.pointerType,o=\"mouse\"===n.pointerType||\"pen\"===n.pointerType;o&&this.processPointerOverOut(t,e,r),this.moveWhenInside&&!r||(this.dispatchEvent(e,\"pointermove\",t),i&&this.dispatchEvent(e,\"touchmove\",t),o&&this.dispatchEvent(e,\"mousemove\",t))},e.prototype.onPointerOut=function(t){if(!this.supportsTouchEvents||\"touch\"!==t.pointerType){var e=this.normalizeToPointerData(t),r=e[0];\"mouse\"===r.pointerType&&(this.mouseOverRenderer=!1,this.setCursorMode(null));var n=this.getInteractionDataForPointerId(r),i=this.configureInteractionEventForDOMEvent(this.eventData,r,n);i.data.originalEvent=r,this.processInteractive(i,this.renderer._lastObjectRendered,this.processPointerOverOut,!1),this.emit(\"pointerout\",i),\"mouse\"===r.pointerType||\"pen\"===r.pointerType?this.emit(\"mouseout\",i):this.releaseInteractionDataForPointerId(n.identifier)}},e.prototype.processPointerOverOut=function(t,e,r){var n=t.data,i=t.data.identifier,o=\"mouse\"===n.pointerType||\"pen\"===n.pointerType,s=e.trackedPointers[i];r&&!s&&(s=e.trackedPointers[i]=new v.default(i)),void 0!==s&&(r&&this.mouseOverRenderer?(s.over||(s.over=!0,this.dispatchEvent(e,\"pointerover\",t),o&&this.dispatchEvent(e,\"mouseover\",t)),o&&null===this.cursor&&(this.cursor=e.cursor)):s.over&&(s.over=!1,this.dispatchEvent(e,\"pointerout\",this.eventData),o&&this.dispatchEvent(e,\"mouseout\",t),s.none&&delete e.trackedPointers[i]))},e.prototype.onPointerOver=function(t){var e=this.normalizeToPointerData(t),r=e[0],n=this.getInteractionDataForPointerId(r),i=this.configureInteractionEventForDOMEvent(this.eventData,r,n);i.data.originalEvent=r,\"mouse\"===r.pointerType&&(this.mouseOverRenderer=!0),this.emit(\"pointerover\",i),\"mouse\"!==r.pointerType&&\"pen\"!==r.pointerType||this.emit(\"mouseover\",i)},e.prototype.getInteractionDataForPointerId=function(t){var e=t.pointerId,r=void 0;return e===b||\"mouse\"===t.pointerType?r=this.mouse:this.activeInteractionData[e]?r=this.activeInteractionData[e]:(r=this.interactionDataPool.pop()||new c.default,r.identifier=e,this.activeInteractionData[e]=r),r._copyEvent(t),r},e.prototype.releaseInteractionDataForPointerId=function(t){var e=this.activeInteractionData[t];e&&(delete this.activeInteractionData[t],e._reset(),this.interactionDataPool.push(e))},e.prototype.configureInteractionEventForDOMEvent=function(t,e,r){return t.data=r,this.mapPositionToPoint(r.global,e.clientX,e.clientY),navigator.isCocoonJS&&\"touch\"===e.pointerType&&(r.global.x=r.global.x/this.resolution,r.global.y=r.global.y/this.resolution),\"touch\"===e.pointerType&&(e.globalX=r.global.x,e.globalY=r.global.y),r.originalEvent=e,t._reset(),t},e.prototype.normalizeToPointerData=function(t){var e=[];if(this.supportsTouchEvents&&t instanceof TouchEvent)for(var r=0,n=t.changedTouches.length;r<n;r++){var i=t.changedTouches[r];void 0===i.button&&(i.button=t.touches.length?1:0),void 0===i.buttons&&(i.buttons=t.touches.length?1:0),void 0===i.isPrimary&&(i.isPrimary=1===t.touches.length&&\"touchstart\"===t.type),void 0===i.width&&(i.width=i.radiusX||1),void 0===i.height&&(i.height=i.radiusY||1),void 0===i.tiltX&&(i.tiltX=0),void 0===i.tiltY&&(i.tiltY=0),void 0===i.pointerType&&(i.pointerType=\"touch\"),void 0===i.pointerId&&(i.pointerId=i.identifier||0),void 0===i.pressure&&(i.pressure=i.force||.5),i.twist=0,i.tangentialPressure=0,void 0===i.layerX&&(i.layerX=i.offsetX=i.clientX),void 0===i.layerY&&(i.layerY=i.offsetY=i.clientY),i.isNormalized=!0,e.push(i)}else!(t instanceof MouseEvent)||this.supportsPointerEvents&&t instanceof window.PointerEvent?e.push(t):(void 0===t.isPrimary&&(t.isPrimary=!0),void 0===t.width&&(t.width=1),void 0===t.height&&(t.height=1),void 0===t.tiltX&&(t.tiltX=0),void 0===t.tiltY&&(t.tiltY=0),void 0===t.pointerType&&(t.pointerType=\"mouse\"),void 0===t.pointerId&&(t.pointerId=b),void 0===t.pressure&&(t.pressure=.5),t.twist=0,t.tangentialPressure=0,t.isNormalized=!0,e.push(t));return e},e.prototype.destroy=function(){this.removeEvents(),this.removeAllListeners(),this.renderer=null,this.mouse=null,this.eventData=null,this.interactionDOMElement=null,this.onPointerDown=null,this.processPointerDown=null,this.onPointerUp=null,this.processPointerUp=null,this.onPointerCancel=null,this.processPointerCancel=null,this.onPointerMove=null,this.processPointerMove=null,this.onPointerOut=null,this.processPointerOverOut=null,this.onPointerOver=null,this._tempPoint=null},e}(g.default);r.default=T,h.WebGLRenderer.registerPlugin(\"interaction\",T),h.CanvasRenderer.registerPlugin(\"interaction\",T)},{\"../core\":65,\"./InteractionData\":155,\"./InteractionEvent\":156,\"./InteractionTrackingData\":158,\"./interactiveTarget\":160,eventemitter3:3}],158:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),o=function(){function t(e){n(this,t),this._pointerId=e,this._flags=t.FLAGS.NONE}return t.prototype._doSet=function(t,e){this._flags=e?this._flags|t:this._flags&~t},i(t,[{key:\"pointerId\",get:function(){return this._pointerId}},{key:\"flags\",get:function(){return this._flags},set:function(t){this._flags=t}},{key:\"none\",get:function(){return this._flags===this.constructor.FLAGS.NONE}},{key:\"over\",get:function(){return 0!=(this._flags&this.constructor.FLAGS.OVER)},set:function(t){this._doSet(this.constructor.FLAGS.OVER,t)}},{key:\"rightDown\",get:function(){return 0!=(this._flags&this.constructor.FLAGS.RIGHT_DOWN)},set:function(t){this._doSet(this.constructor.FLAGS.RIGHT_DOWN,t)}},{key:\"leftDown\",get:function(){return 0!=(this._flags&this.constructor.FLAGS.LEFT_DOWN)},set:function(t){this._doSet(this.constructor.FLAGS.LEFT_DOWN,t)}}]),t}();r.default=o,o.FLAGS=Object.freeze({NONE:0,OVER:1,LEFT_DOWN:2,RIGHT_DOWN:4})},{}],159:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0;var i=t(\"./InteractionData\");Object.defineProperty(r,\"InteractionData\",{enumerable:!0,get:function(){return n(i).default}});var o=t(\"./InteractionManager\");Object.defineProperty(r,\"InteractionManager\",{enumerable:!0,get:function(){return n(o).default}});var s=t(\"./interactiveTarget\");Object.defineProperty(r,\"interactiveTarget\",{enumerable:!0,get:function(){return n(s).default}});var a=t(\"./InteractionTrackingData\");Object.defineProperty(r,\"InteractionTrackingData\",{enumerable:!0,get:function(){return n(a).default}});var u=t(\"./InteractionEvent\");Object.defineProperty(r,\"InteractionEvent\",{enumerable:!0,get:function(){return n(u).default}})},{\"./InteractionData\":155,\"./InteractionEvent\":156,\"./InteractionManager\":157,\"./InteractionTrackingData\":158,\"./interactiveTarget\":160}],160:[function(t,e,r){\"use strict\";r.__esModule=!0,r.default={interactive:!1,interactiveChildren:!0,hitArea:null,get buttonMode(){return\"pointer\"===this.cursor},set buttonMode(t){t?this.cursor=\"pointer\":\"pointer\"===this.cursor&&(this.cursor=null)},cursor:null,get trackedPointers(){return void 0===this._trackedPointers&&(this._trackedPointers={}),this._trackedPointers},_trackedPointers:void 0}},{}],161:[function(t,e,r){\"use strict\";function n(t,e){t.bitmapFont=u.BitmapText.registerFont(t.data,e)}r.__esModule=!0,r.parse=n,r.default=function(){return function(t,e){if(!t.data||t.type!==a.Resource.TYPE.XML)return void e();if(0===t.data.getElementsByTagName(\"page\").length||0===t.data.getElementsByTagName(\"info\").length||null===t.data.getElementsByTagName(\"info\")[0].getAttribute(\"face\"))return void e();var r=t.isDataUrl?\"\":o.dirname(t.url);t.isDataUrl&&(\".\"===r&&(r=\"\"),this.baseUrl&&r&&\"/\"===this.baseUrl.charAt(this.baseUrl.length-1)&&(r+=\"/\")),(r=r.replace(this.baseUrl,\"\"))&&\"/\"!==r.charAt(r.length-1)&&(r+=\"/\");var i=r+t.data.getElementsByTagName(\"page\")[0].getAttribute(\"file\");if(s.utils.TextureCache[i])n(t,s.utils.TextureCache[i]),e();else{var u={crossOrigin:t.crossOrigin,loadType:a.Resource.LOAD_TYPE.IMAGE,metadata:t.metadata.imageMetadata,parentResource:t};this.add(t.name+\"_image\",i,u,function(r){n(t,r.texture),e()})}}};var i=t(\"path\"),o=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(i),s=t(\"../core\"),a=t(\"resource-loader\"),u=t(\"../extras\")},{\"../core\":65,\"../extras\":141,path:8,\"resource-loader\":36}],162:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0,r.shared=r.Resource=r.textureParser=r.getResourcePath=r.spritesheetParser=r.parseBitmapFontData=r.bitmapFontParser=r.Loader=void 0;var i=t(\"./bitmapFontParser\");Object.defineProperty(r,\"bitmapFontParser\",{enumerable:!0,get:function(){return n(i).default}}),Object.defineProperty(r,\"parseBitmapFontData\",{enumerable:!0,get:function(){return i.parse}});var o=t(\"./spritesheetParser\");Object.defineProperty(r,\"spritesheetParser\",{enumerable:!0,get:function(){return n(o).default}}),Object.defineProperty(r,\"getResourcePath\",{enumerable:!0,get:function(){return o.getResourcePath}});var s=t(\"./textureParser\");Object.defineProperty(r,\"textureParser\",{enumerable:!0,get:function(){return n(s).default}});var a=t(\"resource-loader\");Object.defineProperty(r,\"Resource\",{enumerable:!0,get:function(){return a.Resource}});var u=t(\"../core/Application\"),h=n(u),l=t(\"./loader\"),c=n(l);r.Loader=c.default;var d=new c.default;d.destroy=function(){},r.shared=d;var f=h.default.prototype;f._loader=null,Object.defineProperty(f,\"loader\",{get:function(){if(!this._loader){var t=this._options.sharedLoader;this._loader=t?d:new c.default}return this._loader}}),f._parentDestroy=f.destroy,f.destroy=function(t){this._loader&&(this._loader.destroy(),this._loader=null),this._parentDestroy(t)}},{\"../core/Application\":43,\"./bitmapFontParser\":161,\"./loader\":163,\"./spritesheetParser\":164,\"./textureParser\":165,\"resource-loader\":36}],163:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"resource-loader\"),u=n(a),h=t(\"resource-loader/lib/middlewares/parsing/blob\"),l=t(\"eventemitter3\"),c=n(l),d=t(\"./textureParser\"),f=n(d),p=t(\"./spritesheetParser\"),v=n(p),y=t(\"./bitmapFontParser\"),g=n(y),m=function(t){function e(r,n){i(this,e);var s=o(this,t.call(this,r,n));c.default.call(s);for(var a=0;a<e._pixiMiddleware.length;++a)s.use(e._pixiMiddleware[a]());return s.onStart.add(function(t){return s.emit(\"start\",t)}),s.onProgress.add(function(t,e){return s.emit(\"progress\",t,e)}),s.onError.add(function(t,e,r){return s.emit(\"error\",t,e,r)}),s.onLoad.add(function(t,e){return s.emit(\"load\",t,e)}),s.onComplete.add(function(t,e){return s.emit(\"complete\",t,e)}),s}return s(e,t),e.addPixiMiddleware=function(t){e._pixiMiddleware.push(t)},e.prototype.destroy=function(){this.removeAllListeners(),this.reset()},e}(u.default);r.default=m;for(var _ in c.default.prototype)m.prototype[_]=c.default.prototype[_];m._pixiMiddleware=[h.blobMiddlewareFactory,f.default,v.default,g.default];var b=u.default.Resource;b.setExtensionXhrType(\"fnt\",b.XHR_RESPONSE_TYPE.DOCUMENT)},{\"./bitmapFontParser\":161,\"./spritesheetParser\":164,\"./textureParser\":165,eventemitter3:3,\"resource-loader\":36,\"resource-loader/lib/middlewares/parsing/blob\":37}],164:[function(t,e,r){\"use strict\";function n(t,e){return t.isDataUrl?t.data.meta.image:s.default.resolve(t.url.replace(e,\"\"),t.data.meta.image)}r.__esModule=!0,r.default=function(){return function(t,e){var r=t.name+\"_image\";if(!t.data||t.type!==i.Resource.TYPE.JSON||!t.data.frames||this.resources[r])return void e();var o={crossOrigin:t.crossOrigin,loadType:i.Resource.LOAD_TYPE.IMAGE,metadata:t.metadata.imageMetadata,parentResource:t},s=n(t,this.baseUrl);this.add(r,s,o,function(r){var n=new a.Spritesheet(r.texture.baseTexture,t.data,t.url);n.parse(function(){t.spritesheet=n,t.textures=n.textures,e()})})}},r.getResourcePath=n;var i=t(\"resource-loader\"),o=t(\"url\"),s=function(t){return t&&t.__esModule?t:{default:t}}(o),a=t(\"../core\")},{\"../core\":65,\"resource-loader\":36,url:38}],165:[function(t,e,r){\"use strict\";r.__esModule=!0,r.default=function(){return function(t,e){t.data&&t.type===n.Resource.TYPE.IMAGE&&(t.texture=o.default.fromLoader(t.data,t.url,t.name)),e()}};var n=t(\"resource-loader\"),i=t(\"../core/textures/Texture\"),o=function(t){return t&&t.__esModule?t:{default:t}}(i)},{\"../core/textures/Texture\":115,\"resource-loader\":36}],166:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"../core\"),u=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(a),h=t(\"../extras/TextureTransform\"),l=function(t){return t&&t.__esModule?t:{default:t}}(h),c=new u.Point,d=new u.Polygon,f=function(t){function e(r,o,s,a,h){n(this,e);var c=i(this,t.call(this));return c._texture=r,c.uvs=s||new Float32Array([0,0,1,0,1,1,0,1]),c.vertices=o||new Float32Array([0,0,100,0,100,100,0,100]),c.indices=a||new Uint16Array([0,1,3,2]),c.dirty=0,c.indexDirty=0,c.blendMode=u.BLEND_MODES.NORMAL,c.canvasPadding=0,c.drawMode=h||e.DRAW_MODES.TRIANGLE_MESH,c.shader=null,c.tintRgb=new Float32Array([1,1,1]),c._glDatas={},c._uvTransform=new l.default(r),c.uploadUvTransform=!1,c.pluginName=\"mesh\",c}return o(e,t),e.prototype._renderWebGL=function(t){this.refresh(),t.setObjectRenderer(t.plugins[this.pluginName]),t.plugins[this.pluginName].render(this)},e.prototype._renderCanvas=function(t){this.refresh(),t.plugins[this.pluginName].render(this)},e.prototype._onTextureUpdate=function(){this._uvTransform.texture=this._texture,this.refresh()},e.prototype.multiplyUvs=function(){this.uploadUvTransform||this._uvTransform.multiplyUvs(this.uvs)},e.prototype.refresh=function(t){this._uvTransform.update(t)&&this._refresh()},e.prototype._refresh=function(){},e.prototype._calculateBounds=function(){this._bounds.addVertices(this.transform,this.vertices,0,this.vertices.length)},e.prototype.containsPoint=function(t){if(!this.getBounds().contains(t.x,t.y))return!1;this.worldTransform.applyInverse(t,c);for(var r=this.vertices,n=d.points,i=this.indices,o=this.indices.length,s=this.drawMode===e.DRAW_MODES.TRIANGLES?3:1,a=0;a+2<o;a+=s){var u=2*i[a],h=2*i[a+1],l=2*i[a+2];if(n[0]=r[u],n[1]=r[u+1],n[2]=r[h],n[3]=r[h+1],n[4]=r[l],n[5]=r[l+1],d.contains(c.x,c.y))return!0}return!1},s(e,[{key:\"texture\",get:function(){return this._texture},set:function(t){this._texture!==t&&(this._texture=t,t&&(t.baseTexture.hasLoaded?this._onTextureUpdate():t.once(\"update\",this._onTextureUpdate,this)))}},{key:\"tint\",get:function(){return u.utils.rgb2hex(this.tintRgb)},set:function(t){this.tintRgb=u.utils.hex2rgb(t,this.tintRgb)}}]),e}(u.Container);r.default=f,f.DRAW_MODES={TRIANGLE_MESH:0,TRIANGLES:1}},{\"../core\":65,\"../extras/TextureTransform\":136}],167:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"./Plane\"),u=function(t){return t&&t.__esModule?t:{default:t}}(a),h=10,l=function(t){function e(r,o,s,a,u){n(this,e);var l=i(this,t.call(this,r,4,4));return l._origWidth=r.orig.width,l._origHeight=r.orig.height,l._width=l._origWidth,l._height=l._origHeight,l.leftWidth=void 0!==o?o:h,l.rightWidth=void 0!==a?a:h,l.topHeight=void 0!==s?s:h,l.bottomHeight=void 0!==u?u:h,l.refresh(!0),l}return o(e,t),e.prototype.updateHorizontalVertices=function(){var t=this.vertices;t[9]=t[11]=t[13]=t[15]=this._topHeight,t[17]=t[19]=t[21]=t[23]=this._height-this._bottomHeight,t[25]=t[27]=t[29]=t[31]=this._height},e.prototype.updateVerticalVertices=function(){var t=this.vertices;t[2]=t[10]=t[18]=t[26]=this._leftWidth,t[4]=t[12]=t[20]=t[28]=this._width-this._rightWidth,t[6]=t[14]=t[22]=t[30]=this._width},e.prototype._renderCanvas=function(t){var e=t.context;e.globalAlpha=this.worldAlpha\n;var r=this.worldTransform,n=t.resolution;t.roundPixels?e.setTransform(r.a*n,r.b*n,r.c*n,r.d*n,r.tx*n|0,r.ty*n|0):e.setTransform(r.a*n,r.b*n,r.c*n,r.d*n,r.tx*n,r.ty*n);var i=this._texture.baseTexture,o=i.source,s=i.width,a=i.height;this.drawSegment(e,o,s,a,0,1,10,11),this.drawSegment(e,o,s,a,2,3,12,13),this.drawSegment(e,o,s,a,4,5,14,15),this.drawSegment(e,o,s,a,8,9,18,19),this.drawSegment(e,o,s,a,10,11,20,21),this.drawSegment(e,o,s,a,12,13,22,23),this.drawSegment(e,o,s,a,16,17,26,27),this.drawSegment(e,o,s,a,18,19,28,29),this.drawSegment(e,o,s,a,20,21,30,31)},e.prototype.drawSegment=function(t,e,r,n,i,o,s,a){var u=this.uvs,h=this.vertices,l=(u[s]-u[i])*r,c=(u[a]-u[o])*n,d=h[s]-h[i],f=h[a]-h[o];l<1&&(l=1),c<1&&(c=1),d<1&&(d=1),f<1&&(f=1),t.drawImage(e,u[i]*r,u[o]*n,l,c,h[i],h[o],d,f)},e.prototype._refresh=function(){t.prototype._refresh.call(this);var e=this.uvs,r=this._texture;this._origWidth=r.orig.width,this._origHeight=r.orig.height;var n=1/this._origWidth,i=1/this._origHeight;e[0]=e[8]=e[16]=e[24]=0,e[1]=e[3]=e[5]=e[7]=0,e[6]=e[14]=e[22]=e[30]=1,e[25]=e[27]=e[29]=e[31]=1,e[2]=e[10]=e[18]=e[26]=n*this._leftWidth,e[4]=e[12]=e[20]=e[28]=1-n*this._rightWidth,e[9]=e[11]=e[13]=e[15]=i*this._topHeight,e[17]=e[19]=e[21]=e[23]=1-i*this._bottomHeight,this.updateHorizontalVertices(),this.updateVerticalVertices(),this.dirty++,this.multiplyUvs()},s(e,[{key:\"width\",get:function(){return this._width},set:function(t){this._width=t,this._refresh()}},{key:\"height\",get:function(){return this._height},set:function(t){this._height=t,this._refresh()}},{key:\"leftWidth\",get:function(){return this._leftWidth},set:function(t){this._leftWidth=t,this._refresh()}},{key:\"rightWidth\",get:function(){return this._rightWidth},set:function(t){this._rightWidth=t,this._refresh()}},{key:\"topHeight\",get:function(){return this._topHeight},set:function(t){this._topHeight=t,this._refresh()}},{key:\"bottomHeight\",get:function(){return this._bottomHeight},set:function(t){this._bottomHeight=t,this._refresh()}}]),e}(u.default);r.default=l},{\"./Plane\":168}],168:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=t(\"./Mesh\"),a=function(t){return t&&t.__esModule?t:{default:t}}(s),u=function(t){function e(r,o,s){n(this,e);var u=i(this,t.call(this,r));return u._ready=!0,u.verticesX=o||10,u.verticesY=s||10,u.drawMode=a.default.DRAW_MODES.TRIANGLES,u.refresh(),u}return o(e,t),e.prototype._refresh=function(){for(var t=this._texture,e=this.verticesX*this.verticesY,r=[],n=[],i=[],o=[],s=this.verticesX-1,a=this.verticesY-1,u=t.width/s,h=t.height/a,l=0;l<e;l++){var c=l%this.verticesX,d=l/this.verticesX|0;r.push(c*u,d*h),i.push(c/s,d/a)}for(var f=s*a,p=0;p<f;p++){var v=p%s,y=p/s|0,g=y*this.verticesX+v,m=y*this.verticesX+v+1,_=(y+1)*this.verticesX+v,b=(y+1)*this.verticesX+v+1;o.push(g,m,_),o.push(m,b,_)}this.vertices=new Float32Array(r),this.uvs=new Float32Array(i),this.colors=new Float32Array(n),this.indices=new Uint16Array(o),this.indexDirty++,this.multiplyUvs()},e.prototype._onTextureUpdate=function(){a.default.prototype._onTextureUpdate.call(this),this._ready&&this.refresh()},e}(a.default);r.default=u},{\"./Mesh\":166}],169:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=t(\"./Mesh\"),a=function(t){return t&&t.__esModule?t:{default:t}}(s),u=function(t){function e(r,o){n(this,e);var s=i(this,t.call(this,r));return s.points=o,s.vertices=new Float32Array(4*o.length),s.uvs=new Float32Array(4*o.length),s.colors=new Float32Array(2*o.length),s.indices=new Uint16Array(2*o.length),s.autoUpdate=!0,s.refresh(),s}return o(e,t),e.prototype._refresh=function(){var t=this.points;if(!(t.length<1)&&this._texture._uvs){this.vertices.length/4!==t.length&&(this.vertices=new Float32Array(4*t.length),this.uvs=new Float32Array(4*t.length),this.colors=new Float32Array(2*t.length),this.indices=new Uint16Array(2*t.length));var e=this.uvs,r=this.indices,n=this.colors;e[0]=0,e[1]=0,e[2]=0,e[3]=1,n[0]=1,n[1]=1,r[0]=0,r[1]=1;for(var i=t.length,o=1;o<i;o++){var s=4*o,a=o/(i-1);e[s]=a,e[s+1]=0,e[s+2]=a,e[s+3]=1,s=2*o,n[s]=1,n[s+1]=1,s=2*o,r[s]=s,r[s+1]=s+1}this.dirty++,this.indexDirty++,this.multiplyUvs(),this.refreshVertices()}},e.prototype.refreshVertices=function(){var t=this.points;if(!(t.length<1))for(var e=t[0],r=void 0,n=0,i=0,o=this.vertices,s=t.length,a=0;a<s;a++){var u=t[a],h=4*a;r=a<t.length-1?t[a+1]:u,i=-(r.x-e.x),n=r.y-e.y;var l=10*(1-a/(s-1));l>1&&(l=1);var c=Math.sqrt(n*n+i*i),d=this._texture.height/2;n/=c,i/=c,n*=d,i*=d,o[h]=u.x+n,o[h+1]=u.y+i,o[h+2]=u.x-n,o[h+3]=u.y-i,e=u}},e.prototype.updateTransform=function(){this.autoUpdate&&this.refreshVertices(),this.containerUpdateTransform()},e}(a.default);r.default=u},{\"./Mesh\":166}],170:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=t(\"../../core\"),o=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(i),s=t(\"../Mesh\"),a=function(t){return t&&t.__esModule?t:{default:t}}(s),u=function(){function t(e){n(this,t),this.renderer=e}return t.prototype.render=function(t){var e=this.renderer,r=e.context,n=t.worldTransform,i=e.resolution;e.roundPixels?r.setTransform(n.a*i,n.b*i,n.c*i,n.d*i,n.tx*i|0,n.ty*i|0):r.setTransform(n.a*i,n.b*i,n.c*i,n.d*i,n.tx*i,n.ty*i),e.setBlendMode(t.blendMode),t.drawMode===a.default.DRAW_MODES.TRIANGLE_MESH?this._renderTriangleMesh(t):this._renderTriangles(t)},t.prototype._renderTriangleMesh=function(t){for(var e=t.vertices.length/2,r=0;r<e-2;r++){var n=2*r;this._renderDrawTriangle(t,n,n+2,n+4)}},t.prototype._renderTriangles=function(t){for(var e=t.indices,r=e.length,n=0;n<r;n+=3){var i=2*e[n],o=2*e[n+1],s=2*e[n+2];this._renderDrawTriangle(t,i,o,s)}},t.prototype._renderDrawTriangle=function(t,e,r,n){var i=this.renderer.context,o=t.uvs,s=t.vertices,a=t._texture;if(a.valid){var u=a.baseTexture,h=u.source,l=u.width,c=u.height,d=void 0,f=void 0,p=void 0,v=void 0,y=void 0,g=void 0;if(t.uploadUvTransform){var m=t._uvTransform.mapCoord;d=(o[e]*m.a+o[e+1]*m.c+m.tx)*u.width,f=(o[r]*m.a+o[r+1]*m.c+m.tx)*u.width,p=(o[n]*m.a+o[n+1]*m.c+m.tx)*u.width,v=(o[e]*m.b+o[e+1]*m.d+m.ty)*u.height,y=(o[r]*m.b+o[r+1]*m.d+m.ty)*u.height,g=(o[n]*m.b+o[n+1]*m.d+m.ty)*u.height}else d=o[e]*u.width,f=o[r]*u.width,p=o[n]*u.width,v=o[e+1]*u.height,y=o[r+1]*u.height,g=o[n+1]*u.height;var _=s[e],b=s[r],x=s[n],T=s[e+1],w=s[r+1],E=s[n+1];if(t.canvasPadding>0){var S=t.canvasPadding/t.worldTransform.a,O=t.canvasPadding/t.worldTransform.d,M=(_+b+x)/3,P=(T+w+E)/3,C=_-M,R=T-P,A=Math.sqrt(C*C+R*R);_=M+C/A*(A+S),T=P+R/A*(A+O),C=b-M,R=w-P,A=Math.sqrt(C*C+R*R),b=M+C/A*(A+S),w=P+R/A*(A+O),C=x-M,R=E-P,A=Math.sqrt(C*C+R*R),x=M+C/A*(A+S),E=P+R/A*(A+O)}i.save(),i.beginPath(),i.moveTo(_,T),i.lineTo(b,w),i.lineTo(x,E),i.closePath(),i.clip();var I=d*y+v*p+f*g-y*p-v*f-d*g,D=_*y+v*x+b*g-y*x-v*b-_*g,L=d*b+_*p+f*x-b*p-_*f-d*x,N=d*y*x+v*b*p+_*f*g-_*y*p-v*f*x-d*b*g,F=T*y+v*E+w*g-y*E-v*w-T*g,B=d*w+T*p+f*E-w*p-T*f-d*E,k=d*y*E+v*w*p+T*f*g-T*y*p-v*f*E-d*w*g;i.transform(D/I,F/I,L/I,B/I,N/I,k/I),i.drawImage(h,0,0,l*u.resolution,c*u.resolution,0,0,l,c),i.restore(),this.renderer.invalidateBlendMode()}},t.prototype.renderMeshFlat=function(t){var e=this.renderer.context,r=t.vertices,n=r.length/2;e.beginPath();for(var i=1;i<n-2;++i){var o=2*i,s=r[o],a=r[o+1],u=r[o+2],h=r[o+3],l=r[o+4],c=r[o+5];e.moveTo(s,a),e.lineTo(u,h),e.lineTo(l,c)}e.fillStyle=\"#FF0000\",e.fill(),e.closePath()},t.prototype.destroy=function(){this.renderer=null},t}();r.default=u,o.CanvasRenderer.registerPlugin(\"mesh\",u)},{\"../../core\":65,\"../Mesh\":166}],171:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0;var i=t(\"./Mesh\");Object.defineProperty(r,\"Mesh\",{enumerable:!0,get:function(){return n(i).default}});var o=t(\"./webgl/MeshRenderer\");Object.defineProperty(r,\"MeshRenderer\",{enumerable:!0,get:function(){return n(o).default}});var s=t(\"./canvas/CanvasMeshRenderer\");Object.defineProperty(r,\"CanvasMeshRenderer\",{enumerable:!0,get:function(){return n(s).default}});var a=t(\"./Plane\");Object.defineProperty(r,\"Plane\",{enumerable:!0,get:function(){return n(a).default}});var u=t(\"./NineSlicePlane\");Object.defineProperty(r,\"NineSlicePlane\",{enumerable:!0,get:function(){return n(u).default}});var h=t(\"./Rope\");Object.defineProperty(r,\"Rope\",{enumerable:!0,get:function(){return n(h).default}})},{\"./Mesh\":166,\"./NineSlicePlane\":167,\"./Plane\":168,\"./Rope\":169,\"./canvas/CanvasMeshRenderer\":170,\"./webgl/MeshRenderer\":172}],172:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"../../core\"),u=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(a),h=t(\"pixi-gl-core\"),l=n(h),c=t(\"../Mesh\"),d=n(c),f=(t(\"path\"),u.Matrix.IDENTITY),p=function(t){function e(r){i(this,e);var n=o(this,t.call(this,r));return n.shader=null,n}return s(e,t),e.prototype.onContextChange=function(){var t=this.renderer.gl;this.shader=new u.Shader(t,\"attribute vec2 aVertexPosition;\\nattribute vec2 aTextureCoord;\\n\\nuniform mat3 projectionMatrix;\\nuniform mat3 translationMatrix;\\nuniform mat3 uTransform;\\n\\nvarying vec2 vTextureCoord;\\n\\nvoid main(void)\\n{\\n    gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\\n\\n    vTextureCoord = (uTransform * vec3(aTextureCoord, 1.0)).xy;\\n}\\n\",\"varying vec2 vTextureCoord;\\nuniform vec4 uColor;\\n\\nuniform sampler2D uSampler;\\n\\nvoid main(void)\\n{\\n    gl_FragColor = texture2D(uSampler, vTextureCoord) * uColor;\\n}\\n\")},e.prototype.render=function(t){var e=this.renderer,r=e.gl,n=t._texture;if(n.valid){var i=t._glDatas[e.CONTEXT_UID];i||(e.bindVao(null),i={shader:this.shader,vertexBuffer:l.default.GLBuffer.createVertexBuffer(r,t.vertices,r.STREAM_DRAW),uvBuffer:l.default.GLBuffer.createVertexBuffer(r,t.uvs,r.STREAM_DRAW),indexBuffer:l.default.GLBuffer.createIndexBuffer(r,t.indices,r.STATIC_DRAW),vao:null,dirty:t.dirty,indexDirty:t.indexDirty},i.vao=new l.default.VertexArrayObject(r).addIndex(i.indexBuffer).addAttribute(i.vertexBuffer,i.shader.attributes.aVertexPosition,r.FLOAT,!1,8,0).addAttribute(i.uvBuffer,i.shader.attributes.aTextureCoord,r.FLOAT,!1,8,0),t._glDatas[e.CONTEXT_UID]=i),e.bindVao(i.vao),t.dirty!==i.dirty&&(i.dirty=t.dirty,i.uvBuffer.upload(t.uvs)),t.indexDirty!==i.indexDirty&&(i.indexDirty=t.indexDirty,i.indexBuffer.upload(t.indices)),i.vertexBuffer.upload(t.vertices),e.bindShader(i.shader),i.shader.uniforms.uSampler=e.bindTexture(n),e.state.setBlendMode(u.utils.correctBlendMode(t.blendMode,n.baseTexture.premultipliedAlpha)),i.shader.uniforms.uTransform&&(t.uploadUvTransform?i.shader.uniforms.uTransform=t._uvTransform.mapCoord.toArray(!0):i.shader.uniforms.uTransform=f.toArray(!0)),i.shader.uniforms.translationMatrix=t.worldTransform.toArray(!0),i.shader.uniforms.uColor=u.utils.premultiplyRgba(t.tintRgb,t.worldAlpha,i.shader.uniforms.uColor,n.baseTexture.premultipliedAlpha);var o=t.drawMode===d.default.DRAW_MODES.TRIANGLE_MESH?r.TRIANGLE_STRIP:r.TRIANGLES;i.vao.draw(o,t.indices.length,0)}},e}(u.ObjectRenderer);r.default=p,u.WebGLRenderer.registerPlugin(\"mesh\",p)},{\"../../core\":65,\"../Mesh\":166,path:8,\"pixi-gl-core\":15}],173:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}(),a=t(\"../core\"),u=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(a),h=t(\"../core/utils\"),l=function(t){function e(){var r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1500,o=arguments[1],s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:16384,a=arguments.length>3&&void 0!==arguments[3]&&arguments[3];n(this,e);var h=i(this,t.call(this));return s>16384&&(s=16384),s>r&&(s=r),h._properties=[!1,!0,!1,!1,!1],h._maxSize=r,h._batchSize=s,h._glBuffers={},h._bufferToUpdate=0,h.interactiveChildren=!1,h.blendMode=u.BLEND_MODES.NORMAL,h.autoResize=a,h.roundPixels=!0,h.baseTexture=null,h.setProperties(o),h._tint=0,h.tintRgb=new Float32Array(4),h.tint=16777215,h}return o(e,t),e.prototype.setProperties=function(t){t&&(this._properties[0]=\"scale\"in t?!!t.scale:this._properties[0],this._properties[1]=\"position\"in t?!!t.position:this._properties[1],this._properties[2]=\"rotation\"in t?!!t.rotation:this._properties[2],this._properties[3]=\"uvs\"in t?!!t.uvs:this._properties[3],this._properties[4]=\"alpha\"in t||\"tint\"in t?!!t.alpha||!!t.tint:this._properties[4])},e.prototype.updateTransform=function(){this.displayObjectUpdateTransform()},e.prototype.renderWebGL=function(t){var e=this;this.visible&&!(this.worldAlpha<=0)&&this.children.length&&this.renderable&&(this.baseTexture||(this.baseTexture=this.children[0]._texture.baseTexture,this.baseTexture.hasLoaded||this.baseTexture.once(\"update\",function(){return e.onChildrenChange(0)})),t.setObjectRenderer(t.plugins.particle),t.plugins.particle.render(this))},e.prototype.onChildrenChange=function(t){var e=Math.floor(t/this._batchSize);e<this._bufferToUpdate&&(this._bufferToUpdate=e)},e.prototype.renderCanvas=function(t){if(this.visible&&!(this.worldAlpha<=0)&&this.children.length&&this.renderable){var e=t.context,r=this.worldTransform,n=!0,i=0,o=0,s=0,a=0;t.setBlendMode(this.blendMode),e.globalAlpha=this.worldAlpha,this.displayObjectUpdateTransform();for(var u=0;u<this.children.length;++u){var h=this.children[u];if(h.visible){var l=h._texture.frame;if(e.globalAlpha=this.worldAlpha*h.alpha,h.rotation%(2*Math.PI)==0)n&&(e.setTransform(r.a,r.b,r.c,r.d,r.tx*t.resolution,r.ty*t.resolution),n=!1),i=h.anchor.x*(-l.width*h.scale.x)+h.position.x+.5,o=h.anchor.y*(-l.height*h.scale.y)+h.position.y+.5,s=l.width*h.scale.x,a=l.height*h.scale.y;else{n||(n=!0),h.displayObjectUpdateTransform();var c=h.worldTransform;t.roundPixels?e.setTransform(c.a,c.b,c.c,c.d,c.tx*t.resolution|0,c.ty*t.resolution|0):e.setTransform(c.a,c.b,c.c,c.d,c.tx*t.resolution,c.ty*t.resolution),i=h.anchor.x*-l.width+.5,o=h.anchor.y*-l.height+.5,s=l.width,a=l.height}var d=h._texture.baseTexture.resolution;e.drawImage(h._texture.baseTexture.source,l.x*d,l.y*d,l.width*d,l.height*d,i*t.resolution,o*t.resolution,s*t.resolution,a*t.resolution)}}}},e.prototype.destroy=function(e){if(t.prototype.destroy.call(this,e),this._buffers)for(var r=0;r<this._buffers.length;++r)this._buffers[r].destroy();this._properties=null,this._buffers=null},s(e,[{key:\"tint\",get:function(){return this._tint},set:function(t){this._tint=t,(0,h.hex2rgb)(t,this.tintRgb)}}]),e}(u.Container);r.default=l},{\"../core\":65,\"../core/utils\":124}],174:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0;var i=t(\"./ParticleContainer\");Object.defineProperty(r,\"ParticleContainer\",{enumerable:!0,get:function(){return n(i).default}});var o=t(\"./webgl/ParticleRenderer\");Object.defineProperty(r,\"ParticleRenderer\",{enumerable:!0,get:function(){return n(o).default}})},{\"./ParticleContainer\":173,\"./webgl/ParticleRenderer\":176}],175:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var o=t(\"pixi-gl-core\"),s=n(o),a=t(\"../../core/utils/createIndicesForQuads\"),u=n(a),h=function(){function t(e,r,n,o){i(this,t),this.gl=e,this.size=o,this.dynamicProperties=[],this.staticProperties=[];for(var s=0;s<r.length;++s){var a=r[s];a={attribute:a.attribute,size:a.size,uploadFunction:a.uploadFunction,unsignedByte:a.unsignedByte,offset:a.offset},n[s]?this.dynamicProperties.push(a):this.staticProperties.push(a)}this.staticStride=0,this.staticBuffer=null,this.staticData=null,this.staticDataUint32=null,this.dynamicStride=0,this.dynamicBuffer=null,this.dynamicData=null,this.dynamicDataUint32=null,this.initBuffers()}return t.prototype.initBuffers=function(){var t=this.gl,e=0;this.indices=(0,u.default)(this.size),this.indexBuffer=s.default.GLBuffer.createIndexBuffer(t,this.indices,t.STATIC_DRAW),this.dynamicStride=0;for(var r=0;r<this.dynamicProperties.length;++r){var n=this.dynamicProperties[r];n.offset=e,e+=n.size,this.dynamicStride+=n.size}var i=new ArrayBuffer(this.size*this.dynamicStride*4*4);this.dynamicData=new Float32Array(i),this.dynamicDataUint32=new Uint32Array(i),this.dynamicBuffer=s.default.GLBuffer.createVertexBuffer(t,i,t.STREAM_DRAW);var o=0;this.staticStride=0;for(var a=0;a<this.staticProperties.length;++a){var h=this.staticProperties[a];h.offset=o,o+=h.size,this.staticStride+=h.size}var l=new ArrayBuffer(this.size*this.staticStride*4*4);this.staticData=new Float32Array(l),this.staticDataUint32=new Uint32Array(l),this.staticBuffer=s.default.GLBuffer.createVertexBuffer(t,l,t.STATIC_DRAW),this.vao=new s.default.VertexArrayObject(t).addIndex(this.indexBuffer);for(var c=0;c<this.dynamicProperties.length;++c){var d=this.dynamicProperties[c];d.unsignedByte?this.vao.addAttribute(this.dynamicBuffer,d.attribute,t.UNSIGNED_BYTE,!0,4*this.dynamicStride,4*d.offset):this.vao.addAttribute(this.dynamicBuffer,d.attribute,t.FLOAT,!1,4*this.dynamicStride,4*d.offset)}for(var f=0;f<this.staticProperties.length;++f){var p=this.staticProperties[f];p.unsignedByte?this.vao.addAttribute(this.staticBuffer,p.attribute,t.UNSIGNED_BYTE,!0,4*this.staticStride,4*p.offset):this.vao.addAttribute(this.staticBuffer,p.attribute,t.FLOAT,!1,4*this.staticStride,4*p.offset)}},t.prototype.uploadDynamic=function(t,e,r){for(var n=0;n<this.dynamicProperties.length;n++){var i=this.dynamicProperties[n];i.uploadFunction(t,e,r,i.unsignedByte?this.dynamicDataUint32:this.dynamicData,this.dynamicStride,i.offset)}this.dynamicBuffer.upload()},t.prototype.uploadStatic=function(t,e,r){for(var n=0;n<this.staticProperties.length;n++){var i=this.staticProperties[n];i.uploadFunction(t,e,r,i.unsignedByte?this.staticDataUint32:this.staticData,this.staticStride,i.offset)}this.staticBuffer.upload()},t.prototype.destroy=function(){this.dynamicProperties=null,this.dynamicData=null,this.dynamicBuffer.destroy(),this.staticProperties=null,this.staticData=null,this.staticBuffer.destroy()},t}();r.default=h},{\"../../core/utils/createIndicesForQuads\":122,\"pixi-gl-core\":15}],176:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}function i(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function o(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function s(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var a=t(\"../../core\"),u=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(a),h=t(\"./ParticleShader\"),l=n(h),c=t(\"./ParticleBuffer\"),d=n(c),f=t(\"../../core/utils\"),p=function(t){function e(r){i(this,e);var n=o(this,t.call(this,r));return n.shader=null,n.indexBuffer=null,n.properties=null,n.tempMatrix=new u.Matrix,n.CONTEXT_UID=0,n}return s(e,t),e.prototype.onContextChange=function(){var t=this.renderer.gl;this.CONTEXT_UID=this.renderer.CONTEXT_UID,this.shader=new l.default(t),this.properties=[{attribute:this.shader.attributes.aVertexPosition,size:2,uploadFunction:this.uploadVertices,offset:0},{attribute:this.shader.attributes.aPositionCoord,size:2,uploadFunction:this.uploadPosition,offset:0},{attribute:this.shader.attributes.aRotation,size:1,uploadFunction:this.uploadRotation,offset:0},{attribute:this.shader.attributes.aTextureCoord,size:2,uploadFunction:this.uploadUvs,offset:0},{attribute:this.shader.attributes.aColor,size:1,unsignedByte:!0,uploadFunction:this.uploadTint,offset:0}]},e.prototype.start=function(){this.renderer.bindShader(this.shader)},e.prototype.render=function(t){var e=t.children,r=t._maxSize,n=t._batchSize,i=this.renderer,o=e.length;if(0!==o){o>r&&(o=r);var s=t._glBuffers[i.CONTEXT_UID];s||(s=t._glBuffers[i.CONTEXT_UID]=this.generateBuffers(t));var a=e[0]._texture.baseTexture;this.renderer.setBlendMode(u.utils.correctBlendMode(t.blendMode,a.premultipliedAlpha));var h=i.gl,l=t.worldTransform.copy(this.tempMatrix);l.prepend(i._activeRenderTarget.projectionMatrix),this.shader.uniforms.projectionMatrix=l.toArray(!0),this.shader.uniforms.uColor=u.utils.premultiplyRgba(t.tintRgb,t.worldAlpha,this.shader.uniforms.uColor,a.premultipliedAlpha),this.shader.uniforms.uSampler=i.bindTexture(a);for(var c=0,d=0;c<o;c+=n,d+=1){var f=o-c;if(f>n&&(f=n),d>=s.length){if(!t.autoResize)break;s.push(this._generateOneMoreBuffer(t))}var p=s[d];p.uploadDynamic(e,c,f),t._bufferToUpdate===d&&(p.uploadStatic(e,c,f),t._bufferToUpdate=d+1),i.bindVao(p.vao),p.vao.draw(h.TRIANGLES,6*f)}}},e.prototype.generateBuffers=function(t){for(var e=this.renderer.gl,r=[],n=t._maxSize,i=t._batchSize,o=t._properties,s=0;s<n;s+=i)r.push(new d.default(e,this.properties,o,i));return r},e.prototype._generateOneMoreBuffer=function(t){var e=this.renderer.gl,r=t._batchSize,n=t._properties;return new d.default(e,this.properties,n,r)},e.prototype.uploadVertices=function(t,e,r,n,i,o){for(var s=0,a=0,u=0,h=0,l=0;l<r;++l){var c=t[e+l],d=c._texture,f=c.scale.x,p=c.scale.y,v=d.trim,y=d.orig;v?(a=v.x-c.anchor.x*y.width,s=a+v.width,h=v.y-c.anchor.y*y.height,u=h+v.height):(s=y.width*(1-c.anchor.x),a=y.width*-c.anchor.x,u=y.height*(1-c.anchor.y),h=y.height*-c.anchor.y),n[o]=a*f,n[o+1]=h*p,n[o+i]=s*f,n[o+i+1]=h*p,n[o+2*i]=s*f,n[o+2*i+1]=u*p,n[o+3*i]=a*f,n[o+3*i+1]=u*p,o+=4*i}},e.prototype.uploadPosition=function(t,e,r,n,i,o){for(var s=0;s<r;s++){var a=t[e+s].position;n[o]=a.x,n[o+1]=a.y,n[o+i]=a.x,n[o+i+1]=a.y,n[o+2*i]=a.x,n[o+2*i+1]=a.y,n[o+3*i]=a.x,n[o+3*i+1]=a.y,o+=4*i}},e.prototype.uploadRotation=function(t,e,r,n,i,o){for(var s=0;s<r;s++){var a=t[e+s].rotation;n[o]=a,n[o+i]=a,n[o+2*i]=a,n[o+3*i]=a,o+=4*i}},e.prototype.uploadUvs=function(t,e,r,n,i,o){for(var s=0;s<r;++s){var a=t[e+s]._texture._uvs;a?(n[o]=a.x0,n[o+1]=a.y0,n[o+i]=a.x1,n[o+i+1]=a.y1,n[o+2*i]=a.x2,n[o+2*i+1]=a.y2,n[o+3*i]=a.x3,n[o+3*i+1]=a.y3,o+=4*i):(n[o]=0,n[o+1]=0,n[o+i]=0,n[o+i+1]=0,n[o+2*i]=0,n[o+2*i+1]=0,n[o+3*i]=0,n[o+3*i+1]=0,o+=4*i)}},e.prototype.uploadTint=function(t,e,r,n,i,o){for(var s=0;s<r;++s){var a=t[e+s],u=a._texture.baseTexture.premultipliedAlpha,h=a.alpha,l=h<1&&u?(0,f.premultiplyTint)(a._tintRGB,h):a._tintRGB+(255*h<<24);n[o]=l,n[o+i]=l,n[o+2*i]=l,n[o+3*i]=l,o+=4*i}},e.prototype.destroy=function(){this.renderer.gl&&this.renderer.gl.deleteBuffer(this.indexBuffer),t.prototype.destroy.call(this),this.shader.destroy(),this.indices=null,this.tempMatrix=null},e}(u.ObjectRenderer);r.default=p,u.WebGLRenderer.registerPlugin(\"particle\",p)},{\"../../core\":65,\"../../core/utils\":124,\"./ParticleBuffer\":175,\"./ParticleShader\":177}],177:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}r.__esModule=!0;var s=t(\"../../core/Shader\"),a=function(t){return t&&t.__esModule?t:{default:t}}(s),u=function(t){function e(r){return n(this,e),i(this,t.call(this,r,[\"attribute vec2 aVertexPosition;\",\"attribute vec2 aTextureCoord;\",\"attribute vec4 aColor;\",\"attribute vec2 aPositionCoord;\",\"attribute vec2 aScale;\",\"attribute float aRotation;\",\"uniform mat3 projectionMatrix;\",\"uniform vec4 uColor;\",\"varying vec2 vTextureCoord;\",\"varying vec4 vColor;\",\"void main(void){\",\"   vec2 v = aVertexPosition;\",\"   v.x = (aVertexPosition.x) * cos(aRotation) - (aVertexPosition.y) * sin(aRotation);\",\"   v.y = (aVertexPosition.x) * sin(aRotation) + (aVertexPosition.y) * cos(aRotation);\",\"   v = v + aPositionCoord;\",\"   gl_Position = vec4((projectionMatrix * vec3(v, 1.0)).xy, 0.0, 1.0);\",\"   vTextureCoord = aTextureCoord;\",\"   vColor = aColor * uColor;\",\"}\"].join(\"\\n\"),[\"varying vec2 vTextureCoord;\",\"varying vec4 vColor;\",\"uniform sampler2D uSampler;\",\"void main(void){\",\"  vec4 color = texture2D(uSampler, vTextureCoord) * vColor;\",\"  if (color.a == 0.0) discard;\",\"  gl_FragColor = color;\",\"}\"].join(\"\\n\")))}return o(e,t),e}(a.default);r.default=u},{\"../../core/Shader\":44}],178:[function(t,e,r){\"use strict\";Math.sign||(Math.sign=function(t){return t=Number(t),0===t||isNaN(t)?t:t>0?1:-1})},{}],179:[function(t,e,r){\"use strict\";var n=t(\"object-assign\"),i=function(t){return t&&t.__esModule?t:{default:t}}(n);Object.assign||(Object.assign=i.default)},{\"object-assign\":6}],180:[function(t,e,r){\"use strict\";t(\"./Object.assign\"),t(\"./requestAnimationFrame\"),t(\"./Math.sign\"),window.ArrayBuffer||(window.ArrayBuffer=Array),window.Float32Array||(window.Float32Array=Array),window.Uint32Array||(window.Uint32Array=Array),window.Uint16Array||(window.Uint16Array=Array)},{\"./Math.sign\":178,\"./Object.assign\":179,\"./requestAnimationFrame\":181}],181:[function(t,e,r){(function(t){\"use strict\";if(Date.now&&Date.prototype.getTime||(Date.now=function(){return(new Date).getTime()}),!t.performance||!t.performance.now){var e=Date.now();t.performance||(t.performance={}),t.performance.now=function(){return Date.now()-e}}for(var r=Date.now(),n=[\"ms\",\"moz\",\"webkit\",\"o\"],i=0;i<n.length&&!t.requestAnimationFrame;++i){var o=n[i];t.requestAnimationFrame=t[o+\"RequestAnimationFrame\"],t.cancelAnimationFrame=t[o+\"CancelAnimationFrame\"]||t[o+\"CancelRequestAnimationFrame\"]}t.requestAnimationFrame||(t.requestAnimationFrame=function(t){if(\"function\"!=typeof t)throw new TypeError(t+\"is not a function\");var e=Date.now(),n=16+r-e;return n<0&&(n=0),r=e,setTimeout(function(){r=Date.now(),t(performance.now())},n)}),t.cancelAnimationFrame||(t.cancelAnimationFrame=function(t){return clearTimeout(t)})}).call(this,\"undefined\"!=typeof global?global:\"undefined\"!=typeof self?self:\"undefined\"!=typeof window?window:{})},{}],182:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){var r=!1;if(t&&t._textures&&t._textures.length)for(var n=0;n<t._textures.length;n++)if(t._textures[n]instanceof d.Texture){var i=t._textures[n].baseTexture;-1===e.indexOf(i)&&(e.push(i),r=!0)}return r}function o(t,e){return t instanceof d.BaseTexture&&(-1===e.indexOf(t)&&e.push(t),!0)}function s(t,e){if(t._texture&&t._texture instanceof d.Texture){var r=t._texture.baseTexture;return-1===e.indexOf(r)&&e.push(r),!0}return!1}function a(t,e){return e instanceof d.Text&&(e.updateText(!0),!0)}function u(t,e){if(e instanceof d.TextStyle){var r=e.toFontString();return d.TextMetrics.measureFont(r),!0}return!1}function h(t,e){if(t instanceof d.Text){-1===e.indexOf(t.style)&&e.push(t.style),-1===e.indexOf(t)&&e.push(t);var r=t._texture.baseTexture;return-1===e.indexOf(r)&&e.push(r),!0}return!1}function l(t,e){return t instanceof d.TextStyle&&(-1===e.indexOf(t)&&e.push(t),!0)}r.__esModule=!0;var c=t(\"../core\"),d=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(c),f=t(\"./limiters/CountLimiter\"),p=function(t){return t&&t.__esModule?t:{default:t}}(f),v=d.ticker.shared;d.settings.UPLOADS_PER_FRAME=4;var y=function(){function t(e){var r=this;n(this,t),this.limiter=new p.default(d.settings.UPLOADS_PER_FRAME),this.renderer=e,this.uploadHookHelper=null,this.queue=[],this.addHooks=[],this.uploadHooks=[],this.completes=[],this.ticking=!1,this.delayedTick=function(){r.queue&&r.prepareItems()},this.registerFindHook(h),this.registerFindHook(l),this.registerFindHook(i),this.registerFindHook(o),this.registerFindHook(s),this.registerUploadHook(a),this.registerUploadHook(u)}return t.prototype.upload=function(t,e){\"function\"==typeof t&&(e=t,t=null),t&&this.add(t),this.queue.length?(e&&this.completes.push(e),this.ticking||(this.ticking=!0,v.addOnce(this.tick,this,d.UPDATE_PRIORITY.UTILITY))):e&&e()},t.prototype.tick=function(){setTimeout(this.delayedTick,0)},t.prototype.prepareItems=function(){for(this.limiter.beginFrame();this.queue.length&&this.limiter.allowedToUpload();){var t=this.queue[0],e=!1;if(t&&!t._destroyed)for(var r=0,n=this.uploadHooks.length;r<n;r++)if(this.uploadHooks[r](this.uploadHookHelper,t)){this.queue.shift(),e=!0;break}e||this.queue.shift()}if(this.queue.length)v.addOnce(this.tick,this,d.UPDATE_PRIORITY.UTILITY);else{this.ticking=!1;var i=this.completes.slice(0);this.completes.length=0;for(var o=0,s=i.length;o<s;o++)i[o]()}},t.prototype.registerFindHook=function(t){return t&&this.addHooks.push(t),this},t.prototype.registerUploadHook=function(t){return t&&this.uploadHooks.push(t),this},t.prototype.add=function(t){for(var e=0,r=this.addHooks.length;e<r&&!this.addHooks[e](t,this.queue);e++);if(t instanceof d.Container)for(var n=t.children.length-1;n>=0;n--)this.add(t.children[n]);return this},t.prototype.destroy=function(){this.ticking&&v.remove(this.tick,this),this.ticking=!1,this.addHooks=null,\nthis.uploadHooks=null,this.renderer=null,this.completes=null,this.queue=null,this.limiter=null,this.uploadHookHelper=null},t}();r.default=y},{\"../core\":65,\"./limiters/CountLimiter\":185}],183:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function s(t,e){if(e instanceof u.BaseTexture){var r=e.source,n=0===r.width?t.canvas.width:Math.min(t.canvas.width,r.width),i=0===r.height?t.canvas.height:Math.min(t.canvas.height,r.height);return t.ctx.drawImage(r,0,0,n,i,0,0,t.canvas.width,t.canvas.height),!0}return!1}r.__esModule=!0;var a=t(\"../../core\"),u=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(a),h=t(\"../BasePrepare\"),l=function(t){return t&&t.__esModule?t:{default:t}}(h),c=16,d=function(t){function e(r){n(this,e);var o=i(this,t.call(this,r));return o.uploadHookHelper=o,o.canvas=document.createElement(\"canvas\"),o.canvas.width=c,o.canvas.height=c,o.ctx=o.canvas.getContext(\"2d\"),o.registerUploadHook(s),o}return o(e,t),e.prototype.destroy=function(){t.prototype.destroy.call(this),this.ctx=null,this.canvas=null},e}(l.default);r.default=d,u.CanvasRenderer.registerPlugin(\"prepare\",d)},{\"../../core\":65,\"../BasePrepare\":182}],184:[function(t,e,r){\"use strict\";function n(t){return t&&t.__esModule?t:{default:t}}r.__esModule=!0;var i=t(\"./webgl/WebGLPrepare\");Object.defineProperty(r,\"webgl\",{enumerable:!0,get:function(){return n(i).default}});var o=t(\"./canvas/CanvasPrepare\");Object.defineProperty(r,\"canvas\",{enumerable:!0,get:function(){return n(o).default}});var s=t(\"./BasePrepare\");Object.defineProperty(r,\"BasePrepare\",{enumerable:!0,get:function(){return n(s).default}});var a=t(\"./limiters/CountLimiter\");Object.defineProperty(r,\"CountLimiter\",{enumerable:!0,get:function(){return n(a).default}});var u=t(\"./limiters/TimeLimiter\");Object.defineProperty(r,\"TimeLimiter\",{enumerable:!0,get:function(){return n(u).default}})},{\"./BasePrepare\":182,\"./canvas/CanvasPrepare\":183,\"./limiters/CountLimiter\":185,\"./limiters/TimeLimiter\":186,\"./webgl/WebGLPrepare\":187}],185:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(e){n(this,t),this.maxItemsPerFrame=e,this.itemsLeft=0}return t.prototype.beginFrame=function(){this.itemsLeft=this.maxItemsPerFrame},t.prototype.allowedToUpload=function(){return this.itemsLeft-- >0},t}();r.default=i},{}],186:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}r.__esModule=!0;var i=function(){function t(e){n(this,t),this.maxMilliseconds=e,this.frameStart=0}return t.prototype.beginFrame=function(){this.frameStart=Date.now()},t.prototype.allowedToUpload=function(){return Date.now()-this.frameStart<this.maxMilliseconds},t}();r.default=i},{}],187:[function(t,e,r){\"use strict\";function n(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function i(t,e){if(!t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!e||\"object\"!=typeof e&&\"function\"!=typeof e?t:e}function o(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function s(t,e){return e instanceof l.BaseTexture&&(e._glTextures[t.CONTEXT_UID]||t.textureManager.updateTexture(e),!0)}function a(t,e){return e instanceof l.Graphics&&((e.dirty||e.clearDirty||!e._webGL[t.plugins.graphics.CONTEXT_UID])&&t.plugins.graphics.updateGraphics(e),!0)}function u(t,e){return t instanceof l.Graphics&&(e.push(t),!0)}r.__esModule=!0;var h=t(\"../../core\"),l=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}(h),c=t(\"../BasePrepare\"),d=function(t){return t&&t.__esModule?t:{default:t}}(c),f=function(t){function e(r){n(this,e);var o=i(this,t.call(this,r));return o.uploadHookHelper=o.renderer,o.registerFindHook(u),o.registerUploadHook(s),o.registerUploadHook(a),o}return o(e,t),e}(d.default);r.default=f,l.WebGLRenderer.registerPlugin(\"prepare\",f)},{\"../../core\":65,\"../BasePrepare\":182}],188:[function(t,e,r){(function(e){\"use strict\";function n(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e.default=t,e}r.__esModule=!0,r.loader=r.prepare=r.particles=r.mesh=r.loaders=r.interaction=r.filters=r.extras=r.extract=r.accessibility=void 0;var i=t(\"./polyfill\");Object.keys(i).forEach(function(t){\"default\"!==t&&\"__esModule\"!==t&&Object.defineProperty(r,t,{enumerable:!0,get:function(){return i[t]}})});var o=t(\"./core\");Object.keys(o).forEach(function(t){\"default\"!==t&&\"__esModule\"!==t&&Object.defineProperty(r,t,{enumerable:!0,get:function(){return o[t]}})});var s=t(\"./deprecation\"),a=function(t){return t&&t.__esModule?t:{default:t}}(s),u=t(\"./accessibility\"),h=n(u),l=t(\"./extract\"),c=n(l),d=t(\"./extras\"),f=n(d),p=t(\"./filters\"),v=n(p),y=t(\"./interaction\"),g=n(y),m=t(\"./loaders\"),_=n(m),b=t(\"./mesh\"),x=n(b),T=t(\"./particles\"),w=n(T),E=t(\"./prepare\"),S=n(E);o.utils.mixins.performMixins();var O=_.shared||null;r.accessibility=h,r.extract=c,r.extras=f,r.filters=v,r.interaction=g,r.loaders=_,r.mesh=x,r.particles=w,r.prepare=S,r.loader=O,\"function\"==typeof a.default&&(0,a.default)(r),e.PIXI=r}).call(this,\"undefined\"!=typeof global?global:\"undefined\"!=typeof self?self:\"undefined\"!=typeof window?window:{})},{\"./accessibility\":42,\"./core\":65,\"./deprecation\":130,\"./extract\":132,\"./extras\":141,\"./filters\":152,\"./interaction\":159,\"./loaders\":162,\"./mesh\":171,\"./particles\":174,\"./polyfill\":180,\"./prepare\":184}]},{},[188])(188)});\n//# sourceMappingURL=pixi.min.js.map\n</script>\n<script>/*\n * Copyright 2016 Small Batch, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * use this file except in compliance with the License. You may obtain a copy of\n * the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations under\n * the License.\n */\n/* Web Font Loader v1.6.26 - (c) Adobe Systems, Google. License: Apache 2.0 */(function(){function aa(a,b,c){return a.call.apply(a.bind,arguments)}function ba(a,b,c){if(!a)throw Error();if(2<arguments.length){var d=Array.prototype.slice.call(arguments,2);return function(){var c=Array.prototype.slice.call(arguments);Array.prototype.unshift.apply(c,d);return a.apply(b,c)}}return function(){return a.apply(b,arguments)}}function p(a,b,c){p=Function.prototype.bind&&-1!=Function.prototype.bind.toString().indexOf(\"native code\")?aa:ba;return p.apply(null,arguments)}var q=Date.now||function(){return+new Date};function ca(a,b){this.a=a;this.m=b||a;this.c=this.m.document}var da=!!window.FontFace;function t(a,b,c,d){b=a.c.createElement(b);if(c)for(var e in c)c.hasOwnProperty(e)&&(\"style\"==e?b.style.cssText=c[e]:b.setAttribute(e,c[e]));d&&b.appendChild(a.c.createTextNode(d));return b}function u(a,b,c){a=a.c.getElementsByTagName(b)[0];a||(a=document.documentElement);a.insertBefore(c,a.lastChild)}function v(a){a.parentNode&&a.parentNode.removeChild(a)}\nfunction w(a,b,c){b=b||[];c=c||[];for(var d=a.className.split(/\\s+/),e=0;e<b.length;e+=1){for(var f=!1,g=0;g<d.length;g+=1)if(b[e]===d[g]){f=!0;break}f||d.push(b[e])}b=[];for(e=0;e<d.length;e+=1){f=!1;for(g=0;g<c.length;g+=1)if(d[e]===c[g]){f=!0;break}f||b.push(d[e])}a.className=b.join(\" \").replace(/\\s+/g,\" \").replace(/^\\s+|\\s+$/,\"\")}function y(a,b){for(var c=a.className.split(/\\s+/),d=0,e=c.length;d<e;d++)if(c[d]==b)return!0;return!1}\nfunction z(a){if(\"string\"===typeof a.f)return a.f;var b=a.m.location.protocol;\"about:\"==b&&(b=a.a.location.protocol);return\"https:\"==b?\"https:\":\"http:\"}function ea(a){return a.m.location.hostname||a.a.location.hostname}\nfunction A(a,b,c){function d(){k&&e&&f&&(k(g),k=null)}b=t(a,\"link\",{rel:\"stylesheet\",href:b,media:\"all\"});var e=!1,f=!0,g=null,k=c||null;da?(b.onload=function(){e=!0;d()},b.onerror=function(){e=!0;g=Error(\"Stylesheet failed to load\");d()}):setTimeout(function(){e=!0;d()},0);u(a,\"head\",b)}\nfunction B(a,b,c,d){var e=a.c.getElementsByTagName(\"head\")[0];if(e){var f=t(a,\"script\",{src:b}),g=!1;f.onload=f.onreadystatechange=function(){g||this.readyState&&\"loaded\"!=this.readyState&&\"complete\"!=this.readyState||(g=!0,c&&c(null),f.onload=f.onreadystatechange=null,\"HEAD\"==f.parentNode.tagName&&e.removeChild(f))};e.appendChild(f);setTimeout(function(){g||(g=!0,c&&c(Error(\"Script load timeout\")))},d||5E3);return f}return null};function C(){this.a=0;this.c=null}function D(a){a.a++;return function(){a.a--;E(a)}}function F(a,b){a.c=b;E(a)}function E(a){0==a.a&&a.c&&(a.c(),a.c=null)};function G(a){this.a=a||\"-\"}G.prototype.c=function(a){for(var b=[],c=0;c<arguments.length;c++)b.push(arguments[c].replace(/[\\W_]+/g,\"\").toLowerCase());return b.join(this.a)};function H(a,b){this.c=a;this.f=4;this.a=\"n\";var c=(b||\"n4\").match(/^([nio])([1-9])$/i);c&&(this.a=c[1],this.f=parseInt(c[2],10))}function fa(a){return I(a)+\" \"+(a.f+\"00\")+\" 300px \"+J(a.c)}function J(a){var b=[];a=a.split(/,\\s*/);for(var c=0;c<a.length;c++){var d=a[c].replace(/['\"]/g,\"\");-1!=d.indexOf(\" \")||/^\\d/.test(d)?b.push(\"'\"+d+\"'\"):b.push(d)}return b.join(\",\")}function K(a){return a.a+a.f}function I(a){var b=\"normal\";\"o\"===a.a?b=\"oblique\":\"i\"===a.a&&(b=\"italic\");return b}\nfunction ga(a){var b=4,c=\"n\",d=null;a&&((d=a.match(/(normal|oblique|italic)/i))&&d[1]&&(c=d[1].substr(0,1).toLowerCase()),(d=a.match(/([1-9]00|normal|bold)/i))&&d[1]&&(/bold/i.test(d[1])?b=7:/[1-9]00/.test(d[1])&&(b=parseInt(d[1].substr(0,1),10))));return c+b};function ha(a,b){this.c=a;this.f=a.m.document.documentElement;this.h=b;this.a=new G(\"-\");this.j=!1!==b.events;this.g=!1!==b.classes}function ia(a){a.g&&w(a.f,[a.a.c(\"wf\",\"loading\")]);L(a,\"loading\")}function M(a){if(a.g){var b=y(a.f,a.a.c(\"wf\",\"active\")),c=[],d=[a.a.c(\"wf\",\"loading\")];b||c.push(a.a.c(\"wf\",\"inactive\"));w(a.f,c,d)}L(a,\"inactive\")}function L(a,b,c){if(a.j&&a.h[b])if(c)a.h[b](c.c,K(c));else a.h[b]()};function ja(){this.c={}}function ka(a,b,c){var d=[],e;for(e in b)if(b.hasOwnProperty(e)){var f=a.c[e];f&&d.push(f(b[e],c))}return d};function N(a,b){this.c=a;this.f=b;this.a=t(this.c,\"span\",{\"aria-hidden\":\"true\"},this.f)}function O(a){u(a.c,\"body\",a.a)}function P(a){return\"display:block;position:absolute;top:-9999px;left:-9999px;font-size:300px;width:auto;height:auto;line-height:normal;margin:0;padding:0;font-variant:normal;white-space:nowrap;font-family:\"+J(a.c)+\";\"+(\"font-style:\"+I(a)+\";font-weight:\"+(a.f+\"00\")+\";\")};function Q(a,b,c,d,e,f){this.g=a;this.j=b;this.a=d;this.c=c;this.f=e||3E3;this.h=f||void 0}Q.prototype.start=function(){var a=this.c.m.document,b=this,c=q(),d=new Promise(function(d,e){function k(){q()-c>=b.f?e():a.fonts.load(fa(b.a),b.h).then(function(a){1<=a.length?d():setTimeout(k,25)},function(){e()})}k()}),e=new Promise(function(a,d){setTimeout(d,b.f)});Promise.race([e,d]).then(function(){b.g(b.a)},function(){b.j(b.a)})};function R(a,b,c,d,e,f,g){this.v=a;this.B=b;this.c=c;this.a=d;this.s=g||\"BESbswy\";this.f={};this.w=e||3E3;this.u=f||null;this.o=this.j=this.h=this.g=null;this.g=new N(this.c,this.s);this.h=new N(this.c,this.s);this.j=new N(this.c,this.s);this.o=new N(this.c,this.s);a=new H(this.a.c+\",serif\",K(this.a));a=P(a);this.g.a.style.cssText=a;a=new H(this.a.c+\",sans-serif\",K(this.a));a=P(a);this.h.a.style.cssText=a;a=new H(\"serif\",K(this.a));a=P(a);this.j.a.style.cssText=a;a=new H(\"sans-serif\",K(this.a));a=\nP(a);this.o.a.style.cssText=a;O(this.g);O(this.h);O(this.j);O(this.o)}var S={D:\"serif\",C:\"sans-serif\"},T=null;function U(){if(null===T){var a=/AppleWebKit\\/([0-9]+)(?:\\.([0-9]+))/.exec(window.navigator.userAgent);T=!!a&&(536>parseInt(a[1],10)||536===parseInt(a[1],10)&&11>=parseInt(a[2],10))}return T}R.prototype.start=function(){this.f.serif=this.j.a.offsetWidth;this.f[\"sans-serif\"]=this.o.a.offsetWidth;this.A=q();la(this)};\nfunction ma(a,b,c){for(var d in S)if(S.hasOwnProperty(d)&&b===a.f[S[d]]&&c===a.f[S[d]])return!0;return!1}function la(a){var b=a.g.a.offsetWidth,c=a.h.a.offsetWidth,d;(d=b===a.f.serif&&c===a.f[\"sans-serif\"])||(d=U()&&ma(a,b,c));d?q()-a.A>=a.w?U()&&ma(a,b,c)&&(null===a.u||a.u.hasOwnProperty(a.a.c))?V(a,a.v):V(a,a.B):na(a):V(a,a.v)}function na(a){setTimeout(p(function(){la(this)},a),50)}function V(a,b){setTimeout(p(function(){v(this.g.a);v(this.h.a);v(this.j.a);v(this.o.a);b(this.a)},a),0)};function W(a,b,c){this.c=a;this.a=b;this.f=0;this.o=this.j=!1;this.s=c}var X=null;W.prototype.g=function(a){var b=this.a;b.g&&w(b.f,[b.a.c(\"wf\",a.c,K(a).toString(),\"active\")],[b.a.c(\"wf\",a.c,K(a).toString(),\"loading\"),b.a.c(\"wf\",a.c,K(a).toString(),\"inactive\")]);L(b,\"fontactive\",a);this.o=!0;oa(this)};\nW.prototype.h=function(a){var b=this.a;if(b.g){var c=y(b.f,b.a.c(\"wf\",a.c,K(a).toString(),\"active\")),d=[],e=[b.a.c(\"wf\",a.c,K(a).toString(),\"loading\")];c||d.push(b.a.c(\"wf\",a.c,K(a).toString(),\"inactive\"));w(b.f,d,e)}L(b,\"fontinactive\",a);oa(this)};function oa(a){0==--a.f&&a.j&&(a.o?(a=a.a,a.g&&w(a.f,[a.a.c(\"wf\",\"active\")],[a.a.c(\"wf\",\"loading\"),a.a.c(\"wf\",\"inactive\")]),L(a,\"active\")):M(a.a))};function pa(a){this.j=a;this.a=new ja;this.h=0;this.f=this.g=!0}pa.prototype.load=function(a){this.c=new ca(this.j,a.context||this.j);this.g=!1!==a.events;this.f=!1!==a.classes;qa(this,new ha(this.c,a),a)};\nfunction ra(a,b,c,d,e){var f=0==--a.h;(a.f||a.g)&&setTimeout(function(){var a=e||null,k=d||null||{};if(0===c.length&&f)M(b.a);else{b.f+=c.length;f&&(b.j=f);var h,m=[];for(h=0;h<c.length;h++){var l=c[h],n=k[l.c],r=b.a,x=l;r.g&&w(r.f,[r.a.c(\"wf\",x.c,K(x).toString(),\"loading\")]);L(r,\"fontloading\",x);r=null;null===X&&(X=window.FontFace?(x=/Gecko.*Firefox\\/(\\d+)/.exec(window.navigator.userAgent))?42<parseInt(x[1],10):!0:!1);X?r=new Q(p(b.g,b),p(b.h,b),b.c,l,b.s,n):r=new R(p(b.g,b),p(b.h,b),b.c,l,b.s,a,\nn);m.push(r)}for(h=0;h<m.length;h++)m[h].start()}},0)}function qa(a,b,c){var d=[],e=c.timeout;ia(b);var d=ka(a.a,c,a.c),f=new W(a.c,b,e);a.h=d.length;b=0;for(c=d.length;b<c;b++)d[b].load(function(b,d,c){ra(a,f,b,d,c)})};function sa(a,b){this.c=a;this.a=b}function ta(a,b,c){var d=z(a.c);a=(a.a.api||\"fast.fonts.net/jsapi\").replace(/^.*http(s?):(\\/\\/)?/,\"\");return d+\"//\"+a+\"/\"+b+\".js\"+(c?\"?v=\"+c:\"\")}\nsa.prototype.load=function(a){function b(){if(f[\"__mti_fntLst\"+d]){var c=f[\"__mti_fntLst\"+d](),e=[],h;if(c)for(var m=0;m<c.length;m++){var l=c[m].fontfamily;void 0!=c[m].fontStyle&&void 0!=c[m].fontWeight?(h=c[m].fontStyle+c[m].fontWeight,e.push(new H(l,h))):e.push(new H(l))}a(e)}else setTimeout(function(){b()},50)}var c=this,d=c.a.projectId,e=c.a.version;if(d){var f=c.c.m;B(this.c,ta(c,d,e),function(e){e?a([]):(f[\"__MonotypeConfiguration__\"+d]=function(){return c.a},b())}).id=\"__MonotypeAPIScript__\"+\nd}else a([])};function ua(a,b){this.c=a;this.a=b}ua.prototype.load=function(a){var b,c,d=this.a.urls||[],e=this.a.families||[],f=this.a.testStrings||{},g=new C;b=0;for(c=d.length;b<c;b++)A(this.c,d[b],D(g));var k=[];b=0;for(c=e.length;b<c;b++)if(d=e[b].split(\":\"),d[1])for(var h=d[1].split(\",\"),m=0;m<h.length;m+=1)k.push(new H(d[0],h[m]));else k.push(new H(d[0]));F(g,function(){a(k,f)})};function va(a,b,c){a?this.c=a:this.c=b+wa;this.a=[];this.f=[];this.g=c||\"\"}var wa=\"//fonts.googleapis.com/css\";function xa(a,b){for(var c=b.length,d=0;d<c;d++){var e=b[d].split(\":\");3==e.length&&a.f.push(e.pop());var f=\"\";2==e.length&&\"\"!=e[1]&&(f=\":\");a.a.push(e.join(f))}}\nfunction ya(a){if(0==a.a.length)throw Error(\"No fonts to load!\");if(-1!=a.c.indexOf(\"kit=\"))return a.c;for(var b=a.a.length,c=[],d=0;d<b;d++)c.push(a.a[d].replace(/ /g,\"+\"));b=a.c+\"?family=\"+c.join(\"%7C\");0<a.f.length&&(b+=\"&subset=\"+a.f.join(\",\"));0<a.g.length&&(b+=\"&text=\"+encodeURIComponent(a.g));return b};function za(a){this.f=a;this.a=[];this.c={}}\nvar Aa={latin:\"BESbswy\",\"latin-ext\":\"\\u00e7\\u00f6\\u00fc\\u011f\\u015f\",cyrillic:\"\\u0439\\u044f\\u0416\",greek:\"\\u03b1\\u03b2\\u03a3\",khmer:\"\\u1780\\u1781\\u1782\",Hanuman:\"\\u1780\\u1781\\u1782\"},Ba={thin:\"1\",extralight:\"2\",\"extra-light\":\"2\",ultralight:\"2\",\"ultra-light\":\"2\",light:\"3\",regular:\"4\",book:\"4\",medium:\"5\",\"semi-bold\":\"6\",semibold:\"6\",\"demi-bold\":\"6\",demibold:\"6\",bold:\"7\",\"extra-bold\":\"8\",extrabold:\"8\",\"ultra-bold\":\"8\",ultrabold:\"8\",black:\"9\",heavy:\"9\",l:\"3\",r:\"4\",b:\"7\"},Ca={i:\"i\",italic:\"i\",n:\"n\",normal:\"n\"},\nDa=/^(thin|(?:(?:extra|ultra)-?)?light|regular|book|medium|(?:(?:semi|demi|extra|ultra)-?)?bold|black|heavy|l|r|b|[1-9]00)?(n|i|normal|italic)?$/;\nfunction Ea(a){for(var b=a.f.length,c=0;c<b;c++){var d=a.f[c].split(\":\"),e=d[0].replace(/\\+/g,\" \"),f=[\"n4\"];if(2<=d.length){var g;var k=d[1];g=[];if(k)for(var k=k.split(\",\"),h=k.length,m=0;m<h;m++){var l;l=k[m];if(l.match(/^[\\w-]+$/)){var n=Da.exec(l.toLowerCase());if(null==n)l=\"\";else{l=n[2];l=null==l||\"\"==l?\"n\":Ca[l];n=n[1];if(null==n||\"\"==n)n=\"4\";else var r=Ba[n],n=r?r:isNaN(n)?\"4\":n.substr(0,1);l=[l,n].join(\"\")}}else l=\"\";l&&g.push(l)}0<g.length&&(f=g);3==d.length&&(d=d[2],g=[],d=d?d.split(\",\"):\ng,0<d.length&&(d=Aa[d[0]])&&(a.c[e]=d))}a.c[e]||(d=Aa[e])&&(a.c[e]=d);for(d=0;d<f.length;d+=1)a.a.push(new H(e,f[d]))}};function Fa(a,b){this.c=a;this.a=b}var Ga={Arimo:!0,Cousine:!0,Tinos:!0};Fa.prototype.load=function(a){var b=new C,c=this.c,d=new va(this.a.api,z(c),this.a.text),e=this.a.families;xa(d,e);var f=new za(e);Ea(f);A(c,ya(d),D(b));F(b,function(){a(f.a,f.c,Ga)})};function Ha(a,b){this.c=a;this.a=b}Ha.prototype.load=function(a){var b=this.a.id,c=this.c.m;b?B(this.c,(this.a.api||\"https://use.typekit.net\")+\"/\"+b+\".js\",function(b){if(b)a([]);else if(c.Typekit&&c.Typekit.config&&c.Typekit.config.fn){b=c.Typekit.config.fn;for(var e=[],f=0;f<b.length;f+=2)for(var g=b[f],k=b[f+1],h=0;h<k.length;h++)e.push(new H(g,k[h]));try{c.Typekit.load({events:!1,classes:!1,async:!0})}catch(m){}a(e)}},2E3):a([])};function Ia(a,b){this.c=a;this.f=b;this.a=[]}Ia.prototype.load=function(a){var b=this.f.id,c=this.c.m,d=this;b?(c.__webfontfontdeckmodule__||(c.__webfontfontdeckmodule__={}),c.__webfontfontdeckmodule__[b]=function(b,c){for(var g=0,k=c.fonts.length;g<k;++g){var h=c.fonts[g];d.a.push(new H(h.name,ga(\"font-weight:\"+h.weight+\";font-style:\"+h.style)))}a(d.a)},B(this.c,z(this.c)+(this.f.api||\"//f.fontdeck.com/s/css/js/\")+ea(this.c)+\"/\"+b+\".js\",function(b){b&&a([])})):a([])};var Y=new pa(window);Y.a.c.custom=function(a,b){return new ua(b,a)};Y.a.c.fontdeck=function(a,b){return new Ia(b,a)};Y.a.c.monotype=function(a,b){return new sa(b,a)};Y.a.c.typekit=function(a,b){return new Ha(b,a)};Y.a.c.google=function(a,b){return new Fa(b,a)};var Z={load:p(Y.load,Y)};\"function\"===typeof define&&define.amd?define(function(){return Z}):\"undefined\"!==typeof module&&module.exports?module.exports=Z:(window.WebFont=Z,window.WebFontConfig&&Y.load(window.WebFontConfig));}());\n</script>\n<script>var LZString=function(){function o(o,r){if(!t[o]){t[o]={};for(var n=0;n<o.length;n++)t[o][o.charAt(n)]=n}return t[o][r]}var r=String.fromCharCode,n=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\",e=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$\",t={},i={compressToBase64:function(o){if(null==o)return\"\";var r=i._compress(o,6,function(o){return n.charAt(o)});switch(r.length%4){default:case 0:return r;case 1:return r+\"===\";case 2:return r+\"==\";case 3:return r+\"=\"}},decompressFromBase64:function(r){return null==r?\"\":\"\"==r?null:i._decompress(r.length,32,function(e){return o(n,r.charAt(e))})},compressToUTF16:function(o){return null==o?\"\":i._compress(o,15,function(o){return r(o+32)})+\" \"},decompressFromUTF16:function(o){return null==o?\"\":\"\"==o?null:i._decompress(o.length,16384,function(r){return o.charCodeAt(r)-32})},compressToUint8Array:function(o){for(var r=i.compress(o),n=new Uint8Array(2*r.length),e=0,t=r.length;t>e;e++){var s=r.charCodeAt(e);n[2*e]=s>>>8,n[2*e+1]=s%256}return n},decompressFromUint8Array:function(o){if(null===o||void 0===o)return i.decompress(o);for(var n=new Array(o.length/2),e=0,t=n.length;t>e;e++)n[e]=256*o[2*e]+o[2*e+1];var s=[];return n.forEach(function(o){s.push(r(o))}),i.decompress(s.join(\"\"))},compressToEncodedURIComponent:function(o){return null==o?\"\":i._compress(o,6,function(o){return e.charAt(o)})},decompressFromEncodedURIComponent:function(r){return null==r?\"\":\"\"==r?null:(r=r.replace(/ /g,\"+\"),i._decompress(r.length,32,function(n){return o(e,r.charAt(n))}))},compress:function(o){return i._compress(o,16,function(o){return r(o)})},_compress:function(o,r,n){if(null==o)return\"\";var e,t,i,s={},p={},u=\"\",c=\"\",a=\"\",l=2,f=3,h=2,d=[],m=0,v=0;for(i=0;i<o.length;i+=1)if(u=o.charAt(i),Object.prototype.hasOwnProperty.call(s,u)||(s[u]=f++,p[u]=!0),c=a+u,Object.prototype.hasOwnProperty.call(s,c))a=c;else{if(Object.prototype.hasOwnProperty.call(p,a)){if(a.charCodeAt(0)<256){for(e=0;h>e;e++)m<<=1,v==r-1?(v=0,d.push(n(m)),m=0):v++;for(t=a.charCodeAt(0),e=0;8>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}else{for(t=1,e=0;h>e;e++)m=m<<1|t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t=0;for(t=a.charCodeAt(0),e=0;16>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}l--,0==l&&(l=Math.pow(2,h),h++),delete p[a]}else for(t=s[a],e=0;h>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;l--,0==l&&(l=Math.pow(2,h),h++),s[c]=f++,a=String(u)}if(\"\"!==a){if(Object.prototype.hasOwnProperty.call(p,a)){if(a.charCodeAt(0)<256){for(e=0;h>e;e++)m<<=1,v==r-1?(v=0,d.push(n(m)),m=0):v++;for(t=a.charCodeAt(0),e=0;8>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}else{for(t=1,e=0;h>e;e++)m=m<<1|t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t=0;for(t=a.charCodeAt(0),e=0;16>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}l--,0==l&&(l=Math.pow(2,h),h++),delete p[a]}else for(t=s[a],e=0;h>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;l--,0==l&&(l=Math.pow(2,h),h++)}for(t=2,e=0;h>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;for(;;){if(m<<=1,v==r-1){d.push(n(m));break}v++}return d.join(\"\")},decompress:function(o){return null==o?\"\":\"\"==o?null:i._decompress(o.length,32768,function(r){return o.charCodeAt(r)})},_decompress:function(o,n,e){var t,i,s,p,u,c,a,l,f=[],h=4,d=4,m=3,v=\"\",w=[],A={val:e(0),position:n,index:1};for(i=0;3>i;i+=1)f[i]=i;for(p=0,c=Math.pow(2,2),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;switch(t=p){case 0:for(p=0,c=Math.pow(2,8),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;l=r(p);break;case 1:for(p=0,c=Math.pow(2,16),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;l=r(p);break;case 2:return\"\"}for(f[3]=l,s=l,w.push(l);;){if(A.index>o)return\"\";for(p=0,c=Math.pow(2,m),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;switch(l=p){case 0:for(p=0,c=Math.pow(2,8),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;f[d++]=r(p),l=d-1,h--;break;case 1:for(p=0,c=Math.pow(2,16),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;f[d++]=r(p),l=d-1,h--;break;case 2:return w.join(\"\")}if(0==h&&(h=Math.pow(2,m),m++),f[l])v=f[l];else{if(l!==d)return null;v=s+s.charAt(0)}w.push(v),f[d++]=s+v.charAt(0),h--,s=v,0==h&&(h=Math.pow(2,m),m++)}}};return i}();\"function\"==typeof define&&define.amd?define(function(){return LZString}):\"undefined\"!=typeof module&&null!=module&&(module.exports=LZString);\n</script>\n<script>if (!String.prototype.startsWith) {\n    String.prototype.startsWith = function(searchString, position){\n      position = position || 0;\n      return this.substr(position, searchString.length) === searchString;\n  };\n}\n\nif (!Object.keys) {\n    Object.keys = function (obj) {\n        var keys = [],\n            k;\n        for (k in obj) {\n            if (Object.prototype.hasOwnProperty.call(obj, k)) {\n                keys.push(k);\n            }\n        }\n        return keys;\n    };\n}\n\n// http://stackoverflow.com/questions/872310/javascript-swap-array-elements\nArray.prototype.swap = function (x,y) {\n  var b = this[x];\n  this[x] = this[y];\n  this[y] = b;\n  return this;\n}\n\n// Production steps of ECMA-262, Edition 5, 15.4.4.18\n// Reference: http://es5.github.io/#x15.4.4.18\nif (!Array.prototype.forEachBackwards) {\n\n  Array.prototype.forEachBackwards = function(callback, thisArg) {\n\n    var T, k;\n\n    if (this === null) {\n      throw new TypeError('this is null or not defined');\n    }\n\n    // 1. Let O be the result of calling toObject() passing the\n    // |this| value as the argument.\n    var O = Object(this);\n\n    // 2. Let lenValue be the result of calling the Get() internal\n    // method of O with the argument \"length\".\n    // 3. Let len be toUint32(lenValue).\n    var len = O.length >>> 0;\n\n    // 4. If isCallable(callback) is false, throw a TypeError exception. \n    // See: http://es5.github.com/#x9.11\n    if (typeof callback !== 'function') {\n      throw new TypeError(callback + ' is not a function');\n    }\n\n    // 5. If thisArg was supplied, let T be thisArg; else let\n    // T be undefined.\n    if (arguments.length > 1) {\n      T = thisArg;\n    }\n\n    // 6. Let k be 0\n    k = len-1;\n\n    // 7. Repeat, while k < len\n    while (k >= 0) {\n\n      var kValue;\n\n      // a. Let Pk be ToString(k).\n      //    This is implicit for LHS operands of the in operator\n      // b. Let kPresent be the result of calling the HasProperty\n      //    internal method of O with argument Pk.\n      //    This step can be combined with c\n      // c. If kPresent is true, then\n      if (k in O) {\n\n        // i. Let kValue be the result of calling the Get internal\n        // method of O with argument Pk.\n        kValue = O[k];\n\n        // ii. Call the Call internal method of callback with T as\n        // the this value and argument list containing kValue, k, and O.\n        callback.call(T, kValue, k, O);\n      }\n      // d. Increase k by 1.\n      k--;\n    }\n    // 8. return undefined\n  };\n}\n\n//http://stackoverflow.com/questions/7837456/how-to-compare-arrays-in-javascript\n// Warn if overriding existing method\nif(Array.prototype.equals)\n    console.warn(\"Overriding existing Array.prototype.equals. Possible causes: New API defines the method, there's a framework conflict or you've got double inclusions in your code.\");\n// attach the .equals method to Array's prototype to call it on any array\nArray.prototype.equals = function (array) {\n    // if the other array is a falsy value, return\n    if (!array)\n        return false;\n\n    // compare lengths - can save a lot of time \n    if (this.length != array.length)\n        return false;\n\n    for (var i = 0, l=this.length; i < l; i++) {\n        // Check if we have nested arrays\n        if (this[i] instanceof Array && array[i] instanceof Array) {\n            // recurse into the nested arrays\n            if (!this[i].equals(array[i]))\n                return false;       \n        }           \n        else if (this[i] != array[i]) { \n            // Warning - two different object instances will never be equal: {x:20} != {x:20}\n            return false;   \n        }           \n    }       \n    return true;\n}\n// Hide method from for-in loops\nObject.defineProperty(Array.prototype, \"equals\", {enumerable: false});\n\n//if(!BrowserDetectionUtils.isChrome || !BrowserDetectionUtils.isFirefox) {\n    window.polyfillClipboardData = (function () {\n        var pcd = {};\n\n        var data = {};\n        \n        pcd.types = [];\n\n        pcd.setData = function (type,newdata) {\n            data[type] = {type:type,data:newdata};\n            if(pcd.types.indexOf(type) === -1) pcd.types.push(type);\n        }\n\n        pcd.getData = function (type) {\n            return data[type].data;\n        }\n\n        return pcd;\n    })();\n//}\n\nvar BrowserDetect = (function () {\n\n    var browserDetectionUtils = { };\n\n    browserDetectionUtils.isFirefox = \n        navigator.userAgent.search(\"Firefox\");\n\n    browserDetectionUtils.isSafari = \n        navigator.appVersion.search('Safari') != -1 \n     && navigator.appVersion.search('Chrome') == -1 \n     && navigator.appVersion.search('CrMo') == -1 \n     && navigator.appVersion.search('CriOS') == -1;\n\n    browserDetectionUtils.isIe = (\n        navigator.userAgent.toLowerCase().indexOf(\"msie\") != -1 \n     || navigator.userAgent.toLowerCase().indexOf(\"trident\") != -1 );\n\n    browserDetectionUtils.isChrome = \n        /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);\n\n    browserDetectionUtils.inMobileMode =\n        /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);\n\n    return browserDetectionUtils;\n    \n})();\n\n//http://stackoverflow.com/questions/5306680/move-an-array-element-from-one-array-position-to-another\nArray.prototype.move = function (old_index, new_index) {\n    if (new_index >= this.length) {\n        var k = new_index - this.length;\n        while ((k--) + 1) {\n            this.push(undefined);\n        }\n    }\n    this.splice(new_index, 0, this.splice(old_index, 1)[0]);\n    return this; // for testing purposes\n};\n\n// https://tc39.github.io/ecma262/#sec-array.prototype.includes\nif (!Array.prototype.includes) {\n  Object.defineProperty(Array.prototype, 'includes', {\n    value: function(searchElement, fromIndex) {\n\n      // 1. Let O be ? ToObject(this value).\n      if (this == null) {\n        throw new TypeError('\"this\" is null or not defined');\n      }\n\n      var o = Object(this);\n\n      // 2. Let len be ? ToLength(? Get(O, \"length\")).\n      var len = o.length >>> 0;\n\n      // 3. If len is 0, return false.\n      if (len === 0) {\n        return false;\n      }\n\n      // 4. Let n be ? ToInteger(fromIndex).\n      //    (If fromIndex is undefined, this step produces the value 0.)\n      var n = fromIndex | 0;\n\n      // 5. If n ≥ 0, then\n      //  a. Let k be n.\n      // 6. Else n < 0,\n      //  a. Let k be len + n.\n      //  b. If k < 0, let k be 0.\n      var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);\n\n      // 7. Repeat, while k < len\n      while (k < len) {\n        // a. Let elementK be the result of ? Get(O, ! ToString(k)).\n        // b. If SameValueZero(searchElement, elementK) is true, return true.\n        // c. Increase k by 1.\n        // NOTE: === provides the correct \"SameValueZero\" comparison needed here.\n        if (o[k] === searchElement) {\n          return true;\n        }\n        k++;\n      }\n\n      // 8. Return false\n      return false;\n    }\n  });\n}\n\nvar isSafari = navigator.appVersion.search('Safari') != -1 && navigator.appVersion.search('Chrome') == -1 && navigator.appVersion.search('CrMo') == -1 && navigator.appVersion.search('CriOS') == -1;\nvar isIe = (navigator.userAgent.toLowerCase().indexOf(\"msie\") != -1 || navigator.userAgent.toLowerCase().indexOf(\"trident\") != -1);\nvar isChrome = /chrome/.test( navigator.userAgent.toLowerCase() );\n\nvar roundToNearestN = function (val, n, d) {\n  if(d === undefined) d = 20;\n  return parseFloat((Math.round(val/n)*n).toFixed(d));\n}\n\nvar roundToHundredths = function (val) {\n  return roundToNearestN(val, 0.01, 2);\n}\n\nvar buildDiv = function(className, parentElem) {\n  var div = document.createElement('div');\n  div.className = className;\n  if(parentElem) {\n    parentElem.appendChild(div);\n  }\n  return div;\n}\n\nvar buildSpan = function(className, parentElem) {\n  var div = document.createElement('span');\n  div.className = className;\n  if(parentElem) {\n    parentElem.appendChild(div);\n  }\n  return div;\n}\n\n//http://stackoverflow.com/questions/11076975/insert-text-into-textarea-at-cursor-position-javascript\nfunction insertAtCursor(myField, myValue) {\n    //IE support\n    if (document.selection) {\n        myField.focus();\n        sel = document.selection.createRange();\n        sel.text = myValue;\n    }\n    //MOZILLA and others\n    else if (myField.selectionStart || myField.selectionStart == '0') {\n        var startPos = myField.selectionStart;\n        var endPos = myField.selectionEnd;\n        myField.value = myField.value.substring(0, startPos)\n            + myValue\n            + myField.value.substring(endPos, myField.value.length);\n    } else {\n        myField.value += myValue;\n    }\n}\n\nvar startMillis;\nfunction resetElapsedTime () {\n  startMillis = new Date().getTime()\n}\nresetElapsedTime();\nfunction elapsedSeconds () {\n  return Math.floor(elapsedMilliseconds()/1000);\n}\n\nfunction elapsedMilliseconds () {\n  var d = new Date();\n  var n = d.getTime();\n  return n - startMillis;\n}\n\nfunction rotate_point(pointX, pointY, originX, originY, angle) {\n  angle = angle * Math.PI / 180.0;\n  return {\n    x: Math.cos(angle) * (pointX-originX) - Math.sin(angle) * (pointY-originY) + originX,\n    y: Math.sin(angle) * (pointX-originX) + Math.cos(angle) * (pointY-originY) + originY\n  };\n}\n\nElement.prototype.remove = function() {\n    this.parentElement.removeChild(this);\n}\nNodeList.prototype.remove = HTMLCollection.prototype.remove = function() {\n    for(var i = this.length - 1; i >= 0; i--) {\n        if(this[i] && this[i].parentElement) {\n            this[i].parentElement.removeChild(this[i]);\n        }\n    }\n}\n\n// http://stackoverflow.com/questions/9705123/how-can-i-get-sin-cos-and-tan-to-use-degrees-instead-of-radians\nfunction toRadians (angle) {\n  return angle * (Math.PI / 180);\n}\n\nfunction clamp (val, min, max) {\n  return Math.min(Math.max(val, min), max);\n}\n\n\n// \nfunction hexToRgbA(hex, a){\n    var c;\n\n    if(hex === 'none') return 'rgba(0,0,0,0)';\n\n    if(/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)){\n        c= hex.substring(1).split('');\n        if(c.length== 3){\n            c= [c[0], c[0], c[1], c[1], c[2], c[2]];\n        }\n        c= '0x'+c.join('');\n        return 'rgba('+[(c>>16)&255, (c>>8)&255, c&255].join(',')+','+a+')';\n    }\n    console.log(hex);\n    throw new Error('Bad Hex');\n}\n\nfunction dataURItoBlob(dataURI) {\n  // convert base64 to raw binary data held in a string\n  // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this\n  var byteString = atob(dataURI.split(',')[1]);\n\n  // separate out the mime component\n  var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]\n\n  // write the bytes of the string to an ArrayBuffer\n  var ab = new ArrayBuffer(byteString.length);\n  var ia = new Uint8Array(ab);\n  for (var i = 0; i < byteString.length; i++) {\n      ia[i] = byteString.charCodeAt(i);\n  }\n\n  // write the ArrayBuffer to a blob, and you're done\n  var blob = new Blob([ab], {type: mimeString});\n  return blob;\n\n  // Old code\n  // var bb = new BlobBuilder();\n  // bb.append(ab);\n  // return bb.getBlob(mimeString);\n}\n\nfunction deepCopy (val) {\n  if(typeof val === 'object') {\n    return JSON.parse(JSON.stringify(val));\n  } else {\n    return val;\n  }\n}\n\nfunction getAvailableFonts () {\n  var availableFonts = [\n    'Arial', \n    'Times New Roman', \n    'Comic Sans MS', \n    'Georgia', \n    'Palatino Linotype', \n    'Book Antiqua', \n    'Helvetica', \n    'Arial Black', \n    'Impact', \n    'Lucida Sans Unicode', \n    'Tahoma', \n    'Geneva', \n    'Trebuchet MS', \n    'Verdana', \n    'Courier New', \n    'Lucida Console'\n  ];\n  availableFonts.sort();\n  return availableFonts;\n}\n\nfunction elementInsideElement (target, parent) {\n  if(target === parent) return true;\n\n  if(target.parentElement) {\n    if(target.parentElement === target) {\n      return true;\n    } else {\n      return elementInsideElement(target.parentElement, parent)\n    }\n  } else {\n    return false;\n  }\n}\n\nfunction getBrowserAndOSInfo () {\n  var nVer = navigator.appVersion;\n  var nAgt = navigator.userAgent;\n  var browserName  = navigator.appName;\n  var fullVersion  = ''+parseFloat(navigator.appVersion); \n  var majorVersion = parseInt(navigator.appVersion,10);\n  var nameOffset,verOffset,ix;\n\n  // In Opera, the true version is after \"Opera\" or after \"Version\"\n  if ((verOffset=nAgt.indexOf(\"Opera\"))!=-1) {\n   browserName = \"Opera\";\n   fullVersion = nAgt.substring(verOffset+6);\n   if ((verOffset=nAgt.indexOf(\"Version\"))!=-1) \n     fullVersion = nAgt.substring(verOffset+8);\n  }\n  // In MSIE, the true version is after \"MSIE\" in userAgent\n  else if ((verOffset=nAgt.indexOf(\"MSIE\"))!=-1) {\n   browserName = \"Microsoft Internet Explorer\";\n   fullVersion = nAgt.substring(verOffset+5);\n  }\n  // In Chrome, the true version is after \"Chrome\" \n  else if ((verOffset=nAgt.indexOf(\"Chrome\"))!=-1) {\n   browserName = \"Chrome\";\n   fullVersion = nAgt.substring(verOffset+7);\n  }\n  // In Safari, the true version is after \"Safari\" or after \"Version\" \n  else if ((verOffset=nAgt.indexOf(\"Safari\"))!=-1) {\n   browserName = \"Safari\";\n   fullVersion = nAgt.substring(verOffset+7);\n   if ((verOffset=nAgt.indexOf(\"Version\"))!=-1) \n     fullVersion = nAgt.substring(verOffset+8);\n  }\n  // In Firefox, the true version is after \"Firefox\" \n  else if ((verOffset=nAgt.indexOf(\"Firefox\"))!=-1) {\n   browserName = \"Firefox\";\n   fullVersion = nAgt.substring(verOffset+8);\n  }\n  // In most other browsers, \"name/version\" is at the end of userAgent \n  else if ( (nameOffset=nAgt.lastIndexOf(' ')+1) < \n            (verOffset=nAgt.lastIndexOf('/')) ) \n  {\n   browserName = nAgt.substring(nameOffset,verOffset);\n   fullVersion = nAgt.substring(verOffset+1);\n   if (browserName.toLowerCase()==browserName.toUpperCase()) {\n    browserName = navigator.appName;\n   }\n  }\n  // trim the fullVersion string at semicolon/space if present\n  if ((ix=fullVersion.indexOf(\";\"))!=-1)\n     fullVersion=fullVersion.substring(0,ix);\n  if ((ix=fullVersion.indexOf(\" \"))!=-1)\n     fullVersion=fullVersion.substring(0,ix);\n\n  majorVersion = parseInt(''+fullVersion,10);\n  if (isNaN(majorVersion)) {\n   fullVersion  = ''+parseFloat(navigator.appVersion); \n   majorVersion = parseInt(navigator.appVersion,10);\n  }\n\n  /*return''\n   +'Browser name  = '+browserName+'<br>'\n   +'Full version  = '+fullVersion+'<br>'\n   +'Major version = '+majorVersion+'<br>'\n   +'navigator.appName = '+navigator.appName+'<br>'\n   +'navigator.userAgent = '+navigator.userAgent+'<br>';*/\n   return {\n    browser: browserName,\n    browserVersion: fullVersion,\n    navigatorAppName: navigator.appName,\n    navigatorUserAgent: navigator.userAgent,\n    devicePixelRatio: window.devicePixelRatio,\n   }\n\n}\n\n// https://gist.github.com/hurjas/2660489\n\n/**\n * Return a timestamp with the format \"m/d/yy h:MM:ss TT\"\n * @type {Date}\n */\n\nfunction timeStamp() {\n// Create a date object with the current time\n  var now = new Date();\n\n// Create an array with the current month, day and time\n  var date = [ now.getMonth() + 1, now.getDate(), now.getFullYear() ];\n\n// Create an array with the current hour, minute and second\n  var time = [ now.getHours(), now.getMinutes(), now.getSeconds() ];\n\n// Determine AM or PM suffix based on the hour\n  var suffix = ( time[0] < 12 ) ? \"AM\" : \"PM\";\n\n// Convert hour from military time\n  time[0] = ( time[0] < 12 ) ? time[0] : time[0] - 12;\n\n// If hour is 0, set it to 12\n  time[0] = time[0] || 12;\n\n// If seconds and minutes are less than 10, add a zero\n  for ( var i = 1; i < 3; i++ ) {\n    if ( time[i] < 10 ) {\n      time[i] = \"0\" + time[i];\n    }\n  }\n\n// Return the formatted string\n  return date.join(\".\") + \" \" + time.join(\".\") + \" \" + suffix;\n}\n\nfunction invertColor(hexTripletColor) {\n    var color = hexTripletColor;\n    color = color.substring(1); // remove #\n    color = parseInt(color, 16); // convert to integer\n    color = 0xFFFFFF ^ color; // invert three bytes\n    color = color.toString(16); // convert to hex\n    color = (\"000000\" + color).slice(-6); // pad with leading zeros\n    color = \"#\" + color; // prepend #\n    return color;\n}\n\nvar start;\n\nvar startTiming = function () {\n  start = performance.now();\n}\n\nvar stopTiming = function (name, min) {\n  if(min === undefined) min = 0;\n  var t = performance.now();\n  var roundedT = t - start;\n  if(roundedT > min) {\n    console.log(\"SLOW: \" + roundedT + \"ms: \" + name);\n  }\n  start = t\n}\n\nfunction previewImage (image) {\n  var win = window.open('', 'Title', 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, width='+image.width+', height='+image.height+', top=100, left=100');\n  win.document.body.innerHTML = '<div><img src= '+image.src+'></div>';\n}\n\nfunction intersectRect(r1, r2) {\n  return !(r2.left > r1.right || \n           r2.right < r1.left || \n           r2.top > r1.bottom ||\n           r2.bottom < r1.top);\n}\n\nvar GOOGLE_FONTS = [\n\"ABeeZee\",\"Abel\",\"Abhaya Libre\",\"Abril Fatface\",\"Aclonica\",\"Acme\",\"Actor\",\"Adamina\",\"Advent Pro\",\"Aguafina Script\",\"Akronim\",\"Aladin\",\"Aldrich\",\"Alef\",\"Alegreya\",\"Alegreya SC\",\"Alegreya Sans\",\"Alegreya Sans SC\",\"Alex Brush\",\"Alfa Slab One\",\"Alice\",\"Alike\",\"Alike Angular\",\"Allan\",\"Allerta\",\"Allerta Stencil\",\"Allura\",\"Almendra\",\"Almendra Display\",\"Almendra SC\",\"Amarante\",\"Amaranth\",\"Amatic SC\",\"Amatica SC\",\"Amethysta\",\"Amiko\",\"Amiri\",\"Amita\",\"Anaheim\",\"Andada\",\"Andika\",\"Angkor\",\"Annie Use Your Telescope\",\"Anonymous Pro\",\"Antic\",\"Antic Didone\",\"Antic Slab\",\"Anton\",\"Arapey\",\"Arbutus\",\"Arbutus Slab\",\"Architects Daughter\",\"Archivo\",\"Archivo Black\",\"Archivo Narrow\",\"Aref Ruqaa\",\"Arima Madurai\",\"Arimo\",\"Arizonia\",\"Armata\",\"Arsenal\",\"Artifika\",\"Arvo\",\"Arya\",\"Asap\",\"Asap Condensed\",\"Asar\",\"Asset\",\"Assistant\",\"Astloch\",\"Asul\",\"Athiti\",\"Atma\",\"Atomic Age\",\"Aubrey\",\"Audiowide\",\"Autour One\",\"Average\",\"Average Sans\",\"Averia Gruesa Libre\",\"Averia Libre\",\"Averia Sans Libre\",\"Averia Serif Libre\",\"Bad Script\",\"Bahiana\",\"Baloo\",\"Baloo Bhai\",\"Baloo Bhaijaan\",\"Baloo Bhaina\",\"Baloo Chettan\",\"Baloo Da\",\"Baloo Paaji\",\"Baloo Tamma\",\"Baloo Tammudu\",\"Baloo Thambi\",\"Balthazar\",\"Bangers\",\"Barrio\",\"Basic\",\"Battambang\",\"Baumans\",\"Bayon\",\"Belgrano\",\"Bellefair\",\"Belleza\",\"BenchNine\",\"Bentham\",\"Berkshire Swash\",\"Bevan\",\"Bigelow Rules\",\"Bigshot One\",\"Bilbo\",\"Bilbo Swash Caps\",\"BioRhyme\",\"BioRhyme Expanded\",\"Biryani\",\"Bitter\",\"Black Ops One\",\"Bokor\",\"Bonbon\",\"Boogaloo\",\"Bowlby One\",\"Bowlby One SC\",\"Brawler\",\"Bree Serif\",\"Bubblegum Sans\",\"Bubbler One\",\"Buda\",\"Buenard\",\"Bungee\",\"Bungee Hairline\",\"Bungee Inline\",\"Bungee Outline\",\"Bungee Shade\",\"Butcherman\",\"Butterfly Kids\",\"Cabin\",\"Cabin Condensed\",\"Cabin Sketch\",\"Caesar Dressing\",\"Cagliostro\",\"Cairo\",\"Calligraffitti\",\"Cambay\",\"Cambo\",\"Candal\",\"Cantarell\",\"Cantata One\",\"Cantora One\",\"Capriola\",\"Cardo\",\"Carme\",\"Carrois Gothic\",\"Carrois Gothic SC\",\"Carter One\",\"Catamaran\",\"Caudex\",\"Caveat\",\"Caveat Brush\",\"Cedarville Cursive\",\"Ceviche One\",\"Changa\",\"Changa One\",\"Chango\",\"Chathura\",\"Chau Philomene One\",\"Chela One\",\"Chelsea Market\",\"Chenla\",\"Cherry Cream Soda\",\"Cherry Swash\",\"Chewy\",\"Chicle\",\"Chivo\",\"Chonburi\",\"Cinzel\",\"Cinzel Decorative\",\"Clicker Script\",\"Coda\",\"Coda Caption\",\"Codystar\",\"Coiny\",\"Combo\",\"Comfortaa\",\"Coming Soon\",\"Concert One\",\"Condiment\",\"Content\",\"Contrail One\",\"Convergence\",\"Cookie\",\"Copse\",\"Corben\",\"Cormorant\",\"Cormorant Garamond\",\"Cormorant Infant\",\"Cormorant SC\",\"Cormorant Unicase\",\"Cormorant Upright\",\"Courgette\",\"Cousine\",\"Coustard\",\"Covered By Your Grace\",\"Crafty Girls\",\"Creepster\",\"Crete Round\",\"Crimson Text\",\"Croissant One\",\"Crushed\",\"Cuprum\",\"Cutive\",\"Cutive Mono\",\"Damion\",\"Dancing Script\",\"Dangrek\",\"David Libre\",\"Dawning of a New Day\",\"Days One\",\"Dekko\",\"Delius\",\"Delius Swash Caps\",\"Delius Unicase\",\"Della Respira\",\"Denk One\",\"Devonshire\",\"Dhurjati\",\"Didact Gothic\",\"Diplomata\",\"Diplomata SC\",\"Domine\",\"Donegal One\",\"Doppio One\",\"Dorsa\",\"Dosis\",\"Dr Sugiyama\",\"Droid Sans\",\"Droid Sans Mono\",\"Droid Serif\",\"Duru Sans\",\"Dynalight\",\"EB Garamond\",\"Eagle Lake\",\"Eater\",\"Economica\",\"Eczar\",\"El Messiri\",\"Electrolize\",\"Elsie\",\"Elsie Swash Caps\",\"Emblema One\",\"Emilys Candy\",\"Encode Sans\",\"Encode Sans Condensed\",\"Encode Sans Expanded\",\"Encode Sans Semi Condensed\",\"Encode Sans Semi Expanded\",\"Engagement\",\"Englebert\",\"Enriqueta\",\"Erica One\",\"Esteban\",\"Euphoria Script\",\"Ewert\",\"Exo\",\"Exo 2\",\"Expletus Sans\",\"Fanwood Text\",\"Farsan\",\"Fascinate\",\"Fascinate Inline\",\"Faster One\",\"Fasthand\",\"Fauna One\",\"Faustina\",\"Federant\",\"Federo\",\"Felipa\",\"Fenix\",\"Finger Paint\",\"Fira Mono\",\"Fira Sans\",\"Fira Sans Condensed\",\"Fira Sans Extra Condensed\",\"Fjalla One\",\"Fjord One\",\"Flamenco\",\"Flavors\",\"Fondamento\",\"Fontdiner Swanky\",\"Forum\",\"Francois One\",\"Frank Ruhl Libre\",\"Freckle Face\",\"Fredericka the Great\",\"Fredoka One\",\"Freehand\",\"Fresca\",\"Frijole\",\"Fruktur\",\"Fugaz One\",\"GFS Didot\",\"GFS Neohellenic\",\"Gabriela\",\"Gafata\",\"Galada\",\"Galdeano\",\"Galindo\",\"Gentium Basic\",\"Gentium Book Basic\",\"Geo\",\"Geostar\",\"Geostar Fill\",\"Germania One\",\"Gidugu\",\"Gilda Display\",\"Give You Glory\",\"Glass Antiqua\",\"Glegoo\",\"Gloria Hallelujah\",\"Goblin One\",\"Gochi Hand\",\"Gorditas\",\"Goudy Bookletter 1911\",\"Graduate\",\"Grand Hotel\",\"Gravitas One\",\"Great Vibes\",\"Griffy\",\"Gruppo\",\"Gudea\",\"Gurajada\",\"Habibi\",\"Halant\",\"Hammersmith One\",\"Hanalei\",\"Hanalei Fill\",\"Handlee\",\"Hanuman\",\"Happy Monkey\",\"Harmattan\",\"Headland One\",\"Heebo\",\"Henny Penny\",\"Herr Von Muellerhoff\",\"Hind\",\"Hind Guntur\",\"Hind Madurai\",\"Hind Siliguri\",\"Hind Vadodara\",\"Holtwood One SC\",\"Homemade Apple\",\"Homenaje\",\"IM Fell DW Pica\",\"IM Fell DW Pica SC\",\"IM Fell Double Pica\",\"IM Fell Double Pica SC\",\"IM Fell English\",\"IM Fell English SC\",\"IM Fell French Canon\",\"IM Fell French Canon SC\",\"IM Fell Great Primer\",\"IM Fell Great Primer SC\",\"Iceberg\",\"Iceland\",\"Imprima\",\"Inconsolata\",\"Inder\",\"Indie Flower\",\"Inika\",\"Inknut Antiqua\",\"Irish Grover\",\"Istok Web\",\"Italiana\",\"Italianno\",\"Itim\",\"Jacques Francois\",\"Jacques Francois Shadow\",\"Jaldi\",\"Jim Nightshade\",\"Jockey One\",\"Jolly Lodger\",\"Jomhuria\",\"Josefin Sans\",\"Josefin Slab\",\"Joti One\",\"Judson\",\"Julee\",\"Julius Sans One\",\"Junge\",\"Jura\",\"Just Another Hand\",\"Just Me Again Down Here\",\"Kadwa\",\"Kalam\",\"Kameron\",\"Kanit\",\"Kantumruy\",\"Karla\",\"Karma\",\"Katibeh\",\"Kaushan Script\",\"Kavivanar\",\"Kavoon\",\"Kdam Thmor\",\"Keania One\",\"Kelly Slab\",\"Kenia\",\"Khand\",\"Khmer\",\"Khula\",\"Kite One\",\"Knewave\",\"Kotta One\",\"Koulen\",\"Kranky\",\"Kreon\",\"Kristi\",\"Krona One\",\"Kumar One\",\"Kumar One Outline\",\"Kurale\",\"La Belle Aurore\",\"Laila\",\"Lakki Reddy\",\"Lalezar\",\"Lancelot\",\"Lateef\",\"Lato\",\"League Script\",\"Leckerli One\",\"Ledger\",\"Lekton\",\"Lemon\",\"Lemonada\",\"Libre Barcode 128\",\"Libre Barcode 128 Text\",\"Libre Barcode 39\",\"Libre Barcode 39 Extended\",\"Libre Barcode 39 Extended Text\",\"Libre Barcode 39 Text\",\"Libre Baskerville\",\"Libre Franklin\",\"Life Savers\",\"Lilita One\",\"Lily Script One\",\"Limelight\",\"Linden Hill\",\"Lobster\",\"Lobster Two\",\"Londrina Outline\",\"Londrina Shadow\",\"Londrina Sketch\",\"Londrina Solid\",\"Lora\",\"Love Ya Like A Sister\",\"Loved by the King\",\"Lovers Quarrel\",\"Luckiest Guy\",\"Lusitana\",\"Lustria\",\"Macondo\",\"Macondo Swash Caps\",\"Mada\",\"Magra\",\"Maiden Orange\",\"Maitree\",\"Mako\",\"Mallanna\",\"Mandali\",\"Manuale\",\"Marcellus\",\"Marcellus SC\",\"Marck Script\",\"Margarine\",\"Marko One\",\"Marmelad\",\"Martel\",\"Martel Sans\",\"Marvel\",\"Mate\",\"Mate SC\",\"Maven Pro\",\"McLaren\",\"Meddon\",\"MedievalSharp\",\"Medula One\",\"Meera Inimai\",\"Megrim\",\"Meie Script\",\"Merienda\",\"Merienda One\",\"Merriweather\",\"Merriweather Sans\",\"Metal\",\"Metal Mania\",\"Metamorphous\",\"Metrophobic\",\"Michroma\",\"Milonga\",\"Miltonian\",\"Miltonian Tattoo\",\"Miniver\",\"Miriam Libre\",\"Mirza\",\"Miss Fajardose\",\"Mitr\",\"Modak\",\"Modern Antiqua\",\"Mogra\",\"Molengo\",\"Molle\",\"Monda\",\"Monofett\",\"Monoton\",\"Monsieur La Doulaise\",\"Montaga\",\"Montez\",\"Montserrat\",\"Montserrat Alternates\",\"Montserrat Subrayada\",\"Moul\",\"Moulpali\",\"Mountains of Christmas\",\"Mouse Memoirs\",\"Mr Bedfort\",\"Mr Dafoe\",\"Mr De Haviland\",\"Mrs Saint Delafield\",\"Mrs Sheppards\",\"Mukta\",\"Mukta Mahee\",\"Mukta Malar\",\"Mukta Vaani\",\"Muli\",\"Mystery Quest\",\"NTR\",\"Neucha\",\"Neuton\",\"New Rocker\",\"News Cycle\",\"Niconne\",\"Nixie One\",\"Nobile\",\"Nokora\",\"Norican\",\"Nosifer\",\"Nothing You Could Do\",\"Noticia Text\",\"Noto Sans\",\"Noto Serif\",\"Nova Cut\",\"Nova Flat\",\"Nova Mono\",\"Nova Oval\",\"Nova Round\",\"Nova Script\",\"Nova Slim\",\"Nova Square\",\"Numans\",\"Nunito\",\"Nunito Sans\",\"Odor Mean Chey\",\"Offside\",\"Old Standard TT\",\"Oldenburg\",\"Oleo Script\",\"Oleo Script Swash Caps\",\"Open Sans\",\"Open Sans Condensed\",\"Oranienbaum\",\"Orbitron\",\"Oregano\",\"Orienta\",\"Original Surfer\",\"Oswald\",\"Over the Rainbow\",\"Overlock\",\"Overlock SC\",\"Overpass\",\"Overpass Mono\",\"Ovo\",\"Oxygen\",\"Oxygen Mono\",\"PT Mono\",\"PT Sans\",\"PT Sans Caption\",\"PT Sans Narrow\",\"PT Serif\",\"PT Serif Caption\",\"Pacifico\",\"Padauk\",\"Palanquin\",\"Palanquin Dark\",\"Pangolin\",\"Paprika\",\"Parisienne\",\"Passero One\",\"Passion One\",\"Pathway Gothic One\",\"Patrick Hand\",\"Patrick Hand SC\",\"Pattaya\",\"Patua One\",\"Pavanam\",\"Paytone One\",\"Peddana\",\"Peralta\",\"Permanent Marker\",\"Petit Formal Script\",\"Petrona\",\"Philosopher\",\"Piedra\",\"Pinyon Script\",\"Pirata One\",\"Plaster\",\"Play\",\"Playball\",\"Playfair Display\",\"Playfair Display SC\",\"Podkova\",\"Poiret One\",\"Poller One\",\"Poly\",\"Pompiere\",\"Pontano Sans\",\"Poppins\",\"Port Lligat Sans\",\"Port Lligat Slab\",\"Pragati Narrow\",\"Prata\",\"Preahvihear\",\"Press Start 2P\",\"Pridi\",\"Princess Sofia\",\"Prociono\",\"Prompt\",\"Prosto One\",\"Proza Libre\",\"Puritan\",\"Purple Purse\",\"Quando\",\"Quantico\",\"Quattrocento\",\"Quattrocento Sans\",\"Questrial\",\"Quicksand\",\"Quintessential\",\"Qwigley\",\"Racing Sans One\",\"Radley\",\"Rajdhani\",\"Rakkas\",\"Raleway\",\"Raleway Dots\",\"Ramabhadra\",\"Ramaraja\",\"Rambla\",\"Rammetto One\",\"Ranchers\",\"Rancho\",\"Ranga\",\"Rasa\",\"Rationale\",\"Ravi Prakash\",\"Redressed\",\"Reem Kufi\",\"Reenie Beanie\",\"Revalia\",\"Rhodium Libre\",\"Ribeye\",\"Ribeye Marrow\",\"Righteous\",\"Risque\",\"Roboto\",\"Roboto Condensed\",\"Roboto Mono\",\"Roboto Slab\",\"Rochester\",\"Rock Salt\",\"Rokkitt\",\"Romanesco\",\"Ropa Sans\",\"Rosario\",\"Rosarivo\",\"Rouge Script\",\"Rozha One\",\"Rubik\",\"Rubik Mono One\",\"Ruda\",\"Rufina\",\"Ruge Boogie\",\"Ruluko\",\"Rum Raisin\",\"Ruslan Display\",\"Russo One\",\"Ruthie\",\"Rye\",\"Sacramento\",\"Sahitya\",\"Sail\",\"Saira\",\"Saira Condensed\",\"Saira Extra Condensed\",\"Saira Semi Condensed\",\"Salsa\",\"Sanchez\",\"Sancreek\",\"Sansita\",\"Sarala\",\"Sarina\",\"Sarpanch\",\"Satisfy\",\"Scada\",\"Scheherazade\",\"Schoolbell\",\"Scope One\",\"Seaweed Script\",\"Secular One\",\"Sedgwick Ave\",\"Sedgwick Ave Display\",\"Sevillana\",\"Seymour One\",\"Shadows Into Light\",\"Shadows Into Light Two\",\"Shanti\",\"Share\",\"Share Tech\",\"Share Tech Mono\",\"Shojumaru\",\"Short Stack\",\"Shrikhand\",\"Siemreap\",\"Sigmar One\",\"Signika\",\"Signika Negative\",\"Simonetta\",\"Sintony\",\"Sirin Stencil\",\"Six Caps\",\"Skranji\",\"Slabo 13px\",\"Slabo 27px\",\"Slackey\",\"Smokum\",\"Smythe\",\"Sniglet\",\"Snippet\",\"Snowburst One\",\"Sofadi One\",\"Sofia\",\"Sonsie One\",\"Sorts Mill Goudy\",\"Source Code Pro\",\"Source Sans Pro\",\"Source Serif Pro\",\"Space Mono\",\"Special Elite\",\"Spectral\",\"Spicy Rice\",\"Spinnaker\",\"Spirax\",\"Squada One\",\"Sree Krushnadevaraya\",\"Sriracha\",\"Stalemate\",\"Stalinist One\",\"Stardos Stencil\",\"Stint Ultra Condensed\",\"Stint Ultra Expanded\",\"Stoke\",\"Strait\",\"Sue Ellen Francisco\",\"Suez One\",\"Sumana\",\"Sunshiney\",\"Supermercado One\",\"Sura\",\"Suranna\",\"Suravaram\",\"Suwannaphum\",\"Swanky and Moo Moo\",\"Syncopate\",\"Tangerine\",\"Taprom\",\"Tauri\",\"Taviraj\",\"Teko\",\"Telex\",\"Tenali Ramakrishna\",\"Tenor Sans\",\"Text Me One\",\"The Girl Next Door\",\"Tienne\",\"Tillana\",\"Timmana\",\"Tinos\",\"Titan One\",\"Titillium Web\",\"Trade Winds\",\"Trirong\",\"Trocchi\",\"Trochut\",\"Trykker\",\"Tulpen One\",\"Ubuntu\",\"Ubuntu Condensed\",\"Ubuntu Mono\",\"Ultra\",\"Uncial Antiqua\",\"Underdog\",\"Unica One\",\"UnifrakturCook\",\"UnifrakturMaguntia\",\"Unkempt\",\"Unlock\",\"Unna\",\"VT323\",\"Vampiro One\",\"Varela\",\"Varela Round\",\"Vast Shadow\",\"Vesper Libre\",\"Vibur\",\"Vidaloka\",\"Viga\",\"Voces\",\"Volkhov\",\"Vollkorn\",\"Voltaire\",\"Waiting for the Sunrise\",\"Wallpoet\",\"Walter Turncoat\",\"Warnes\",\"Wellfleet\",\"Wendy One\",\"Wire One\",\"Work Sans\",\"Yanone Kaffeesatz\",\"Yantramanav\",\"Yatra One\",\"Yellowtail\",\"Yeseva One\",\"Yesteryear\",\"Yrsa\",\"Zeyada\",\"Zilla Slab\",\"Zilla Slab Highlight\"]\nfunction getAllGoogleFonts () {\n  return GOOGLE_FONTS;\n}\n\nfunction loadGoogleFonts (fontFamilyArray, callback) {\n  if(fontFamilyArray.length === 0) return;\n  WebFont.load({\n    google: {\n      families: fontFamilyArray,\n    },\n    active: callback,\n  });\n}\n</script>\n<script>// https://www.npmjs.com/package/keycode\n// Original key mappings lifted from http://jsfiddle.net/vWx8V/ via http://stackoverflow.com/questions/5603195/full-list-of-javascript-keycodes\n\nvar keyCharToCode = {\n    \"BACKSPACE\": 8,\n    \"TAB\": 9,\n    \"ENTER\": 13,\n    \"CTRL\": 17,\n    \"ALT\": 18,\n    \"PAUSE/BREAK\": 19,\n    \"CAPS LOCK\": 20,\n    \"ESC\": 27,\n    \"SPACE\": 32,\n    \"PAGE UP\": 33,\n    \"PAGE DOWN\": 34,\n    \"END\": 35,\n    \"HOME\": 36,\n    \"LEFT\": 37,\n    \"UP\": 38,\n    \"RIGHT\": 39,\n    \"DOWN\": 40,\n    \"INSERT\": 45,\n    \"DELETE\": 46,\n    \"0\": 48,\n    \"1\": 49,\n    \"2\": 50,\n    \"3\": 51,\n    \"4\": 52,\n    \"5\": 53,\n    \"6\": 54,\n    \"7\": 55,\n    \"8\": 56,\n    \"9\": 57,\n    \"A\": 65,\n    \"B\": 66,\n    \"C\": 67,\n    \"D\": 68,\n    \"E\": 69,\n    \"F\": 70,\n    \"G\": 71,\n    \"H\": 72,\n    \"I\": 73,\n    \"J\": 74,\n    \"K\": 75,\n    \"L\": 76,\n    \"M\": 77,\n    \"N\": 78,\n    \"O\": 79,\n    \"P\": 80,\n    \"Q\": 81,\n    \"R\": 82,\n    \"S\": 83,\n    \"T\": 84,\n    \"U\": 85,\n    \"V\": 86,\n    \"W\": 87,\n    \"X\": 88,\n    \"Y\": 89,\n    \"Z\": 90,\n    \"NUM 0\": 96,\n    \"NUM 1\": 97,\n    \"NUM 2\": 98,\n    \"NUM 3\": 99,\n    \"NUM 4\": 100,\n    \"NUM 5\": 101,\n    \"NUM 6\": 102,\n    \"NUM 7\": 103,\n    \"NUM 8\": 104,\n    \"NUM 9\": 105,\n    \"NUM *\": 106,\n    \"NUM +\": 107,\n    \"NUM -\": 109,\n    \"NUM .\": 110,\n    \"NUM /\": 111,\n    \"F1\": 112,\n    \"F2\": 113,\n    \"F3\": 114,\n    \"F4\": 115,\n    \"F5\": 116,\n    \"F6\": 117,\n    \"F7\": 118,\n    \"F8\": 119,\n    \"F9\": 120,\n    \"F10\": 121,\n    \"F11\": 122,\n    \"F12\": 123,\n    \"NUM LOCK\": 144,\n    \"SCROLL LOCK\": 145,\n    \"MY COMPUTER\": 182,\n    \"MY CALCULATOR\": 183,\n    \";\": 186,\n    \"=\": 187,\n    \",\": 188,\n    \"-\": 189,\n    \".\": 190,\n    \"/\": 191,\n    \"`\": 192,\n    \"[\": 219,\n    \"\\\\\": 220,\n    \"]\": 221,\n    \"'\": 222\n};\n\nvar codeToKeyChar = {};\nfor (var key in keyCharToCode) {\n    codeToKeyChar[keyCharToCode[key]] = key;\n}</script>\n<script>// Framerate keeper \n// http://www.html5gamedevs.com/topic/1828-how-to-calculate-fps-in-plain-javascript/\nvar fps = { startTime : 0,\n\tframeNumber : 0,\n\tgetFPS : function() {\n\t\tthis.frameNumber++;\n\n\t\tvar d = new Date().getTime();\n\t\tvar currentTime = ( d - this.startTime ) / 1000;\n\t\tvar result = Math.floor( ( this.frameNumber / currentTime ) );\n\n\t\tif( currentTime > 1 ) {\n\t\t\tthis.startTime = new Date().getTime();\n\t\t\tthis.frameNumber = 0;\n\t\t}\n\n\t\treturn result;\n\t}   \n};</script>\n<script>/*\n * base64-arraybuffer\n * https://github.com/niklasvh/base64-arraybuffer\n *\n * Copyright (c) 2012 Niklas von Hertzen\n * Licensed under the MIT license.\n */\nvar Base64ArrayBuffer = (function () {\n  \"use strict\";\n\n  var base64ArrayBuffer = { };\n\n  var chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n  // Use a lookup table to find the index.\n  var lookup = new Uint8Array(256);\n  for (var i = 0; i < chars.length; i++) {\n    lookup[chars.charCodeAt(i)] = i;\n  }\n\n  base64ArrayBuffer.encode = function(arraybuffer) {\n    var bytes = new Uint8Array(arraybuffer),\n    i, len = bytes.length, base64 = \"\";\n\n    for (i = 0; i < len; i+=3) {\n      base64 += chars[bytes[i] >> 2];\n      base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];\n      base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];\n      base64 += chars[bytes[i + 2] & 63];\n    }\n\n    if ((len % 3) === 2) {\n      base64 = base64.substring(0, base64.length - 1) + \"=\";\n    } else if (len % 3 === 1) {\n      base64 = base64.substring(0, base64.length - 2) + \"==\";\n    }\n\n    return base64;\n  };\n\n  base64ArrayBuffer.decode =  function(base64) {\n    var bufferLength = base64.length * 0.75,\n    len = base64.length, i, p = 0,\n    encoded1, encoded2, encoded3, encoded4;\n\n    if (base64[base64.length - 1] === \"=\") {\n      bufferLength--;\n      if (base64[base64.length - 2] === \"=\") {\n        bufferLength--;\n      }\n    }\n\n    var arraybuffer = new ArrayBuffer(bufferLength),\n    bytes = new Uint8Array(arraybuffer);\n\n    for (i = 0; i < len; i+=4) {\n      encoded1 = lookup[base64.charCodeAt(i)];\n      encoded2 = lookup[base64.charCodeAt(i+1)];\n      encoded3 = lookup[base64.charCodeAt(i+2)];\n      encoded4 = lookup[base64.charCodeAt(i+3)];\n\n      bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);\n      bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);\n      bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);\n    }\n\n    return arraybuffer;\n  };\n\n  return base64ArrayBuffer;\n\n})();\n</script>\n<script>http://blog.acipo.com/blob-detection-js/\n\nfunction unique(arr){\n/// Returns an object with the counts of unique elements in arr\n/// unique([1,2,1,1,1,2,3,4]) === { 1:4, 2:2, 3:1, 4:1 }\n\n    var value, counts = {};\n    var i, l = arr.length;\n    for( i=0; i<l; i+=1) {\n        value = arr[i];\n        if( counts[value] ){\n            counts[value] += 1;\n        }else{\n            counts[value] = 1;\n        }\n    }\n\n    return counts;\n}\n\nfunction FindBlobs(src) {\n\n  var xSize = src.width,\n      ySize = src.height,\n      srcPixels = src.data,\n      x, y, pos;\n\n  // This will hold the indecies of the regions we find\n  var blobMap = [];\n  var label = 1;\n\n  // The labelTable remember when blobs of differen labels merge\n  // so labelTabel[1] = 2; means that label 1 and 2 are the same blob\n  var labelTable = [0];\n\n  // Start by labeling every pixel as blob 0\n  for(y=0; y<ySize; y++){\n    blobMap.push([]);\n    for(x=0; x<xSize; x++){\n      blobMap[y].push(0);\n    }\n  }  \n\n  // Temporary variables for neighboring pixels and other stuff\n  var nn, nw, ne, ww, ee, sw, ss, se, minIndex;\n  var luma = 0;\n  var isVisible = 0;\n\n  // We're going to run this algorithm twice\n  // The first time identifies all of the blobs candidates the second pass\n  // merges any blobs that the first pass failed to merge\n  var nIter = 2;\n  while( nIter-- ){\n\n    // We leave a 1 pixel border which is ignored so we do not get array\n    // out of bounds errors\n    for( y=1; y<ySize-1; y++){\n      for( x=1; x<xSize-1; x++){\n\n        pos = (y*xSize+x)*4;\n\n        // We're only looking at the alpha channel in this case but you can\n        // use more complicated heuristics\n        isVisible = (srcPixels[pos+3] > 0);\n\n        if( isVisible ){\n\n          // Find the lowest blob index nearest this pixel\n          nw = blobMap[y-1][x-1] || 0;\n          nn = blobMap[y-1][x-0] || 0;\n          ne = blobMap[y-1][x+1] || 0;\n          ww = blobMap[y-0][x-1] || 0;\n          ee = blobMap[y-0][x+1] || 0;\n          sw = blobMap[y+1][x-1] || 0;\n          ss = blobMap[y+1][x-0] || 0;\n          se = blobMap[y+1][x+1] || 0;\n          minIndex = ww;\n          if( 0 < ww && ww < minIndex ){ minIndex = ww; }\n          if( 0 < ee && ee < minIndex ){ minIndex = ee; }\n          if( 0 < nn && nn < minIndex ){ minIndex = nn; }\n          if( 0 < ne && ne < minIndex ){ minIndex = ne; }\n          if( 0 < nw && nw < minIndex ){ minIndex = nw; }\n          if( 0 < ss && ss < minIndex ){ minIndex = ss; }\n          if( 0 < se && se < minIndex ){ minIndex = se; }\n          if( 0 < sw && sw < minIndex ){ minIndex = sw; }\n  \n          // This point starts a new blob -- increase the lable count and\n          // and an entry for it in the label table\n          if( minIndex === 0 ){\n            blobMap[y][x] = label;\n            labelTable.push(label);\n            label += 1;\n  \n          // This point is part of an old blob -- update the labels of the\n          // neighboring pixels in the label table so that we know a merge\n          // should occur and mark this pixel with the label.\n          }else{\n            if( minIndex < labelTable[nw] ){ labelTable[nw] = minIndex; }\n            if( minIndex < labelTable[nn] ){ labelTable[nn] = minIndex; }\n            if( minIndex < labelTable[ne] ){ labelTable[ne] = minIndex; }\n            if( minIndex < labelTable[ww] ){ labelTable[ww] = minIndex; }\n            if( minIndex < labelTable[ee] ){ labelTable[ee] = minIndex; }\n            if( minIndex < labelTable[sw] ){ labelTable[sw] = minIndex; }\n            if( minIndex < labelTable[ss] ){ labelTable[ss] = minIndex; }\n            if( minIndex < labelTable[se] ){ labelTable[se] = minIndex; }\n\n            blobMap[y][x] = minIndex;\n          }\n\n        // This pixel isn't visible so we won't mark it as special\n        }else{\n          blobMap[y][x] = 0;\n        }\n  \n      }\n    }\n  \n    // Compress the table of labels so that every location refers to only 1\n    // matching location\n    var i = labelTable.length;\n    while( i-- ){\n      label = labelTable[i];\n      while( label !== labelTable[label] ){\n        label = labelTable[label];\n      }\n      labelTable[i] = label;\n    }\n  \n    // Merge the blobs with multiple labels\n    for(y=0; y<ySize; y++){\n      for(x=0; x<xSize; x++){\n        label = blobMap[y][x];\n        if( label === 0 ){ continue; }\n        while( label !== labelTable[label] ){\n          label = labelTable[label];\n        }\n        blobMap[y][x] = label;\n      }\n    }\n  }\n\n  // The blobs may have unusual labels: [1,38,205,316,etc..]\n  // Let's rename them: [1,2,3,4,etc..]\n\n  var uniqueLabels = unique(labelTable);\n  var labelCount = 0;\n  for(uniqueLabel in uniqueLabels) labelCount++;\n\n  var i = 0;\n  for( label in uniqueLabels ){\n    labelTable[label] = i++;\n  }\n\n  // convert the blobs to the minimized labels\n  for(y=0; y<ySize; y++){\n    for(x=0; x<xSize; x++){\n      label = blobMap[y][x];\n      blobMap[y][x] = labelTable[label];\n    }\n  }\n\n  // Return the blob data:\n  return {blobMap:blobMap, nBlobs:labelCount};\n\n};\n\n\nfunction ColorTheBlobs(dst,blobs,colors){\n    var xSize = dst.width,\n        ySize = dst.height,\n        dstPixels = dst.data,\n        x, y, pos;\n\n    var label, color, nColors = colors.length;\n\n    for(y=0; y<ySize; y++){\n        for(x=0; x<xSize; x++){\n            pos = (y*xSize+x)*4;\n\n            label = blobs[y][x];\n\n            if( label !== 0 ){\n                color = colors[ label % nColors ];\n                dstPixels[ pos+0 ] = color[0];\n                dstPixels[ pos+1 ] = color[1];\n                dstPixels[ pos+2 ] = color[2];\n                dstPixels[ pos+3 ] = color[3];\n            }else{\n                dstPixels[ pos+3 ] = 0;\n            }\n        }\n    }\n\n}\n\nfunction GetBlobMap (img, callback) {\n  ImageToCanvas(img, function (canvas,context) {\n    var canvas = canvas;//document.getElementById('canvas-draw');\n    var contex = context;//canvas.getContext('2d');\n    var imageData = contex.getImageData(0,0,canvas.width,canvas.height);\n\n    var blobResults = FindBlobs(imageData);\n    var blobLabels = blobResults.blobMap;\n    var nBlobs = blobResults.nBlobs;\n\n    var blobCanvas = document.createElement('canvas');//document.getElementById('canvas-blob');\n    blobCanvas.width = canvas.width;\n    blobCanvas.height = canvas.height;\n    var blobContex = blobCanvas.getContext('2d');\n    var blobImageData = contex.getImageData(0,0,canvas.width,canvas.height);\n\n    // this means you can only have 255 blobs, ya dummy!\n    var colors = [];\n    for(var i = 0; i <= 255; i+=1) {\n      colors.push([i,0,0,255]);\n    }\n    ColorTheBlobs(blobImageData,blobLabels,colors);\n    \n    blobContex.putImageData(blobImageData,0,0);\n\n    var blobMap = new Image();\n    blobMap.onload = function () {\n      callback({blobMap:blobMap, nBlobs:nBlobs});\n    }\n    blobMap.src = blobCanvas.toDataURL();\n  });\n}\n\nfunction GetBlobImages (blobMap, nBlobs, image, callback) {\n\tvar imagesData = [];\n\n\tvar label;\n\tfor(label=1; label<=nBlobs; label++) {\n\t\timagesData[label] = GetBlobImage(blobMap, image, label);\n\t}\n\n\tvar images = [];\n\tvar done = false;\n\n\tfunction processBlobImage (i) {\n\t\tvar data = imagesData[i];\n\t\tif(data) {\n\t\t\tctx.putImageData(data,0,0);\n\n\t\t\tvar image = new Image();\n\t\t\timage.onload = function () {\n\t\t\t\t//callback(image);\n\t\t\t\timages.push(image);\n\t\t\t\tif(images.length >= nBlobs-1) {\n\t\t\t\t\tif(!done) callback(images);\n\t\t\t\t\tdone = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\timage.src = canvas.toDataURL();\n\t\t}\n\t}\n\n\tfor(label=1; label<=nBlobs; label++) {\n\t\tif(done) return;\n\n\t\tvar canvas = document.createElement('canvas');\n\t\tcanvas.width = image.width;\n\t\tcanvas.height = image.height;\n\t\tvar ctx = canvas.getContext('2d');\n\n\t\tprocessBlobImage(label);\n\t}\n}\n\nfunction GetBlobImage (blobMap, originalImg, label) {\n\n\tvar blobMapData = ImageToImageData(blobMap)\n\tvar originalImgData = ImageToImageData(originalImg)\n\n\tvar xSize = blobMapData.width,\n        ySize = blobMapData.height,\n        blobMapPixels = blobMapData.data,\n        x, y, pos;\n\n    var originalImgPixels = originalImgData.data;\n\n    var canvas = document.createElement('canvas');\n    var ctx = canvas.getContext('2d');\n    var newImgData = ctx.createImageData(originalImgData);\n    var newImagePixels = newImgData.data;\n\n    var blobExistsWithLabel = false;\n\n    for(y=0; y<ySize; y++){\n        for(x=0; x<xSize; x++){\n            pos = (y*xSize+x)*4;\n\n            if(blobMapPixels[ pos+0 ] === label) {\n            \tnewImagePixels[ pos+0 ] = originalImgPixels[ pos+0 ];\n            \tnewImagePixels[ pos+1 ] = originalImgPixels[ pos+1 ];\n            \tnewImagePixels[ pos+2 ] = originalImgPixels[ pos+2 ];\n            \tnewImagePixels[ pos+3 ] = originalImgPixels[ pos+3 ];\n            \tblobExistsWithLabel = true;\n            } else {\n            \tnewImagePixels[ pos+0 ] = 0;\n\t            newImagePixels[ pos+1 ] = 0;\n\t            newImagePixels[ pos+2 ] = 0;\n\t            newImagePixels[ pos+3 ] = 0;\n            }\n        }\n    }\n\n    return blobExistsWithLabel ? newImgData : null;\n}\n\nfunction FindBlobsAndGetBlobImages (imgData, callback) {\n\n\tGetBlobMap(imgData, function (blobResult) {\n        var img = new Image();\n        img.onload = function () {\n            GetBlobImages(blobResult.blobMap, blobResult.nBlobs, img, function (blobImages) {\n                callback(blobImages);\n            });\n        }\n        img.src = imgData;\n    });\n\n}\n\n// Image cropping / padding (zrispo)\n\nvar CropImage = function (src, callback, args) {\n    var canvas = document.createElement('canvas');\n    canvas.width = args.width;\n    canvas.height = args.height;\n\n    var context = canvas.getContext('2d');\n    var imageObj = new Image();\n\n    imageObj.onload = function() {\n        // draw cropped image\n        var sourceX = args.x;\n        var sourceY = args.y;\n        var sourceWidth = args.width;\n        var sourceHeight = args.height;\n        var destWidth = sourceWidth;\n        var destHeight = sourceHeight;\n        var destX = canvas.width / 2 - destWidth / 2;\n        var destY = canvas.height / 2 - destHeight / 2;\n\n        context.drawImage(imageObj, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight);\n\n        callback(canvas.toDataURL());\n    };\n\n    imageObj.src = src;\n}\n\nfunction AddPaddingToImage (img, callback) {\n    var oddWidth = img.width % 2 === 1;\n    var oddHeight = img.height % 2 === 1;\n\n    if (oddWidth && oddHeight) {\n        CropImage(img.src, callback, {\n            x: 0,\n            y: 0,\n            width: img.width+1,\n            height: img.height+1\n        });\n    } else if (oddWidth) {\n        CropImage(img.src, callback, {\n            x: 0,\n            y: 0,\n            width: img.width+1,\n            height: img.height\n        });\n    } else if (oddHeight) {\n        CropImage(img.src, callback, {\n            x: 0,\n            y: 0,\n            width: img.width,\n            height: img.height+1\n        });\n    } else {\n        callback(img.src);\n    }\n\n}\n\n// Canvas <-> Image conversion (zrispo)\n\nvar ImageToCanvas = function (src, callback, args) {\n\n  var image = new Image();\n    image.onload = function () {\n      var w = image.width;\n        var h = image.height;\n\n        if(args && args.width)  w = args.width;\n        if(args && args.height) h = args.height;\n\n        var canvas = document.createElement('canvas');\n        canvas.height = h;\n        canvas.width = w;\n        \n        var ctx = canvas.getContext('2d');\n        ctx.drawImage( image, 0, 0, w, h );\n        callback(canvas,ctx);\n    };\n    image.setAttribute('crossOrigin', 'anonymous');\n    image.src = src;\n\n}\n\nfunction ImageToImageData (img) {\n    var canvas = document.createElement('canvas');\n    canvas.width = img.width;\n    canvas.height = img.height;\n    var ctx = canvas.getContext('2d');\n    ctx.drawImage(img, 0, 0)\n    return ctx.getImageData(0,0,canvas.width,canvas.height);\n}\n\nfunction PixelsToImageData (pixelData) {\n\n}\n\n// Color picking (unknown source??)\n\nvar GetColorAtCoords = function (img, x, y, format) {\n  \n  if(x < 0 || y < 0 || x > img.width || y > img.height) {\n    console.error(\"GetColorAtCoords: coords out of bounds: (\"+x+\",\"+y+\")\")\n  }\n\n  var canvas = document.createElement('canvas');\n  canvas.width = img.width;\n  canvas.height = img.height;\n  var context = canvas.getContext('2d');\n  context.drawImage(img, 0, 0);\n  var data = context.getImageData(0, 0, canvas.width, canvas.height).data;\n\n  var i = (x + y*img.width) * 4;\n\n  var color = {};\n  color.r = data[i+0];\n  color.g = data[i+1];\n  color.b = data[i+2];\n  color.a = data[i+3];\n\n  if (!format) {\n    return color;\n  }\n\n  if (format === \"rgba\") {\n    return color;\n  } else if (format === \"hex\") {\n    // http://jsfiddle.net/Mottie/xcqpF/1/light/\n    function rgb2hex(rgb){\n      rgb = rgb.match(/^rgba?[\\s+]?\\([\\s+]?(\\d+)[\\s+]?,[\\s+]?(\\d+)[\\s+]?,[\\s+]?(\\d+)[\\s+]?/i);\n      return (rgb && rgb.length === 4) ? \"#\" +\n        (\"0\" + parseInt(rgb[1],10).toString(16)).slice(-2) +\n        (\"0\" + parseInt(rgb[2],10).toString(16)).slice(-2) +\n        (\"0\" + parseInt(rgb[3],10).toString(16)).slice(-2) : '';\n    }\n    return rgb2hex(\"rgb(\"+color.r+\",\"+color.g+\",\"+color.b+\")\").toUpperCase();\n  }\n\n}\n\n// Blank pixel remover / cropper\n\n// http://stackoverflow.com/questions/12175991/crop-image-white-space-automatically-using-jquery\n\nvar removeBlankPixels = function (img, imgWidth, imgHeight) {\n    var canvas = document.createElement('canvas');\n    var context = canvas.getContext('2d');\n\n    canvas.width = img.width;\n    canvas.height = img.height;\n    context.drawImage(img, 0, 0)\n\n    var imageData = context.getImageData(0, 0, imgWidth, imgHeight),\n        data = imageData.data,\n        getRBG = function(x, y) {\n            var offset = imgWidth * y + x;\n            return {\n                red:     data[offset * 4],\n                green:   data[offset * 4 + 1],\n                blue:    data[offset * 4 + 2],\n                opacity: data[offset * 4 + 3]\n            };\n        },\n        isWhite = function (rgb) {\n            // many images contain noise, as the white is not a pure #fff white\n            //return rgb.red > 200 && rgb.green > 200 && rgb.blue > 200;\n            return rgb.opacity === 0;\n        },\n        scanY = function (fromTop) {\n            var offset = fromTop ? 1 : -1;\n            \n            // loop through each row\n            for(var y = fromTop ? 0 : imgHeight - 1; fromTop ? (y < imgHeight) : (y > -1); y += offset) {\n                \n                // loop through each column\n                for(var x = 0; x < imgWidth; x++) {\n                    var rgb = getRBG(x, y);\n                    if (!isWhite(rgb)) {\n                        return y;                        \n                    }      \n                }\n            }\n            return null; // all image is white\n        },\n        scanX = function (fromLeft) {\n            var offset = fromLeft? 1 : -1;\n            \n            // loop through each column\n            for(var x = fromLeft ? 0 : imgWidth - 1; fromLeft ? (x < imgWidth) : (x > -1); x += offset) {\n                \n                // loop through each row\n                for(var y = 0; y < imgHeight; y++) {\n                    var rgb = getRBG(x, y);\n                    if (!isWhite(rgb)) {\n                        return x;                        \n                    }      \n                }\n            }\n            return null; // all image is white\n        };\n    \n    var cropTop = scanY(true),\n        cropBottom = scanY(false),\n        cropLeft = scanX(true),\n        cropRight = scanX(false),\n        cropWidth = cropRight - cropLeft + 1,\n        cropHeight = cropBottom - cropTop + 1;\n    \n    var croppedCanvas = document.createElement('canvas');\n    croppedCanvas.width = cropWidth;\n    croppedCanvas.height = cropHeight;\n\n    //$(\"<canvas>\").attr({ width: cropWidth, height: cropHeight });\n    \n    // finally crop the guy\n    croppedCanvas.getContext(\"2d\").drawImage(\n        canvas,\n        cropLeft, cropTop, \n        cropWidth, cropHeight,\n        0, 0, \n        cropWidth, cropHeight );\n    \n    /*$(\"body\").\n        append(\"<p>same image with white spaces cropped:</p>\").\n        append($croppedCanvas);*/\n    //console.log(cropTop, cropBottom, cropLeft, cropRight);\n\n    var dataURL = croppedCanvas.toDataURL();\n    return {dataURL:dataURL, left:cropLeft, top:cropTop};\n};\n\nfunction getColorIndicesForCoord(x, y, width) {\n  var red = y * (width * 4) + x * 4;\n  return {\n    r: red,\n    g: red+1,\n    b: red+2,\n    a: red+3,\n  }\n  //[red, red + 1, red + 2, red + 3];\n}\n\nfunction getPixelAt (x,y,width,height,imageData) {\n  if(x<0 || y<0 || x>=width || y>=height) return null;\n\n  var offset = (y*width+x)*4;\n  return {\n    r: imageData[offset],\n    g: imageData[offset+1],\n    b: imageData[offset+2],\n    a: imageData[offset+3]\n  }\n}\n\nfunction setPixelAt (x,y,width,height,imageData,color) {\n  var offset = (y*width+x)*4;\n  imageData[offset] = color.r\n  imageData[offset+1] = color.g\n  imageData[offset+2] = color.b\n  imageData[offset+3] = color.a\n}\n</script>\n<script>/*jshint eqnull:true*/\n(function (root) {\n  \"use strict\";\n\n  var GLOBAL_KEY = \"Random\";\n\n  var imul = (typeof Math.imul !== \"function\" || Math.imul(0xffffffff, 5) !== -5 ?\n    function (a, b) {\n      var ah = (a >>> 16) & 0xffff;\n      var al = a & 0xffff;\n      var bh = (b >>> 16) & 0xffff;\n      var bl = b & 0xffff;\n      // the shift by 0 fixes the sign on the high part\n      // the final |0 converts the unsigned value into a signed value\n      return (al * bl) + (((ah * bl + al * bh) << 16) >>> 0) | 0;\n    } :\n    Math.imul);\n\n  var stringRepeat = (typeof String.prototype.repeat === \"function\" && \"x\".repeat(3) === \"xxx\" ?\n    function (x, y) {\n      return x.repeat(y);\n    } : function (pattern, count) {\n      var result = \"\";\n      while (count > 0) {\n        if (count & 1) {\n          result += pattern;\n        }\n        count >>= 1;\n        pattern += pattern;\n      }\n      return result;\n    });\n\n  function Random(engine) {\n    if (!(this instanceof Random)) {\n      return new Random(engine);\n    }\n\n    if (engine == null) {\n      engine = Random.engines.nativeMath;\n    } else if (typeof engine !== \"function\") {\n      throw new TypeError(\"Expected engine to be a function, got \" + typeof engine);\n    }\n    this.engine = engine;\n  }\n  var proto = Random.prototype;\n\n  Random.engines = {\n    nativeMath: function () {\n      return (Math.random() * 0x100000000) | 0;\n    },\n    mt19937: (function (Int32Array) {\n      // http://en.wikipedia.org/wiki/Mersenne_twister\n      function refreshData(data) {\n        var k = 0;\n        var tmp = 0;\n        for (;\n          (k | 0) < 227; k = (k + 1) | 0) {\n          tmp = (data[k] & 0x80000000) | (data[(k + 1) | 0] & 0x7fffffff);\n          data[k] = data[(k + 397) | 0] ^ (tmp >>> 1) ^ ((tmp & 0x1) ? 0x9908b0df : 0);\n        }\n\n        for (;\n          (k | 0) < 623; k = (k + 1) | 0) {\n          tmp = (data[k] & 0x80000000) | (data[(k + 1) | 0] & 0x7fffffff);\n          data[k] = data[(k - 227) | 0] ^ (tmp >>> 1) ^ ((tmp & 0x1) ? 0x9908b0df : 0);\n        }\n\n        tmp = (data[623] & 0x80000000) | (data[0] & 0x7fffffff);\n        data[623] = data[396] ^ (tmp >>> 1) ^ ((tmp & 0x1) ? 0x9908b0df : 0);\n      }\n\n      function temper(value) {\n        value ^= value >>> 11;\n        value ^= (value << 7) & 0x9d2c5680;\n        value ^= (value << 15) & 0xefc60000;\n        return value ^ (value >>> 18);\n      }\n\n      function seedWithArray(data, source) {\n        var i = 1;\n        var j = 0;\n        var sourceLength = source.length;\n        var k = Math.max(sourceLength, 624) | 0;\n        var previous = data[0] | 0;\n        for (;\n          (k | 0) > 0; --k) {\n          data[i] = previous = ((data[i] ^ imul((previous ^ (previous >>> 30)), 0x0019660d)) + (source[j] | 0) + (j | 0)) | 0;\n          i = (i + 1) | 0;\n          ++j;\n          if ((i | 0) > 623) {\n            data[0] = data[623];\n            i = 1;\n          }\n          if (j >= sourceLength) {\n            j = 0;\n          }\n        }\n        for (k = 623;\n          (k | 0) > 0; --k) {\n          data[i] = previous = ((data[i] ^ imul((previous ^ (previous >>> 30)), 0x5d588b65)) - i) | 0;\n          i = (i + 1) | 0;\n          if ((i | 0) > 623) {\n            data[0] = data[623];\n            i = 1;\n          }\n        }\n        data[0] = 0x80000000;\n      }\n\n      function mt19937() {\n        var data = new Int32Array(624);\n        var index = 0;\n        var uses = 0;\n\n        function next() {\n          if ((index | 0) >= 624) {\n            refreshData(data);\n            index = 0;\n          }\n\n          var value = data[index];\n          index = (index + 1) | 0;\n          uses += 1;\n          return temper(value) | 0;\n        }\n        next.getUseCount = function() {\n          return uses;\n        };\n        next.discard = function (count) {\n          uses += count;\n          if ((index | 0) >= 624) {\n            refreshData(data);\n            index = 0;\n          }\n          while ((count - index) > 624) {\n            count -= 624 - index;\n            refreshData(data);\n            index = 0;\n          }\n          index = (index + count) | 0;\n          return next;\n        };\n        next.seed = function (initial) {\n          var previous = 0;\n          data[0] = previous = initial | 0;\n\n          for (var i = 1; i < 624; i = (i + 1) | 0) {\n            data[i] = previous = (imul((previous ^ (previous >>> 30)), 0x6c078965) + i) | 0;\n          }\n          index = 624;\n          uses = 0;\n          return next;\n        };\n        next.seedWithArray = function (source) {\n          next.seed(0x012bd6aa);\n          seedWithArray(data, source);\n          return next;\n        };\n        next.autoSeed = function () {\n          return next.seedWithArray(Random.generateEntropyArray());\n        };\n        return next;\n      }\n\n      return mt19937;\n    }(typeof Int32Array === \"function\" ? Int32Array : Array)),\n    browserCrypto: (typeof crypto !== \"undefined\" && typeof crypto.getRandomValues === \"function\" && typeof Int32Array === \"function\") ? (function () {\n      var data = null;\n      var index = 128;\n\n      return function () {\n        if (index >= 128) {\n          if (data === null) {\n            data = new Int32Array(128);\n          }\n          crypto.getRandomValues(data);\n          index = 0;\n        }\n\n        return data[index++] | 0;\n      };\n    }()) : null\n  };\n\n  Random.generateEntropyArray = function () {\n    var array = [];\n    var engine = Random.engines.nativeMath;\n    for (var i = 0; i < 16; ++i) {\n      array[i] = engine() | 0;\n    }\n    array.push(new Date().getTime() | 0);\n    return array;\n  };\n\n  function returnValue(value) {\n    return function () {\n      return value;\n    };\n  }\n\n  // [-0x80000000, 0x7fffffff]\n  Random.int32 = function (engine) {\n    return engine() | 0;\n  };\n  proto.int32 = function () {\n    return Random.int32(this.engine);\n  };\n\n  // [0, 0xffffffff]\n  Random.uint32 = function (engine) {\n    return engine() >>> 0;\n  };\n  proto.uint32 = function () {\n    return Random.uint32(this.engine);\n  };\n\n  // [0, 0x1fffffffffffff]\n  Random.uint53 = function (engine) {\n    var high = engine() & 0x1fffff;\n    var low = engine() >>> 0;\n    return (high * 0x100000000) + low;\n  };\n  proto.uint53 = function () {\n    return Random.uint53(this.engine);\n  };\n\n  // [0, 0x20000000000000]\n  Random.uint53Full = function (engine) {\n    while (true) {\n      var high = engine() | 0;\n      if (high & 0x200000) {\n        if ((high & 0x3fffff) === 0x200000 && (engine() | 0) === 0) {\n          return 0x20000000000000;\n        }\n      } else {\n        var low = engine() >>> 0;\n        return ((high & 0x1fffff) * 0x100000000) + low;\n      }\n    }\n  };\n  proto.uint53Full = function () {\n    return Random.uint53Full(this.engine);\n  };\n\n  // [-0x20000000000000, 0x1fffffffffffff]\n  Random.int53 = function (engine) {\n    var high = engine() | 0;\n    var low = engine() >>> 0;\n    return ((high & 0x1fffff) * 0x100000000) + low + (high & 0x200000 ? -0x20000000000000 : 0);\n  };\n  proto.int53 = function () {\n    return Random.int53(this.engine);\n  };\n\n  // [-0x20000000000000, 0x20000000000000]\n  Random.int53Full = function (engine) {\n    while (true) {\n      var high = engine() | 0;\n      if (high & 0x400000) {\n        if ((high & 0x7fffff) === 0x400000 && (engine() | 0) === 0) {\n          return 0x20000000000000;\n        }\n      } else {\n        var low = engine() >>> 0;\n        return ((high & 0x1fffff) * 0x100000000) + low + (high & 0x200000 ? -0x20000000000000 : 0);\n      }\n    }\n  };\n  proto.int53Full = function () {\n    return Random.int53Full(this.engine);\n  };\n\n  function add(generate, addend) {\n    if (addend === 0) {\n      return generate;\n    } else {\n      return function (engine) {\n        return generate(engine) + addend;\n      };\n    }\n  }\n\n  Random.integer = (function () {\n    function isPowerOfTwoMinusOne(value) {\n      return ((value + 1) & value) === 0;\n    }\n\n    function bitmask(masking) {\n      return function (engine) {\n        return engine() & masking;\n      };\n    }\n\n    function downscaleToLoopCheckedRange(range) {\n      var extendedRange = range + 1;\n      var maximum = extendedRange * Math.floor(0x100000000 / extendedRange);\n      return function (engine) {\n        var value = 0;\n        do {\n          value = engine() >>> 0;\n        } while (value >= maximum);\n        return value % extendedRange;\n      };\n    }\n\n    function downscaleToRange(range) {\n      if (isPowerOfTwoMinusOne(range)) {\n        return bitmask(range);\n      } else {\n        return downscaleToLoopCheckedRange(range);\n      }\n    }\n\n    function isEvenlyDivisibleByMaxInt32(value) {\n      return (value | 0) === 0;\n    }\n\n    function upscaleWithHighMasking(masking) {\n      return function (engine) {\n        var high = engine() & masking;\n        var low = engine() >>> 0;\n        return (high * 0x100000000) + low;\n      };\n    }\n\n    function upscaleToLoopCheckedRange(extendedRange) {\n      var maximum = extendedRange * Math.floor(0x20000000000000 / extendedRange);\n      return function (engine) {\n        var ret = 0;\n        do {\n          var high = engine() & 0x1fffff;\n          var low = engine() >>> 0;\n          ret = (high * 0x100000000) + low;\n        } while (ret >= maximum);\n        return ret % extendedRange;\n      };\n    }\n\n    function upscaleWithinU53(range) {\n      var extendedRange = range + 1;\n      if (isEvenlyDivisibleByMaxInt32(extendedRange)) {\n        var highRange = ((extendedRange / 0x100000000) | 0) - 1;\n        if (isPowerOfTwoMinusOne(highRange)) {\n          return upscaleWithHighMasking(highRange);\n        }\n      }\n      return upscaleToLoopCheckedRange(extendedRange);\n    }\n\n    function upscaleWithinI53AndLoopCheck(min, max) {\n      return function (engine) {\n        var ret = 0;\n        do {\n          var high = engine() | 0;\n          var low = engine() >>> 0;\n          ret = ((high & 0x1fffff) * 0x100000000) + low + (high & 0x200000 ? -0x20000000000000 : 0);\n        } while (ret < min || ret > max);\n        return ret;\n      };\n    }\n\n    return function (min, max) {\n      min = Math.floor(min);\n      max = Math.floor(max);\n      if (min < -0x20000000000000 || !isFinite(min)) {\n        throw new RangeError(\"Expected min to be at least \" + (-0x20000000000000));\n      } else if (max > 0x20000000000000 || !isFinite(max)) {\n        throw new RangeError(\"Expected max to be at most \" + 0x20000000000000);\n      }\n\n      var range = max - min;\n      if (range <= 0 || !isFinite(range)) {\n        return returnValue(min);\n      } else if (range === 0xffffffff) {\n        if (min === 0) {\n          return Random.uint32;\n        } else {\n          return add(Random.int32, min + 0x80000000);\n        }\n      } else if (range < 0xffffffff) {\n        return add(downscaleToRange(range), min);\n      } else if (range === 0x1fffffffffffff) {\n        return add(Random.uint53, min);\n      } else if (range < 0x1fffffffffffff) {\n        return add(upscaleWithinU53(range), min);\n      } else if (max - 1 - min === 0x1fffffffffffff) {\n        return add(Random.uint53Full, min);\n      } else if (min === -0x20000000000000 && max === 0x20000000000000) {\n        return Random.int53Full;\n      } else if (min === -0x20000000000000 && max === 0x1fffffffffffff) {\n        return Random.int53;\n      } else if (min === -0x1fffffffffffff && max === 0x20000000000000) {\n        return add(Random.int53, 1);\n      } else if (max === 0x20000000000000) {\n        return add(upscaleWithinI53AndLoopCheck(min - 1, max - 1), 1);\n      } else {\n        return upscaleWithinI53AndLoopCheck(min, max);\n      }\n    };\n  }());\n  proto.integer = function (min, max) {\n    return Random.integer(min, max)(this.engine);\n  };\n\n  // [0, 1] (floating point)\n  Random.realZeroToOneInclusive = function (engine) {\n    return Random.uint53Full(engine) / 0x20000000000000;\n  };\n  proto.realZeroToOneInclusive = function () {\n    return Random.realZeroToOneInclusive(this.engine);\n  };\n\n  // [0, 1) (floating point)\n  Random.realZeroToOneExclusive = function (engine) {\n    return Random.uint53(engine) / 0x20000000000000;\n  };\n  proto.realZeroToOneExclusive = function () {\n    return Random.realZeroToOneExclusive(this.engine);\n  };\n\n  Random.real = (function () {\n    function multiply(generate, multiplier) {\n      if (multiplier === 1) {\n        return generate;\n      } else if (multiplier === 0) {\n        return function () {\n          return 0;\n        };\n      } else {\n        return function (engine) {\n          return generate(engine) * multiplier;\n        };\n      }\n    }\n\n    return function (left, right, inclusive) {\n      if (!isFinite(left)) {\n        throw new RangeError(\"Expected left to be a finite number\");\n      } else if (!isFinite(right)) {\n        throw new RangeError(\"Expected right to be a finite number\");\n      }\n      return add(\n        multiply(\n          inclusive ? Random.realZeroToOneInclusive : Random.realZeroToOneExclusive,\n          right - left),\n        left);\n    };\n  }());\n  proto.real = function (min, max, inclusive) {\n    return Random.real(min, max, inclusive)(this.engine);\n  };\n\n  Random.bool = (function () {\n    function isLeastBitTrue(engine) {\n      return (engine() & 1) === 1;\n    }\n\n    function lessThan(generate, value) {\n      return function (engine) {\n        return generate(engine) < value;\n      };\n    }\n\n    function probability(percentage) {\n      if (percentage <= 0) {\n        return returnValue(false);\n      } else if (percentage >= 1) {\n        return returnValue(true);\n      } else {\n        var scaled = percentage * 0x100000000;\n        if (scaled % 1 === 0) {\n          return lessThan(Random.int32, (scaled - 0x80000000) | 0);\n        } else {\n          return lessThan(Random.uint53, Math.round(percentage * 0x20000000000000));\n        }\n      }\n    }\n\n    return function (numerator, denominator) {\n      if (denominator == null) {\n        if (numerator == null) {\n          return isLeastBitTrue;\n        }\n        return probability(numerator);\n      } else {\n        if (numerator <= 0) {\n          return returnValue(false);\n        } else if (numerator >= denominator) {\n          return returnValue(true);\n        }\n        return lessThan(Random.integer(0, denominator - 1), numerator);\n      }\n    };\n  }());\n  proto.bool = function (numerator, denominator) {\n    return Random.bool(numerator, denominator)(this.engine);\n  };\n\n  function toInteger(value) {\n    var number = +value;\n    if (number < 0) {\n      return Math.ceil(number);\n    } else {\n      return Math.floor(number);\n    }\n  }\n\n  function convertSliceArgument(value, length) {\n    if (value < 0) {\n      return Math.max(value + length, 0);\n    } else {\n      return Math.min(value, length);\n    }\n  }\n  Random.pick = function (engine, array, begin, end) {\n    var length = array.length;\n    var start = begin == null ? 0 : convertSliceArgument(toInteger(begin), length);\n    var finish = end === void 0 ? length : convertSliceArgument(toInteger(end), length);\n    if (start >= finish) {\n      return void 0;\n    }\n    var distribution = Random.integer(start, finish - 1);\n    return array[distribution(engine)];\n  };\n  proto.pick = function (array, begin, end) {\n    return Random.pick(this.engine, array, begin, end);\n  };\n\n  function returnUndefined() {\n    return void 0;\n  }\n  var slice = Array.prototype.slice;\n  Random.picker = function (array, begin, end) {\n    var clone = slice.call(array, begin, end);\n    if (!clone.length) {\n      return returnUndefined;\n    }\n    var distribution = Random.integer(0, clone.length - 1);\n    return function (engine) {\n      return clone[distribution(engine)];\n    };\n  };\n\n  Random.shuffle = function (engine, array, downTo) {\n    var length = array.length;\n    if (length) {\n      if (downTo == null) {\n        downTo = 0;\n      }\n      for (var i = (length - 1) >>> 0; i > downTo; --i) {\n        var distribution = Random.integer(0, i);\n        var j = distribution(engine);\n        if (i !== j) {\n          var tmp = array[i];\n          array[i] = array[j];\n          array[j] = tmp;\n        }\n      }\n    }\n    return array;\n  };\n  proto.shuffle = function (array) {\n    return Random.shuffle(this.engine, array);\n  };\n\n  Random.sample = function (engine, population, sampleSize) {\n    if (sampleSize < 0 || sampleSize > population.length || !isFinite(sampleSize)) {\n      throw new RangeError(\"Expected sampleSize to be within 0 and the length of the population\");\n    }\n\n    if (sampleSize === 0) {\n      return [];\n    }\n\n    var clone = slice.call(population);\n    var length = clone.length;\n    if (length === sampleSize) {\n      return Random.shuffle(engine, clone, 0);\n    }\n    var tailLength = length - sampleSize;\n    return Random.shuffle(engine, clone, tailLength - 1).slice(tailLength);\n  };\n  proto.sample = function (population, sampleSize) {\n    return Random.sample(this.engine, population, sampleSize);\n  };\n\n  Random.die = function (sideCount) {\n    return Random.integer(1, sideCount);\n  };\n  proto.die = function (sideCount) {\n    return Random.die(sideCount)(this.engine);\n  };\n\n  Random.dice = function (sideCount, dieCount) {\n    var distribution = Random.die(sideCount);\n    return function (engine) {\n      var result = [];\n      result.length = dieCount;\n      for (var i = 0; i < dieCount; ++i) {\n        result[i] = distribution(engine);\n      }\n      return result;\n    };\n  };\n  proto.dice = function (sideCount, dieCount) {\n    return Random.dice(sideCount, dieCount)(this.engine);\n  };\n\n  // http://en.wikipedia.org/wiki/Universally_unique_identifier\n  Random.uuid4 = (function () {\n    function zeroPad(string, zeroCount) {\n      return stringRepeat(\"0\", zeroCount - string.length) + string;\n    }\n\n    return function (engine) {\n      var a = engine() >>> 0;\n      var b = engine() | 0;\n      var c = engine() | 0;\n      var d = engine() >>> 0;\n\n      return (\n        zeroPad(a.toString(16), 8) +\n        \"-\" +\n        zeroPad((b & 0xffff).toString(16), 4) +\n        \"-\" +\n        zeroPad((((b >> 4) & 0x0fff) | 0x4000).toString(16), 4) +\n        \"-\" +\n        zeroPad(((c & 0x3fff) | 0x8000).toString(16), 4) +\n        \"-\" +\n        zeroPad(((c >> 4) & 0xffff).toString(16), 4) +\n        zeroPad(d.toString(16), 8));\n    };\n  }());\n  proto.uuid4 = function () {\n    return Random.uuid4(this.engine);\n  };\n\n  Random.string = (function () {\n    // has 2**x chars, for faster uniform distribution\n    var DEFAULT_STRING_POOL = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-\";\n\n    return function (pool) {\n      if (pool == null) {\n        pool = DEFAULT_STRING_POOL;\n      }\n\n      var length = pool.length;\n      if (!length) {\n        throw new Error(\"Expected pool not to be an empty string\");\n      }\n\n      var distribution = Random.integer(0, length - 1);\n      return function (engine, length) {\n        var result = \"\";\n        for (var i = 0; i < length; ++i) {\n          var j = distribution(engine);\n          result += pool.charAt(j);\n        }\n        return result;\n      };\n    };\n  }());\n  proto.string = function (length, pool) {\n    return Random.string(pool)(this.engine, length);\n  };\n\n  Random.hex = (function () {\n    var LOWER_HEX_POOL = \"0123456789abcdef\";\n    var lowerHex = Random.string(LOWER_HEX_POOL);\n    var upperHex = Random.string(LOWER_HEX_POOL.toUpperCase());\n\n    return function (upper) {\n      if (upper) {\n        return upperHex;\n      } else {\n        return lowerHex;\n      }\n    };\n  }());\n  proto.hex = function (length, upper) {\n    return Random.hex(upper)(this.engine, length);\n  };\n\n  Random.date = function (start, end) {\n    if (!(start instanceof Date)) {\n      throw new TypeError(\"Expected start to be a Date, got \" + typeof start);\n    } else if (!(end instanceof Date)) {\n      throw new TypeError(\"Expected end to be a Date, got \" + typeof end);\n    }\n    var distribution = Random.integer(start.getTime(), end.getTime());\n    return function (engine) {\n      return new Date(distribution(engine));\n    };\n  };\n  proto.date = function (start, end) {\n    return Random.date(start, end)(this.engine);\n  };\n\n  if (typeof define === \"function\" && define.amd) {\n    define(function () {\n      return Random;\n    });\n  } else if (typeof module !== \"undefined\" && typeof require === \"function\") {\n    module.exports = Random;\n  } else {\n    (function () {\n      var oldGlobal = root[GLOBAL_KEY];\n      Random.noConflict = function () {\n        root[GLOBAL_KEY] = oldGlobal;\n        return this;\n      };\n    }());\n    root[GLOBAL_KEY] = Random;\n  }\n}(this));\n\nwindow.random = new Random();\nwindow.randomInt = function (min,max) { return random.integer(min,max); };\nwindow.randomBool = function () { return random.bool() };\nwindow.randomFloat = function (min,max) { return random.real(min,max); };</script>\n<script>/* SAT.js - Version 0.6.0 - Copyright 2012 - 2016 - Jim Riecken <jimr@jimr.ca> - released under the MIT License. https://github.com/jriecken/sat-js */\nfunction x(){function c(a,e){this.x=a||0;this.y=e||0}function B(a,e){this.pos=a||new c;this.r=e||0}function n(a,e){this.pos=a||new c;this.angle=0;this.offset=new c;this.u(e||[])}function q(a,e,b){this.pos=a||new c;this.w=e||0;this.h=b||0}function w(){this.b=this.a=null;this.overlapN=new c;this.overlapV=new c;this.clear()}function C(a,e,b){for(var h=Number.MAX_VALUE,c=-Number.MAX_VALUE,k=a.length,g=0;g<k;g++){var d=a[g].f(e);d<h&&(h=d);d>c&&(c=d)}b[0]=h;b[1]=c}function y(a,e,b,h,c,k){var g=r.pop(),\nd=r.pop();a=m.pop().c(e).sub(a);e=a.f(c);C(b,c,g);C(h,c,d);d[0]+=e;d[1]+=e;if(g[0]>d[1]||d[0]>g[1])return m.push(a),r.push(g),r.push(d),!0;k&&(g[0]<d[0]?(k.aInB=!1,g[1]<d[1]?(b=g[1]-d[0],k.bInA=!1):(b=g[1]-d[0],h=d[1]-g[0],b=b<h?b:-h)):(k.bInA=!1,g[1]>d[1]?(b=g[0]-d[1],k.aInB=!1):(b=g[1]-d[0],h=d[1]-g[0],b=b<h?b:-h)),h=Math.abs(b),h<k.overlap&&(k.overlap=h,k.overlapN.c(c),0>b&&k.overlapN.reverse()));m.push(a);r.push(g);r.push(d);return!1}function z(a,e){var b=a.g(),c=e.f(a);return 0>c?-1:c>b?1:0}\nfunction D(a,e,b){for(var c=m.pop().c(e.pos).sub(a.pos),l=e.r,k=l*l,g=a.calcPoints,d=g.length,u=m.pop(),f=m.pop(),n=0;n<d;n++){var v=n===d-1?0:n+1,r=0===n?d-1:n-1,q=0,t=null;u.c(a.edges[n]);f.c(c).sub(g[n]);b&&f.g()>k&&(b.aInB=!1);var p=z(u,f);if(-1===p){u.c(a.edges[r]);v=m.pop().c(c).sub(g[r]);p=z(u,v);if(1===p){p=f.j();if(p>l)return m.push(c),m.push(u),m.push(f),m.push(v),!1;b&&(b.bInA=!1,t=f.normalize(),q=l-p)}m.push(v)}else if(1===p){if(u.c(a.edges[v]),f.c(c).sub(g[v]),p=z(u,f),-1===p){p=f.j();\nif(p>l)return m.push(c),m.push(u),m.push(f),!1;b&&(b.bInA=!1,t=f.normalize(),q=l-p)}}else{v=u.m().normalize();p=f.f(v);r=Math.abs(p);if(0<p&&r>l)return m.push(c),m.push(v),m.push(f),!1;b&&(t=v,q=l-p,0<=p||q<2*l)&&(b.bInA=!1)}t&&b&&Math.abs(q)<Math.abs(b.overlap)&&(b.overlap=q,b.overlapN.c(t))}b&&(b.a=a,b.b=e,b.overlapV.c(b.overlapN).scale(b.overlap));m.push(c);m.push(u);m.push(f);return!0}function E(a,e,b){for(var c=a.calcPoints,l=c.length,k=e.calcPoints,g=k.length,d=0;d<l;d++)if(y(a.pos,e.pos,c,\nk,a.normals[d],b))return!1;for(d=0;d<g;d++)if(y(a.pos,e.pos,c,k,e.normals[d],b))return!1;b&&(b.a=a,b.b=e,b.overlapV.c(b.overlapN).scale(b.overlap));return!0}var f={};f.Vector=c;f.V=c;c.prototype.copy=c.prototype.c=function(a){this.x=a.x;this.y=a.y;return this};c.prototype.clone=c.prototype.clone=function(){return new c(this.x,this.y)};c.prototype.perp=c.prototype.m=function(){var a=this.x;this.x=this.y;this.y=-a;return this};c.prototype.rotate=c.prototype.rotate=function(a){var e=this.x,b=this.y;\nthis.x=e*Math.cos(a)-b*Math.sin(a);this.y=e*Math.sin(a)+b*Math.cos(a);return this};c.prototype.reverse=c.prototype.reverse=function(){this.x=-this.x;this.y=-this.y;return this};c.prototype.normalize=c.prototype.normalize=function(){var a=this.j();0<a&&(this.x/=a,this.y/=a);return this};c.prototype.add=c.prototype.add=function(a){this.x+=a.x;this.y+=a.y;return this};c.prototype.sub=c.prototype.sub=function(a){this.x-=a.x;this.y-=a.y;return this};c.prototype.scale=c.prototype.scale=function(a,e){this.x*=\na;this.y*=e||a;return this};c.prototype.project=c.prototype.o=function(a){var e=this.f(a)/a.g();this.x=e*a.x;this.y=e*a.y;return this};c.prototype.projectN=c.prototype.s=function(a){var e=this.f(a);this.x=e*a.x;this.y=e*a.y;return this};c.prototype.reflect=function(a){var e=this.x,b=this.y;this.o(a).scale(2);this.x-=e;this.y-=b;return this};c.prototype.reflectN=function(a){var e=this.x,b=this.y;this.s(a).scale(2);this.x-=e;this.y-=b;return this};c.prototype.dot=c.prototype.f=function(a){return this.x*\na.x+this.y*a.y};c.prototype.len2=c.prototype.g=function(){return this.f(this)};c.prototype.len=c.prototype.j=function(){return Math.sqrt(this.g())};f.Circle=B;B.prototype.getAABB=function(){var a=this.r,e=this.pos.clone().sub(new c(a,a));return(new q(e,2*a,2*a)).l()};f.Polygon=n;n.prototype.setPoints=n.prototype.u=function(a){if(!this.points||this.points.length!==a.length){var e,b=this.calcPoints=[],h=this.edges=[],l=this.normals=[];for(e=0;e<a.length;e++)b.push(new c),h.push(new c),l.push(new c)}this.points=\na;this.i();return this};n.prototype.setAngle=function(a){this.angle=a;this.i();return this};n.prototype.setOffset=function(a){this.offset=a;this.i();return this};n.prototype.rotate=n.prototype.rotate=function(a){for(var e=this.points,b=e.length,c=0;c<b;c++)e[c].rotate(a);this.i();return this};n.prototype.translate=n.prototype.translate=function(a,c){for(var b=this.points,h=b.length,l=0;l<h;l++)b[l].x+=a,b[l].y+=c;this.i();return this};n.prototype.i=function(){var a=this.calcPoints,c=this.edges,b=\nthis.normals,h=this.points,l=this.offset,k=this.angle,g=h.length,d;for(d=0;d<g;d++){var f=a[d].c(h[d]);f.x+=l.x;f.y+=l.y;0!==k&&f.rotate(k)}for(d=0;d<g;d++)h=a[d],h=c[d].c(d<g-1?a[d+1]:a[0]).sub(h),b[d].c(h).m().normalize()};n.prototype.getAABB=function(){for(var a=this.calcPoints,e=a.length,b=a[0].x,h=a[0].y,f=a[0].x,k=a[0].y,g=1;g<e;g++){var d=a[g];d.x<b?b=d.x:d.x>f&&(f=d.x);d.y<h?h=d.y:d.y>k&&(k=d.y)}return(new q(this.pos.clone().add(new c(b,h)),f-b,k-h)).l()};f.Box=q;q.prototype.toPolygon=q.prototype.l=\nfunction(){var a=this.pos,e=this.w,b=this.h;return new n(new c(a.x,a.y),[new c,new c(e,0),new c(e,b),new c(0,b)])};f.Response=w;w.prototype.clear=w.prototype.clear=function(){this.bInA=this.aInB=!0;this.overlap=Number.MAX_VALUE;return this};for(var m=[],t=0;10>t;t++)m.push(new c);for(var r=[],t=0;5>t;t++)r.push([]);var A=new w,F=(new q(new c,1E-6,1E-6)).l();f.isSeparatingAxis=y;f.pointInCircle=function(a,c){var b=m.pop().c(a).sub(c.pos),h=c.r*c.r,f=b.g();m.push(b);return f<=h};f.pointInPolygon=function(a,\nc){F.pos.c(a);A.clear();var b=E(F,c,A);b&&(b=A.aInB);return b};f.testCircleCircle=function(a,c,b){var f=m.pop().c(c.pos).sub(a.pos),l=a.r+c.r,k=f.g();if(k>l*l)return m.push(f),!1;b&&(k=Math.sqrt(k),b.a=a,b.b=c,b.overlap=l-k,b.overlapN.c(f.normalize()),b.overlapV.c(f).scale(b.overlap),b.aInB=a.r<=c.r&&k<=c.r-a.r,b.bInA=c.r<=a.r&&k<=a.r-c.r);m.push(f);return!0};f.testPolygonCircle=D;f.testCirclePolygon=function(a,c,b){if((a=D(c,a,b))&&b){c=b.a;var f=b.aInB;b.overlapN.reverse();b.overlapV.reverse();\nb.a=b.b;b.b=c;b.aInB=b.bInA;b.bInA=f}return a};f.testPolygonPolygon=E;return f}\"function\"===typeof define&&define.amd?define(x):\"object\"===typeof exports?module.exports=x():this.SAT=x();</script>\n<script>/*! jQuery v2.1.4 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */\n!function(a,b){\"object\"==typeof module&&\"object\"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error(\"jQuery requires a window with a document\");return b(a)}:b(a)}(\"undefined\"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m=\"2.1.4\",n=function(a,b){return new n.fn.init(a,b)},o=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,p=/^-ms-/,q=/-([\\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:\"\",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for(\"boolean\"==typeof g&&(j=g,g=arguments[h]||{},h++),\"object\"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:\"jQuery\"+(m+Math.random()).replace(/\\D/g,\"\"),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return\"function\"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return\"object\"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,\"isPrototypeOf\")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+\"\":\"object\"==typeof a||\"function\"==typeof a?h[i.call(a)]||\"object\":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf(\"use strict\")?(b=l.createElement(\"script\"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,\"ms-\").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?\"\":(a+\"\").replace(o,\"\")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,\"string\"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return\"string\"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"),function(a,b){h[\"[object \"+b+\"]\"]=b.toLowerCase()});function s(a){var b=\"length\"in a&&a.length,c=n.type(a);return\"function\"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:\"array\"===c||0===b||\"number\"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u=\"sizzle\"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K=\"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",L=\"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",M=\"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",N=M.replace(\"w\",\"w#\"),O=\"\\\\[\"+L+\"*(\"+M+\")(?:\"+L+\"*([*^$|!~]?=)\"+L+\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\"+N+\"))|)\"+L+\"*\\\\]\",P=\":(\"+M+\")(?:\\\\((('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\"+O+\")*)|.*)\\\\)|)\",Q=new RegExp(L+\"+\",\"g\"),R=new RegExp(\"^\"+L+\"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\"+L+\"+$\",\"g\"),S=new RegExp(\"^\"+L+\"*,\"+L+\"*\"),T=new RegExp(\"^\"+L+\"*([>+~]|\"+L+\")\"+L+\"*\"),U=new RegExp(\"=\"+L+\"*([^\\\\]'\\\"]*?)\"+L+\"*\\\\]\",\"g\"),V=new RegExp(P),W=new RegExp(\"^\"+N+\"$\"),X={ID:new RegExp(\"^#(\"+M+\")\"),CLASS:new RegExp(\"^\\\\.(\"+M+\")\"),TAG:new RegExp(\"^(\"+M.replace(\"w\",\"w*\")+\")\"),ATTR:new RegExp(\"^\"+O),PSEUDO:new RegExp(\"^\"+P),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+L+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+L+\"*(?:([+-]|)\"+L+\"*(\\\\d+)|))\"+L+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+K+\")$\",\"i\"),needsContext:new RegExp(\"^\"+L+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+L+\"*((?:-\\\\d)?\\\\d*)\"+L+\"*\\\\)|)(?=[^-]|$)\",\"i\")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\\d$/i,$=/^[^{]+\\{\\s*\\[native \\w/,_=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,aa=/[+~]/,ba=/'|\\\\/g,ca=new RegExp(\"\\\\\\\\([\\\\da-f]{1,6}\"+L+\"?|(\"+L+\")|.)\",\"ig\"),da=function(a,b,c){var d=\"0x\"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,\"string\"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&\"object\"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute(\"id\"))?s=r.replace(ba,\"\\\\$&\"):b.setAttribute(\"id\",s),s=\"[id='\"+s+\"'] \",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(\",\")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute(\"id\")}}}return i(a.replace(R,\"$1\"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+\" \")>d.cacheLength&&delete b[a.shift()],b[c+\" \"]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement(\"div\");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split(\"|\"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return\"input\"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return(\"input\"===c||\"button\"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&\"undefined\"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?\"HTML\"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener(\"unload\",ea,!1):e.attachEvent&&e.attachEvent(\"onunload\",ea)),p=!f(g),c.attributes=ja(function(a){return a.className=\"i\",!a.getAttribute(\"className\")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment(\"\")),!a.getElementsByTagName(\"*\").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(\"undefined\"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute(\"id\")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c=\"undefined\"!=typeof a.getAttributeNode&&a.getAttributeNode(\"id\");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return\"undefined\"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if(\"*\"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML=\"<a id='\"+u+\"'></a><select id='\"+u+\"-\\f]' msallowcapture=''><option selected=''></option></select>\",a.querySelectorAll(\"[msallowcapture^='']\").length&&q.push(\"[*^$]=\"+L+\"*(?:''|\\\"\\\")\"),a.querySelectorAll(\"[selected]\").length||q.push(\"\\\\[\"+L+\"*(?:value|\"+K+\")\"),a.querySelectorAll(\"[id~=\"+u+\"-]\").length||q.push(\"~=\"),a.querySelectorAll(\":checked\").length||q.push(\":checked\"),a.querySelectorAll(\"a#\"+u+\"+*\").length||q.push(\".#.+[+~]\")}),ja(function(a){var b=g.createElement(\"input\");b.setAttribute(\"type\",\"hidden\"),a.appendChild(b).setAttribute(\"name\",\"D\"),a.querySelectorAll(\"[name=d]\").length&&q.push(\"name\"+L+\"*[*^$|!~]?=\"),a.querySelectorAll(\":enabled\").length||q.push(\":enabled\",\":disabled\"),a.querySelectorAll(\"*,:x\"),q.push(\",.*:\")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,\"div\"),s.call(a,\"[s!='']:x\"),r.push(\"!=\",P)}),q=q.length&&new RegExp(q.join(\"|\")),r=r.length&&new RegExp(r.join(\"|\")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,\"='$1']\"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error(\"Syntax error, unrecognized expression: \"+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c=\"\",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if(\"string\"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{\">\":{dir:\"parentNode\",first:!0},\" \":{dir:\"parentNode\"},\"+\":{dir:\"previousSibling\",first:!0},\"~\":{dir:\"previousSibling\"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||\"\").replace(ca,da),\"~=\"===a[2]&&(a[3]=\" \"+a[3]+\" \"),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),\"nth\"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*(\"even\"===a[3]||\"odd\"===a[3])),a[5]=+(a[7]+a[8]||\"odd\"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||\"\":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(\")\",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return\"*\"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+\" \"];return b||(b=new RegExp(\"(^|\"+L+\")\"+a+\"(\"+L+\"|$)\"))&&y(a,function(a){return b.test(\"string\"==typeof a.className&&a.className||\"undefined\"!=typeof a.getAttribute&&a.getAttribute(\"class\")||\"\")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?\"!=\"===b:b?(e+=\"\",\"=\"===b?e===c:\"!=\"===b?e!==c:\"^=\"===b?c&&0===e.indexOf(c):\"*=\"===b?c&&e.indexOf(c)>-1:\"$=\"===b?c&&e.slice(-c.length)===c:\"~=\"===b?(\" \"+e.replace(Q,\" \")+\" \").indexOf(c)>-1:\"|=\"===b?e===c||e.slice(0,c.length+1)===c+\"-\":!1):!0}},CHILD:function(a,b,c,d,e){var f=\"nth\"!==a.slice(0,3),g=\"last\"!==a.slice(-4),h=\"of-type\"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?\"nextSibling\":\"previousSibling\",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p=\"only\"===a&&!o&&\"nextSibling\"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error(\"unsupported pseudo: \"+a);return e[u]?e(b):e.length>1?(c=[a,a,\"\",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,\"$1\"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||\"\")||ga.error(\"unsupported lang: \"+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute(\"xml:lang\")||b.getAttribute(\"lang\"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+\"-\");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return\"input\"===b&&!!a.checked||\"option\"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return\"input\"===b&&\"button\"===a.type||\"button\"===b},text:function(a){var b;return\"input\"===a.nodeName.toLowerCase()&&\"text\"===a.type&&(null==(b=a.getAttribute(\"type\"))||\"text\"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=ma(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=na(b);function qa(){}qa.prototype=d.filters=d.pseudos,d.setFilters=new qa,g=ga.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+\" \"];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R,\" \")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?ga.error(a):z(a,i).slice(0)};function ra(a){for(var b=0,c=a.length,d=\"\";c>b;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&\"parentNode\"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||\"*\",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[\" \"],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:\" \"===a[i-2].type?\"*\":\"\"})).replace(R,\"$1\"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q=\"0\",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG(\"*\",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+\" \"];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n=\"function\"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&\"ID\"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split(\"\").sort(B).join(\"\")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement(\"div\"))}),ja(function(a){return a.innerHTML=\"<a href='#'></a>\",\"#\"===a.firstChild.getAttribute(\"href\")})||ka(\"type|href|height|width\",function(a,b,c){return c?void 0:a.getAttribute(b,\"type\"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML=\"<input/>\",a.firstChild.setAttribute(\"value\",\"\"),\"\"===a.firstChild.getAttribute(\"value\")})||ka(\"value\",function(a,b,c){return c||\"input\"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute(\"disabled\")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);n.find=t,n.expr=t.selectors,n.expr[\":\"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,w=/^.[^:#\\[\\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if(\"string\"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=\":not(\"+a+\")\"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if(\"string\"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+\" \"+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,\"string\"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if(\"string\"==typeof a){if(c=\"<\"===a[0]&&\">\"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?\"undefined\"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||\"string\"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?\"string\"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,\"parentNode\")},parentsUntil:function(a,b,c){return n.dir(a,\"parentNode\",c)},next:function(a){return D(a,\"nextSibling\")},prev:function(a){return D(a,\"previousSibling\")},nextAll:function(a){return n.dir(a,\"nextSibling\")},prevAll:function(a){return n.dir(a,\"previousSibling\")},nextUntil:function(a,b,c){return n.dir(a,\"nextSibling\",c)},prevUntil:function(a,b,c){return n.dir(a,\"previousSibling\",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return\"Until\"!==a.slice(-5)&&(d=c),d&&\"string\"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a=\"string\"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);\"function\"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&\"string\"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[[\"resolve\",\"done\",n.Callbacks(\"once memory\"),\"resolved\"],[\"reject\",\"fail\",n.Callbacks(\"once memory\"),\"rejected\"],[\"notify\",\"progress\",n.Callbacks(\"memory\")]],c=\"pending\",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+\"With\"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+\"With\"](this===e?d:this,arguments),this},e[f[0]+\"With\"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler(\"ready\"),n(l).off(\"ready\"))))}});function I(){l.removeEventListener(\"DOMContentLoaded\",I,!1),a.removeEventListener(\"load\",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),\"complete\"===l.readyState?setTimeout(n.ready):(l.addEventListener(\"DOMContentLoaded\",I,!1),a.addEventListener(\"load\",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if(\"object\"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if(\"string\"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&\"string\"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d=\"data-\"+b.replace(O,\"-$1\").toLowerCase(),c=a.getAttribute(d),\"string\"==typeof c){try{c=\"true\"===c?!0:\"false\"===c?!1:\"null\"===c?null:+c+\"\"===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){\nreturn M.access(a,b,c)},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,\"hasDataAttrs\"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf(\"data-\")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,\"hasDataAttrs\",!0)}return e}return\"object\"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf(\"-\")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||\"fx\")+\"queue\",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||\"fx\";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};\"inprogress\"===e&&(e=c.shift(),d--),e&&(\"fx\"===b&&c.unshift(\"inprogress\"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+\"queueHooks\";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks(\"once memory\").add(function(){L.remove(a,[b+\"queue\",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return\"string\"!=typeof a&&(b=a,a=\"fx\",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),\"fx\"===a&&\"inprogress\"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||\"fx\",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};\"string\"!=typeof a&&(b=a,a=void 0),a=a||\"fx\";while(g--)c=L.get(f[g],a+\"queueHooks\"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var Q=/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,R=[\"Top\",\"Right\",\"Bottom\",\"Left\"],S=function(a,b){return a=b||a,\"none\"===n.css(a,\"display\")||!n.contains(a.ownerDocument,a)},T=/^(?:checkbox|radio)$/i;!function(){var a=l.createDocumentFragment(),b=a.appendChild(l.createElement(\"div\")),c=l.createElement(\"input\");c.setAttribute(\"type\",\"radio\"),c.setAttribute(\"checked\",\"checked\"),c.setAttribute(\"name\",\"t\"),b.appendChild(c),k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML=\"<textarea>x</textarea>\",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U=\"undefined\";k.focusinBubbles=\"onfocusin\"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||\"\").match(E)||[\"\"],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||\"\").split(\".\").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(\".\")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||\"\").match(E)||[\"\"],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||\"\").split(\".\").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp(\"(^|\\\\.)\"+p.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&(\"**\"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,\"events\"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,\"type\")?b.type:b,r=j.call(b,\"namespace\")?b.namespace.split(\".\"):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(\".\")>=0&&(r=q.split(\".\"),q=r.shift(),r.sort()),k=q.indexOf(\":\")<0&&\"on\"+q,b=b[n.expando]?b:new n.Event(q,\"object\"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join(\".\"),b.namespace_re=b.namespace?new RegExp(\"(^|\\\\.)\"+r.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,\"events\")||{})[b.type]&&L.get(g,\"handle\"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,\"events\")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||\"click\"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||\"click\"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+\" \",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},props:\"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),fixHooks:{},keyHooks:{props:\"char charCode key keyCode\".split(\" \"),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:\"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),filter:function(a,b){var c,d,e,f=b.button;return null==a.pageX&&null!=b.clientX&&(c=a.target.ownerDocument||l,d=c.documentElement,e=c.body,a.pageX=b.clientX+(d&&d.scrollLeft||e&&e.scrollLeft||0)-(d&&d.clientLeft||e&&e.clientLeft||0),a.pageY=b.clientY+(d&&d.scrollTop||e&&e.scrollTop||0)-(d&&d.clientTop||e&&e.clientTop||0)),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},fix:function(a){if(a[n.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=W.test(e)?this.mouseHooks:V.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new n.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=l),3===a.target.nodeType&&(a.target=a.target.parentNode),g.filter?g.filter(a,f):a},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==_()&&this.focus?(this.focus(),!1):void 0},delegateType:\"focusin\"},blur:{trigger:function(){return this===_()&&this.blur?(this.blur(),!1):void 0},delegateType:\"focusout\"},click:{trigger:function(){return\"checkbox\"===this.type&&this.click&&n.nodeName(this,\"input\")?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,\"a\")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=n.extend(new n.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?n.event.trigger(e,null,b):n.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?Z:$):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={isDefaultPrevented:$,isPropagationStopped:$,isImmediatePropagationStopped:$,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=Z,a&&a.preventDefault&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=Z,a&&a.stopPropagation&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=Z,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:\"mouseover\",mouseleave:\"mouseout\",pointerenter:\"pointerover\",pointerleave:\"pointerout\"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!n.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.focusinBubbles||n.each({focus:\"focusin\",blur:\"focusout\"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a),!0)};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=L.access(d,b);e||d.addEventListener(a,c,!0),L.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=L.access(d,b)-1;e?L.access(d,b,e):(d.removeEventListener(a,c,!0),L.remove(d,b))}}}),n.fn.extend({on:function(a,b,c,d,e){var f,g;if(\"object\"==typeof a){\"string\"!=typeof b&&(c=c||b,b=void 0);for(g in a)this.on(g,b,c,a[g],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&(\"string\"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=$;else if(!d)return this;return 1===e&&(f=d,d=function(a){return n().off(a),f.apply(this,arguments)},d.guid=f.guid||(f.guid=n.guid++)),this.each(function(){n.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+\".\"+d.namespace:d.origType,d.selector,d.handler),this;if(\"object\"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||\"function\"==typeof b)&&(c=b,b=void 0),c===!1&&(c=$),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});var aa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,ba=/<([\\w:]+)/,ca=/<|&#?\\w+;/,da=/<(?:script|style|link)/i,ea=/checked\\s*(?:[^=]|=\\s*.checked.)/i,fa=/^$|\\/(?:java|ecma)script/i,ga=/^true\\/(.*)/,ha=/^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,ia={option:[1,\"<select multiple='multiple'>\",\"</select>\"],thead:[1,\"<table>\",\"</table>\"],col:[2,\"<table><colgroup>\",\"</colgroup></table>\"],tr:[2,\"<table><tbody>\",\"</tbody></table>\"],td:[3,\"<table><tbody><tr>\",\"</tr></tbody></table>\"],_default:[0,\"\",\"\"]};ia.optgroup=ia.option,ia.tbody=ia.tfoot=ia.colgroup=ia.caption=ia.thead,ia.th=ia.td;function ja(a,b){return n.nodeName(a,\"table\")&&n.nodeName(11!==b.nodeType?b:b.firstChild,\"tr\")?a.getElementsByTagName(\"tbody\")[0]||a.appendChild(a.ownerDocument.createElement(\"tbody\")):a}function ka(a){return a.type=(null!==a.getAttribute(\"type\"))+\"/\"+a.type,a}function la(a){var b=ga.exec(a.type);return b?a.type=b[1]:a.removeAttribute(\"type\"),a}function ma(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],\"globalEval\",!b||L.get(b[c],\"globalEval\"))}function na(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function oa(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||\"*\"):a.querySelectorAll?a.querySelectorAll(b||\"*\"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pa(a,b){var c=b.nodeName.toLowerCase();\"input\"===c&&T.test(a.type)?b.checked=a.checked:(\"input\"===c||\"textarea\"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=oa(h),f=oa(a),d=0,e=f.length;e>d;d++)pa(f[d],g[d]);if(b)if(c)for(f=f||oa(a),g=g||oa(h),d=0,e=f.length;e>d;d++)na(f[d],g[d]);else na(a,h);return g=oa(h,\"script\"),g.length>0&&ma(g,!i&&oa(a,\"script\")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if(\"object\"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(ca.test(e)){f=f||k.appendChild(b.createElement(\"div\")),g=(ba.exec(e)||[\"\",\"\"])[1].toLowerCase(),h=ia[g]||ia._default,f.innerHTML=h[1]+e.replace(aa,\"<$1></$2>\")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=\"\"}else l.push(b.createTextNode(e));k.textContent=\"\",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=oa(k.appendChild(e),\"script\"),i&&ma(f),c)){j=0;while(e=f[j++])fa.test(e.type||\"\")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(oa(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&ma(oa(c,\"script\")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(oa(a,!1)),a.textContent=\"\");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if(\"string\"==typeof a&&!da.test(a)&&!ia[(ba.exec(a)||[\"\",\"\"])[1].toLowerCase()]){a=a.replace(aa,\"<$1></$2>\");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(oa(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(oa(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&\"string\"==typeof p&&!k.checkClone&&ea.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(oa(c,\"script\"),ka),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,oa(h,\"script\"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,la),j=0;g>j;j++)h=f[j],fa.test(h.type||\"\")&&!L.access(h,\"globalEval\")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(ha,\"\")))}return this}}),n.each({appendTo:\"append\",prependTo:\"prepend\",insertBefore:\"before\",insertAfter:\"after\",replaceAll:\"replaceWith\"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qa,ra={};function sa(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],\"display\");return e.detach(),f}function ta(a){var b=l,c=ra[a];return c||(c=sa(a,b),\"none\"!==c&&c||(qa=(qa||n(\"<iframe frameborder='0' width='0' height='0'/>\")).appendTo(b.documentElement),b=qa[0].contentDocument,b.write(),b.close(),c=sa(a,b),qa.detach()),ra[a]=c),c}var ua=/^margin/,va=new RegExp(\"^(\"+Q+\")(?!px)[a-z%]+$\",\"i\"),wa=function(b){return b.ownerDocument.defaultView.opener?b.ownerDocument.defaultView.getComputedStyle(b,null):a.getComputedStyle(b,null)};function xa(a,b,c){var d,e,f,g,h=a.style;return c=c||wa(a),c&&(g=c.getPropertyValue(b)||c[b]),c&&(\"\"!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),va.test(g)&&ua.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+\"\":g}function ya(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d=l.documentElement,e=l.createElement(\"div\"),f=l.createElement(\"div\");if(f.style){f.style.backgroundClip=\"content-box\",f.cloneNode(!0).style.backgroundClip=\"\",k.clearCloneStyle=\"content-box\"===f.style.backgroundClip,e.style.cssText=\"border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;position:absolute\",e.appendChild(f);function g(){f.style.cssText=\"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute\",f.innerHTML=\"\",d.appendChild(e);var g=a.getComputedStyle(f,null);b=\"1%\"!==g.top,c=\"4px\"===g.width,d.removeChild(e)}a.getComputedStyle&&n.extend(k,{pixelPosition:function(){return g(),b},boxSizingReliable:function(){return null==c&&g(),c},reliableMarginRight:function(){var b,c=f.appendChild(l.createElement(\"div\"));return c.style.cssText=f.style.cssText=\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0\",c.style.marginRight=c.style.width=\"0\",f.style.width=\"1px\",d.appendChild(e),b=!parseFloat(a.getComputedStyle(c,null).marginRight),d.removeChild(e),f.removeChild(c),b}})}}(),n.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var za=/^(none|table(?!-c[ea]).+)/,Aa=new RegExp(\"^(\"+Q+\")(.*)$\",\"i\"),Ba=new RegExp(\"^([+-])=(\"+Q+\")\",\"i\"),Ca={position:\"absolute\",visibility:\"hidden\",display:\"block\"},Da={letterSpacing:\"0\",fontWeight:\"400\"},Ea=[\"Webkit\",\"O\",\"Moz\",\"ms\"];function Fa(a,b){if(b in a)return b;var c=b[0].toUpperCase()+b.slice(1),d=b,e=Ea.length;while(e--)if(b=Ea[e]+c,b in a)return b;return d}function Ga(a,b,c){var d=Aa.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||\"px\"):b}function Ha(a,b,c,d,e){for(var f=c===(d?\"border\":\"content\")?4:\"width\"===b?1:0,g=0;4>f;f+=2)\"margin\"===c&&(g+=n.css(a,c+R[f],!0,e)),d?(\"content\"===c&&(g-=n.css(a,\"padding\"+R[f],!0,e)),\"margin\"!==c&&(g-=n.css(a,\"border\"+R[f]+\"Width\",!0,e))):(g+=n.css(a,\"padding\"+R[f],!0,e),\"padding\"!==c&&(g+=n.css(a,\"border\"+R[f]+\"Width\",!0,e)));return g}function Ia(a,b,c){var d=!0,e=\"width\"===b?a.offsetWidth:a.offsetHeight,f=wa(a),g=\"border-box\"===n.css(a,\"boxSizing\",!1,f);if(0>=e||null==e){if(e=xa(a,b,f),(0>e||null==e)&&(e=a.style[b]),va.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Ha(a,b,c||(g?\"border\":\"content\"),d,f)+\"px\"}function Ja(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=L.get(d,\"olddisplay\"),c=d.style.display,b?(f[g]||\"none\"!==c||(d.style.display=\"\"),\"\"===d.style.display&&S(d)&&(f[g]=L.access(d,\"olddisplay\",ta(d.nodeName)))):(e=S(d),\"none\"===c&&e||L.set(d,\"olddisplay\",e?c:n.css(d,\"display\"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&\"none\"!==d.style.display&&\"\"!==d.style.display||(d.style.display=b?f[g]||\"\":\"none\"));return a}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=xa(a,\"opacity\");return\"\"===c?\"1\":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{\"float\":\"cssFloat\"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;return b=n.cssProps[h]||(n.cssProps[h]=Fa(i,h)),g=n.cssHooks[b]||n.cssHooks[h],void 0===c?g&&\"get\"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,\"string\"===f&&(e=Ba.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(n.css(a,b)),f=\"number\"),null!=c&&c===c&&(\"number\"!==f||n.cssNumber[h]||(c+=\"px\"),k.clearCloneStyle||\"\"!==c||0!==b.indexOf(\"background\")||(i[b]=\"inherit\"),g&&\"set\"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Fa(a.style,h)),g=n.cssHooks[b]||n.cssHooks[h],g&&\"get\"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=xa(a,b,d)),\"normal\"===e&&b in Da&&(e=Da[b]),\"\"===c||c?(f=parseFloat(e),c===!0||n.isNumeric(f)?f||0:e):e}}),n.each([\"height\",\"width\"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?za.test(n.css(a,\"display\"))&&0===a.offsetWidth?n.swap(a,Ca,function(){return Ia(a,b,d)}):Ia(a,b,d):void 0},set:function(a,c,d){var e=d&&wa(a);return Ga(a,c,d?Ha(a,b,d,\"border-box\"===n.css(a,\"boxSizing\",!1,e),e):0)}}}),n.cssHooks.marginRight=ya(k.reliableMarginRight,function(a,b){return b?n.swap(a,{display:\"inline-block\"},xa,[a,\"marginRight\"]):void 0}),n.each({margin:\"\",padding:\"\",border:\"Width\"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f=\"string\"==typeof c?c.split(\" \"):[c];4>d;d++)e[a+R[d]+b]=f[d]||f[d-2]||f[0];return e}},ua.test(a)||(n.cssHooks[a+b].set=Ga)}),n.fn.extend({css:function(a,b){return J(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=wa(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return Ja(this,!0)},hide:function(){return Ja(this)},toggle:function(a){return\"boolean\"==typeof a?a?this.show():this.hide():this.each(function(){S(this)?n(this).show():n(this).hide()})}});function Ka(a,b,c,d,e){return new Ka.prototype.init(a,b,c,d,e)}n.Tween=Ka,Ka.prototype={constructor:Ka,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||\"swing\",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?\"\":\"px\")},cur:function(){var a=Ka.propHooks[this.prop];return a&&a.get?a.get(this):Ka.propHooks._default.get(this)},run:function(a){var b,c=Ka.propHooks[this.prop];return this.options.duration?this.pos=b=n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Ka.propHooks._default.set(this),this}},Ka.prototype.init.prototype=Ka.prototype,Ka.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=n.css(a.elem,a.prop,\"\"),b&&\"auto\"!==b?b:0):a.elem[a.prop]},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[n.cssProps[a.prop]]||n.cssHooks[a.prop])?n.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Ka.propHooks.scrollTop=Ka.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},n.fx=Ka.prototype.init,n.fx.step={};var La,Ma,Na=/^(?:toggle|show|hide)$/,Oa=new RegExp(\"^(?:([+-])=|)(\"+Q+\")([a-z%]*)$\",\"i\"),Pa=/queueHooks$/,Qa=[Va],Ra={\"*\":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=Oa.exec(b),f=e&&e[3]||(n.cssNumber[a]?\"\":\"px\"),g=(n.cssNumber[a]||\"px\"!==f&&+d)&&Oa.exec(n.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||\".5\",g/=h,n.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function Sa(){return setTimeout(function(){La=void 0}),La=n.now()}function Ta(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=R[d],e[\"margin\"+c]=e[\"padding\"+c]=a;return b&&(e.opacity=e.width=a),e}function Ua(a,b,c){for(var d,e=(Ra[b]||[]).concat(Ra[\"*\"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function Va(a,b,c){var d,e,f,g,h,i,j,k,l=this,m={},o=a.style,p=a.nodeType&&S(a),q=L.get(a,\"fxshow\");c.queue||(h=n._queueHooks(a,\"fx\"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,l.always(function(){l.always(function(){h.unqueued--,n.queue(a,\"fx\").length||h.empty.fire()})})),1===a.nodeType&&(\"height\"in b||\"width\"in b)&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=n.css(a,\"display\"),k=\"none\"===j?L.get(a,\"olddisplay\")||ta(a.nodeName):j,\"inline\"===k&&\"none\"===n.css(a,\"float\")&&(o.display=\"inline-block\")),c.overflow&&(o.overflow=\"hidden\",l.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],Na.exec(e)){if(delete b[d],f=f||\"toggle\"===e,e===(p?\"hide\":\"show\")){if(\"show\"!==e||!q||void 0===q[d])continue;p=!0}m[d]=q&&q[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(m))\"inline\"===(\"none\"===j?ta(a.nodeName):j)&&(o.display=j);else{q?\"hidden\"in q&&(p=q.hidden):q=L.access(a,\"fxshow\",{}),f&&(q.hidden=!p),p?n(a).show():l.done(function(){n(a).hide()}),l.done(function(){var b;L.remove(a,\"fxshow\");for(b in m)n.style(a,b,m[b])});for(d in m)g=Ua(p?q[d]:0,d,l),d in q||(q[d]=g.start,p&&(g.end=g.start,g.start=\"width\"===d||\"height\"===d?1:0))}}function Wa(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&\"expand\"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function Xa(a,b,c){var d,e,f=0,g=Qa.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=La||Sa(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:La||Sa(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(Wa(k,j.opts.specialEasing);g>f;f++)if(d=Qa[f].call(j,a,k,j.opts))return d;return n.map(k,Ua,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(Xa,{tweener:function(a,b){n.isFunction(a)?(b=a,a=[\"*\"]):a=a.split(\" \");for(var c,d=0,e=a.length;e>d;d++)c=a[d],Ra[c]=Ra[c]||[],Ra[c].unshift(b)},prefilter:function(a,b){b?Qa.unshift(a):Qa.push(a)}}),n.speed=function(a,b,c){var d=a&&\"object\"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:\"number\"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue=\"fx\"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(S).css(\"opacity\",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=Xa(this,n.extend({},a),f);(e||L.get(this,\"finish\"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return\"string\"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||\"fx\",[]),this.each(function(){var b=!0,e=null!=a&&a+\"queueHooks\",f=n.timers,g=L.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&Pa.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||\"fx\"),this.each(function(){var b,c=L.get(this),d=c[a+\"queue\"],e=c[a+\"queueHooks\"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each([\"toggle\",\"show\",\"hide\"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||\"boolean\"==typeof a?c.apply(this,arguments):this.animate(Ta(b,!0),a,d,e)}}),n.each({slideDown:Ta(\"show\"),slideUp:Ta(\"hide\"),slideToggle:Ta(\"toggle\"),fadeIn:{opacity:\"show\"},fadeOut:{opacity:\"hide\"},fadeToggle:{opacity:\"toggle\"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=0,c=n.timers;for(La=n.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||n.fx.stop(),La=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){Ma||(Ma=setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){clearInterval(Ma),Ma=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(a,b){return a=n.fx?n.fx.speeds[a]||a:a,b=b||\"fx\",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a=l.createElement(\"input\"),b=l.createElement(\"select\"),c=b.appendChild(l.createElement(\"option\"));a.type=\"checkbox\",k.checkOn=\"\"!==a.value,k.optSelected=c.selected,b.disabled=!0,k.optDisabled=!c.disabled,a=l.createElement(\"input\"),a.value=\"t\",a.type=\"radio\",k.radioValue=\"t\"===a.value}();var Ya,Za,$a=n.expr.attrHandle;n.fn.extend({attr:function(a,b){return J(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===U?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),d=n.attrHooks[b]||(n.expr.match.bool.test(b)?Za:Ya)),\nvoid 0===c?d&&\"get\"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?void 0:e):null!==c?d&&\"set\"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+\"\"),c):void n.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)&&(a[d]=!1),a.removeAttribute(c)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&\"radio\"===b&&n.nodeName(a,\"input\")){var c=a.value;return a.setAttribute(\"type\",b),c&&(a.value=c),b}}}}}),Za={set:function(a,b,c){return b===!1?n.removeAttr(a,c):a.setAttribute(c,c),c}},n.each(n.expr.match.bool.source.match(/\\w+/g),function(a,b){var c=$a[b]||n.find.attr;$a[b]=function(a,b,d){var e,f;return d||(f=$a[b],$a[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,$a[b]=f),e}});var _a=/^(?:input|select|textarea|button)$/i;n.fn.extend({prop:function(a,b){return J(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[n.propFix[a]||a]})}}),n.extend({propFix:{\"for\":\"htmlFor\",\"class\":\"className\"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!n.isXMLDoc(a),f&&(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&\"set\"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&\"get\"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){return a.hasAttribute(\"tabindex\")||_a.test(a.nodeName)||a.href?a.tabIndex:-1}}}}),k.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null}}),n.each([\"tabIndex\",\"readOnly\",\"maxLength\",\"cellSpacing\",\"cellPadding\",\"rowSpan\",\"colSpan\",\"useMap\",\"frameBorder\",\"contentEditable\"],function(){n.propFix[this.toLowerCase()]=this});var ab=/[\\t\\r\\n\\f]/g;n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h=\"string\"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,this.className))});if(h)for(b=(a||\"\").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(\" \"+c.className+\" \").replace(ab,\" \"):\" \")){f=0;while(e=b[f++])d.indexOf(\" \"+e+\" \")<0&&(d+=e+\" \");g=n.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0===arguments.length||\"string\"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,this.className))});if(h)for(b=(a||\"\").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(\" \"+c.className+\" \").replace(ab,\" \"):\"\")){f=0;while(e=b[f++])while(d.indexOf(\" \"+e+\" \")>=0)d=d.replace(\" \"+e+\" \",\" \");g=a?n.trim(d):\"\",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return\"boolean\"==typeof b&&\"string\"===c?b?this.addClass(a):this.removeClass(a):this.each(n.isFunction(a)?function(c){n(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if(\"string\"===c){var b,d=0,e=n(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===U||\"boolean\"===c)&&(this.className&&L.set(this,\"__className__\",this.className),this.className=this.className||a===!1?\"\":L.get(this,\"__className__\")||\"\")})},hasClass:function(a){for(var b=\" \"+a+\" \",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(\" \"+this[c].className+\" \").replace(ab,\" \").indexOf(b)>=0)return!0;return!1}});var bb=/\\r/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e=\"\":\"number\"==typeof e?e+=\"\":n.isArray(e)&&(e=n.map(e,function(a){return null==a?\"\":a+\"\"})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&\"set\"in b&&void 0!==b.set(this,e,\"value\")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&\"get\"in b&&void 0!==(c=b.get(e,\"value\"))?c:(c=e.value,\"string\"==typeof c?c.replace(bb,\"\"):null==c?\"\":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,\"value\");return null!=b?b:n.trim(n.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f=\"select-one\"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute(\"disabled\"))||c.parentNode.disabled&&n.nodeName(c.parentNode,\"optgroup\"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=n.inArray(d.value,f)>=0)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),n.each([\"radio\",\"checkbox\"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>=0:void 0}},k.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute(\"value\")?\"on\":a.value})}),n.each(\"blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu\".split(\" \"),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,\"**\"):this.off(b,a||\"**\",c)}});var cb=n.now(),db=/\\?/;n.parseJSON=function(a){return JSON.parse(a+\"\")},n.parseXML=function(a){var b,c;if(!a||\"string\"!=typeof a)return null;try{c=new DOMParser,b=c.parseFromString(a,\"text/xml\")}catch(d){b=void 0}return(!b||b.getElementsByTagName(\"parsererror\").length)&&n.error(\"Invalid XML: \"+a),b};var eb=/#.*$/,fb=/([?&])_=[^&]*/,gb=/^(.*?):[ \\t]*([^\\r\\n]*)$/gm,hb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,ib=/^(?:GET|HEAD)$/,jb=/^\\/\\//,kb=/^([\\w.+-]+:)(?:\\/\\/(?:[^\\/?#]*@|)([^\\/?#:]*)(?::(\\d+)|)|)/,lb={},mb={},nb=\"*/\".concat(\"*\"),ob=a.location.href,pb=kb.exec(ob.toLowerCase())||[];function qb(a){return function(b,c){\"string\"!=typeof b&&(c=b,b=\"*\");var d,e=0,f=b.toLowerCase().match(E)||[];if(n.isFunction(c))while(d=f[e++])\"+\"===d[0]?(d=d.slice(1)||\"*\",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function rb(a,b,c,d){var e={},f=a===mb;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return\"string\"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e[\"*\"]&&g(\"*\")}function sb(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&n.extend(!0,a,d),a}function tb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while(\"*\"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader(\"Content-Type\"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+\" \"+i[0]]){f=e;break}g||(g=e)}f=f||g}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function ub(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if(\"*\"===f)f=i;else if(\"*\"!==i&&i!==f){if(g=j[i+\" \"+f]||j[\"* \"+f],!g)for(e in j)if(h=e.split(\" \"),h[1]===f&&(g=j[i+\" \"+h[0]]||j[\"* \"+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a[\"throws\"])b=g(b);else try{b=g(b)}catch(l){return{state:\"parsererror\",error:g?l:\"No conversion from \"+i+\" to \"+f}}}return{state:\"success\",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:ob,type:\"GET\",isLocal:hb.test(pb[1]),global:!0,processData:!0,async:!0,contentType:\"application/x-www-form-urlencoded; charset=UTF-8\",accepts:{\"*\":nb,text:\"text/plain\",html:\"text/html\",xml:\"application/xml, text/xml\",json:\"application/json, text/javascript\"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:\"responseXML\",text:\"responseText\",json:\"responseJSON\"},converters:{\"* text\":String,\"text html\":!0,\"text json\":n.parseJSON,\"text xml\":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?sb(sb(a,n.ajaxSettings),b):sb(n.ajaxSettings,a)},ajaxPrefilter:qb(lb),ajaxTransport:qb(mb),ajax:function(a,b){\"object\"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=n.ajaxSetup({},b),l=k.context||k,m=k.context&&(l.nodeType||l.jquery)?n(l):n.event,o=n.Deferred(),p=n.Callbacks(\"once memory\"),q=k.statusCode||{},r={},s={},t=0,u=\"canceled\",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!f){f={};while(b=gb.exec(e))f[b[1].toLowerCase()]=b[2]}b=f[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?e:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return c&&c.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||ob)+\"\").replace(eb,\"\").replace(jb,pb[1]+\"//\"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=n.trim(k.dataType||\"*\").toLowerCase().match(E)||[\"\"],null==k.crossDomain&&(h=kb.exec(k.url.toLowerCase()),k.crossDomain=!(!h||h[1]===pb[1]&&h[2]===pb[2]&&(h[3]||(\"http:\"===h[1]?\"80\":\"443\"))===(pb[3]||(\"http:\"===pb[1]?\"80\":\"443\")))),k.data&&k.processData&&\"string\"!=typeof k.data&&(k.data=n.param(k.data,k.traditional)),rb(lb,k,b,v),2===t)return v;i=n.event&&k.global,i&&0===n.active++&&n.event.trigger(\"ajaxStart\"),k.type=k.type.toUpperCase(),k.hasContent=!ib.test(k.type),d=k.url,k.hasContent||(k.data&&(d=k.url+=(db.test(d)?\"&\":\"?\")+k.data,delete k.data),k.cache===!1&&(k.url=fb.test(d)?d.replace(fb,\"$1_=\"+cb++):d+(db.test(d)?\"&\":\"?\")+\"_=\"+cb++)),k.ifModified&&(n.lastModified[d]&&v.setRequestHeader(\"If-Modified-Since\",n.lastModified[d]),n.etag[d]&&v.setRequestHeader(\"If-None-Match\",n.etag[d])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader(\"Content-Type\",k.contentType),v.setRequestHeader(\"Accept\",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+(\"*\"!==k.dataTypes[0]?\", \"+nb+\"; q=0.01\":\"\"):k.accepts[\"*\"]);for(j in k.headers)v.setRequestHeader(j,k.headers[j]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u=\"abort\";for(j in{success:1,error:1,complete:1})v[j](k[j]);if(c=rb(mb,k,b,v)){v.readyState=1,i&&m.trigger(\"ajaxSend\",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort(\"timeout\")},k.timeout));try{t=1,c.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,\"No Transport\");function x(a,b,f,h){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),c=void 0,e=h||\"\",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,f&&(u=tb(k,v,f)),u=ub(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader(\"Last-Modified\"),w&&(n.lastModified[d]=w),w=v.getResponseHeader(\"etag\"),w&&(n.etag[d]=w)),204===a||\"HEAD\"===k.type?x=\"nocontent\":304===a?x=\"notmodified\":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x=\"error\",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+\"\",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,i&&m.trigger(j?\"ajaxSuccess\":\"ajaxError\",[v,k,j?r:s]),p.fireWith(l,[v,x]),i&&(m.trigger(\"ajaxComplete\",[v,k]),--n.active||n.event.trigger(\"ajaxStop\")))}return v},getJSON:function(a,b,c){return n.get(a,b,c,\"json\")},getScript:function(a,b){return n.get(a,void 0,b,\"script\")}}),n.each([\"get\",\"post\"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),n._evalUrl=function(a){return n.ajax({url:a,type:\"GET\",dataType:\"script\",async:!1,global:!1,\"throws\":!0})},n.fn.extend({wrapAll:function(a){var b;return n.isFunction(a)?this.each(function(b){n(this).wrapAll(a.call(this,b))}):(this[0]&&(b=n(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this)},wrapInner:function(a){return this.each(n.isFunction(a)?function(b){n(this).wrapInner(a.call(this,b))}:function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,\"body\")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var vb=/%20/g,wb=/\\[\\]$/,xb=/\\r?\\n/g,yb=/^(?:submit|button|image|reset|file)$/i,zb=/^(?:input|select|textarea|keygen)/i;function Ab(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||wb.test(a)?d(a,e):Ab(a+\"[\"+(\"object\"==typeof e?b:\"\")+\"]\",e,c,d)});else if(c||\"object\"!==n.type(b))d(a,b);else for(e in b)Ab(a+\"[\"+e+\"]\",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?\"\":b,d[d.length]=encodeURIComponent(a)+\"=\"+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Ab(c,a[c],b,e);return d.join(\"&\").replace(vb,\"+\")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,\"elements\");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(\":disabled\")&&zb.test(this.nodeName)&&!yb.test(a)&&(this.checked||!T.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(xb,\"\\r\\n\")}}):{name:b.name,value:c.replace(xb,\"\\r\\n\")}}).get()}}),n.ajaxSettings.xhr=function(){try{return new XMLHttpRequest}catch(a){}};var Bb=0,Cb={},Db={0:200,1223:204},Eb=n.ajaxSettings.xhr();a.attachEvent&&a.attachEvent(\"onunload\",function(){for(var a in Cb)Cb[a]()}),k.cors=!!Eb&&\"withCredentials\"in Eb,k.ajax=Eb=!!Eb,n.ajaxTransport(function(a){var b;return k.cors||Eb&&!a.crossDomain?{send:function(c,d){var e,f=a.xhr(),g=++Bb;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c[\"X-Requested-With\"]||(c[\"X-Requested-With\"]=\"XMLHttpRequest\");for(e in c)f.setRequestHeader(e,c[e]);b=function(a){return function(){b&&(delete Cb[g],b=f.onload=f.onerror=null,\"abort\"===a?f.abort():\"error\"===a?d(f.status,f.statusText):d(Db[f.status]||f.status,f.statusText,\"string\"==typeof f.responseText?{text:f.responseText}:void 0,f.getAllResponseHeaders()))}},f.onload=b(),f.onerror=b(\"error\"),b=Cb[g]=b(\"abort\");try{f.send(a.hasContent&&a.data||null)}catch(h){if(b)throw h}},abort:function(){b&&b()}}:void 0}),n.ajaxSetup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/(?:java|ecma)script/},converters:{\"text script\":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter(\"script\",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type=\"GET\")}),n.ajaxTransport(\"script\",function(a){if(a.crossDomain){var b,c;return{send:function(d,e){b=n(\"<script>\").prop({async:!0,charset:a.scriptCharset,src:a.url}).on(\"load error\",c=function(a){b.remove(),c=null,a&&e(\"error\"===a.type?404:200,a.type)}),l.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Fb=[],Gb=/(=)\\?(?=&|$)|\\?\\?/;n.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var a=Fb.pop()||n.expando+\"_\"+cb++;return this[a]=!0,a}}),n.ajaxPrefilter(\"json jsonp\",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Gb.test(b.url)?\"url\":\"string\"==typeof b.data&&!(b.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&Gb.test(b.data)&&\"data\");return h||\"jsonp\"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Gb,\"$1\"+e):b.jsonp!==!1&&(b.url+=(db.test(b.url)?\"&\":\"?\")+b.jsonp+\"=\"+e),b.converters[\"script json\"]=function(){return g||n.error(e+\" was not called\"),g[0]},b.dataTypes[0]=\"json\",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Fb.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),\"script\"):void 0}),n.parseHTML=function(a,b,c){if(!a||\"string\"!=typeof a)return null;\"boolean\"==typeof b&&(c=b,b=!1),b=b||l;var d=v.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=n.buildFragment([a],b,e),e&&e.length&&n(e).remove(),n.merge([],d.childNodes))};var Hb=n.fn.load;n.fn.load=function(a,b,c){if(\"string\"!=typeof a&&Hb)return Hb.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(\" \");return h>=0&&(d=n.trim(a.slice(h)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&\"object\"==typeof b&&(e=\"POST\"),g.length>0&&n.ajax({url:a,type:e,dataType:\"html\",data:b}).done(function(a){f=arguments,g.html(d?n(\"<div>\").append(n.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,f||[a.responseText,b,a])}),this},n.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};var Ib=a.document.documentElement;function Jb(a){return n.isWindow(a)?a:9===a.nodeType&&a.defaultView}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,\"position\"),l=n(a),m={};\"static\"===k&&(a.style.position=\"relative\"),h=l.offset(),f=n.css(a,\"top\"),i=n.css(a,\"left\"),j=(\"absolute\"===k||\"fixed\"===k)&&(f+i).indexOf(\"auto\")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),\"using\"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d=this[0],e={top:0,left:0},f=d&&d.ownerDocument;if(f)return b=f.documentElement,n.contains(b,d)?(typeof d.getBoundingClientRect!==U&&(e=d.getBoundingClientRect()),c=Jb(f),{top:e.top+c.pageYOffset-b.clientTop,left:e.left+c.pageXOffset-b.clientLeft}):e},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return\"fixed\"===n.css(c,\"position\")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],\"html\")||(d=a.offset()),d.top+=n.css(a[0],\"borderTopWidth\",!0),d.left+=n.css(a[0],\"borderLeftWidth\",!0)),{top:b.top-d.top-n.css(c,\"marginTop\",!0),left:b.left-d.left-n.css(c,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||Ib;while(a&&!n.nodeName(a,\"html\")&&\"static\"===n.css(a,\"position\"))a=a.offsetParent;return a||Ib})}}),n.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(b,c){var d=\"pageYOffset\"===c;n.fn[b]=function(e){return J(this,function(b,e,f){var g=Jb(b);return void 0===f?g?g[c]:b[e]:void(g?g.scrollTo(d?a.pageXOffset:f,d?f:a.pageYOffset):b[e]=f)},b,e,arguments.length,null)}}),n.each([\"top\",\"left\"],function(a,b){n.cssHooks[b]=ya(k.pixelPosition,function(a,c){return c?(c=xa(a,b),va.test(c)?n(a).position()[b]+\"px\":c):void 0})}),n.each({Height:\"height\",Width:\"width\"},function(a,b){n.each({padding:\"inner\"+a,content:b,\"\":\"outer\"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||\"boolean\"!=typeof d),g=c||(d===!0||e===!0?\"margin\":\"border\");return J(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement[\"client\"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body[\"scroll\"+a],e[\"scroll\"+a],b.body[\"offset\"+a],e[\"offset\"+a],e[\"client\"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,\"function\"==typeof define&&define.amd&&define(\"jquery\",[],function(){return n});var Kb=a.jQuery,Lb=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=Lb),b&&a.jQuery===n&&(a.jQuery=Kb),n},typeof b===U&&(a.jQuery=a.$=n),n});\n//# sourceMappingURL=jquery.min.map</script>\n<script>/**\n * Tween.js - Licensed under the MIT license\n * https://github.com/tweenjs/tween.js\n * ----------------------------------------------\n *\n * See https://github.com/tweenjs/tween.js/graphs/contributors for the full list of contributors.\n * Thank you all, you're awesome!\n */\n\nvar TWEEN = TWEEN || (function () {\n\n\tvar _tweens = [];\n\n\treturn {\n\n\t\tgetAll: function () {\n\n\t\t\treturn _tweens;\n\n\t\t},\n\n\t\tremoveAll: function () {\n\n\t\t\t_tweens = [];\n\n\t\t},\n\n\t\tadd: function (tween) {\n\n\t\t\t_tweens.push(tween);\n\n\t\t},\n\n\t\tremove: function (tween) {\n\n\t\t\tvar i = _tweens.indexOf(tween);\n\n\t\t\tif (i !== -1) {\n\t\t\t\t_tweens.splice(i, 1);\n\t\t\t}\n\n\t\t},\n\n\t\tupdate: function (time, preserve) {\n\n\t\t\tif (_tweens.length === 0) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tvar i = 0;\n\n\t\t\ttime = time !== undefined ? time : TWEEN.now();\n\n\t\t\twhile (i < _tweens.length) {\n\n\t\t\t\tif (_tweens[i].update(time) || preserve) {\n\t\t\t\t\ti++;\n\t\t\t\t} else {\n\t\t\t\t\t_tweens.splice(i, 1);\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn true;\n\n\t\t}\n\t};\n\n})();\n\n\n// Include a performance.now polyfill.\n// In node.js, use process.hrtime.\nif (typeof (window) === 'undefined' && typeof (process) !== 'undefined') {\n\tTWEEN.now = function () {\n\t\tvar time = process.hrtime();\n\n\t\t// Convert [seconds, nanoseconds] to milliseconds.\n\t\treturn time[0] * 1000 + time[1] / 1000000;\n\t};\n}\n// In a browser, use window.performance.now if it is available.\nelse if (typeof (window) !== 'undefined' &&\n         window.performance !== undefined &&\n\t\t window.performance.now !== undefined) {\n\t// This must be bound, because directly assigning this function\n\t// leads to an invocation exception in Chrome.\n\tTWEEN.now = window.performance.now.bind(window.performance);\n}\n// Use Date.now if it is available.\nelse if (Date.now !== undefined) {\n\tTWEEN.now = Date.now;\n}\n// Otherwise, use 'new Date().getTime()'.\nelse {\n\tTWEEN.now = function () {\n\t\treturn new Date().getTime();\n\t};\n}\n\n\nTWEEN.Tween = function (object) {\n\n\tvar _object = object;\n\tvar _valuesStart = {};\n\tvar _valuesEnd = {};\n\tvar _valuesStartRepeat = {};\n\tvar _duration = 1000;\n\tvar _repeat = 0;\n\tvar _repeatDelayTime;\n\tvar _yoyo = false;\n\tvar _isPlaying = false;\n\tvar _reversed = false;\n\tvar _delayTime = 0;\n\tvar _startTime = null;\n\tvar _easingFunction = TWEEN.Easing.Linear.None;\n\tvar _interpolationFunction = TWEEN.Interpolation.Linear;\n\tvar _chainedTweens = [];\n\tvar _onStartCallback = null;\n\tvar _onStartCallbackFired = false;\n\tvar _onUpdateCallback = null;\n\tvar _onCompleteCallback = null;\n\tvar _onStopCallback = null;\n\n\tthis.to = function (properties, duration) {\n\n\t\t_valuesEnd = properties;\n\n\t\tif (duration !== undefined) {\n\t\t\t_duration = duration;\n\t\t}\n\n\t\treturn this;\n\n\t};\n\n\tthis.start = function (time) {\n\n\t\tTWEEN.add(this);\n\n\t\t_isPlaying = true;\n\n\t\t_onStartCallbackFired = false;\n\n\t\t_startTime = time !== undefined ? time : TWEEN.now();\n\t\t_startTime += _delayTime;\n\n\t\tfor (var property in _valuesEnd) {\n\n\t\t\t// Check if an Array was provided as property value\n\t\t\tif (_valuesEnd[property] instanceof Array) {\n\n\t\t\t\tif (_valuesEnd[property].length === 0) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Create a local copy of the Array with the start value at the front\n\t\t\t\t_valuesEnd[property] = [_object[property]].concat(_valuesEnd[property]);\n\n\t\t\t}\n\n\t\t\t// If `to()` specifies a property that doesn't exist in the source object,\n\t\t\t// we should not set that property in the object\n\t\t\tif (_object[property] === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Save the starting value.\n\t\t\t_valuesStart[property] = _object[property];\n\n\t\t\tif ((_valuesStart[property] instanceof Array) === false) {\n\t\t\t\t_valuesStart[property] *= 1.0; // Ensures we're using numbers, not strings\n\t\t\t}\n\n\t\t\t_valuesStartRepeat[property] = _valuesStart[property] || 0;\n\n\t\t}\n\n\t\treturn this;\n\n\t};\n\n\tthis.stop = function () {\n\n\t\tif (!_isPlaying) {\n\t\t\treturn this;\n\t\t}\n\n\t\tTWEEN.remove(this);\n\t\t_isPlaying = false;\n\n\t\tif (_onStopCallback !== null) {\n\t\t\t_onStopCallback.call(_object, _object);\n\t\t}\n\n\t\tthis.stopChainedTweens();\n\t\treturn this;\n\n\t};\n\n\tthis.end = function () {\n\n\t\tthis.update(_startTime + _duration);\n\t\treturn this;\n\n\t};\n\n\tthis.stopChainedTweens = function () {\n\n\t\tfor (var i = 0, numChainedTweens = _chainedTweens.length; i < numChainedTweens; i++) {\n\t\t\t_chainedTweens[i].stop();\n\t\t}\n\n\t};\n\n\tthis.delay = function (amount) {\n\n\t\t_delayTime = amount;\n\t\treturn this;\n\n\t};\n\n\tthis.repeat = function (times) {\n\n\t\t_repeat = times;\n\t\treturn this;\n\n\t};\n\n\tthis.repeatDelay = function (amount) {\n\n\t\t_repeatDelayTime = amount;\n\t\treturn this;\n\n\t};\n\n\tthis.yoyo = function (yoyo) {\n\n\t\t_yoyo = yoyo;\n\t\treturn this;\n\n\t};\n\n\n\tthis.easing = function (easing) {\n\n\t\t_easingFunction = easing;\n\t\treturn this;\n\n\t};\n\n\tthis.interpolation = function (interpolation) {\n\n\t\t_interpolationFunction = interpolation;\n\t\treturn this;\n\n\t};\n\n\tthis.chain = function () {\n\n\t\t_chainedTweens = arguments;\n\t\treturn this;\n\n\t};\n\n\tthis.onStart = function (callback) {\n\n\t\t_onStartCallback = callback;\n\t\treturn this;\n\n\t};\n\n\tthis.onUpdate = function (callback) {\n\n\t\t_onUpdateCallback = callback;\n\t\treturn this;\n\n\t};\n\n\tthis.onComplete = function (callback) {\n\n\t\t_onCompleteCallback = callback;\n\t\treturn this;\n\n\t};\n\n\tthis.onStop = function (callback) {\n\n\t\t_onStopCallback = callback;\n\t\treturn this;\n\n\t};\n\n\tthis.update = function (time) {\n\n\t\tvar property;\n\t\tvar elapsed;\n\t\tvar value;\n\n\t\tif (time < _startTime) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (_onStartCallbackFired === false) {\n\n\t\t\tif (_onStartCallback !== null) {\n\t\t\t\t_onStartCallback.call(_object, _object);\n\t\t\t}\n\n\t\t\t_onStartCallbackFired = true;\n\t\t}\n\n\t\telapsed = (time - _startTime) / _duration;\n\t\telapsed = elapsed > 1 ? 1 : elapsed;\n\n\t\tvalue = _easingFunction(elapsed);\n\n\t\tfor (property in _valuesEnd) {\n\n\t\t\t// Don't update properties that do not exist in the source object\n\t\t\tif (_valuesStart[property] === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tvar start = _valuesStart[property] || 0;\n\t\t\tvar end = _valuesEnd[property];\n\n\t\t\tif (end instanceof Array) {\n\n\t\t\t\t_object[property] = _interpolationFunction(end, value);\n\n\t\t\t} else {\n\n\t\t\t\t// Parses relative end values with start as base (e.g.: +10, -3)\n\t\t\t\tif (typeof (end) === 'string') {\n\n\t\t\t\t\tif (end.charAt(0) === '+' || end.charAt(0) === '-') {\n\t\t\t\t\t\tend = start + parseFloat(end);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tend = parseFloat(end);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Protect against non numeric properties.\n\t\t\t\tif (typeof (end) === 'number') {\n\t\t\t\t\t_object[property] = start + (end - start) * value;\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tif (_onUpdateCallback !== null) {\n\t\t\t_onUpdateCallback.call(_object, value);\n\t\t}\n\n\t\tif (elapsed === 1) {\n\n\t\t\tif (_repeat > 0) {\n\n\t\t\t\tif (isFinite(_repeat)) {\n\t\t\t\t\t_repeat--;\n\t\t\t\t}\n\n\t\t\t\t// Reassign starting values, restart by making startTime = now\n\t\t\t\tfor (property in _valuesStartRepeat) {\n\n\t\t\t\t\tif (typeof (_valuesEnd[property]) === 'string') {\n\t\t\t\t\t\t_valuesStartRepeat[property] = _valuesStartRepeat[property] + parseFloat(_valuesEnd[property]);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (_yoyo) {\n\t\t\t\t\t\tvar tmp = _valuesStartRepeat[property];\n\n\t\t\t\t\t\t_valuesStartRepeat[property] = _valuesEnd[property];\n\t\t\t\t\t\t_valuesEnd[property] = tmp;\n\t\t\t\t\t}\n\n\t\t\t\t\t_valuesStart[property] = _valuesStartRepeat[property];\n\n\t\t\t\t}\n\n\t\t\t\tif (_yoyo) {\n\t\t\t\t\t_reversed = !_reversed;\n\t\t\t\t}\n\n\t\t\t\tif (_repeatDelayTime !== undefined) {\n\t\t\t\t\t_startTime = time + _repeatDelayTime;\n\t\t\t\t} else {\n\t\t\t\t\t_startTime = time + _delayTime;\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\n\t\t\t\tif (_onCompleteCallback !== null) {\n\n\t\t\t\t\t_onCompleteCallback.call(_object, _object);\n\t\t\t\t}\n\n\t\t\t\tfor (var i = 0, numChainedTweens = _chainedTweens.length; i < numChainedTweens; i++) {\n\t\t\t\t\t// Make the chained tweens start exactly at the time they should,\n\t\t\t\t\t// even if the `update()` method was called way past the duration of the tween\n\t\t\t\t\t_chainedTweens[i].start(_startTime + _duration);\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn true;\n\n\t};\n\n};\n\n\nTWEEN.Easing = {\n\n\tLinear: {\n\n\t\tNone: function (k) {\n\n\t\t\treturn k;\n\n\t\t}\n\n\t},\n\n\tQuadratic: {\n\n\t\tIn: function (k) {\n\n\t\t\treturn k * k;\n\n\t\t},\n\n\t\tOut: function (k) {\n\n\t\t\treturn k * (2 - k);\n\n\t\t},\n\n\t\tInOut: function (k) {\n\n\t\t\tif ((k *= 2) < 1) {\n\t\t\t\treturn 0.5 * k * k;\n\t\t\t}\n\n\t\t\treturn - 0.5 * (--k * (k - 2) - 1);\n\n\t\t}\n\n\t},\n\n\tCubic: {\n\n\t\tIn: function (k) {\n\n\t\t\treturn k * k * k;\n\n\t\t},\n\n\t\tOut: function (k) {\n\n\t\t\treturn --k * k * k + 1;\n\n\t\t},\n\n\t\tInOut: function (k) {\n\n\t\t\tif ((k *= 2) < 1) {\n\t\t\t\treturn 0.5 * k * k * k;\n\t\t\t}\n\n\t\t\treturn 0.5 * ((k -= 2) * k * k + 2);\n\n\t\t}\n\n\t},\n\n\tQuartic: {\n\n\t\tIn: function (k) {\n\n\t\t\treturn k * k * k * k;\n\n\t\t},\n\n\t\tOut: function (k) {\n\n\t\t\treturn 1 - (--k * k * k * k);\n\n\t\t},\n\n\t\tInOut: function (k) {\n\n\t\t\tif ((k *= 2) < 1) {\n\t\t\t\treturn 0.5 * k * k * k * k;\n\t\t\t}\n\n\t\t\treturn - 0.5 * ((k -= 2) * k * k * k - 2);\n\n\t\t}\n\n\t},\n\n\tQuintic: {\n\n\t\tIn: function (k) {\n\n\t\t\treturn k * k * k * k * k;\n\n\t\t},\n\n\t\tOut: function (k) {\n\n\t\t\treturn --k * k * k * k * k + 1;\n\n\t\t},\n\n\t\tInOut: function (k) {\n\n\t\t\tif ((k *= 2) < 1) {\n\t\t\t\treturn 0.5 * k * k * k * k * k;\n\t\t\t}\n\n\t\t\treturn 0.5 * ((k -= 2) * k * k * k * k + 2);\n\n\t\t}\n\n\t},\n\n\tSinusoidal: {\n\n\t\tIn: function (k) {\n\n\t\t\treturn 1 - Math.cos(k * Math.PI / 2);\n\n\t\t},\n\n\t\tOut: function (k) {\n\n\t\t\treturn Math.sin(k * Math.PI / 2);\n\n\t\t},\n\n\t\tInOut: function (k) {\n\n\t\t\treturn 0.5 * (1 - Math.cos(Math.PI * k));\n\n\t\t}\n\n\t},\n\n\tExponential: {\n\n\t\tIn: function (k) {\n\n\t\t\treturn k === 0 ? 0 : Math.pow(1024, k - 1);\n\n\t\t},\n\n\t\tOut: function (k) {\n\n\t\t\treturn k === 1 ? 1 : 1 - Math.pow(2, - 10 * k);\n\n\t\t},\n\n\t\tInOut: function (k) {\n\n\t\t\tif (k === 0) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tif (k === 1) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\tif ((k *= 2) < 1) {\n\t\t\t\treturn 0.5 * Math.pow(1024, k - 1);\n\t\t\t}\n\n\t\t\treturn 0.5 * (- Math.pow(2, - 10 * (k - 1)) + 2);\n\n\t\t}\n\n\t},\n\n\tCircular: {\n\n\t\tIn: function (k) {\n\n\t\t\treturn 1 - Math.sqrt(1 - k * k);\n\n\t\t},\n\n\t\tOut: function (k) {\n\n\t\t\treturn Math.sqrt(1 - (--k * k));\n\n\t\t},\n\n\t\tInOut: function (k) {\n\n\t\t\tif ((k *= 2) < 1) {\n\t\t\t\treturn - 0.5 * (Math.sqrt(1 - k * k) - 1);\n\t\t\t}\n\n\t\t\treturn 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1);\n\n\t\t}\n\n\t},\n\n\tElastic: {\n\n\t\tIn: function (k) {\n\n\t\t\tif (k === 0) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tif (k === 1) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\treturn -Math.pow(2, 10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI);\n\n\t\t},\n\n\t\tOut: function (k) {\n\n\t\t\tif (k === 0) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tif (k === 1) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\treturn Math.pow(2, -10 * k) * Math.sin((k - 0.1) * 5 * Math.PI) + 1;\n\n\t\t},\n\n\t\tInOut: function (k) {\n\n\t\t\tif (k === 0) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tif (k === 1) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\tk *= 2;\n\n\t\t\tif (k < 1) {\n\t\t\t\treturn -0.5 * Math.pow(2, 10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI);\n\t\t\t}\n\n\t\t\treturn 0.5 * Math.pow(2, -10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI) + 1;\n\n\t\t}\n\n\t},\n\n\tBack: {\n\n\t\tIn: function (k) {\n\n\t\t\tvar s = 1.70158;\n\n\t\t\treturn k * k * ((s + 1) * k - s);\n\n\t\t},\n\n\t\tOut: function (k) {\n\n\t\t\tvar s = 1.70158;\n\n\t\t\treturn --k * k * ((s + 1) * k + s) + 1;\n\n\t\t},\n\n\t\tInOut: function (k) {\n\n\t\t\tvar s = 1.70158 * 1.525;\n\n\t\t\tif ((k *= 2) < 1) {\n\t\t\t\treturn 0.5 * (k * k * ((s + 1) * k - s));\n\t\t\t}\n\n\t\t\treturn 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2);\n\n\t\t}\n\n\t},\n\n\tBounce: {\n\n\t\tIn: function (k) {\n\n\t\t\treturn 1 - TWEEN.Easing.Bounce.Out(1 - k);\n\n\t\t},\n\n\t\tOut: function (k) {\n\n\t\t\tif (k < (1 / 2.75)) {\n\t\t\t\treturn 7.5625 * k * k;\n\t\t\t} else if (k < (2 / 2.75)) {\n\t\t\t\treturn 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75;\n\t\t\t} else if (k < (2.5 / 2.75)) {\n\t\t\t\treturn 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375;\n\t\t\t} else {\n\t\t\t\treturn 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375;\n\t\t\t}\n\n\t\t},\n\n\t\tInOut: function (k) {\n\n\t\t\tif (k < 0.5) {\n\t\t\t\treturn TWEEN.Easing.Bounce.In(k * 2) * 0.5;\n\t\t\t}\n\n\t\t\treturn TWEEN.Easing.Bounce.Out(k * 2 - 1) * 0.5 + 0.5;\n\n\t\t}\n\n\t}\n\n};\n\nTWEEN.Interpolation = {\n\n\tLinear: function (v, k) {\n\n\t\tvar m = v.length - 1;\n\t\tvar f = m * k;\n\t\tvar i = Math.floor(f);\n\t\tvar fn = TWEEN.Interpolation.Utils.Linear;\n\n\t\tif (k < 0) {\n\t\t\treturn fn(v[0], v[1], f);\n\t\t}\n\n\t\tif (k > 1) {\n\t\t\treturn fn(v[m], v[m - 1], m - f);\n\t\t}\n\n\t\treturn fn(v[i], v[i + 1 > m ? m : i + 1], f - i);\n\n\t},\n\n\tBezier: function (v, k) {\n\n\t\tvar b = 0;\n\t\tvar n = v.length - 1;\n\t\tvar pw = Math.pow;\n\t\tvar bn = TWEEN.Interpolation.Utils.Bernstein;\n\n\t\tfor (var i = 0; i <= n; i++) {\n\t\t\tb += pw(1 - k, n - i) * pw(k, i) * v[i] * bn(n, i);\n\t\t}\n\n\t\treturn b;\n\n\t},\n\n\tCatmullRom: function (v, k) {\n\n\t\tvar m = v.length - 1;\n\t\tvar f = m * k;\n\t\tvar i = Math.floor(f);\n\t\tvar fn = TWEEN.Interpolation.Utils.CatmullRom;\n\n\t\tif (v[0] === v[m]) {\n\n\t\t\tif (k < 0) {\n\t\t\t\ti = Math.floor(f = m * (1 + k));\n\t\t\t}\n\n\t\t\treturn fn(v[(i - 1 + m) % m], v[i], v[(i + 1) % m], v[(i + 2) % m], f - i);\n\n\t\t} else {\n\n\t\t\tif (k < 0) {\n\t\t\t\treturn v[0] - (fn(v[0], v[0], v[1], v[1], -f) - v[0]);\n\t\t\t}\n\n\t\t\tif (k > 1) {\n\t\t\t\treturn v[m] - (fn(v[m], v[m], v[m - 1], v[m - 1], f - m) - v[m]);\n\t\t\t}\n\n\t\t\treturn fn(v[i ? i - 1 : 0], v[i], v[m < i + 1 ? m : i + 1], v[m < i + 2 ? m : i + 2], f - i);\n\n\t\t}\n\n\t},\n\n\tUtils: {\n\n\t\tLinear: function (p0, p1, t) {\n\n\t\t\treturn (p1 - p0) * t + p0;\n\n\t\t},\n\n\t\tBernstein: function (n, i) {\n\n\t\t\tvar fc = TWEEN.Interpolation.Utils.Factorial;\n\n\t\t\treturn fc(n) / fc(i) / fc(n - i);\n\n\t\t},\n\n\t\tFactorial: (function () {\n\n\t\t\tvar a = [1];\n\n\t\t\treturn function (n) {\n\n\t\t\t\tvar s = 1;\n\n\t\t\t\tif (a[n]) {\n\t\t\t\t\treturn a[n];\n\t\t\t\t}\n\n\t\t\t\tfor (var i = n; i > 1; i--) {\n\t\t\t\t\ts *= i;\n\t\t\t\t}\n\n\t\t\t\ta[n] = s;\n\t\t\t\treturn s;\n\n\t\t\t};\n\n\t\t})(),\n\n\t\tCatmullRom: function (p0, p1, p2, p3, t) {\n\n\t\t\tvar v0 = (p2 - p0) * 0.5;\n\t\t\tvar v1 = (p3 - p1) * 0.5;\n\t\t\tvar t2 = t * t;\n\t\t\tvar t3 = t * t2;\n\n\t\t\treturn (2 * p1 - 2 * p2 + v0 + v1) * t3 + (- 3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1;\n\n\t\t}\n\n\t}\n\n};\n\n// UMD (Universal Module Definition)\n(function (root) {\n\n\tif (typeof define === 'function' && define.amd) {\n\n\t\t// AMD\n\t\tdefine([], function () {\n\t\t\treturn TWEEN;\n\t\t});\n\n\t} else if (typeof module !== 'undefined' && typeof exports === 'object') {\n\n\t\t// Node.js\n\t\tmodule.exports = TWEEN;\n\n\t} else if (root !== undefined) {\n\n\t\t// Global variable\n\t\troot.TWEEN = TWEEN;\n\n\t}\n\n})(this);\n</script>\n<script>//https://github.com/mattdesl/lerp/blob/master/index.js\nvar lerp = function (v0, v1, t) { return v0*(1-t)+v1*t; };</script>\n<script>/*!\n * Bowser - a browser detector\n * https://github.com/ded/bowser\n * MIT License | (c) Dustin Diaz 2015\n */\n\n!function (root, name, definition) {\n  if (typeof module != 'undefined' && module.exports) module.exports = definition()\n  else if (typeof define == 'function' && define.amd) define(name, definition)\n  else root[name] = definition()\n}(this, 'bowser', function () {\n  /**\n    * See useragents.js for examples of navigator.userAgent\n    */\n\n  var t = true\n\n  function detect(ua) {\n\n    function getFirstMatch(regex) {\n      var match = ua.match(regex);\n      return (match && match.length > 1 && match[1]) || '';\n    }\n\n    function getSecondMatch(regex) {\n      var match = ua.match(regex);\n      return (match && match.length > 1 && match[2]) || '';\n    }\n\n    var iosdevice = getFirstMatch(/(ipod|iphone|ipad)/i).toLowerCase()\n      , likeAndroid = /like android/i.test(ua)\n      , android = !likeAndroid && /android/i.test(ua)\n      , nexusMobile = /nexus\\s*[0-6]\\s*/i.test(ua)\n      , nexusTablet = !nexusMobile && /nexus\\s*[0-9]+/i.test(ua)\n      , chromeos = /CrOS/.test(ua)\n      , silk = /silk/i.test(ua)\n      , sailfish = /sailfish/i.test(ua)\n      , tizen = /tizen/i.test(ua)\n      , webos = /(web|hpw)os/i.test(ua)\n      , windowsphone = /windows phone/i.test(ua)\n      , samsungBrowser = /SamsungBrowser/i.test(ua)\n      , windows = !windowsphone && /windows/i.test(ua)\n      , mac = !iosdevice && !silk && /macintosh/i.test(ua)\n      , linux = !android && !sailfish && !tizen && !webos && /linux/i.test(ua)\n      , edgeVersion = getFirstMatch(/edge\\/(\\d+(\\.\\d+)?)/i)\n      , versionIdentifier = getFirstMatch(/version\\/(\\d+(\\.\\d+)?)/i)\n      , tablet = /tablet/i.test(ua)\n      , mobile = !tablet && /[^-]mobi/i.test(ua)\n      , xbox = /xbox/i.test(ua)\n      , result\n\n    if (/opera/i.test(ua)) {\n      //  an old Opera\n      result = {\n        name: 'Opera'\n      , opera: t\n      , version: versionIdentifier || getFirstMatch(/(?:opera|opr|opios)[\\s\\/](\\d+(\\.\\d+)?)/i)\n      }\n    } else if (/opr|opios/i.test(ua)) {\n      // a new Opera\n      result = {\n        name: 'Opera'\n        , opera: t\n        , version: getFirstMatch(/(?:opr|opios)[\\s\\/](\\d+(\\.\\d+)?)/i) || versionIdentifier\n      }\n    }\n    else if (/SamsungBrowser/i.test(ua)) {\n      result = {\n        name: 'Samsung Internet for Android'\n        , samsungBrowser: t\n        , version: versionIdentifier || getFirstMatch(/(?:SamsungBrowser)[\\s\\/](\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (/coast/i.test(ua)) {\n      result = {\n        name: 'Opera Coast'\n        , coast: t\n        , version: versionIdentifier || getFirstMatch(/(?:coast)[\\s\\/](\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (/yabrowser/i.test(ua)) {\n      result = {\n        name: 'Yandex Browser'\n      , yandexbrowser: t\n      , version: versionIdentifier || getFirstMatch(/(?:yabrowser)[\\s\\/](\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (/ucbrowser/i.test(ua)) {\n      result = {\n          name: 'UC Browser'\n        , ucbrowser: t\n        , version: getFirstMatch(/(?:ucbrowser)[\\s\\/](\\d+(?:\\.\\d+)+)/i)\n      }\n    }\n    else if (/mxios/i.test(ua)) {\n      result = {\n        name: 'Maxthon'\n        , maxthon: t\n        , version: getFirstMatch(/(?:mxios)[\\s\\/](\\d+(?:\\.\\d+)+)/i)\n      }\n    }\n    else if (/epiphany/i.test(ua)) {\n      result = {\n        name: 'Epiphany'\n        , epiphany: t\n        , version: getFirstMatch(/(?:epiphany)[\\s\\/](\\d+(?:\\.\\d+)+)/i)\n      }\n    }\n    else if (/puffin/i.test(ua)) {\n      result = {\n        name: 'Puffin'\n        , puffin: t\n        , version: getFirstMatch(/(?:puffin)[\\s\\/](\\d+(?:\\.\\d+)?)/i)\n      }\n    }\n    else if (/sleipnir/i.test(ua)) {\n      result = {\n        name: 'Sleipnir'\n        , sleipnir: t\n        , version: getFirstMatch(/(?:sleipnir)[\\s\\/](\\d+(?:\\.\\d+)+)/i)\n      }\n    }\n    else if (/k-meleon/i.test(ua)) {\n      result = {\n        name: 'K-Meleon'\n        , kMeleon: t\n        , version: getFirstMatch(/(?:k-meleon)[\\s\\/](\\d+(?:\\.\\d+)+)/i)\n      }\n    }\n    else if (windowsphone) {\n      result = {\n        name: 'Windows Phone'\n      , windowsphone: t\n      }\n      if (edgeVersion) {\n        result.msedge = t\n        result.version = edgeVersion\n      }\n      else {\n        result.msie = t\n        result.version = getFirstMatch(/iemobile\\/(\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (/msie|trident/i.test(ua)) {\n      result = {\n        name: 'Internet Explorer'\n      , msie: t\n      , version: getFirstMatch(/(?:msie |rv:)(\\d+(\\.\\d+)?)/i)\n      }\n    } else if (chromeos) {\n      result = {\n        name: 'Chrome'\n      , chromeos: t\n      , chromeBook: t\n      , chrome: t\n      , version: getFirstMatch(/(?:chrome|crios|crmo)\\/(\\d+(\\.\\d+)?)/i)\n      }\n    } else if (/chrome.+? edge/i.test(ua)) {\n      result = {\n        name: 'Microsoft Edge'\n      , msedge: t\n      , version: edgeVersion\n      }\n    }\n    else if (/vivaldi/i.test(ua)) {\n      result = {\n        name: 'Vivaldi'\n        , vivaldi: t\n        , version: getFirstMatch(/vivaldi\\/(\\d+(\\.\\d+)?)/i) || versionIdentifier\n      }\n    }\n    else if (sailfish) {\n      result = {\n        name: 'Sailfish'\n      , sailfish: t\n      , version: getFirstMatch(/sailfish\\s?browser\\/(\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (/seamonkey\\//i.test(ua)) {\n      result = {\n        name: 'SeaMonkey'\n      , seamonkey: t\n      , version: getFirstMatch(/seamonkey\\/(\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (/firefox|iceweasel|fxios/i.test(ua)) {\n      result = {\n        name: 'Firefox'\n      , firefox: t\n      , version: getFirstMatch(/(?:firefox|iceweasel|fxios)[ \\/](\\d+(\\.\\d+)?)/i)\n      }\n      if (/\\((mobile|tablet);[^\\)]*rv:[\\d\\.]+\\)/i.test(ua)) {\n        result.firefoxos = t\n      }\n    }\n    else if (silk) {\n      result =  {\n        name: 'Amazon Silk'\n      , silk: t\n      , version : getFirstMatch(/silk\\/(\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (/phantom/i.test(ua)) {\n      result = {\n        name: 'PhantomJS'\n      , phantom: t\n      , version: getFirstMatch(/phantomjs\\/(\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (/slimerjs/i.test(ua)) {\n      result = {\n        name: 'SlimerJS'\n        , slimer: t\n        , version: getFirstMatch(/slimerjs\\/(\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (/blackberry|\\bbb\\d+/i.test(ua) || /rim\\stablet/i.test(ua)) {\n      result = {\n        name: 'BlackBerry'\n      , blackberry: t\n      , version: versionIdentifier || getFirstMatch(/blackberry[\\d]+\\/(\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (webos) {\n      result = {\n        name: 'WebOS'\n      , webos: t\n      , version: versionIdentifier || getFirstMatch(/w(?:eb)?osbrowser\\/(\\d+(\\.\\d+)?)/i)\n      };\n      /touchpad\\//i.test(ua) && (result.touchpad = t)\n    }\n    else if (/bada/i.test(ua)) {\n      result = {\n        name: 'Bada'\n      , bada: t\n      , version: getFirstMatch(/dolfin\\/(\\d+(\\.\\d+)?)/i)\n      };\n    }\n    else if (tizen) {\n      result = {\n        name: 'Tizen'\n      , tizen: t\n      , version: getFirstMatch(/(?:tizen\\s?)?browser\\/(\\d+(\\.\\d+)?)/i) || versionIdentifier\n      };\n    }\n    else if (/qupzilla/i.test(ua)) {\n      result = {\n        name: 'QupZilla'\n        , qupzilla: t\n        , version: getFirstMatch(/(?:qupzilla)[\\s\\/](\\d+(?:\\.\\d+)+)/i) || versionIdentifier\n      }\n    }\n    else if (/chromium/i.test(ua)) {\n      result = {\n        name: 'Chromium'\n        , chromium: t\n        , version: getFirstMatch(/(?:chromium)[\\s\\/](\\d+(?:\\.\\d+)?)/i) || versionIdentifier\n      }\n    }\n    else if (/chrome|crios|crmo/i.test(ua)) {\n      result = {\n        name: 'Chrome'\n        , chrome: t\n        , version: getFirstMatch(/(?:chrome|crios|crmo)\\/(\\d+(\\.\\d+)?)/i)\n      }\n    }\n    else if (android) {\n      result = {\n        name: 'Android'\n        , version: versionIdentifier\n      }\n    }\n    else if (/safari|applewebkit/i.test(ua)) {\n      result = {\n        name: 'Safari'\n      , safari: t\n      }\n      if (versionIdentifier) {\n        result.version = versionIdentifier\n      }\n    }\n    else if (iosdevice) {\n      result = {\n        name : iosdevice == 'iphone' ? 'iPhone' : iosdevice == 'ipad' ? 'iPad' : 'iPod'\n      }\n      // WTF: version is not part of user agent in web apps\n      if (versionIdentifier) {\n        result.version = versionIdentifier\n      }\n    }\n    else if(/googlebot/i.test(ua)) {\n      result = {\n        name: 'Googlebot'\n      , googlebot: t\n      , version: getFirstMatch(/googlebot\\/(\\d+(\\.\\d+))/i) || versionIdentifier\n      }\n    }\n    else {\n      result = {\n        name: getFirstMatch(/^(.*)\\/(.*) /),\n        version: getSecondMatch(/^(.*)\\/(.*) /)\n     };\n   }\n\n    // set webkit or gecko flag for browsers based on these engines\n    if (!result.msedge && /(apple)?webkit/i.test(ua)) {\n      if (/(apple)?webkit\\/537\\.36/i.test(ua)) {\n        result.name = result.name || \"Blink\"\n        result.blink = t\n      } else {\n        result.name = result.name || \"Webkit\"\n        result.webkit = t\n      }\n      if (!result.version && versionIdentifier) {\n        result.version = versionIdentifier\n      }\n    } else if (!result.opera && /gecko\\//i.test(ua)) {\n      result.name = result.name || \"Gecko\"\n      result.gecko = t\n      result.version = result.version || getFirstMatch(/gecko\\/(\\d+(\\.\\d+)?)/i)\n    }\n\n    // set OS flags for platforms that have multiple browsers\n    if (!result.windowsphone && !result.msedge && (android || result.silk)) {\n      result.android = t\n    } else if (!result.windowsphone && !result.msedge && iosdevice) {\n      result[iosdevice] = t\n      result.ios = t\n    } else if (mac) {\n      result.mac = t\n    } else if (xbox) {\n      result.xbox = t\n    } else if (windows) {\n      result.windows = t\n    } else if (linux) {\n      result.linux = t\n    }\n\n    // OS version extraction\n    var osVersion = '';\n    if (result.windowsphone) {\n      osVersion = getFirstMatch(/windows phone (?:os)?\\s?(\\d+(\\.\\d+)*)/i);\n    } else if (iosdevice) {\n      osVersion = getFirstMatch(/os (\\d+([_\\s]\\d+)*) like mac os x/i);\n      osVersion = osVersion.replace(/[_\\s]/g, '.');\n    } else if (android) {\n      osVersion = getFirstMatch(/android[ \\/-](\\d+(\\.\\d+)*)/i);\n    } else if (result.webos) {\n      osVersion = getFirstMatch(/(?:web|hpw)os\\/(\\d+(\\.\\d+)*)/i);\n    } else if (result.blackberry) {\n      osVersion = getFirstMatch(/rim\\stablet\\sos\\s(\\d+(\\.\\d+)*)/i);\n    } else if (result.bada) {\n      osVersion = getFirstMatch(/bada\\/(\\d+(\\.\\d+)*)/i);\n    } else if (result.tizen) {\n      osVersion = getFirstMatch(/tizen[\\/\\s](\\d+(\\.\\d+)*)/i);\n    }\n    if (osVersion) {\n      result.osversion = osVersion;\n    }\n\n    // device type extraction\n    var osMajorVersion = osVersion.split('.')[0];\n    if (\n         tablet\n      || nexusTablet\n      || iosdevice == 'ipad'\n      || (android && (osMajorVersion == 3 || (osMajorVersion >= 4 && !mobile)))\n      || result.silk\n    ) {\n      result.tablet = t\n    } else if (\n         mobile\n      || iosdevice == 'iphone'\n      || iosdevice == 'ipod'\n      || android\n      || nexusMobile\n      || result.blackberry\n      || result.webos\n      || result.bada\n    ) {\n      result.mobile = t\n    }\n\n    // Graded Browser Support\n    // http://developer.yahoo.com/yui/articles/gbs\n    if (result.msedge ||\n        (result.msie && result.version >= 10) ||\n        (result.yandexbrowser && result.version >= 15) ||\n\t\t    (result.vivaldi && result.version >= 1.0) ||\n        (result.chrome && result.version >= 20) ||\n        (result.samsungBrowser && result.version >= 4) ||\n        (result.firefox && result.version >= 20.0) ||\n        (result.safari && result.version >= 6) ||\n        (result.opera && result.version >= 10.0) ||\n        (result.ios && result.osversion && result.osversion.split(\".\")[0] >= 6) ||\n        (result.blackberry && result.version >= 10.1)\n        || (result.chromium && result.version >= 20)\n        ) {\n      result.a = t;\n    }\n    else if ((result.msie && result.version < 10) ||\n        (result.chrome && result.version < 20) ||\n        (result.firefox && result.version < 20.0) ||\n        (result.safari && result.version < 6) ||\n        (result.opera && result.version < 10.0) ||\n        (result.ios && result.osversion && result.osversion.split(\".\")[0] < 6)\n        || (result.chromium && result.version < 20)\n        ) {\n      result.c = t\n    } else result.x = t\n\n    return result\n  }\n\n  var bowser = detect(typeof navigator !== 'undefined' ? navigator.userAgent || '' : '')\n\n  bowser.test = function (browserList) {\n    for (var i = 0; i < browserList.length; ++i) {\n      var browserItem = browserList[i];\n      if (typeof browserItem=== 'string') {\n        if (browserItem in bowser) {\n          return true;\n        }\n      }\n    }\n    return false;\n  }\n\n  /**\n   * Get version precisions count\n   *\n   * @example\n   *   getVersionPrecision(\"1.10.3\") // 3\n   *\n   * @param  {string} version\n   * @return {number}\n   */\n  function getVersionPrecision(version) {\n    return version.split(\".\").length;\n  }\n\n  /**\n   * Array::map polyfill\n   *\n   * @param  {Array} arr\n   * @param  {Function} iterator\n   * @return {Array}\n   */\n  function map(arr, iterator) {\n    var result = [], i;\n    if (Array.prototype.map) {\n      return Array.prototype.map.call(arr, iterator);\n    }\n    for (i = 0; i < arr.length; i++) {\n      result.push(iterator(arr[i]));\n    }\n    return result;\n  }\n\n  /**\n   * Calculate browser version weight\n   *\n   * @example\n   *   compareVersions(['1.10.2.1',  '1.8.2.1.90'])    // 1\n   *   compareVersions(['1.010.2.1', '1.09.2.1.90']);  // 1\n   *   compareVersions(['1.10.2.1',  '1.10.2.1']);     // 0\n   *   compareVersions(['1.10.2.1',  '1.0800.2']);     // -1\n   *\n   * @param  {Array<String>} versions versions to compare\n   * @return {Number} comparison result\n   */\n  function compareVersions(versions) {\n    // 1) get common precision for both versions, for example for \"10.0\" and \"9\" it should be 2\n    var precision = Math.max(getVersionPrecision(versions[0]), getVersionPrecision(versions[1]));\n    var chunks = map(versions, function (version) {\n      var delta = precision - getVersionPrecision(version);\n\n      // 2) \"9\" -> \"9.0\" (for precision = 2)\n      version = version + new Array(delta + 1).join(\".0\");\n\n      // 3) \"9.0\" -> [\"000000000\"\", \"000000009\"]\n      return map(version.split(\".\"), function (chunk) {\n        return new Array(20 - chunk.length).join(\"0\") + chunk;\n      }).reverse();\n    });\n\n    // iterate in reverse order by reversed chunks array\n    while (--precision >= 0) {\n      // 4) compare: \"000000009\" > \"000000010\" = false (but \"9\" > \"10\" = true)\n      if (chunks[0][precision] > chunks[1][precision]) {\n        return 1;\n      }\n      else if (chunks[0][precision] === chunks[1][precision]) {\n        if (precision === 0) {\n          // all version chunks are same\n          return 0;\n        }\n      }\n      else {\n        return -1;\n      }\n    }\n  }\n\n  /**\n   * Check if browser is unsupported\n   *\n   * @example\n   *   bowser.isUnsupportedBrowser({\n   *     msie: \"10\",\n   *     firefox: \"23\",\n   *     chrome: \"29\",\n   *     safari: \"5.1\",\n   *     opera: \"16\",\n   *     phantom: \"534\"\n   *   });\n   *\n   * @param  {Object}  minVersions map of minimal version to browser\n   * @param  {Boolean} [strictMode = false] flag to return false if browser wasn't found in map\n   * @param  {String}  [ua] user agent string\n   * @return {Boolean}\n   */\n  function isUnsupportedBrowser(minVersions, strictMode, ua) {\n    var _bowser = bowser;\n\n    // make strictMode param optional with ua param usage\n    if (typeof strictMode === 'string') {\n      ua = strictMode;\n      strictMode = void(0);\n    }\n\n    if (strictMode === void(0)) {\n      strictMode = false;\n    }\n    if (ua) {\n      _bowser = detect(ua);\n    }\n\n    var version = \"\" + _bowser.version;\n    for (var browser in minVersions) {\n      if (minVersions.hasOwnProperty(browser)) {\n        if (_bowser[browser]) {\n          if (typeof minVersions[browser] !== 'string') {\n            throw new Error('Browser version in the minVersion map should be a string: ' + browser + ': ' + String(minVersions));\n          }\n\n          // browser version and min supported version.\n          return compareVersions([version, minVersions[browser]]) < 0;\n        }\n      }\n    }\n\n    return strictMode; // not found\n  }\n\n  /**\n   * Check if browser is supported\n   *\n   * @param  {Object} minVersions map of minimal version to browser\n   * @param  {Boolean} [strictMode = false] flag to return false if browser wasn't found in map\n   * @param  {String}  [ua] user agent string\n   * @return {Boolean}\n   */\n  function check(minVersions, strictMode, ua) {\n    return !isUnsupportedBrowser(minVersions, strictMode, ua);\n  }\n\n  bowser.isUnsupportedBrowser = isUnsupportedBrowser;\n  bowser.compareVersions = compareVersions;\n  bowser.check = check;\n\n  /*\n   * Set our detect method to the main bowser object so we can\n   * reuse it to test other user agents.\n   * This is needed to implement future tests.\n   */\n  bowser._detect = detect;\n\n  return bowser\n});\n</script>\n<script>/*! howler.js v2.0.3 | (c) 2013-2017, James Simpson of GoldFire Studios | MIT License | howlerjs.com */\n!function(){\"use strict\";var e=function(){this.init()};e.prototype={init:function(){var e=this||n;return e._counter=0,e._codecs={},e._howls=[],e._muted=!1,e._volume=1,e._canPlayEvent=\"canplaythrough\",e._navigator=\"undefined\"!=typeof window&&window.navigator?window.navigator:null,e.masterGain=null,e.noAudio=!1,e.usingWebAudio=!0,e.autoSuspend=!0,e.ctx=null,e.mobileAutoEnable=!0,e._setup(),e},volume:function(e){var o=this||n;if(e=parseFloat(e),o.ctx||_(),void 0!==e&&e>=0&&e<=1){if(o._volume=e,o._muted)return o;o.usingWebAudio&&(o.masterGain.gain.value=e);for(var t=0;t<o._howls.length;t++)if(!o._howls[t]._webAudio)for(var r=o._howls[t]._getSoundIds(),a=0;a<r.length;a++){var u=o._howls[t]._soundById(r[a]);u&&u._node&&(u._node.volume=u._volume*e)}return o}return o._volume},mute:function(e){var o=this||n;o.ctx||_(),o._muted=e,o.usingWebAudio&&(o.masterGain.gain.value=e?0:o._volume);for(var t=0;t<o._howls.length;t++)if(!o._howls[t]._webAudio)for(var r=o._howls[t]._getSoundIds(),a=0;a<r.length;a++){var u=o._howls[t]._soundById(r[a]);u&&u._node&&(u._node.muted=!!e||u._muted)}return o},unload:function(){for(var e=this||n,o=e._howls.length-1;o>=0;o--)e._howls[o].unload();return e.usingWebAudio&&e.ctx&&void 0!==e.ctx.close&&(e.ctx.close(),e.ctx=null,_()),e},codecs:function(e){return(this||n)._codecs[e.replace(/^x-/,\"\")]},_setup:function(){var e=this||n;if(e.state=e.ctx?e.ctx.state||\"running\":\"running\",e._autoSuspend(),!e.usingWebAudio)if(\"undefined\"!=typeof Audio)try{var o=new Audio;void 0===o.oncanplaythrough&&(e._canPlayEvent=\"canplay\")}catch(n){e.noAudio=!0}else e.noAudio=!0;try{var o=new Audio;o.muted&&(e.noAudio=!0)}catch(e){}return e.noAudio||e._setupCodecs(),e},_setupCodecs:function(){var e=this||n,o=null;try{o=\"undefined\"!=typeof Audio?new Audio:null}catch(n){return e}if(!o||\"function\"!=typeof o.canPlayType)return e;var t=o.canPlayType(\"audio/mpeg;\").replace(/^no$/,\"\"),r=e._navigator&&e._navigator.userAgent.match(/OPR\\/([0-6].)/g),a=r&&parseInt(r[0].split(\"/\")[1],10)<33;return e._codecs={mp3:!(a||!t&&!o.canPlayType(\"audio/mp3;\").replace(/^no$/,\"\")),mpeg:!!t,opus:!!o.canPlayType('audio/ogg; codecs=\"opus\"').replace(/^no$/,\"\"),ogg:!!o.canPlayType('audio/ogg; codecs=\"vorbis\"').replace(/^no$/,\"\"),oga:!!o.canPlayType('audio/ogg; codecs=\"vorbis\"').replace(/^no$/,\"\"),wav:!!o.canPlayType('audio/wav; codecs=\"1\"').replace(/^no$/,\"\"),aac:!!o.canPlayType(\"audio/aac;\").replace(/^no$/,\"\"),caf:!!o.canPlayType(\"audio/x-caf;\").replace(/^no$/,\"\"),m4a:!!(o.canPlayType(\"audio/x-m4a;\")||o.canPlayType(\"audio/m4a;\")||o.canPlayType(\"audio/aac;\")).replace(/^no$/,\"\"),mp4:!!(o.canPlayType(\"audio/x-mp4;\")||o.canPlayType(\"audio/mp4;\")||o.canPlayType(\"audio/aac;\")).replace(/^no$/,\"\"),weba:!!o.canPlayType('audio/webm; codecs=\"vorbis\"').replace(/^no$/,\"\"),webm:!!o.canPlayType('audio/webm; codecs=\"vorbis\"').replace(/^no$/,\"\"),dolby:!!o.canPlayType('audio/mp4; codecs=\"ec-3\"').replace(/^no$/,\"\"),flac:!!(o.canPlayType(\"audio/x-flac;\")||o.canPlayType(\"audio/flac;\")).replace(/^no$/,\"\")},e},_enableMobileAudio:function(){var e=this||n,o=/iPhone|iPad|iPod|Android|BlackBerry|BB10|Silk|Mobi/i.test(e._navigator&&e._navigator.userAgent),t=!!(\"ontouchend\"in window||e._navigator&&e._navigator.maxTouchPoints>0||e._navigator&&e._navigator.msMaxTouchPoints>0);if(!e._mobileEnabled&&e.ctx&&(o||t)){e._mobileEnabled=!1,e._mobileUnloaded||44100===e.ctx.sampleRate||(e._mobileUnloaded=!0,e.unload()),e._scratchBuffer=e.ctx.createBuffer(1,1,22050);var r=function(){var n=e.ctx.createBufferSource();n.buffer=e._scratchBuffer,n.connect(e.ctx.destination),void 0===n.start?n.noteOn(0):n.start(0),n.onended=function(){n.disconnect(0),e._mobileEnabled=!0,e.mobileAutoEnable=!1,document.removeEventListener(\"touchend\",r,!0)}};return document.addEventListener(\"touchend\",r,!0),e}},_autoSuspend:function(){var e=this;if(e.autoSuspend&&e.ctx&&void 0!==e.ctx.suspend&&n.usingWebAudio){for(var o=0;o<e._howls.length;o++)if(e._howls[o]._webAudio)for(var t=0;t<e._howls[o]._sounds.length;t++)if(!e._howls[o]._sounds[t]._paused)return e;return e._suspendTimer&&clearTimeout(e._suspendTimer),e._suspendTimer=setTimeout(function(){e.autoSuspend&&(e._suspendTimer=null,e.state=\"suspending\",e.ctx.suspend().then(function(){e.state=\"suspended\",e._resumeAfterSuspend&&(delete e._resumeAfterSuspend,e._autoResume())}))},3e4),e}},_autoResume:function(){var e=this;if(e.ctx&&void 0!==e.ctx.resume&&n.usingWebAudio)return\"running\"===e.state&&e._suspendTimer?(clearTimeout(e._suspendTimer),e._suspendTimer=null):\"suspended\"===e.state?(e.state=\"resuming\",e.ctx.resume().then(function(){e.state=\"running\";for(var n=0;n<e._howls.length;n++)e._howls[n]._emit(\"resume\")}),e._suspendTimer&&(clearTimeout(e._suspendTimer),e._suspendTimer=null)):\"suspending\"===e.state&&(e._resumeAfterSuspend=!0),e}};var n=new e,o=function(e){var n=this;if(!e.src||0===e.src.length)return void console.error(\"An array of source files must be passed with any new Howl.\");n.init(e)};o.prototype={init:function(e){var o=this;return n.ctx||_(),o._autoplay=e.autoplay||!1,o._format=\"string\"!=typeof e.format?e.format:[e.format],o._html5=e.html5||!1,o._muted=e.mute||!1,o._loop=e.loop||!1,o._pool=e.pool||5,o._preload=\"boolean\"!=typeof e.preload||e.preload,o._rate=e.rate||1,o._sprite=e.sprite||{},o._src=\"string\"!=typeof e.src?e.src:[e.src],o._volume=void 0!==e.volume?e.volume:1,o._duration=0,o._state=\"unloaded\",o._sounds=[],o._endTimers={},o._queue=[],o._onend=e.onend?[{fn:e.onend}]:[],o._onfade=e.onfade?[{fn:e.onfade}]:[],o._onload=e.onload?[{fn:e.onload}]:[],o._onloaderror=e.onloaderror?[{fn:e.onloaderror}]:[],o._onpause=e.onpause?[{fn:e.onpause}]:[],o._onplay=e.onplay?[{fn:e.onplay}]:[],o._onstop=e.onstop?[{fn:e.onstop}]:[],o._onmute=e.onmute?[{fn:e.onmute}]:[],o._onvolume=e.onvolume?[{fn:e.onvolume}]:[],o._onrate=e.onrate?[{fn:e.onrate}]:[],o._onseek=e.onseek?[{fn:e.onseek}]:[],o._onresume=[],o._webAudio=n.usingWebAudio&&!o._html5,void 0!==n.ctx&&n.ctx&&n.mobileAutoEnable&&n._enableMobileAudio(),n._howls.push(o),o._autoplay&&o._queue.push({event:\"play\",action:function(){o.play()}}),o._preload&&o.load(),o},load:function(){var e=this,o=null;if(n.noAudio)return void e._emit(\"loaderror\",null,\"No audio support.\");\"string\"==typeof e._src&&(e._src=[e._src]);for(var r=0;r<e._src.length;r++){var u,i;if(e._format&&e._format[r])u=e._format[r];else{if(\"string\"!=typeof(i=e._src[r])){e._emit(\"loaderror\",null,\"Non-string found in selected audio sources - ignoring.\");continue}u=/^data:audio\\/([^;,]+);/i.exec(i),u||(u=/\\.([^.]+)$/.exec(i.split(\"?\",1)[0])),u&&(u=u[1].toLowerCase())}if(u||console.warn('No file extension was found. Consider using the \"format\" property or specify an extension.'),u&&n.codecs(u)){o=e._src[r];break}}return o?(e._src=o,e._state=\"loading\",\"https:\"===window.location.protocol&&\"http:\"===o.slice(0,5)&&(e._html5=!0,e._webAudio=!1),new t(e),e._webAudio&&a(e),e):void e._emit(\"loaderror\",null,\"No codec support for selected audio sources.\")},play:function(e,o){var t=this,r=null;if(\"number\"==typeof e)r=e,e=null;else{if(\"string\"==typeof e&&\"loaded\"===t._state&&!t._sprite[e])return null;if(void 0===e){e=\"__default\";for(var a=0,u=0;u<t._sounds.length;u++)t._sounds[u]._paused&&!t._sounds[u]._ended&&(a++,r=t._sounds[u]._id);1===a?e=null:r=null}}var i=r?t._soundById(r):t._inactiveSound();if(!i)return null;if(r&&!e&&(e=i._sprite||\"__default\"),\"loaded\"!==t._state&&!t._sprite[e])return t._queue.push({event:\"play\",action:function(){t.play(t._soundById(i._id)?i._id:void 0)}}),i._id;if(r&&!i._paused)return o||setTimeout(function(){t._emit(\"play\",i._id)},0),i._id;t._webAudio&&n._autoResume();var d=Math.max(0,i._seek>0?i._seek:t._sprite[e][0]/1e3),_=Math.max(0,(t._sprite[e][0]+t._sprite[e][1])/1e3-d),s=1e3*_/Math.abs(i._rate);i._paused=!1,i._ended=!1,i._sprite=e,i._seek=d,i._start=t._sprite[e][0]/1e3,i._stop=(t._sprite[e][0]+t._sprite[e][1])/1e3,i._loop=!(!i._loop&&!t._sprite[e][2]);var l=i._node;if(t._webAudio){var c=function(){t._refreshBuffer(i);var e=i._muted||t._muted?0:i._volume;l.gain.setValueAtTime(e,n.ctx.currentTime),i._playStart=n.ctx.currentTime,void 0===l.bufferSource.start?i._loop?l.bufferSource.noteGrainOn(0,d,86400):l.bufferSource.noteGrainOn(0,d,_):i._loop?l.bufferSource.start(0,d,86400):l.bufferSource.start(0,d,_),s!==1/0&&(t._endTimers[i._id]=setTimeout(t._ended.bind(t,i),s)),o||setTimeout(function(){t._emit(\"play\",i._id)},0)},f=\"running\"===n.state;if(\"loaded\"===t._state&&f)c();else{var p=f||\"loaded\"!==t._state?\"load\":\"resume\";t.once(p,c,f?i._id:null),t._clearTimer(i._id)}}else{var v=function(){l.currentTime=d,l.muted=i._muted||t._muted||n._muted||l.muted,l.volume=i._volume*n.volume(),l.playbackRate=i._rate,l.play(),s!==1/0&&(t._endTimers[i._id]=setTimeout(t._ended.bind(t,i),s)),o||t._emit(\"play\",i._id)},m=\"loaded\"===t._state&&(window&&window.ejecta||!l.readyState&&n._navigator.isCocoonJS);if(4===l.readyState||m)v();else{var h=function(){v(),l.removeEventListener(n._canPlayEvent,h,!1)};l.addEventListener(n._canPlayEvent,h,!1),t._clearTimer(i._id)}}return i._id},pause:function(e){var n=this;if(\"loaded\"!==n._state)return n._queue.push({event:\"pause\",action:function(){n.pause(e)}}),n;for(var o=n._getSoundIds(e),t=0;t<o.length;t++){n._clearTimer(o[t]);var r=n._soundById(o[t]);if(r&&!r._paused&&(r._seek=n.seek(o[t]),r._rateSeek=0,r._paused=!0,n._stopFade(o[t]),r._node))if(n._webAudio){if(!r._node.bufferSource)return n;void 0===r._node.bufferSource.stop?r._node.bufferSource.noteOff(0):r._node.bufferSource.stop(0),n._cleanBuffer(r._node)}else isNaN(r._node.duration)&&r._node.duration!==1/0||r._node.pause();arguments[1]||n._emit(\"pause\",r?r._id:null)}return n},stop:function(e,n){var o=this;if(\"loaded\"!==o._state)return o._queue.push({event:\"stop\",action:function(){o.stop(e)}}),o;for(var t=o._getSoundIds(e),r=0;r<t.length;r++){o._clearTimer(t[r]);var a=o._soundById(t[r]);if(a&&(a._seek=a._start||0,a._rateSeek=0,a._paused=!0,a._ended=!0,o._stopFade(t[r]),a._node))if(o._webAudio){if(!a._node.bufferSource)return n||o._emit(\"stop\",a._id),o;void 0===a._node.bufferSource.stop?a._node.bufferSource.noteOff(0):a._node.bufferSource.stop(0),o._cleanBuffer(a._node)}else isNaN(a._node.duration)&&a._node.duration!==1/0||(a._node.currentTime=a._start||0,a._node.pause());a&&!n&&o._emit(\"stop\",a._id)}return o},mute:function(e,o){var t=this;if(\"loaded\"!==t._state)return t._queue.push({event:\"mute\",action:function(){t.mute(e,o)}}),t;if(void 0===o){if(\"boolean\"!=typeof e)return t._muted;t._muted=e}for(var r=t._getSoundIds(o),a=0;a<r.length;a++){var u=t._soundById(r[a]);u&&(u._muted=e,t._webAudio&&u._node?u._node.gain.setValueAtTime(e?0:u._volume,n.ctx.currentTime):u._node&&(u._node.muted=!!n._muted||e),t._emit(\"mute\",u._id))}return t},volume:function(){var e,o,t=this,r=arguments;if(0===r.length)return t._volume;if(1===r.length||2===r.length&&void 0===r[1]){t._getSoundIds().indexOf(r[0])>=0?o=parseInt(r[0],10):e=parseFloat(r[0])}else r.length>=2&&(e=parseFloat(r[0]),o=parseInt(r[1],10));var a;if(!(void 0!==e&&e>=0&&e<=1))return a=o?t._soundById(o):t._sounds[0],a?a._volume:0;if(\"loaded\"!==t._state)return t._queue.push({event:\"volume\",action:function(){t.volume.apply(t,r)}}),t;void 0===o&&(t._volume=e),o=t._getSoundIds(o);for(var u=0;u<o.length;u++)(a=t._soundById(o[u]))&&(a._volume=e,r[2]||t._stopFade(o[u]),t._webAudio&&a._node&&!a._muted?a._node.gain.setValueAtTime(e,n.ctx.currentTime):a._node&&!a._muted&&(a._node.volume=e*n.volume()),t._emit(\"volume\",a._id));return t},fade:function(e,o,t,r){var a=this,u=Math.abs(e-o),i=e>o?\"out\":\"in\",d=u/.01,_=d>0?t/d:t;if(_<4&&(d=Math.ceil(d/(4/_)),_=4),\"loaded\"!==a._state)return a._queue.push({event:\"fade\",action:function(){a.fade(e,o,t,r)}}),a;a.volume(e,r);for(var s=a._getSoundIds(r),l=0;l<s.length;l++){var c=a._soundById(s[l]);if(c){if(r||a._stopFade(s[l]),a._webAudio&&!c._muted){var f=n.ctx.currentTime,p=f+t/1e3;c._volume=e,c._node.gain.setValueAtTime(e,f),c._node.gain.linearRampToValueAtTime(o,p)}var v=e;c._interval=setInterval(function(n,t){d>0&&(v+=\"in\"===i?.01:-.01),v=Math.max(0,v),v=Math.min(1,v),v=Math.round(100*v)/100,a._webAudio?(void 0===r&&(a._volume=v),t._volume=v):a.volume(v,n,!0),(o<e&&v<=o||o>e&&v>=o)&&(clearInterval(t._interval),t._interval=null,a.volume(o,n),a._emit(\"fade\",n))}.bind(a,s[l],c),_)}}return a},_stopFade:function(e){var o=this,t=o._soundById(e);return t&&t._interval&&(o._webAudio&&t._node.gain.cancelScheduledValues(n.ctx.currentTime),clearInterval(t._interval),t._interval=null,o._emit(\"fade\",e)),o},loop:function(){var e,n,o,t=this,r=arguments;if(0===r.length)return t._loop;if(1===r.length){if(\"boolean\"!=typeof r[0])return!!(o=t._soundById(parseInt(r[0],10)))&&o._loop;e=r[0],t._loop=e}else 2===r.length&&(e=r[0],n=parseInt(r[1],10));for(var a=t._getSoundIds(n),u=0;u<a.length;u++)(o=t._soundById(a[u]))&&(o._loop=e,t._webAudio&&o._node&&o._node.bufferSource&&(o._node.bufferSource.loop=e,e&&(o._node.bufferSource.loopStart=o._start||0,o._node.bufferSource.loopEnd=o._stop)));return t},rate:function(){var e,o,t=this,r=arguments;if(0===r.length)o=t._sounds[0]._id;else if(1===r.length){var a=t._getSoundIds(),u=a.indexOf(r[0]);u>=0?o=parseInt(r[0],10):e=parseFloat(r[0])}else 2===r.length&&(e=parseFloat(r[0]),o=parseInt(r[1],10));var i;if(\"number\"!=typeof e)return i=t._soundById(o),i?i._rate:t._rate;if(\"loaded\"!==t._state)return t._queue.push({event:\"rate\",action:function(){t.rate.apply(t,r)}}),t;void 0===o&&(t._rate=e),o=t._getSoundIds(o);for(var d=0;d<o.length;d++)if(i=t._soundById(o[d])){i._rateSeek=t.seek(o[d]),i._playStart=t._webAudio?n.ctx.currentTime:i._playStart,i._rate=e,t._webAudio&&i._node&&i._node.bufferSource?i._node.bufferSource.playbackRate.value=e:i._node&&(i._node.playbackRate=e);var _=t.seek(o[d]),s=(t._sprite[i._sprite][0]+t._sprite[i._sprite][1])/1e3-_,l=1e3*s/Math.abs(i._rate);!t._endTimers[o[d]]&&i._paused||(t._clearTimer(o[d]),t._endTimers[o[d]]=setTimeout(t._ended.bind(t,i),l)),t._emit(\"rate\",i._id)}return t},seek:function(){var e,o,t=this,r=arguments;if(0===r.length)o=t._sounds[0]._id;else if(1===r.length){var a=t._getSoundIds(),u=a.indexOf(r[0]);u>=0?o=parseInt(r[0],10):(o=t._sounds[0]._id,e=parseFloat(r[0]))}else 2===r.length&&(e=parseFloat(r[0]),o=parseInt(r[1],10));if(void 0===o)return t;if(\"loaded\"!==t._state)return t._queue.push({event:\"seek\",action:function(){t.seek.apply(t,r)}}),t;var i=t._soundById(o);if(i){if(!(\"number\"==typeof e&&e>=0)){if(t._webAudio){var d=t.playing(o)?n.ctx.currentTime-i._playStart:0,_=i._rateSeek?i._rateSeek-i._seek:0;return i._seek+(_+d*Math.abs(i._rate))}return i._node.currentTime}var s=t.playing(o);s&&t.pause(o,!0),i._seek=e,i._ended=!1,t._clearTimer(o),s&&t.play(o,!0),!t._webAudio&&i._node&&(i._node.currentTime=e),t._emit(\"seek\",o)}return t},playing:function(e){var n=this;if(\"number\"==typeof e){var o=n._soundById(e);return!!o&&!o._paused}for(var t=0;t<n._sounds.length;t++)if(!n._sounds[t]._paused)return!0;return!1},duration:function(e){var n=this,o=n._duration,t=n._soundById(e);return t&&(o=n._sprite[t._sprite][1]/1e3),o},state:function(){return this._state},unload:function(){for(var e=this,o=e._sounds,t=0;t<o.length;t++){o[t]._paused||e.stop(o[t]._id),e._webAudio||(o[t]._node.src=\"data:audio/wav;base64,UklGRigAAABXQVZFZm10IBIAAAABAAEARKwAAIhYAQACABAAAABkYXRhAgAAAAEA\",o[t]._node.removeEventListener(\"error\",o[t]._errorFn,!1),o[t]._node.removeEventListener(n._canPlayEvent,o[t]._loadFn,!1)),delete o[t]._node,e._clearTimer(o[t]._id);var a=n._howls.indexOf(e);a>=0&&n._howls.splice(a,1)}var u=!0;for(t=0;t<n._howls.length;t++)if(n._howls[t]._src===e._src){u=!1;break}return r&&u&&delete r[e._src],n.noAudio=!1,e._state=\"unloaded\",e._sounds=[],e=null,null},on:function(e,n,o,t){var r=this,a=r[\"_on\"+e];return\"function\"==typeof n&&a.push(t?{id:o,fn:n,once:t}:{id:o,fn:n}),r},off:function(e,n,o){var t=this,r=t[\"_on\"+e],a=0;if(n){for(a=0;a<r.length;a++)if(n===r[a].fn&&o===r[a].id){r.splice(a,1);break}}else if(e)t[\"_on\"+e]=[];else{var u=Object.keys(t);for(a=0;a<u.length;a++)0===u[a].indexOf(\"_on\")&&Array.isArray(t[u[a]])&&(t[u[a]]=[])}return t},once:function(e,n,o){var t=this;return t.on(e,n,o,1),t},_emit:function(e,n,o){for(var t=this,r=t[\"_on\"+e],a=r.length-1;a>=0;a--)r[a].id&&r[a].id!==n&&\"load\"!==e||(setTimeout(function(e){e.call(this,n,o)}.bind(t,r[a].fn),0),r[a].once&&t.off(e,r[a].fn,r[a].id));return t},_loadQueue:function(){var e=this;if(e._queue.length>0){var n=e._queue[0];e.once(n.event,function(){e._queue.shift(),e._loadQueue()}),n.action()}return e},_ended:function(e){var o=this,t=e._sprite,r=!(!e._loop&&!o._sprite[t][2]);if(o._emit(\"end\",e._id),!o._webAudio&&r&&o.stop(e._id,!0).play(e._id),o._webAudio&&r){o._emit(\"play\",e._id),e._seek=e._start||0,e._rateSeek=0,e._playStart=n.ctx.currentTime;var a=1e3*(e._stop-e._start)/Math.abs(e._rate);o._endTimers[e._id]=setTimeout(o._ended.bind(o,e),a)}return o._webAudio&&!r&&(e._paused=!0,e._ended=!0,e._seek=e._start||0,e._rateSeek=0,o._clearTimer(e._id),o._cleanBuffer(e._node),n._autoSuspend()),o._webAudio||r||o.stop(e._id),o},_clearTimer:function(e){var n=this;return n._endTimers[e]&&(clearTimeout(n._endTimers[e]),delete n._endTimers[e]),n},_soundById:function(e){for(var n=this,o=0;o<n._sounds.length;o++)if(e===n._sounds[o]._id)return n._sounds[o];return null},_inactiveSound:function(){var e=this;e._drain();for(var n=0;n<e._sounds.length;n++)if(e._sounds[n]._ended)return e._sounds[n].reset();return new t(e)},_drain:function(){var e=this,n=e._pool,o=0,t=0;if(!(e._sounds.length<n)){for(t=0;t<e._sounds.length;t++)e._sounds[t]._ended&&o++;for(t=e._sounds.length-1;t>=0;t--){if(o<=n)return;e._sounds[t]._ended&&(e._webAudio&&e._sounds[t]._node&&e._sounds[t]._node.disconnect(0),e._sounds.splice(t,1),o--)}}},_getSoundIds:function(e){var n=this;if(void 0===e){for(var o=[],t=0;t<n._sounds.length;t++)o.push(n._sounds[t]._id);return o}return[e]},_refreshBuffer:function(e){var o=this;return e._node.bufferSource=n.ctx.createBufferSource(),e._node.bufferSource.buffer=r[o._src],e._panner?e._node.bufferSource.connect(e._panner):e._node.bufferSource.connect(e._node),e._node.bufferSource.loop=e._loop,e._loop&&(e._node.bufferSource.loopStart=e._start||0,e._node.bufferSource.loopEnd=e._stop),e._node.bufferSource.playbackRate.value=e._rate,o},_cleanBuffer:function(e){var n=this;if(n._scratchBuffer){e.bufferSource.onended=null,e.bufferSource.disconnect(0);try{e.bufferSource.buffer=n._scratchBuffer}catch(e){}}return e.bufferSource=null,n}};var t=function(e){this._parent=e,this.init()};t.prototype={init:function(){var e=this,o=e._parent;return e._muted=o._muted,e._loop=o._loop,e._volume=o._volume,e._muted=o._muted,e._rate=o._rate,e._seek=0,e._paused=!0,e._ended=!0,e._sprite=\"__default\",e._id=++n._counter,o._sounds.push(e),e.create(),e},create:function(){var e=this,o=e._parent,t=n._muted||e._muted||e._parent._muted?0:e._volume;return o._webAudio?(e._node=void 0===n.ctx.createGain?n.ctx.createGainNode():n.ctx.createGain(),e._node.gain.setValueAtTime(t,n.ctx.currentTime),e._node.paused=!0,e._node.connect(n.masterGain)):(e._node=new Audio,e._errorFn=e._errorListener.bind(e),e._node.addEventListener(\"error\",e._errorFn,!1),e._loadFn=e._loadListener.bind(e),e._node.addEventListener(n._canPlayEvent,e._loadFn,!1),e._node.src=o._src,e._node.preload=\"auto\",e._node.volume=t*n.volume(),e._node.load()),e},reset:function(){var e=this,o=e._parent;return e._muted=o._muted,e._loop=o._loop,e._volume=o._volume,e._muted=o._muted,e._rate=o._rate,e._seek=0,e._rateSeek=0,e._paused=!0,e._ended=!0,e._sprite=\"__default\",e._id=++n._counter,e},_errorListener:function(){var e=this;e._parent._emit(\"loaderror\",e._id,e._node.error?e._node.error.code:0),e._node.removeEventListener(\"error\",e._errorListener,!1)},_loadListener:function(){var e=this,o=e._parent;o._duration=Math.ceil(10*e._node.duration)/10,0===Object.keys(o._sprite).length&&(o._sprite={__default:[0,1e3*o._duration]}),\"loaded\"!==o._state&&(o._state=\"loaded\",o._emit(\"load\"),o._loadQueue()),e._node.removeEventListener(n._canPlayEvent,e._loadFn,!1)}};var r={},a=function(e){var n=e._src;if(r[n])return e._duration=r[n].duration,void d(e);if(/^data:[^;]+;base64,/.test(n)){for(var o=atob(n.split(\",\")[1]),t=new Uint8Array(o.length),a=0;a<o.length;++a)t[a]=o.charCodeAt(a);i(t.buffer,e)}else{var _=new XMLHttpRequest;_.open(\"GET\",n,!0),_.responseType=\"arraybuffer\",_.onload=function(){var n=(_.status+\"\")[0];if(\"0\"!==n&&\"2\"!==n&&\"3\"!==n)return void e._emit(\"loaderror\",null,\"Failed loading audio file with status: \"+_.status+\".\");i(_.response,e)},_.onerror=function(){e._webAudio&&(e._html5=!0,e._webAudio=!1,e._sounds=[],delete r[n],e.load())},u(_)}},u=function(e){try{e.send()}catch(n){e.onerror()}},i=function(e,o){n.ctx.decodeAudioData(e,function(e){e&&o._sounds.length>0&&(r[o._src]=e,d(o,e))},function(){o._emit(\"loaderror\",null,\"Decoding audio data failed.\")})},d=function(e,n){n&&!e._duration&&(e._duration=n.duration),0===Object.keys(e._sprite).length&&(e._sprite={__default:[0,1e3*e._duration]}),\"loaded\"!==e._state&&(e._state=\"loaded\",e._emit(\"load\"),e._loadQueue())},_=function(){try{\"undefined\"!=typeof AudioContext?n.ctx=new AudioContext:\"undefined\"!=typeof webkitAudioContext?n.ctx=new webkitAudioContext:n.usingWebAudio=!1}catch(e){n.usingWebAudio=!1}var e=/iP(hone|od|ad)/.test(n._navigator&&n._navigator.platform),o=n._navigator&&n._navigator.appVersion.match(/OS (\\d+)_(\\d+)_?(\\d+)?/),t=o?parseInt(o[1],10):null;if(e&&t&&t<9){var r=/safari/.test(n._navigator&&n._navigator.userAgent.toLowerCase());(n._navigator&&n._navigator.standalone&&!r||n._navigator&&!n._navigator.standalone&&!r)&&(n.usingWebAudio=!1)}n.usingWebAudio&&(n.masterGain=void 0===n.ctx.createGain?n.ctx.createGainNode():n.ctx.createGain(),n.masterGain.gain.value=1,n.masterGain.connect(n.ctx.destination)),n._setup()};\"function\"==typeof define&&define.amd&&define([],function(){return{Howler:n,Howl:o}}),\"undefined\"!=typeof exports&&(exports.Howler=n,exports.Howl=o),\"undefined\"!=typeof window?(window.HowlerGlobal=e,window.Howler=n,window.Howl=o,window.Sound=t):\"undefined\"!=typeof global&&(global.HowlerGlobal=e,global.Howler=n,global.Howl=o,global.Sound=t)}();\n/*! Spatial Plugin */\n!function(){\"use strict\";HowlerGlobal.prototype._pos=[0,0,0],HowlerGlobal.prototype._orientation=[0,0,-1,0,1,0],HowlerGlobal.prototype.stereo=function(n){var e=this;if(!e.ctx||!e.ctx.listener)return e;for(var o=e._howls.length-1;o>=0;o--)e._howls[o].stereo(n);return e},HowlerGlobal.prototype.pos=function(n,e,o){var t=this;return t.ctx&&t.ctx.listener?(e=\"number\"!=typeof e?t._pos[1]:e,o=\"number\"!=typeof o?t._pos[2]:o,\"number\"!=typeof n?t._pos:(t._pos=[n,e,o],t.ctx.listener.setPosition(t._pos[0],t._pos[1],t._pos[2]),t)):t},HowlerGlobal.prototype.orientation=function(n,e,o,t,r,i){var a=this;if(!a.ctx||!a.ctx.listener)return a;var p=a._orientation;return e=\"number\"!=typeof e?p[1]:e,o=\"number\"!=typeof o?p[2]:o,t=\"number\"!=typeof t?p[3]:t,r=\"number\"!=typeof r?p[4]:r,i=\"number\"!=typeof i?p[5]:i,\"number\"!=typeof n?p:(a._orientation=[n,e,o,t,r,i],a.ctx.listener.setOrientation(n,e,o,t,r,i),a)},Howl.prototype.init=function(n){return function(e){var o=this;return o._orientation=e.orientation||[1,0,0],o._stereo=e.stereo||null,o._pos=e.pos||null,o._pannerAttr={coneInnerAngle:void 0!==e.coneInnerAngle?e.coneInnerAngle:360,coneOuterAngle:void 0!==e.coneOuterAngle?e.coneOuterAngle:360,coneOuterGain:void 0!==e.coneOuterGain?e.coneOuterGain:0,distanceModel:void 0!==e.distanceModel?e.distanceModel:\"inverse\",maxDistance:void 0!==e.maxDistance?e.maxDistance:1e4,panningModel:void 0!==e.panningModel?e.panningModel:\"HRTF\",refDistance:void 0!==e.refDistance?e.refDistance:1,rolloffFactor:void 0!==e.rolloffFactor?e.rolloffFactor:1},o._onstereo=e.onstereo?[{fn:e.onstereo}]:[],o._onpos=e.onpos?[{fn:e.onpos}]:[],o._onorientation=e.onorientation?[{fn:e.onorientation}]:[],n.call(this,e)}}(Howl.prototype.init),Howl.prototype.stereo=function(e,o){var t=this;if(!t._webAudio)return t;if(\"loaded\"!==t._state)return t._queue.push({event:\"stereo\",action:function(){t.stereo(e,o)}}),t;var r=void 0===Howler.ctx.createStereoPanner?\"spatial\":\"stereo\";if(void 0===o){if(\"number\"!=typeof e)return t._stereo;t._stereo=e,t._pos=[e,0,0]}for(var i=t._getSoundIds(o),a=0;a<i.length;a++){var p=t._soundById(i[a]);if(p){if(\"number\"!=typeof e)return p._stereo;p._stereo=e,p._pos=[e,0,0],p._node&&(p._pannerAttr.panningModel=\"equalpower\",p._panner&&p._panner.pan||n(p,r),\"spatial\"===r?p._panner.setPosition(e,0,0):p._panner.pan.value=e),t._emit(\"stereo\",p._id)}}return t},Howl.prototype.pos=function(e,o,t,r){var i=this;if(!i._webAudio)return i;if(\"loaded\"!==i._state)return i._queue.push({event:\"pos\",action:function(){i.pos(e,o,t,r)}}),i;if(o=\"number\"!=typeof o?0:o,t=\"number\"!=typeof t?-.5:t,void 0===r){if(\"number\"!=typeof e)return i._pos;i._pos=[e,o,t]}for(var a=i._getSoundIds(r),p=0;p<a.length;p++){var s=i._soundById(a[p]);if(s){if(\"number\"!=typeof e)return s._pos;s._pos=[e,o,t],s._node&&(s._panner&&!s._panner.pan||n(s,\"spatial\"),s._panner.setPosition(e,o,t)),i._emit(\"pos\",s._id)}}return i},Howl.prototype.orientation=function(e,o,t,r){var i=this;if(!i._webAudio)return i;if(\"loaded\"!==i._state)return i._queue.push({event:\"orientation\",action:function(){i.orientation(e,o,t,r)}}),i;if(o=\"number\"!=typeof o?i._orientation[1]:o,t=\"number\"!=typeof t?i._orientation[2]:t,void 0===r){if(\"number\"!=typeof e)return i._orientation;i._orientation=[e,o,t]}for(var a=i._getSoundIds(r),p=0;p<a.length;p++){var s=i._soundById(a[p]);if(s){if(\"number\"!=typeof e)return s._orientation;s._orientation=[e,o,t],s._node&&(s._panner||(s._pos||(s._pos=i._pos||[0,0,-.5]),n(s,\"spatial\")),s._panner.setOrientation(e,o,t)),i._emit(\"orientation\",s._id)}}return i},Howl.prototype.pannerAttr=function(){var e,o,t,r=this,i=arguments;if(!r._webAudio)return r;if(0===i.length)return r._pannerAttr;if(1===i.length){if(\"object\"!=typeof i[0])return t=r._soundById(parseInt(i[0],10)),t?t._pannerAttr:r._pannerAttr;e=i[0],void 0===o&&(r._pannerAttr={coneInnerAngle:void 0!==e.coneInnerAngle?e.coneInnerAngle:r._coneInnerAngle,coneOuterAngle:void 0!==e.coneOuterAngle?e.coneOuterAngle:r._coneOuterAngle,coneOuterGain:void 0!==e.coneOuterGain?e.coneOuterGain:r._coneOuterGain,distanceModel:void 0!==e.distanceModel?e.distanceModel:r._distanceModel,maxDistance:void 0!==e.maxDistance?e.maxDistance:r._maxDistance,panningModel:void 0!==e.panningModel?e.panningModel:r._panningModel,refDistance:void 0!==e.refDistance?e.refDistance:r._refDistance,rolloffFactor:void 0!==e.rolloffFactor?e.rolloffFactor:r._rolloffFactor})}else 2===i.length&&(e=i[0],o=parseInt(i[1],10));for(var a=r._getSoundIds(o),p=0;p<a.length;p++)if(t=r._soundById(a[p])){var s=t._pannerAttr;s={coneInnerAngle:void 0!==e.coneInnerAngle?e.coneInnerAngle:s.coneInnerAngle,coneOuterAngle:void 0!==e.coneOuterAngle?e.coneOuterAngle:s.coneOuterAngle,coneOuterGain:void 0!==e.coneOuterGain?e.coneOuterGain:s.coneOuterGain,distanceModel:void 0!==e.distanceModel?e.distanceModel:s.distanceModel,maxDistance:void 0!==e.maxDistance?e.maxDistance:s.maxDistance,panningModel:void 0!==e.panningModel?e.panningModel:s.panningModel,refDistance:void 0!==e.refDistance?e.refDistance:s.refDistance,rolloffFactor:void 0!==e.rolloffFactor?e.rolloffFactor:s.rolloffFactor};var l=t._panner;l?(l.coneInnerAngle=s.coneInnerAngle,l.coneOuterAngle=s.coneOuterAngle,l.coneOuterGain=s.coneOuterGain,l.distanceModel=s.distanceModel,l.maxDistance=s.maxDistance,l.panningModel=s.panningModel,l.refDistance=s.refDistance,l.rolloffFactor=s.rolloffFactor):(t._pos||(t._pos=r._pos||[0,0,-.5]),n(t,\"spatial\"))}return r},Sound.prototype.init=function(n){return function(){var e=this,o=e._parent;e._orientation=o._orientation,e._stereo=o._stereo,e._pos=o._pos,e._pannerAttr=o._pannerAttr,n.call(this),e._stereo?o.stereo(e._stereo):e._pos&&o.pos(e._pos[0],e._pos[1],e._pos[2],e._id)}}(Sound.prototype.init),Sound.prototype.reset=function(n){return function(){var e=this,o=e._parent;return e._orientation=o._orientation,e._pos=o._pos,e._pannerAttr=o._pannerAttr,n.call(this)}}(Sound.prototype.reset);var n=function(n,e){e=e||\"spatial\",\"spatial\"===e?(n._panner=Howler.ctx.createPanner(),n._panner.coneInnerAngle=n._pannerAttr.coneInnerAngle,n._panner.coneOuterAngle=n._pannerAttr.coneOuterAngle,n._panner.coneOuterGain=n._pannerAttr.coneOuterGain,n._panner.distanceModel=n._pannerAttr.distanceModel,n._panner.maxDistance=n._pannerAttr.maxDistance,n._panner.panningModel=n._pannerAttr.panningModel,n._panner.refDistance=n._pannerAttr.refDistance,n._panner.rolloffFactor=n._pannerAttr.rolloffFactor,n._panner.setPosition(n._pos[0],n._pos[1],n._pos[2]),n._panner.setOrientation(n._orientation[0],n._orientation[1],n._orientation[2])):(n._panner=Howler.ctx.createStereoPanner(),n._panner.pan.value=n._stereo),n._panner.connect(n._node),n._paused||n._parent.pause(n._id,!0).play(n._id)}}();</script>\n<script>var URLParameterUtils = (function () {\n\n\tvar urlParameterUtils = { };\n\n\turlParameterUtils.getParameterByName = function (name, url) {\n\t    if (!url) url = window.location.href;\n\t    name = name.replace(/[\\[\\]]/g, \"\\\\$&\");\n\t    var regex = new RegExp(\"[?&]\" + name + \"(=([^&#]*)|&|#|$)\"),\n\t        results = regex.exec(url);\n\t    if (!results) return null;\n\t    if (!results[2]) return '';\n\t    return decodeURIComponent(results[2].replace(/\\+/g, \" \"));\n\t}\n\n\t//http://stackoverflow.com/questions/1634748/how-can-i-delete-a-query-string-parameter-in-javascript\n\turlParameterUtils.clearURLParam = function (parameter) {\n\t    //prefer to use l.search if you have a location/link object\n\t    var url = window.location.href;\n\t    var urlparts= url.split('?');   \n\t    if (urlparts.length>=2) {\n\n\t        var prefix= encodeURIComponent(parameter)+'=';\n\t        var pars= urlparts[1].split(/[&;]/g);\n\n\t        //reverse iteration as may be destructive\n\t        for (var i= pars.length; i-- > 0;) {    \n\t            //idiom for string.startsWith\n\t            if (pars[i].lastIndexOf(prefix, 0) !== -1) {  \n\t                pars.splice(i, 1);\n\t            }\n\t        }\n\n\t        url= urlparts[0] + (pars.length > 0 ? '?' + pars.join('&') : \"\");\n\t        //console.log(url)\n\t        //window.location.href = url;\n\t        history.pushState(null, null, url);\n\t        return url;\n\t    } else {\n\t        return url;\n\t    }\n\t}\n\n\treturn urlParameterUtils;\n\n})();</script>\n<script>// stats.js - http://github.com/mrdoob/stats.js\n(function(f,e){\"object\"===typeof exports&&\"undefined\"!==typeof module?module.exports=e():\"function\"===typeof define&&define.amd?define(e):f.Stats=e()})(this,function(){var f=function(){function e(a){c.appendChild(a.dom);return a}function u(a){for(var d=0;d<c.children.length;d++)c.children[d].style.display=d===a?\"block\":\"none\";l=a}var l=0,c=document.createElement(\"div\");c.style.cssText=\"position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000\";c.addEventListener(\"click\",function(a){a.preventDefault();\nu(++l%c.children.length)},!1);var k=(performance||Date).now(),g=k,a=0,r=e(new f.Panel(\"FPS\",\"#0ff\",\"#002\")),h=e(new f.Panel(\"MS\",\"#0f0\",\"#020\"));if(self.performance&&self.performance.memory)var t=e(new f.Panel(\"MB\",\"#f08\",\"#201\"));u(0);return{REVISION:16,dom:c,addPanel:e,showPanel:u,begin:function(){k=(performance||Date).now()},end:function(){a++;var c=(performance||Date).now();h.update(c-k,200);if(c>g+1E3&&(r.update(1E3*a/(c-g),100),g=c,a=0,t)){var d=performance.memory;t.update(d.usedJSHeapSize/\n1048576,d.jsHeapSizeLimit/1048576)}return c},update:function(){k=this.end()},domElement:c,setMode:u}};f.Panel=function(e,f,l){var c=Infinity,k=0,g=Math.round,a=g(window.devicePixelRatio||1),r=80*a,h=48*a,t=3*a,v=2*a,d=3*a,m=15*a,n=74*a,p=30*a,q=document.createElement(\"canvas\");q.width=r;q.height=h;q.style.cssText=\"width:80px;height:48px\";var b=q.getContext(\"2d\");b.font=\"bold \"+9*a+\"px Helvetica,Arial,sans-serif\";b.textBaseline=\"top\";b.fillStyle=l;b.fillRect(0,0,r,h);b.fillStyle=f;b.fillText(e,t,v);\nb.fillRect(d,m,n,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d,m,n,p);return{dom:q,update:function(h,w){c=Math.min(c,h);k=Math.max(k,h);b.fillStyle=l;b.globalAlpha=1;b.fillRect(0,0,r,m);b.fillStyle=f;b.fillText(g(h)+\" \"+e+\" (\"+g(c)+\"-\"+g(k)+\")\",t,v);b.drawImage(q,d+a,m,n-a,p,d,m,n-a,p);b.fillRect(d+n-a,m,a,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d+n-a,m,a,g((1-h/w)*p))}}};return f});\n</script>\n<script>window.saveData = function (key, data) {\n\tif(!localStorage.savedData) \n\t\tlocalStorage.savedData = JSON.stringify({});\n\n\tvar savedData = JSON.parse(localStorage.savedData)\n\tvar type = typeof data;\n\tsavedData[key] = {\n\t\ttype: type,\n\t\tdata: (type === 'object') ? JSON.stringify(data) : data\n\t};\n\tlocalStorage.savedData = JSON.stringify(savedData);\n}\n\nwindow.getData = function (key) {\n\tvar savedData = JSON.parse(localStorage.savedData)\n\tif(savedData[key] !== undefined) {\n\t\tvar value = savedData[key];\n\t\tif(value.type === 'number') {\n\t\t\treturn parseFloat(value.data)\n\t\t} else if (value.type === 'string') {\n\t\t\treturn value.data;\n\t\t} else if (value.type === 'object') {\n\t\t\treturn JSON.parse(value.data);\n\t\t}\n\t} else {\n\t\tthrow (new Error(key + \" does not exist in saved data.\"))\n\t}\n}\n</script>\n<script>/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar tweenValueNames = [\"x\",\"y\",\"scaleX\",\"scaleY\",\"rotation\",\"opacity\"];\n\nvar WickTween = function() {\n    this.x = 0;\n    this.y = 0; \n    this.z = 0; \n    this.scaleX = 1;\n    this.scaleY = 1;\n    this.rotation = 0;\n    this.opacity = 1;\n\n    this.playheadPosition = 0;\n    this.rotations = 0;\n\n    this.uuid = random.uuid4();\n\n    this.tweenType = 'Linear';\n    this.tweenDir = 'None';\n}\n\nWickTween.fromWickObjectState = function (wickObject) {\n\tvar tween = new WickTween();\n\n\ttweenValueNames.forEach(function (name) {\n\t\ttween[name] = wickObject[name];\n\t});\n\n\treturn tween;\n}\n\nWickTween.prototype.copy = function () {\n    var copy = new WickTween();\n\n    copy.x = this.x;\n    copy.y = this.y; \n    copy.z = this.z; \n    copy.scaleX = this.scaleX;\n    copy.scaleY = this.scaleY;\n    copy.rotation = this.rotation;\n    copy.opacity = this.opacity;\n\n    copy.playheadPosition = this.playheadPosition;\n    copy.rotations = this.rotations;\n\n    copy.tweenType = this.tweenType;\n    copy.tweenDir = this.tweenDir;\n\n    return copy;\n}\n\nWickTween.prototype.updateFromWickObjectState = function (wickObject) {\n    var self = this;\n    \n    tweenValueNames.forEach(function (name) {\n        self[name] = wickObject[name];\n    });\n}\n\nWickTween.prototype.applyTweenToWickObject = function(wickObject) {\n\tvar that = this;\n\n\ttweenValueNames.forEach(function (name) {\n\t\twickObject[name] = that[name];\n\t});\n};\n\nWickTween.interpolateTweens = function (tweenA, tweenB, t) {\n\tvar interpTween = new WickTween();\n\n\tvar tweenFunc = (tweenA.tweenType === \"Linear\") ? (TWEEN.Easing.Linear.None) : (TWEEN.Easing[tweenA.tweenType][tweenA.tweenDir]);\n\ttweenValueNames.forEach(function (name) {\n\t\tvar tt = tweenFunc(t);\n        var valA = tweenA[name];\n        var valB = tweenB[name];\n        if(name === 'rotation') {\n            while(valA < -180) valA += 360;\n            while(valB < -180) valB += 360;\n            while(valA > 180) valA -= 360;\n            while(valB > 180) valB -= 360;\n            valB += tweenA.rotations * 360;\n        }\n\t\tinterpTween[name] = lerp(valA, valB, tt);\n\t});\n\n\treturn interpTween;\n}\n</script>\n<script>/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar WickFrame = function () {\n    // Identifier so we can do e.g. movePlayheadTo(\"menu\") \n    this.name = \"New Frame\";\n\n    // Store all objects in frame. \n    this.wickObjects = [];\n\n    this.tweens = [];\n\n    // All path data of the frame (Stored as SVG)\n    this.pathData = null;\n\n    // Where this frame exists on the timeline\n    this.playheadPosition = null;\n\n    // Frame length for long frames\n    this.length = 1;\n\n    // Should the frame reset on being entered?\n    this.alwaysSaveState = false;\n\n    // Generate unique id\n    this.uuid = random.uuid4();\n\n    // The layer that this frame belongs to\n    this.parentLayer = null;\n\n    // Set all scripts to defaults\n    //this.wickScript = \"function load() {\\n\\t\\n}\\n\\nfunction update() {\\n\\t\\n}\\n\";\n    this.wickScript = \"\";\n};\n    \nWickFrame.prototype.tick = function () {\n    var self = this;\n    \n    if(this.wickScript !== '' || this.audioAssetUUID) {\n        // Inactive -> Inactive\n        // Do nothing, frame is still inactive\n        if (!this._wasActiveLastTick && !this._active) {\n\n        }\n        // Inactive -> Active\n        // Frame just became active! It's fresh!\n        else if (!this._wasActiveLastTick && this._active) {\n            if(this.wickScript !== '') {\n                (wickPlayer || wickEditor).project.initScript(this);\n                \n                (wickPlayer || wickEditor).project.runScript(this, 'load');\n                (wickPlayer || wickEditor).project.runScript(this, 'update');\n            }\n\n            if (this.audioAssetUUID) {\n                this._updateAudio();\n                this._playSound(); \n            }\n\n        }\n        // Active -> Active\n        // Frame is active!\n        else if (this._wasActiveLastTick && this._active) {\n            if(this.wickScript !== '') {\n                (wickPlayer || wickEditor).project.runScript(this, 'update');\n            }\n        }    \n        // Active -> Inactive\n        // Frame just stopped being active. Clean up!\n        else if (this._wasActiveLastTick && !this._active) {\n            if (this.audioAssetUUID) {\n                this._stopSound();\n            }\n        }\n        \n        if(this._wasClicked) {\n            (wickPlayer || wickEditor).project.runScript(this, 'mousePressed');\n            this._wasClicked = false;\n        }\n\n        if(this._beingClicked) {\n            (wickPlayer || wickEditor).project.runScript(this, 'mouseDown');\n        }\n\n        if(this._wasHoveredOver) {\n            (wickPlayer || wickEditor).project.runScript(this, 'mouseHover');\n            this._wasHoveredOver = false;\n        }\n\n        if(this._mouseJustLeft) {\n            (wickPlayer || wickEditor).project.runScript(this, 'mouseLeave');\n            this._mouseJustLeft = false;\n        }\n\n        if(this._wasClickedOff) {\n            (wickPlayer || wickEditor).project.runScript(this, 'mouseReleased');\n            this._wasClickedOff = false;\n        }\n\n        wickPlayer.inputHandler.getAllKeysJustReleased().forEach(function (key) {\n            (wickPlayer || wickEditor).project.runScript(self, 'keyReleased', key);\n        });\n\n        wickPlayer.inputHandler.getAllKeysJustPressed().forEach(function (key) {\n            (wickPlayer || wickEditor).project.runScript(self, 'keyPressed', key);\n        });\n\n        wickPlayer.inputHandler.getAllKeysDown().forEach(function (key) {\n            (wickPlayer || wickEditor).project.runScript(self, 'keyDown', key);\n        });\n    }\n\n    this.wickObjects.forEach(function (wickObject) {\n        wickObject.tick();\n    });\n}\n\nWickFrame.prototype.isActive = function () {\n    var parent = this.parentLayer.parentWickObject;\n\n    //if(parent.isRoot) console.log(parent.playheadPosition)\n\n    /*console.log(\"---\")\n    console.log(\"ph \"+(parent.playheadPosition))\n    console.log(\"s  \"+(this.playheadPosition))\n    console.log(\"e  \"+(this.playheadPosition+this.length))\n    console.log(\"---\")*/\n\n    return parent.playheadPosition >= this.playheadPosition\n        && parent.playheadPosition < this.playheadPosition+this.length\n        && parent.isActive();\n}\n\nWickFrame.prototype.hasScript = function () {\n    return this.wickScript !== \"\";\n}\n\n// Extend our frame to encompass more frames. \nWickFrame.prototype.extend = function(length) {\n    this.length += length; \n}\n\n// Reduce the number of frames this WickFrame Occupies. \nWickFrame.prototype.shrink = function(length) {\n    // Never \"shrink\" by a negative amount. \n    if (length <= 0) {\n        return;\n    }\n\n    originalLength = this.length; \n    this.length -= length; \n\n    // determine and return the actual change in frames. \n    if (this.length <= 0) {\n        this.length = 1;\n        return originalLength - 1;\n    } else {\n        return length; \n    }\n}\n\nWickFrame.prototype.copy = function () {\n\n    var copiedFrame = new WickFrame();\n\n    copiedFrame.name = this.name;\n    copiedFrame.playheadPosition = this.playheadPosition;\n    copiedFrame.length = this.length;\n    copiedFrame.wickScript = this.wickScript;\n    copiedFrame.uuid = random.uuid4();\n    copiedFrame.sourceUUID = this.uuid;\n\n    this.wickObjects.forEach(function (wickObject) {\n        copiedFrame.wickObjects.push(wickObject.copy());\n    })\n\n    this.tweens.forEach(function (tween) {\n        copiedFrame.tweens.push(tween.copy());\n    })\n\n    return copiedFrame;\n\n}\n\nWickFrame.prototype.remove = function () {\n    this.parentLayer.removeFrame(this);\n}\n\nWickFrame.prototype.touchesFrame = function (frame) {\n    var A = this;\n    var B = frame;\n\n    if(A._beingMoved || B._beingMoved) return false;\n\n    var AStart = A.playheadPosition;\n    var AEnd = A.playheadPosition + A.length;\n\n    var BStart = B.playheadPosition;\n    var BEnd = B.playheadPosition + B.length;\n\n    return !(BStart >= AEnd || BEnd <= AStart);\n}\n\nWickFrame.prototype.encodeStrings = function () {\n\n    if(this.wickScripts) {\n        for (var key in this.wickScripts) {\n            this.wickScripts[key] = WickProject.Compressor.encodeString(this.wickScripts[key]);\n        }\n    }\n    if(this.wickScript) {\n        this.wickScript = WickProject.Compressor.encodeString(this.wickScript);\n    }\n\n    if(this.pathData) this.pathData = WickProject.Compressor.encodeString(this.pathData);\n\n}\n\nWickFrame.prototype.decodeStrings = function () {\n\n    if(this.wickScripts) {\n        for (var key in this.wickScripts) {\n            this.wickScripts[key] = WickProject.Compressor.decodeString(this.wickScripts[key]);\n        }\n    }\n    if(this.wickScript) {\n        this.wickScript = WickProject.Compressor.decodeString(this.wickScript);\n    }\n\n    if(this.pathData) this.pathData = WickProject.Compressor.decodeString(this.pathData);\n\n}\n\nWickFrame.prototype.getFrameEnd = function () {\n    return this.playheadPosition + this.length; \n}\n\nWickFrame.prototype.getObjectByUUID = function () {\n\n    var foundWickObject;\n\n    this.wickObjects.forEach(function (wickObject) {\n        if(wickObject.uuid === uuid) {\n            foundWickObject = wickObject;\n        }\n    });\n\n    return foundWickObject;\n\n}\n\nWickFrame.prototype.getAsJSON = function () {\n    this.wickObjects.forEach(function (wickObject) {\n        wickObject.encodeStrings();\n    });\n\n    var frameJSON = JSON.stringify(this, WickProject.Exporter.JSONReplacerObject);\n\n    this.wickObjects.forEach(function (wickObject) {\n        wickObject.decodeStrings();\n    });\n\n    return frameJSON;\n}\n\nWickFrame.fromJSON = function (frameJSON) {\n    var frame = JSON.parse(frameJSON);\n    frame.__proto__ = WickFrame.prototype;\n    if(frame.tweens) {\n        frame.tweens.forEach(function (tween) {\n            tween.__proto__ = WickTween.prototype;\n        });\n    }\n    frame.uuid = random.uuid4();\n    frame.wickObjects.forEach(function (wickObject) {\n        WickObject.addPrototypes(wickObject);\n        wickObject.generateParentObjectReferences();\n        wickObject.decodeStrings();\n        wickObject.uuid = random.uuid4();\n    })\n    return frame;\n}\n\nWickFrame.fromJSONArray = function (jsonArrayObject) {\n    var frames = [];\n\n    var framesJSONArray = jsonArrayObject.wickObjectArray;\n    framesJSONArray.forEach(function (frameJSON) {\n        var newframe = WickFrame.fromJSON(frameJSON)\n        frames.push(newframe)\n    });\n\n    return frames;\n}\n\nWickFrame.prototype.getNextOpenPlayheadPosition = function () {\n    return this.parentLayer.getNextOpenPlayheadPosition(this.playheadPosition);\n}\n\nWickFrame.prototype.addTween = function (newTween) {\n    var self = this;\n\n    var replacedTween = false;\n    self.tweens.forEach(function (tween) {\n        if (tween.playheadPosition === newTween.playheadPosition) {\n            self.tweens[self.tweens.indexOf(tween)] = newTween;\n            replacedTween = true;\n        }\n    });\n\n    if(!replacedTween)\n        self.tweens.push(newTween);\n}\n\nWickFrame.prototype.removeTween = function (tweenToDelete) {\n    var self = this;\n\n    var deleteTweenIndex = null;\n    self.tweens.forEach(function (tween) {\n        if(deleteTweenIndex) return;\n        if (tweenToDelete === tween) {\n            deleteTweenIndex = self.tweens.indexOf(tween);\n        }\n    });\n\n    if(deleteTweenIndex !== null) {\n        self.tweens.splice(deleteTweenIndex, 1);\n    }\n}\n\nWickFrame.prototype.getCurrentTween = function () {\n    return this.getTweenAtFrame(this.parentObject.playheadPosition-this.playheadPosition)\n}\n\nWickFrame.prototype.getTweenAtPlayheadPosition = function (playheadPosition) {\n    var foundTween;\n    this.tweens.forEach(function (tween) {\n        if(foundTween) return;\n        if(tween.playheadPosition === playheadPosition) foundTween = tween;\n    })\n    return foundTween;\n}\n\nWickFrame.prototype.hasTweenAtFrame = function () {\n    var playheadPosition = this.parentObject.playheadPosition-this.playheadPosition;\n\n    var foundTween = false\n    this.tweens.forEach(function (tween) {\n        if(foundTween) return;\n        if(tween.playheadPosition === playheadPosition) foundTween = true;\n    })\n    return foundTween;\n}\n\nWickFrame.prototype.getTweenAtFrame = function (playheadPosition) {\n    var playheadPosition = this.parentObject.playheadPosition-this.playheadPosition;\n    \n    var foundTween;\n    this.tweens.forEach(function (tween) {\n        if(foundTween) return;\n        if(tween.playheadPosition === playheadPosition) foundTween = tween;\n    })\n    return foundTween;\n}\n\nWickFrame.prototype.getFromTween = function () {\n    var foundTween = null;\n\n    var relativePlayheadPosition = this.parentObject.playheadPosition-this.playheadPosition;\n\n    var seekPlayheadPosition = relativePlayheadPosition;\n    while (!foundTween && seekPlayheadPosition >= 0) {\n        this.tweens.forEach(function (tween) {\n            if(tween.playheadPosition === seekPlayheadPosition) {\n                foundTween = tween;\n            }\n        });\n        seekPlayheadPosition--;\n    }\n\n    return foundTween;\n}\n\nWickFrame.prototype.getToTween = function () {\n    var foundTween = null;\n\n    var relativePlayheadPosition = this.parentObject.playheadPosition-this.playheadPosition;\n\n    var seekPlayheadPosition = relativePlayheadPosition;\n    var parentFrameLength = this.length;\n    while (!foundTween && seekPlayheadPosition < parentFrameLength) {\n        this.tweens.forEach(function (tween) {\n            if(tween.playheadPosition === seekPlayheadPosition) {\n                foundTween = tween;\n            }\n        });\n        seekPlayheadPosition++;\n    }\n\n    return foundTween;\n}\n\nWickFrame.prototype.applyTween = function () {\n\n    var self = this;\n\n    var tweenToApply;\n\n    if(self.tweens.length === 1) {\n        tweenToApply = self.tweens[0];\n    } else if (self.tweens.length > 1) {\n        var tweenFrom = self.getFromTween();\n        var tweenTo = self.getToTween();\n\n        if (tweenFrom && tweenTo) {\n            var A = tweenFrom.playheadPosition;\n            var B = tweenTo.playheadPosition;\n            var L = B-A;\n            var P = (this.parentObject.playheadPosition-this.playheadPosition)-A;\n            var T = P/L;\n            if(B-A === 0) T = 1;\n            \n            tweenToApply = WickTween.interpolateTweens(tweenFrom, tweenTo, T);\n        }\n        if (!tweenFrom && tweenTo) {\n            tweenToApply = tweenTo;\n        }\n        if (!tweenTo && tweenFrom) {\n            tweenToApply = tweenFrom;\n        }\n    }\n\n    if(!tweenToApply) return;\n    self.wickObjects.forEach(function (wickObject) {\n        tweenToApply.applyTweenToWickObject(wickObject);\n    });\n\n}\n\nWickFrame.prototype._updateAudio = function () {\n    // Lazily create sound objects\n    if (!this.howl) {\n        if(window.wickPlayer) {\n            this.howl = wickPlayer.audioPlayer.makeSound(this.audioAssetUUID); \n        } else {\n            this.howl = new Howl({\n                src: [wickEditor.project.library.getAsset(this.audioAssetUUID).getData()]\n            });\n        }\n    }\n}\n\nWickFrame.prototype._playSound = function () {\n    if (this.volume) {\n        this.howl.volume(this.volume);\n    }\n    var howlerID = this.howl.play(); \n}\n\nWickFrame.prototype._stopSound = function () {\n    this.howl.stop(); \n}\n\n</script>\n<script>/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar WickLayer = function () {\n    this.frames = [new WickFrame()];\n    this.frames[0].playheadPosition = 0;\n\n    this.identifier = \"Layer 1\"\n    this.locked = false;\n    this.hidden = false;\n\n    this.parentWickObject = null; // The WickObject that this layer belongs to\n};\n\nWickLayer.prototype.getTotalLength = function () {\n    var length = 0;\n\n    this.frames.forEach(function (frame) {\n        var frameEnd = frame.playheadPosition + frame.length;\n        if(frameEnd > length) length = frameEnd;\n    });\n\n    return length;\n}\n\nWickLayer.prototype.getFrameAtPlayheadPosition = function (playheadPosition) {\n    var foundFrame = null;\n\n    this.frames.forEach(function (frame) {\n        if(foundFrame) return;\n        if(playheadPosition >= frame.playheadPosition && playheadPosition < frame.playheadPosition+frame.length) {\n            foundFrame = frame;\n        }\n    });\n\n    return foundFrame;\n}\n\nWickLayer.prototype.getCurrentFrame = function () {\n    return this.getFrameAtPlayheadPosition(this.parentWickObject.playheadPosition);\n}\n\n\nWickLayer.prototype.addFrame = function(newFrame, i) {\n    if(i) console.error(\"DEPERACATED! TELL ZJ!\");\n\n    this.frames.push(newFrame);\n}\n\nWickLayer.prototype.removeFrame = function(frame) {\n    var i = this.frames.indexOf(frame);\n    this.frames.splice(i, 1);\n}\n\nWickLayer.prototype.copy = function () {\n\n    var copiedLayer = new WickLayer();\n    copiedLayer.frames = [];\n\n    this.frames.forEach(function (frame) {\n        copiedLayer.frames.push(frame.copy());\n    })\n\n    return copiedLayer;\n\n}\n\nWickLayer.prototype.getFrameByIdentifier = function (id) {\n\n    var foundFrame = null;\n\n    this.frames.forEach(function (frame) {\n        if(frame.identifier === id) {\n            foundFrame = frame;\n        }\n    });\n\n    return foundFrame;\n\n}\n\nWickLayer.prototype.getRelativePlayheadPosition = function (wickObj, args) {\n\n    var playheadRelativePosition = this.playheadPosition - wickObj.parentFrame.playheadPosition;\n\n    if(args && args.normalized) playheadRelativePosition /= wickObj.parentFrame.length-1;\n\n    return playheadRelativePosition;\n\n}\n\nWickLayer.prototype.getFramesAtPlayheadPosition = function(pos, args) {\n    var frames = [];\n\n    var counter = 0;\n    for(var f = 0; f < this.frames.length; f++) {\n        var frame = this.frames[f];\n        for(var i = 0; i < frame.length; i++) {\n            if(counter == pos) {\n                frames.push(frame);\n            }\n            counter++;\n        }\n    }\n\n    return frames;\n}\n\nWickLayer.prototype.getNextOpenPlayheadPosition = function (startPosition) {\n    var targetPosition = startPosition;\n\n    while(this.getFrameAtPlayheadPosition(targetPosition)) {\n        targetPosition ++;\n    }\n\n    return targetPosition;\n}\n\nWickLayer.prototype.getLastFrame = function (playheadPosition) {\n    var lastFrame = null;\n\n    if(!playheadPosition) playheadPosition = 0;\n\n    // Look backwards\n    this.frames.forEach(function (frame) {\n        if(!lastFrame) lastFrame = frame;\n        if(frame.playheadPosition > lastFrame.playheadPosition && frame.playheadPosition < playheadPosition) {\n            lastFrame = frame;\n        }\n    });\n\n    if(lastFrame.playheadPosition > playheadPosition) return null;\n\n    return lastFrame;\n}\n\nWickLayer.prototype.containsWickObject = function (o) {\n    \n}\n</script>\n<script>/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar WickObject = function () {\n\n// Internals\n\n    // Unique id\n    this.uuid = random.uuid4();\n\n    // Name is optional, added by user\n    this.name = undefined;\n\n// Positioning\n\n    this.x = 0;\n    this.y = 0;\n    this.width = undefined;\n    this.height = undefined;\n    this.scaleX = 1;\n    this.scaleY = 1;\n    this.rotation = 0;\n    this.flipX = false;\n    this.flipY = false;\n    this.opacity = 1;\n\n// Common\n    \n    //this.wickScript = \"function load() {\\n\\t\\n}\\n\\nfunction update() {\\n\\t\\n}\\n\";\n    this.wickScript = \"\";\n\n// Static\n\n    this.assetUUID = null;\n    this.loop = false;\n\n// Text\n\n    this.isText = false;\n\n// Images\n\n    this.isImage = false;\n\n// Symbols\n\n    this.isSymbol = false;\n    this.isButton = false;\n    this.isGroup = false;\n\n    // Used to keep track of what frame is being edited\n    this.playheadPosition = null;\n    this.currentLayer = null;\n\n    // List of layers, only used by symbols\n    this.layers = undefined;\n\n// Render\n    \n    this._renderDirty = false;  // Tell the renderer if this object has changed. \n\n};\n\nWickObject.fromJSON = function (jsonString) {\n    // Parse JSON\n    var newWickObject = JSON.parse(jsonString);\n\n    // Put prototypes back on object ('class methods'), they don't get JSONified on project export.\n    WickObject.addPrototypes(newWickObject);\n\n    // Decode scripts back to human-readble and eval()-able format\n    newWickObject.decodeStrings();\n\n    return newWickObject;\n}\n\nWickObject.fromJSONArray = function (jsonArrayObject) {\n    var newWickObjects = [];\n\n    var wickObjectJSONArray = jsonArrayObject.wickObjectArray;\n    for (var i = 0; i < wickObjectJSONArray.length; i++) {\n        \n        var newWickObject = WickObject.fromJSON(wickObjectJSONArray[i]);\n        \n        if(wickObjectJSONArray.length > 1) {\n            newWickObject.x += jsonArrayObject.groupPosition.x;\n            newWickObject.y += jsonArrayObject.groupPosition.y;\n        }\n\n        newWickObjects.push(newWickObject);\n    }\n\n    return newWickObjects;\n}\n\nWickObject.createPathObject = function (svg) {\n    var obj = new WickObject();\n    obj.isPath = true;\n    obj.pathData = svg;\n\n    return obj;\n}\n\nWickObject.createTextObject = function (text) {\n    var obj = new WickObject();\n\n    obj.isText = true;\n    obj.width = 400;\n    obj.textData = {\n        fontFamily: 'Arial',\n        fontSize: 40,\n        fontStyle: 'normal',\n        fontWeight: 'normal',\n        lineHeight: 1.0,\n        fill: '#000000',\n        textAlign: 'left',\n        text: text\n    };\n\n    return obj;\n}\n\nWickObject.createNewSymbol = function (name) {\n\n    var symbol = new WickObject();\n\n    symbol.isSymbol = true;\n    symbol.playheadPosition = 0;\n    symbol.currentLayer = 0;\n    symbol.layers = [new WickLayer()];\n    symbol.name = name;\n\n    return symbol;\n\n}\n\n// Create a new symbol and add every object in wickObjects as children\nWickObject.createSymbolFromWickObjects = function (wickObjects) {\n\n    var symbol = WickObject.createNewSymbol();\n\n    // Calculate center of all WickObjects\n    var topLeft = {x:Number.MAX_SAFE_INTEGER, y:Number.MAX_SAFE_INTEGER};\n    var bottomRight = {x:-Number.MAX_SAFE_INTEGER,y:-Number.MAX_SAFE_INTEGER};\n    wickObjects.forEach(function (wickObj) {\n        topLeft.x = Math.min(topLeft.x, wickObj.x - wickObj.width /2);\n        topLeft.y = Math.min(topLeft.y, wickObj.y - wickObj.height/2);\n        bottomRight.x = Math.max(bottomRight.x, wickObj.x + wickObj.width /2);\n        bottomRight.y = Math.max(bottomRight.y, wickObj.y + wickObj.height/2);\n    });\n\n    var center = {\n        x: topLeft.x + (bottomRight.x - topLeft.x)/2,\n        y: topLeft.y + (bottomRight.y - topLeft.y)/2\n    }\n    symbol.x = center.x;\n    symbol.y = center.y;\n\n    var firstFrame = symbol.layers[0].frames[0];\n    for(var i = 0; i < wickObjects.length; i++) {\n        firstFrame.wickObjects[i] = wickObjects[i];\n\n        firstFrame.wickObjects[i].x = wickObjects[i].x - symbol.x;\n        firstFrame.wickObjects[i].y = wickObjects[i].y - symbol.y;\n    }\n\n    symbol.width  = firstFrame.wickObjects[0].width;\n    symbol.height = firstFrame.wickObjects[0].height;\n\n    return symbol;\n\n}\n\nWickObject.prototype.copy = function () {\n\n    var copiedObject = new WickObject();\n\n    copiedObject.name = this.name;\n    copiedObject.x = this.x;\n    copiedObject.y = this.y;\n    copiedObject.width = this.width;\n    copiedObject.height = this.height;\n    copiedObject.scaleX = this.scaleX;\n    copiedObject.scaleY = this.scaleY;\n    copiedObject.rotation = this.rotation;\n    copiedObject.flipX = this.flipX;\n    copiedObject.flipY = this.flipY;\n    copiedObject.opacity = this.opacity;\n    copiedObject.uuid = random.uuid4();\n    copiedObject.sourceUUID = this.uuid;\n    copiedObject.assetUUID = this.assetUUID;\n    copiedObject.svgX = this.svgX;\n    copiedObject.svgY = this.svgY;\n    copiedObject.pathData = this.pathData;\n    copiedObject.isImage = this.isImage;\n    copiedObject.isPath = this.isPath;\n    copiedObject.isText = this.isText;\n    copiedObject.isButton = this.isButton;\n    copiedObject.isGroup = this.isGroup;\n    copiedObject.cachedAbsolutePosition = this.getAbsolutePosition();\n    copiedObject.svgStrokeWidth = this.svgStrokeWidth;\n\n    if(this.isText)\n        copiedObject.textData = JSON.parse(JSON.stringify(this.textData));\n\n    copiedObject.wickScript = this.wickScript\n\n    if(this.isSymbol) {\n        copiedObject.isSymbol = true;\n\n        copiedObject.playheadPosition = 0;\n        copiedObject.currentLayer = 0;\n\n        copiedObject.layers = [];\n        this.layers.forEach(function (layer) {\n            copiedObject.layers.push(layer.copy());\n        });\n    } else {\n        copiedObject.isSymbol = false;\n    }\n\n    return copiedObject;\n\n}\n\nWickObject.prototype.getAsJSON = function () {\n    var oldX = this.x;\n    var oldY = this.y;\n\n    var absPos = this.getAbsolutePosition();\n    this.x = absPos.x;\n    this.y = absPos.y;\n\n    // Encode scripts to avoid JSON format problems\n    this.encodeStrings();\n\n    var JSONWickObject = JSON.stringify(this, WickProject.Exporter.JSONReplacerObject);\n\n    // Put prototypes back on object ('class methods'), they don't get JSONified on project export.\n    WickObject.addPrototypes(this);\n\n    // Decode scripts back to human-readble and eval()-able format\n    this.decodeStrings();\n\n    this.x = oldX;\n    this.y = oldY;\n\n    return JSONWickObject;\n}\n\nWickObject.prototype.downloadAsFile = function () {\n\n    var filename = this.name || \"wickobject\";\n\n    if(this.isSymbol) {\n        var blob = new Blob([this.getAsJSON()], {type: \"text/plain;charset=utf-8\"});\n        saveAs(blob, filename+\".json\");\n        return;\n    }\n\n    var asset = wickEditor.project.library.getAsset(this.assetUUID);\n\n    if(asset.type === 'image') {\n        var ext = asset.getData().split(\"/\")[1].split(';')[0];\n        saveAs(dataURItoBlob(asset.getData()), filename+\".\"+ext);\n        return;\n    }\n\n    console.error(\"export not supported for this type of wickobject yet\");\n\n}\n\nWickObject.addPrototypes = function (obj) {\n\n    // Put the prototype back on this object\n    obj.__proto__ = WickObject.prototype;\n\n    if(obj.isSymbol) {\n        obj.layers.forEach(function (layer) {\n            layer.__proto__ = WickLayer.prototype;\n            layer.frames.forEach(function(frame) {\n                frame.__proto__ = WickFrame.prototype;\n\n                if(frame.tweens) {\n                    frame.tweens.forEach(function (tween) {\n                        tween.__proto__ = WickTween.prototype;\n                    });\n                }\n            });\n        });\n\n        obj.getAllChildObjects().forEach(function(currObj) {\n            WickObject.addPrototypes(currObj);\n        });\n    }\n}\n\n/* Encodes scripts and strings to avoid JSON format problems */\nWickObject.prototype.encodeStrings = function () {\n\n    if(this.wickScript) {\n        this.wickScript = WickProject.Compressor.encodeString(this.wickScript);\n    }\n\n    if(this.textData) {\n        this.textData.text = WickProject.Compressor.encodeString(this.textData.text);\n    }\n\n    if(this.pathData) {\n        this.pathData = WickProject.Compressor.encodeString(this.pathData);\n    }\n\n    if(this.isSymbol) {\n        this.getAllFrames().forEach(function (frame) {\n            frame.encodeStrings();\n        });\n\n        this.getAllChildObjects().forEach(function(child) {\n            child.encodeStrings();\n        });\n    }\n\n}\n\n/* Decodes scripts and strings back to human-readble and eval()-able format */\nWickObject.prototype.decodeStrings = function () {\n    \n    if(this.wickScript) {\n        this.wickScript = WickProject.Compressor.decodeString(this.wickScript);\n    }\n\n    if(this.textData) {\n        this.textData.text = WickProject.Compressor.decodeString(this.textData.text);\n    }\n\n    if(this.pathData) {\n        this.pathData = WickProject.Compressor.decodeString(this.pathData);\n    }\n\n    if(this.isSymbol) {\n        this.getAllFrames().forEach(function (frame) {\n            frame.decodeStrings();\n        });\n\n        this.getAllChildObjects().forEach(function(child) {\n            child.decodeStrings();\n        });\n    }\n\n}\n\nWickObject.prototype.generateParentObjectReferences = function() {\n\n    var self = this;\n\n    if(!self.isSymbol) return;\n\n    self.layers.forEach(function (layer) {\n        layer.parentWickObject = self;\n\n        layer.frames.forEach(function (frame) {\n            frame.parentLayer = layer;\n            frame.parentObject = self;\n\n            frame.wickObjects.forEach(function (wickObject) {\n                wickObject.parentObject = self;\n                wickObject.parentFrame = frame;\n\n                wickObject.generateParentObjectReferences();\n            });\n        });\n    });\n\n}\n\nWickObject.prototype.generateObjectNameReferences = function () {\n\n    var that = this;\n\n    this.getAllChildObjects().forEach(function(child) {\n        that[child.name] = child;\n\n        if(child.isSymbol) {\n            child.generateObjectNameReferences();\n        }\n    });\n\n}\n\nWickObject.prototype.getCurrentLayer = function() {\n    return this.layers[this.currentLayer];\n}\n\nWickObject.prototype.addLayer = function (layer) {\n    var currentLayerNum = 0;\n\n    this.layers.forEach(function (layer) {\n        var splitName = layer.identifier.split(\"Layer \")\n        if(splitName && splitName.length > 1) {\n            layerNum = parseInt(splitName[1]);\n            if(layerNum > currentLayerNum) {\n                currentLayerNum = layerNum;\n            }\n        }\n    });\n\n    layer.identifier = \"Layer \" + (currentLayerNum+1);\n\n    this.layers.push(layer);\n}\n\nWickObject.prototype.removeLayer = function (layer) {\n    var that = this;\n    this.layers.forEach(function (currLayer) {\n        if(layer === currLayer) {\n            that.layers.splice(that.layers.indexOf(layer), 1);\n        }\n    });\n}\n\nWickObject.prototype.getTotalTimelineLength = function () {\n    var longestLayerLength = 0;\n\n    this.layers.forEach(function (layer) {\n        var layerLength = layer.getTotalLength();\n        if(layerLength > longestLayerLength) {\n            longestLayerLength = layerLength;\n        }\n    });\n\n    return longestLayerLength;\n\n}\n\nWickObject.prototype.updateFrameTween = function (relativePlayheadPosition) {\n    var frame = this.parentFrame;\n    var tween = frame.getTweenAtFrame(relativePlayheadPosition);\n\n    if(tween) {\n        tween.updateFromWickObjectState(this);\n    }\n}\n\n/* Return all child objects of a parent object */\nWickObject.prototype.getAllChildObjects = function () {\n\n    if (!this.isSymbol) {\n        return [];\n    }\n\n    var children = [];\n    for(var l = this.layers.length-1; l >= 0; l--) {\n        var layer = this.layers[l];\n        for(var f = 0; f < layer.frames.length; f++) {\n            var frame = layer.frames[f];\n            for(var o = 0; o < frame.wickObjects.length; o++) {\n                children.push(frame.wickObjects[o]);\n            }\n        }\n    }\n    return children;\n}\n\n/* Return all child objects in the parent objects current frame. */\nWickObject.prototype.getAllActiveChildObjects = function () {\n\n    if (!this.isSymbol) {\n        return [];\n    }\n\n    var children = [];\n    for (var l = this.layers.length-1; l >= 0; l--) {\n        var layer = this.layers[l];\n        var frame = layer.getFrameAtPlayheadPosition(this.playheadPosition);\n        if(frame) {\n            frame.wickObjects.forEach(function (obj) {\n                children.push(obj);\n            });\n        }\n    }\n    return children;\n}\n\n/* Return all child objects of a parent object (and their children) */\nWickObject.prototype.getAllChildObjectsRecursive = function () {\n\n    if (!this.isSymbol) {\n        return [this];\n    }\n\n    var children = [this];\n    this.layers.forEachBackwards(function (layer) {\n        layer.frames.forEach(function (frame) {\n            frame.wickObjects.forEach(function (wickObject) {\n                children = children.concat(wickObject.getAllChildObjectsRecursive());\n            });\n        });\n    });\n    return children;\n}\n\n/* Return all active child objects of a parent object (and their children) */\nWickObject.prototype.getAllActiveChildObjectsRecursive = function (includeParents) {\n\n    if (!this.isSymbol) {\n        return [];\n    }\n\n    var children = [];\n    for (var l = this.layers.length-1; l >= 0; l--) {\n        var frame = this.layers[l].getFrameAtPlayheadPosition(this.playheadPosition);\n        if(frame) {\n            for(var o = 0; o < frame.wickObjects.length; o++) {\n                var obj = frame.wickObjects[o];\n                if(includeParents || !obj.isSymbol) children.push(obj);\n                children = children.concat(obj.getAllActiveChildObjectsRecursive(includeParents));\n            }\n        }\n    }\n    return children;\n\n}\n\n/* Return all child objects in the parent objects current layer. */\nWickObject.prototype.getAllActiveLayerChildObjects = function () {\n\n    if (!this.isSymbol) {\n        return [];\n    }\n\n    var children = [];\n    var layer = this.getCurrentLayer();\n    var frame = layer.getFrameAtPlayheadPosition(this.playheadPosition);\n    if(frame) {\n        frame.wickObjects.forEach(function (obj) {\n            children.push(obj);\n        });\n    }\n    return children;\n}\n\n// Use this to get objects on other layers\nWickObject.prototype.getAllInactiveSiblings = function () {\n\n    if(!this.parentObject) {\n        return [];\n    }\n\n    var that = this;\n    var siblings = [];\n    this.parentObject.getAllActiveChildObjects().forEach(function (child) {\n        if(child !== that) {\n            siblings.push(child);\n        }\n    });\n    siblings = siblings.concat(this.parentObject.getAllInactiveSiblings());\n\n    return siblings;\n\n}\n\n// Use this for onion skinning\nWickObject.prototype.getNearbyObjects = function (numFramesBack, numFramesForward) {\n\n    // Get nearby frames\n\n    var nearbyFrames = [];\n\n    var startPlayheadPosition = Math.max(0, this.playheadPosition - numFramesBack);\n    var endPlayheadPosition = this.playheadPosition + numFramesForward;\n    var tempPlayheadPosition = startPlayheadPosition;\n\n    while(tempPlayheadPosition <= endPlayheadPosition) {\n        var frame = this.getCurrentLayer().getFrameAtPlayheadPosition(tempPlayheadPosition);\n\n        if(frame && tempPlayheadPosition !== this.playheadPosition && nearbyFrames.indexOf(frame) == -1) {\n            nearbyFrames.push(frame);\n        }\n        \n        tempPlayheadPosition ++;\n    }\n\n    // Get objects in nearby frames\n\n    var nearbyObjects = [];\n\n    nearbyFrames.forEach(function(frame) {\n        nearbyObjects = nearbyObjects.concat(frame.wickObjects);\n    });\n\n    return nearbyObjects;\n\n}\n\n//\nWickObject.prototype.getObjectsOnFirstFrame = function () {\n\n    var objectsOnFirstFrame = [];\n\n    this.layers.forEach(function (layer) {\n        layer.frames[0].wickObjects.forEach(function (wickObj) {\n            objectsOnFirstFrame.push(wickObj);\n        });\n    });\n\n    return objectsOnFirstFrame;\n\n}\n\nWickObject.prototype.getParents = function () {\n    if(!this.isSymbol) {\n        return [];\n    } else if(this.isRoot) {\n        return [this];\n    } else {\n        return this.parentObject.getParents().concat([this]);\n    }\n}\n\n/* Excludes children of children */\nWickObject.prototype.getTotalNumChildren = function () {\n    var count = 0;\n    for(var l = 0; l < this.layers.length; l++) {\n        for(var f = 0; f < this.layers[l].frames.length; f++) {\n            for(var o = 0; o < this.layers[l].frames[f].wickObjects.length; o++) {\n                count++;\n            }\n        }\n    }\n    return count;\n}\n\nWickObject.prototype.getAllFrames = function () {\n\n    if(!this.isSymbol) return [];\n\n    var allFrames = [];\n\n    this.layers.forEach(function (layer) {\n        layer.frames.forEach(function (frame) {\n            allFrames.push(frame);\n        });\n    });\n\n    return allFrames;\n}\n\nWickObject.prototype.getFrameWithChild = function (child) {\n\n    var foundFrame = null;\n\n    this.layers.forEach(function (layer) {\n        layer.frames.forEach(function (frame) {\n            frame.wickObjects.forEach(function (wickObject) {\n                if(wickObject.uuid === child.uuid) {\n                    foundFrame = frame;\n                }\n            });\n        });\n    });\n\n    return foundFrame;\n}\n\nWickObject.prototype.getLayerWithChild = function (child) {\n\n    var foundLayer = null;\n\n    this.layers.forEach(function (layer) {\n        layer.frames.forEach(function (frame) {\n            if(frame.wickObjects.indexOf(child) !== -1) {\n                foundLayer = layer;\n            }\n        });\n    });\n\n    return foundLayer;\n}\n\nWickObject.prototype.remove = function () {\n    this.parentObject.removeChild(this);\n}\n\nWickObject.prototype.removeChild = function (childToRemove) {\n\n    if(!this.isSymbol) {\n        return;\n    }\n\n    var that = this;\n    this.getAllChildObjects().forEach(function(child) {\n        if(child == childToRemove) {\n            var index = child.parentFrame.wickObjects.indexOf(child);\n            child.parentFrame.wickObjects.splice(index, 1);\n        }\n    });\n}\n\nWickObject.prototype.getZIndex = function () {\n    return this.parentFrame.wickObjects.indexOf(this);\n}\n\n/* Get the absolute position of this object (the position not relative to the parents) */\nWickObject.prototype.getAbsolutePosition = function () {\n    if(this.isRoot) {\n        return {\n            x: this.x,\n            y: this.y\n        };\n    } else if (!this.parentObject) {\n        return this.cachedAbsolutePosition;\n    } else {\n        var parent = this.parentObject;\n        var parentPosition = parent.getAbsolutePosition();\n        return {\n            x: this.x + parentPosition.x,\n            y: this.y + parentPosition.y\n        };\n    }\n}\n\n/* Get the absolute position of this object taking into account the scale of the parent */\nWickObject.prototype.getAbsolutePositionTransformed = function () {\n    if(this.isRoot) {\n        return {\n            x: this.x,\n            y: this.y\n        };\n    } else {\n        var parent = this.parentObject;\n        var parentPosition = parent.getAbsolutePositionTransformed();\n        var parentScale = parent.getAbsoluteScale()\n        var parentFlip = parent.getAbsoluteFlip();\n        var rotatedPosition = {x:this.x*parentScale.x, y:this.y*parentScale.y};\n        if(parentFlip.x) rotatedPosition.x *= -1;\n        if(parentFlip.y) rotatedPosition.y *= -1;\n        rotatedPosition = rotate_point(rotatedPosition.x, rotatedPosition.y, 0, 0, parent.getAbsoluteRotation());\n        return {\n            x: rotatedPosition.x + parentPosition.x,\n            y: rotatedPosition.y + parentPosition.y\n        };\n    }\n}\n\nWickObject.prototype.getAbsoluteScale = function () {\n    if(this.isRoot) {\n        return {\n            x: this.scaleX,\n            y: this.scaleY\n        };\n    } else {\n        var parentScale = this.parentObject.getAbsoluteScale();\n        return {\n            x: this.scaleX * parentScale.x,\n            y: this.scaleY * parentScale.y\n        };\n    }\n}\n\nWickObject.prototype.getAbsoluteRotation = function () {\n    if(this.isRoot) {\n        return this.rotation;\n    } else {\n        var parentRotation = this.parentObject.getAbsoluteRotation();\n        return this.rotation + parentRotation;\n    }\n}\n\nWickObject.prototype.getAbsoluteOpacity = function () {\n    if(this.isRoot) {\n        return this.opacity;\n    } else {\n        var parentOpacity = this.parentObject.getAbsoluteOpacity();\n        return this.opacity * parentOpacity;\n    }\n}\n\nWickObject.prototype.getAbsoluteFlip = function () {\n    if(this.isRoot) {\n        return {\n            x: this.flipX,\n            y: this.flipY\n        };\n    } else {\n        var parentFlip = this.parentObject.getAbsoluteFlip();\n        return {\n            x: this.flipX !== parentFlip.x,\n            y: this.flipY !== parentFlip.y\n        };\n    }\n}\n\nWickObject.prototype.getAbsoluteTransformations = function () {\n    return {\n        position: this.getAbsolutePositionTransformed(),\n        scale: this.getAbsoluteScale(),\n        rotation: this.getAbsoluteRotation(),\n        opacity: this.getAbsoluteOpacity(),\n        flip: this.getAbsoluteFlip(),\n    }\n}\n\nWickObject.prototype.isOnActiveLayer = function (activeLayer) {\n\n    return this.parentFrame.parentLayer === activeLayer;\n\n}\n\nWickObject.prototype.play = function () {\n\n    this._playing = true;\n}\n\nWickObject.prototype.stop = function () {\n\n    this._playing = false;\n}\n\nWickObject.prototype.getFrameById = function (identifier) {\n    var foundFrame = null;\n\n    this.getAllFrames().forEach(function (frame) {\n        if(frame.name === identifier) {\n            foundFrame = frame;\n        }\n    });\n\n    return foundFrame;\n}\n\nWickObject.prototype.gotoAndStop = function (frame) {\n    this.movePlayheadTo(frame);\n    this.stop();\n}\n\nWickObject.prototype.gotoAndPlay = function (frame) {\n    this.movePlayheadTo(frame);\n    this.play();\n}\n\nWickObject.prototype.movePlayheadTo = function (frame) {\n\n    var oldFrame = this.getCurrentLayer().getCurrentFrame();\n\n    // Frames are zero-indexed internally but start at one in the editor GUI, so you gotta subtract 1.\n    if (typeof frame === 'number') {\n        var actualFrame = frame-1;\n\n        var endOfFrames = this.getFramesEnd(); \n        // Only navigate to an integer frame if it is nonnegative and a valid frame\n        if(actualFrame < endOfFrames) {\n            this._newPlayheadPosition = actualFrame;\n        } else {\n            throw (new Error(\"Failed to navigate to frame \\'\" + actualFrame + \"\\': is not a valid frame.\"));\n        }\n\n    } else if (typeof frame === 'string') {\n\n        var foundFrame = this.getFrameById(frame)\n\n        if (foundFrame) {\n            if(this.playheadPosition < foundFrame.playheadPosition || this.playheadPosition >= foundFrame.playheadPosition+foundFrame.length-1) {\n                this._newPlayheadPosition = foundFrame.playheadPosition;\n            }\n        } else {\n            throw (new Error(\"Failed to navigate to frame. \\'\" + frame + \"\\' is not a valid frame.\"));\n        }\n\n    }\n\n}\n\nWickObject.prototype.gotoNextFrame = function () {\n\n    var nextFramePos = this.playheadPosition+1;\n    var totalLength = this.layers[this.currentLayer].getTotalLength();\n    if(nextFramePos >= totalLength) {\n        nextFramePos = 0;\n    }\n\n    this._newPlayheadPosition = nextFramePos;\n\n}\n\nWickObject.prototype.gotoPrevFrame = function () {\n\n    var nextFramePos = this.playheadPosition-1;\n    if(nextFramePos < 0) {\n        nextFramePos = this.layers[this.currentLayer].getTotalLength()-1;\n    }\n\n    this._newPlayheadPosition = nextFramePos;\n\n}\n\nWickObject.prototype.getFramesEnd = function() {\n    endFrame = 0; \n\n    this.layers.forEach(function (layer) {\n        layer.frames.forEach( function (frame) {\n            endFrame = Math.max (frame.getFrameEnd(), endFrame); \n        })\n    });\n\n    return endFrame;\n\n}\n\nWickObject.prototype.hitTest = function (otherObj) {\n    this.regenBounds();\n    otherObj.regenBounds();\n\n    return intersectRect(this.bounds, otherObj.bounds);\n}\n\nWickObject.prototype.regenBounds = function () {\n    var self = this;\n    if(this.isSymbol) {\n        this.bounds = {\n            left: Infinity,\n            right: -Infinity,\n            top: Infinity,\n            bottom: -Infinity,\n        }\n        this.getAllActiveChildObjects().forEach(function (child) {\n            child.regenBounds();\n            self.bounds.left = Math.min(child.bounds.left, self.bounds.left)\n            self.bounds.right = Math.max(child.bounds.right, self.bounds.right)\n            self.bounds.top = Math.min(child.bounds.top, self.bounds.top)\n            self.bounds.bottom = Math.max(child.bounds.bottom, self.bounds.bottom)\n        });\n    } else {\n        var absPos = this.getAbsolutePosition();\n        this.bounds = {\n            left: absPos.x - this.width/2,\n            right: absPos.x + this.width/2,\n            top: absPos.y - this.height/2,\n            bottom: absPos.y + this.height/2,\n        };\n    }\n}\n\nWickObject.prototype.isPointInside = function(point) {\n\n    var objects = this.getAllActiveChildObjectsRecursive(false);\n    if(!this.isSymbol) {\n        objects.push(this);\n    }\n\n    var hit = false;\n\n    objects.forEach(function(object) {\n        if(hit) return;\n\n        var transformedPosition = object.getAbsolutePositionTransformed();\n        var transformedPoint = {x:point.x, y:point.y};\n        var transformedScale = object.getAbsoluteScale();\n        var transformedWidth = (object.width+object.svgStrokeWidth)*transformedScale.x;\n        var transformedHeight = (object.height+object.svgStrokeWidth)*transformedScale.y;\n\n        transformedPoint = rotate_point(\n            transformedPoint.x, \n            transformedPoint.y, \n            transformedPosition.x, \n            transformedPosition.y,\n            -object.getAbsoluteRotation()\n        );\n\n        // Bounding box check\n        if ( transformedPoint.x >= transformedPosition.x - transformedWidth /2 &&\n             transformedPoint.y >= transformedPosition.y - transformedHeight/2 &&\n             transformedPoint.x <= transformedPosition.x + transformedWidth /2 &&\n             transformedPoint.y <= transformedPosition.y + transformedHeight/2 ) {\n\n            if(!object.alphaMask) {\n                hit = true;\n                return;\n            }\n\n            var relativePoint = {\n                x: transformedPoint.x - transformedPosition.x + transformedWidth /2,\n                y: transformedPoint.y - transformedPosition.y + transformedHeight/2\n            }\n\n            // Alpha mask check\n            var objectAlphaMaskIndex =\n                (Math.floor(relativePoint.x/transformedScale.x)%Math.floor(object.width+object.svgStrokeWidth)) +\n                (Math.floor(relativePoint.y/transformedScale.y)*Math.floor(object.width+object.svgStrokeWidth));\n            if(!object.alphaMask[(objectAlphaMaskIndex)] && \n               objectAlphaMaskIndex < object.alphaMask.length &&\n               objectAlphaMaskIndex >= 0) {\n                hit = true;\n                return;\n            }\n        }\n    });\n\n    return hit;\n}\n\nWickObject.prototype.clone = function (args) {\n    return wickPlayer.cloneObject(this, args);\n};\n\nWickObject.prototype.delete = function () {\n    return wickPlayer.deleteObject(this);\n};\n\nWickObject.prototype.setCursor = function (cursor) {\n    this.cursor = cursor;\n}\n\nWickObject.prototype.isHoveredOver = function () {\n    return this.hoveredOver;\n}\n\nWickObject.prototype.prepareForPlayer = function () {\n    // Set all playhead vars\n    if(this.isSymbol) {\n        // Set this object to it's first frame\n        this.playheadPosition = 0;\n\n        this.clones = [];\n\n        // Start the object playing\n        this._playing = true;\n        this._active = false;\n        this._wasActiveLastTick = false;\n\n        this.layers.forEach(function (layer) {\n            layer.hidden = false;\n        })\n\n        this.getAllFrames().forEach(function (frame) {\n            //frame.prepareForPlayer();\n        });\n        this.getAllChildObjects().forEach(function (o) {\n            o.prepareForPlayer();\n        })\n    }\n\n    // Reset the mouse hovered over state flag\n    this.hoveredOver = false;\n}\n\n/* Generate alpha mask for per-pixel hit detection */\nWickObject.prototype.generateAlphaMask = function (imageData) {\n\n    var that = this;\n\n    var alphaMaskSrc = imageData || that.asset.getData();\n    if(!alphaMaskSrc) return;\n\n    //window.open(alphaMaskSrc)\n\n    ImageToCanvas(alphaMaskSrc, function (canvas,ctx) {\n        //if(window.wickPlayer) window.open(canvas.toDataURL())\n        var w = canvas.width;\n        var h = canvas.height;\n        var rgba = ctx.getImageData(0,0,w,h).data;\n        that.alphaMask = [];\n        for (var y = 0; y < h; y ++) {\n            for (var x = 0; x < w; x ++) {\n                var alphaMaskIndex = x+y*w;\n                that.alphaMask[alphaMaskIndex] = rgba[alphaMaskIndex*4+3] <= 10;\n            }\n        }\n    }, {width:Math.floor(that.width+that.svgStrokeWidth), height:Math.floor(that.height+that.svgStrokeWidth)} );\n\n}\n\nWickObject.prototype.getCurrentFrames = function () {\n    var currentFrames = [];\n\n    this.layers.forEach(function (layer) {\n        var frame = layer.getCurrentFrame();\n        if(frame) currentFrames.push(frame)\n    });\n\n    return currentFrames;\n}\n\nWickObject.prototype.tick = function () {\n    var self = this;\n\n    if(this.isSymbol) {\n        this.layers.forEach(function (layer) {\n            layer.frames.forEach(function (frame) {\n                frame.tick();\n            });\n        });\n    }\n\n    if(this.isButton) {\n        this.stop();\n        if(this._beingClicked) {\n            if(this.getFrameById('mousePressed'))\n                this.movePlayheadTo('mousePressed');\n        } else if (this.hoveredOver) {\n            if(this.getFrameById('mouseHover'))\n                this.movePlayheadTo('mouseHover');\n        } else {\n            if(this.getFrameById('mouseReleased'))\n                this.movePlayheadTo('mouseReleased');\n        }\n    }\n\n    if(this.isSymbol) {\n        if(true) {\n            if(this._wasClicked) {\n                (wickPlayer || wickEditor).project.runScript(this, 'mousePressed');\n                this._wasClicked = false;\n            }\n\n            if(this._beingClicked) {\n                (wickPlayer || wickEditor).project.runScript(this, 'mouseDown');\n                this._wasClicked = false;\n            }\n\n            if(this._wasClickedOff) {\n                (wickPlayer || wickEditor).project.runScript(this, 'mouseReleased');\n                this._wasClickedOff = false;\n            }\n\n            if(this.isHoveredOver()) {\n                (wickPlayer || wickEditor).project.runScript(this, 'mouseHover');\n            }\n\n            if(this._wasHoveredOver) {\n                (wickPlayer || wickEditor).project.runScript(this, 'mouseEnter');\n                this._wasHoveredOver = false;\n            }\n\n            if(this._mouseJustLeft) {\n                (wickPlayer || wickEditor).project.runScript(this, 'mouseLeave');\n                this._mouseJustLeft = false;\n            }\n\n            wickPlayer.inputHandler.getAllKeysJustReleased().forEach(function (key) {\n                (wickPlayer || wickEditor).project.runScript(self, 'keyReleased', key);\n            });\n\n            wickPlayer.inputHandler.getAllKeysJustPressed().forEach(function (key) {\n                (wickPlayer || wickEditor).project.runScript(self, 'keyPressed', key);\n            });\n\n            wickPlayer.inputHandler.getAllKeysDown().forEach(function (key) {\n                (wickPlayer || wickEditor).project.runScript(self, 'keyDown', key);\n            });\n\n            // Inactive -> Inactive\n            if (!this._wasActiveLastTick && !this._active) {\n                \n            }\n            // Inactive -> Active\n            else if (!this._wasActiveLastTick && this._active) {\n                (wickPlayer || wickEditor).project.initScript(this);\n\n                (wickPlayer || wickEditor).project.runScript(this, 'load');\n                (wickPlayer || wickEditor).project.runScript(this, 'update');\n\n                if(this._newPlayheadPosition!==undefined) this.playheadPosition = this._newPlayheadPosition;\n            }\n            // Active -> Active\n            else if (this._wasActiveLastTick && this._active) {\n                (wickPlayer || wickEditor).project.runScript(this, 'update');\n            }\n            // Active -> Inactive\n            else if (this._wasActiveLastTick && !this._active) {\n                if(!this.parentFrame.alwaysSaveState) {\n                    wickPlayer.resetStateOfObject(this);\n                }\n            }\n        }\n\n        if(this.isSymbol) {\n            if(this._active) {\n                this.advanceTimeline();\n            }\n        \n            this.currentFrameNumber = this.playheadPosition+1;\n            var self = this;\n            this.layers.forEach(function (layer) {\n                var frame = layer.getCurrentFrame();\n                if(frame && frame.name) {\n                    self.currentFrameName = frame.name;\n                }\n            })\n        }\n    }\n\n}\n\nWickObject.prototype.advanceTimeline = function () {\n    if(this._playing && this.isSymbol && this._newPlayheadPosition === undefined) {\n        this._newPlayheadPosition = this.playheadPosition+1;\n        if(this._newPlayheadPosition >= this.getTotalTimelineLength()) {\n            this._newPlayheadPosition = 0;\n        }\n    }\n}\n\nWickObject.prototype.isActive = function () {\n    if(this.isRoot) return true;\n\n    return this.parentFrame._active;\n}\n\nWickObject.prototype.setText = function (text) {\n    this.textData.text = String(text); // Convert to a string, just in case.\n    this._renderDirty = true;  \n}\n\nWickObject.prototype.pointTo = function ( x2, y2 ) {\n    var dx = this.x - x2,\n        dy = this.y - y2;\n    \n    this.rotation = Math.atan2(dy,dx) * 180 / Math.PI - 90;\n};\n</script>\n<script>/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar WickAsset = function (data, type, filename, compress) {\n\n    this.data = data;\n    this.type = type;\n    this.filename = filename;\n    this.compressed = compress;\n\n    if(compress) {\n        console.log(\"big file size: \" + this.data.length);\n        this.data = LZString.compressToBase64(this.data);\n        console.log(\"compressed file size: \" + this.data.length);\n        console.log(\"Look how much space we saved wow!\");\n    }\n\n}\n\nWickAsset.prototype.getData = function () {\n    if(this.compressed) {\n        return LZString.decompressFromBase64(this.data);\n    } else {\n        return this.data;\n    }\n}\n\nWickAsset.prototype.getType = function () {\n    return this.type;\n}\n\nWickAsset.prototype.getFilename = function () {\n    return this.filename;\n}</script>\n<script>/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar WickProject = function () {\n\n    // Create the root object. The editor is always editing the root\n    // object or its sub-objects and cannot ever leave the root object.\n    this.createNewRootObject();\n\n    // Only used by the editor. Keeps track of current object editor is editing.\n    this.currentObject = this.rootObject;\n    this.rootObject.currentFrame = 0;\n\n    this.library = new AssetLibrary();\n\n    this.name = \"New Project\";\n\n    this.onionSkinning = false;\n    this.smallFramesMode = false;\n    \n    this.width = 720;\n    this.height = 480;\n\n    this.backgroundColor = \"#FFFFFF\";\n    this.transparent = false;\n\n    this.pixelPerfectRendering = false;\n\n    this.framerate = 12;\n\n    this.uuid = random.uuid4();\n\n    this._selection = [];\n\n    if(window.wickVersion) this.wickVersion = window.wickVersion;\n\n};\n\nWickProject.prototype.createNewRootObject = function () {\n    var rootObject = new WickObject();\n    rootObject.isSymbol = true;\n    rootObject.isRoot = true;\n    rootObject.playheadPosition = 0;\n    rootObject.currentLayer = 0;\n    var firstLayer = new WickLayer();\n    firstLayer.identifier = \"Layer 1\";\n    rootObject.layers = [firstLayer];\n    rootObject.x = 0;\n    rootObject.y = 0;\n    rootObject.opacity = 1.0;\n    this.rootObject = rootObject;\n    this.rootObject.generateParentObjectReferences();\n}\n\nWickProject.fromFile = function (file, callback) {\n\n    var reader = new FileReader();\n    reader.onload = function(e) {\n        if (file.type === \"text/html\") {\n            callback(WickProject.fromWebpage(e.target.result));\n        } else if (file.type === \"application/json\") {\n            callback(WickProject.fromJSON(e.target.result));\n        }\n    };\n    reader.readAsText(file);\n\n}\n\nWickProject.fromZIP = function (file, callback) {\n      JSZip.loadAsync(file).then(function (zip) {\n          return zip.file(\"index.html\").async(\"text\");\n        }).then(function (txt) {\n          callback(WickProject.fromWebpage(txt));\n        });\n}\n\nWickProject.fromWebpage = function (webpageString) {\n\n    var extractedProjectJSON;\n\n    var webpageStringLines = webpageString.split('\\n');\n    webpageStringLines.forEach(function (line) {\n        if(line.startsWith(\"<script>var wickPlayer = new WickPlayer(); wickPlayer.runProject(\")) {\n            extractedProjectJSON = line.split(\"'\")[1];\n        }\n    });\n\n    if(!extractedProjectJSON) {\n        // Oh no, something went wrong\n        console.error(\"Bundled JSON project not found in specified HTML file (webpageString). The HTML supplied might not be a Wick project, or zach might have changed the way projects are bundled. See WickProject.Exporter.js!\");\n        return null;\n    } else {\n        // Found a bundled project's JSON, let's load it!\n        return WickProject.fromJSON(extractedProjectJSON);\n    }\n}\n\nWickProject.fromJSON = function (rawJSONProject) {\n\n    var JSONString = WickProject.Compressor.decompressProject(rawJSONProject);\n\n    // Replace current project with project in JSON\n    var projectFromJSON = JSON.parse(JSONString);\n\n    // Put prototypes back on object ('class methods'), they don't get JSONified on project export.\n    projectFromJSON.__proto__ = WickProject.prototype;\n    WickObject.addPrototypes(projectFromJSON.rootObject);\n\n    WickProject.fixForBackwardsCompatibility(projectFromJSON);\n    projectFromJSON.library.__proto__ = AssetLibrary.prototype;\n    AssetLibrary.addPrototypes(projectFromJSON.library);\n\n    // Decode scripts back to human-readble and eval()-able format\n    projectFromJSON.rootObject.decodeStrings();\n\n    // Add references to wickobject's parents (optimization)\n    projectFromJSON.rootObject.generateParentObjectReferences();\n    projectFromJSON.regenAssetReferences();\n\n    // Start at the first from of the root object\n    projectFromJSON.currentObject = projectFromJSON.rootObject;\n    projectFromJSON.rootObject.playheadPosition = 0;\n    projectFromJSON.currentObject.currentLayer = 0;\n\n    projectFromJSON.currentObject = projectFromJSON.rootObject;\n\n    return projectFromJSON;\n}\n\n// Backwards compatibility for old Wick projects\nWickProject.fixForBackwardsCompatibility = function (project) {\n\n    var allObjectsInProject = project.rootObject.getAllChildObjectsRecursive();\n    allObjectsInProject.push(project.rootObject);\n    allObjectsInProject.forEach(function (wickObj) {\n        // Tweens belong to frames now\n        if(wickObj.tweens) wickObj.tweens = null;\n\n        if(!wickObj.isSymbol) return\n        wickObj.layers.forEach(function (layer) {\n            if(!layer.locked) layer.locked = false;\n            if(!layer.hidden) layer.hidden = false;\n            layer.frames.forEach(function (frame) {\n                if(!frame.tweens) frame.tweens = [];\n                // Make sure tweens have rotations now\n                frame.tweens.forEach(function (tween) {\n                    if(!tween.rotations) tween.rotations = 0;\n                });\n            });\n        });\n    });\n\n    // Selection is handled in the project now\n    if(!project._selection){\n        project._selection = [];\n    }\n\n    // Data for sounds and images is stored in the asset library now\n    if(!project.library) {\n        project.library = new AssetLibrary();\n\n        allObjectsInProject.forEach(function (wickObject) {\n            if(wickObject.imageData) {\n                var asset = new WickAsset(wickObject.imageData, 'image', 'untitled');\n                wickObject.assetUUID = project.library.addAsset(asset);\n                wickObject.isImage = true;\n                wickObject.imageData = null;\n                wickObject.name = 'untitled';\n            } else if(wickObject.audioData) {\n                var asset = new WickAsset(wickObject.imageData, 'audio', 'untitled');\n                var assetUUID = project.library.addAsset(asset);\n            }\n        })\n    }\n\n    project.library.__proto__ = AssetLibrary.prototype;\n    project.library.regenAssetUUIDs();\n\n}\n\nWickProject.prototype.getAsJSON = function (callback, format) {\n\n    var self = this;\n\n    // Encode scripts/text to avoid JSON format problems\n    self.rootObject.encodeStrings();\n\n    // Add some browser/OS/wick editor version info for debugging other ppl's projects\n    self.metaInfo = getBrowserAndOSInfo();\n    self.metaInfo.wickVersion = wickEditor.version;\n    self.metaInfo.dateSaved = new Date().toGMTString();\n\n    var JSONProject = JSON.stringify(self, WickProject.Exporter.JSONReplacer, format);\n    \n    // Decode scripts back to human-readble and eval()-able format\n    self.rootObject.decodeStrings();\n\n    callback(JSONProject);\n\n}\n\nWickProject.prototype.getCopyData = function () {\n    var objectJSONs = [];\n    var objects = this.getSelectedObjects();\n    objects.forEach(function(obj) {\n        if(obj instanceof WickObject)\n            obj._tempZIndex = wickEditor.project.getCurrentFrame().wickObjects.indexOf(obj);\n    })\n    objects.sort(function (a,b) {\n        return a._tempZIndex - b._tempZIndex;\n    });\n    for(var i = 0; i < objects.length; i++) {\n        objectJSONs.push(objects[i].getAsJSON());\n    }\n    var clipboardObject = {\n        groupPosition: {x : 0,\n                        y : 0},\n        wickObjectArray: objectJSONs\n    }\n    return JSON.stringify(clipboardObject);\n}\n\nWickProject.prototype.getCurrentObject = function () {\n    return this.currentObject;\n}\n\nWickProject.prototype.getCurrentLayer = function () {\n    return this.getCurrentObject().getCurrentLayer();\n}\n\nWickProject.prototype.getCurrentFrame = function () {\n    return this.getCurrentObject().getCurrentLayer().getCurrentFrame();\n}\n\nWickProject.prototype.getCurrentFrames = function () {\n    return this.getCurrentObject().getCurrentFrames();\n}\n\nWickProject.prototype.getAllObjects = function () {\n    var allObjectsInProject = this.rootObject.getAllChildObjectsRecursive();\n    return allObjectsInProject;\n}\n\nWickProject.prototype.getAllFrames = function () {\n    var frames = [];\n\n    var allObjectsInProject = this.getAllObjects();\n    allObjectsInProject.forEach(function (obj) {\n        frames = frames.concat(obj.getAllFrames());\n    });\n\n    return frames;\n}\n\nWickProject.prototype.getObjectByUUID = function (uuid) {\n    var allObjectsInProject = this.rootObject.getAllChildObjectsRecursive();\n    allObjectsInProject.push(this.rootObject);\n\n    var foundObj = null;\n    allObjectsInProject.forEach(function (object) {\n        if(foundObj) return;\n        if(object.uuid === uuid) {\n            foundObj = object;\n        }\n    });\n\n    return foundObj;\n}\n\nWickProject.prototype.getObject = function (name) {\n    return this.getObjectByName(name);\n}\n\nWickProject.prototype.getObjectByName = function (name) {\n    var allObjectsInProject = this.rootObject.getAllChildObjectsRecursive();\n    allObjectsInProject.push(this.rootObject);\n\n    var foundObj = null;\n    allObjectsInProject.forEach(function (object) {\n        if(foundObj) return;\n        if(object.name === name) {\n            foundObj = object;\n        }\n    });\n\n    return foundObj;\n}\n\nWickProject.prototype.getFrameByUUID = function (uuid) {\n    var allObjectsInProject = this.rootObject.getAllChildObjectsRecursive();\n    allObjectsInProject.push(this.rootObject);\n\n    var foundFrame = null;\n    allObjectsInProject.forEach(function (object) {\n        if(!object.isSymbol) return;\n        object.layers.forEach(function (layer) {\n            layer.frames.forEach(function (frame) {\n                if(frame.uuid === uuid) {\n                    foundFrame = frame;\n                }   \n            });\n        })\n    });\n\n    return foundFrame;\n}\n\nWickProject.prototype.addObject = function (wickObject, zIndex, ignoreSymbolOffset) {\n\n    var frame = this.getCurrentFrame();\n\n    if(!ignoreSymbolOffset) {\n        var insideSymbolOffset = this.currentObject.getAbsolutePosition();\n        wickObject.x -= insideSymbolOffset.x;\n        wickObject.y -= insideSymbolOffset.y;\n    }\n\n    if(!wickObject.uuid) wickObject.uuid = random.uuid4();\n    \n    if(zIndex === undefined || zIndex === null) {\n        frame.wickObjects.push(wickObject);\n    } else {\n        frame.wickObjects.splice(zIndex, 0, wickObject);\n    }\n\n    this.rootObject.generateParentObjectReferences();\n\n}\n\nWickProject.prototype.getNextAvailableName = function (baseName) {\n\n    var nextName = baseName;\n    var number = 0;\n\n    this.getAllObjects().forEach(function (object) {\n        if(!object.name) return;\n        var nameSuffix = object.name.split(baseName)[1]\n\n        if(nameSuffix === \"\") {\n            if(number === 0)\n                number = 1;\n        } else {\n            var prefixNumber = parseInt(nameSuffix);\n            if(!isNaN(prefixNumber) && prefixNumber > number) \n                number = prefixNumber;\n        }\n    });\n\n    if(number === 0) {\n        return baseName;\n    } else {\n        return baseName + \" \" + (number+1);\n    }\n\n}\n\nWickProject.prototype.jumpToObject = function (obj) {\n\n    var that = this;\n\n    this.rootObject.getAllChildObjectsRecursive().forEach(function (child) {\n        if(child.uuid === obj.uuid) {\n            that.currentObject = child.parentObject;\n        }\n    });\n\n    var currentObject = this.currentObject;\n    var frameWithChild = currentObject.getFrameWithChild(obj);\n    var playheadPositionWithChild = frameWithChild.playheadPosition\n    currentObject.playheadPosition = playheadPositionWithChild;\n\n}\n\nWickProject.prototype.jumpToFrame = function (frame) {\n\n    var that = this;\n\n    var allObjectsInProject = this.rootObject.getAllChildObjectsRecursive();\n    allObjectsInProject.push(this.rootObject);\n    allObjectsInProject.forEach(function (child) {\n        if(!child.isSymbol) return;\n        child.layers.forEach(function (layer) {\n            layer.frames.forEach(function (currframe) {\n                if(frame === currframe) {\n                    that.currentObject = child;\n                }\n            })\n        })\n    });\n\n    var currentObject = this.currentObject;\n    var frameWithChild = frame;\n    var playheadPositionWithChild = frameWithChild.playheadPosition\n    currentObject.playheadPosition = playheadPositionWithChild;\n}\n\nWickProject.prototype.hasSyntaxErrors = function () {\n\n    var projectHasSyntaxErrors = false;\n\n    this.rootObject.getAllChildObjectsRecursive().forEach(function (child) {\n        child.getAllFrames().forEach(function (frame) {\n            if(frame.scriptError && frame.scriptError.type === 'syntax') {\n                projectHasSyntaxErrors = true;\n            }\n        });\n\n        if(child.scriptError && child.scriptError.type === 'syntax') {\n            projectHasSyntaxErrors = true;\n        }\n    });\n\n    return projectHasSyntaxErrors;\n\n}\n\nWickProject.prototype.handleWickError = function (e, objectCausedError) {\n\n    objectCausedError = window.errorCausingObject\n    if(objectCausedError.objectClonedFrom) {\n        objectCausedError = objectCausedError.objectClonedFrom\n    }\n\n    if (window.wickEditor) {\n        //if(!wickEditor.builtinplayer.running) return;\n\n        console.log(\"Exception thrown while running script of WickObject: \" + this.name);\n        console.log(e);\n        var lineNumber = null;\n        if(e.stack) {\n            e.stack.split('\\n').forEach(function (line) {\n                if(lineNumber) return;\n                if(!line.includes(\"<anonymous>:\")) return;\n\n                lineNumber = parseInt(line.split(\"<anonymous>:\")[1].split(\":\")[0]);\n            });\n        }\n        if(lineNumber) lineNumber -= 12;\n\n        //console.log(e.stack.split(\"\\n\")[1].split('<anonymous>:')[1].split(\":\")[0]);\n        //console.log(e.stack.split(\"\\n\"))\n        //if(wickEditor.builtinplayer.running) wickEditor.builtinplayer.stopRunningProject()\n        \n        wickEditor.builtinplayer.stopRunningProject()\n\n        wickEditor.scriptingide.displayError(objectCausedError, {\n            message: e,\n            line: lineNumber,\n            type: 'runtime'\n        });\n\n        objectCausedError.scriptError = {\n            message: e,\n            line: lineNumber,\n            type: 'runtime'\n        }\n\n    } else {\n        alert(\"An exception was thrown while running a WickObject script. See console!\");\n        console.log(e);\n    }\n}\n\nWickProject.prototype.isObjectSelected = function (obj) {\n    var selected = false;\n\n    this._selection.forEach(function (uuid) {\n        if(obj.uuid === uuid) selected = true;\n    });\n\n    return selected;\n}\n\nWickProject.prototype.isTypeSelected = function (type) {\n    var self = this;\n    var selected = false;\n\n    this._selection.forEach(function (uuid) {\n        var obj = self.getObjectByUUID(uuid) \n               || self.getFrameByUUID(uuid);\n        if(obj instanceof type) selected = true;\n    });\n\n    return selected;\n}\n\nWickProject.prototype.getSelectedObject = function () {\n    var selectedObjects = this.getSelectedObjects();\n    if(selectedObjects.length !== 1) {\n        return null;\n    } else {\n        return selectedObjects[0];\n    }\n}\n\nWickProject.prototype.getSelectedObjectByType = function (type) {\n    var selectedObjects = this.getSelectedObjects();\n    returnObject = null;\n    \n    selectedObjects.forEach(function (obj) {\n        if(obj instanceof type) {\n            returnObject = obj;\n        }\n    })\n\n    return returnObject;\n}\n\nWickProject.prototype.getSelectedObjects = function () {\n    var self = this;\n\n    var objs = [];\n    this._selection.forEach(function (uuid) {\n        var obj = self.getObjectByUUID(uuid) \n               || self.getFrameByUUID(uuid);\n               //|| self.getTweenByUUID(uuid);\n        if(obj) objs.push(obj);\n    });\n\n    return objs;\n}\n\nWickProject.prototype.getSelectedWickObjects = function () {\n    var self = this;\n\n    var objs = [];\n    this._selection.forEach(function (uuid) {\n        var obj = self.getObjectByUUID(uuid);\n        if(obj) objs.push(obj);\n    });\n\n    return objs;\n}\n\nWickProject.prototype.getSelectedObjectsUUIDs = function () {\n    var self = this;\n\n    var objs = [];\n    this._selection.forEach(function (uuid) {\n        var obj = self.getObjectByUUID(uuid) \n               || self.getFrameByUUID(uuid);\n        if(obj) objs.push(obj.uuid);\n    });\n\n    return objs;\n}\n\nWickProject.prototype.getNumSelectedObjects = function (obj) {\n    return this.getSelectedObjects().length;\n}\n\nWickProject.prototype.selectObject = function (obj) {\n    wickEditor.inspector.clearSpecialMode();\n    if(this._selection.indexOf(obj.uuid) === -1)\n        this._selection.push(obj.uuid);\n}\n\nWickProject.prototype.selectObjectByUUID = function (uuid) {\n    wickEditor.inspector.clearSpecialMode();\n    if(this._selection.indexOf(uuid) === -1)\n        this._selection.push(uuid);\n}\n\nWickProject.prototype.clearSelection = function () {\n    var thingsWereCleared = false;\n    if(this._selection.length > 0)  thingsWereCleared = true;\n    this._selection = [];\n    return thingsWereCleared;\n}\n\nWickProject.prototype.deselectObject = function (obj) {\n    wickEditor.inspector.clearSpecialMode();\n    for ( var i = 0; i < this._selection.length; i++ ) {\n        var uuid = this._selection[i];\n        if(obj.uuid === uuid) {\n            this._selection[i] = null;\n        }\n    }\n}\n\nWickProject.prototype.deselectObjectType = function (type) {\n    var deselectionHappened = false;\n    \n    for ( var i = 0; i < this._selection.length; i++ ) {\n        var uuid = this._selection[i];\n        var obj = this.getObjectByUUID(uuid) \n               || this.getFrameByUUID(uuid);\n        if(obj instanceof type) {\n            this._selection[i] = null;\n            deselectionHappened = true;\n        }\n    }\n\n    this._selection = this._selection.filter(function (obj) {\n        return obj !== null;\n    });\n\n    return deselectionHappened;\n}\n\nWickProject.prototype.loadBuiltinFunctions = function (contextObject) {\n\n    if(contextObject.wickScript === '') return;\n\n    var objectScope = null;\n    if(contextObject instanceof WickObject) {\n        objectScope = contextObject.parentObject;\n    } else if (contextObject instanceof WickFrame) {\n        objectScope = contextObject.parentLayer.parentWickObject;\n    }\n\n    window.project = wickPlayer.project || wickEditor.project;\n    window.parentObject = contextObject.parentObject;\n    window.root = project.rootObject;\n\n    window.play           = function ()      { objectScope.play(); }\n    window.stop           = function ()      { objectScope.stop(); }\n    window.movePlayheadTo = function (frame) { objectScope.movePlayheadTo(frame); }\n    window.gotoAndStop    = function (frame) { objectScope.gotoAndStop(frame); }\n    window.gotoAndPlay    = function (frame) { objectScope.gotoAndPlay(frame); }\n    window.gotoNextFrame  = function ()      { objectScope.gotoNextFrame(); }\n    window.gotoPrevFrame  = function ()      { objectScope.gotoPrevFrame(); }\n\n    window.keyIsDown      = function (keyString) { return wickPlayer.inputHandler.keyIsDown(keyString); };\n    window.keyJustPressed = function (keyString) { return wickPlayer.inputHandler.keyJustPressed(keyString); }\n    window.mouseX = wickPlayer.inputHandler.getMouse().x;\n    window.mouseY = wickPlayer.inputHandler.getMouse().y;\n    window.mouseMoveX = wickPlayer.inputHandler.getMouseDiff().x;\n    window.mouseMoveY = wickPlayer.inputHandler.getMouseDiff().y;\n    window.hideCursor = function () { wickPlayer.inputHandler.hideCursor(); };\n    window.showCursor = function () { wickPlayer.inputHandler.showCursor(); };\n\n    // WickObjects in same frame (scope) are accessable without using root./parent.\n    if(objectScope) {\n        objectScope.getAllChildObjects().forEach(function(child) {\n            if(child.name) window[child.name] = child;\n        });\n    }\n    if(objectScope) {\n        objectScope.getAllActiveChildObjects().forEach(function(child) {\n            if(child.name) window[child.name] = child;\n        });\n    }\n\n}\n\nvar WickObjectBuiltins = [\n    'load',\n    'update',\n    'mousePressed',\n    'mouseDown',\n    'mouseReleased',\n    'mouseHover',\n    'mouseEnter',\n    \"mouseLeave\",\n    \"keyPressed\",\n    \"keyDown\",\n    \"keyReleased\",\n];\n\nWickProject.prototype.loadScriptOfObject = function (obj) {\n\n    if(obj.wickScript === '') return;\n\n    if(!window.cachedWickScripts) window.cachedWickScripts = {};\n\n    var dummyInitScript = \"\";\n    var dummyLoaderScript = \"\";\n    WickObjectBuiltins.forEach(function (builtinName) {\n        dummyInitScript += 'function ' + builtinName + ' (){return;};\\n';\n        dummyLoaderScript += '\\nthis.'+builtinName+\"=\"+builtinName+\";\";\n    });\n\n    var evalScriptTag = '<script>\\nwindow.cachedWickScripts[\"'+obj.uuid+'\"] = function () {\\n' + dummyInitScript + obj.wickScript + dummyLoaderScript + '\\n}\\n<'+'/'+'script>';\n    $('head').append(evalScriptTag);\n}\n\nWickProject.prototype.initScript = function (obj) {\n    window.errorCausingObject = obj;\n\n    if(!window.cachedWickScripts) window.cachedWickScripts = {};\n    \n    if(!obj.cachedWickScript) {\n        if(obj.sourceUUID) {\n            obj.cachedWickScript = window.cachedWickScripts[obj.sourceUUID];\n        } else {\n            obj.cachedWickScript = window.cachedWickScripts[obj.uuid];\n        }\n    }\n\n    if(obj.cachedWickScript) {\n        this.loadBuiltinFunctions(obj);\n        try {\n            obj.cachedWickScript();\n        } catch (e) {\n            this.handleWickError(e,obj);\n        }\n    }\n}\n\nWickProject.prototype.runScript = function (obj, fnName, arg1, arg2, arg3) {\n\n    window.errorCausingObject = obj;\n\n    try {\n        if(obj[fnName]) {\n            this.loadBuiltinFunctions(obj);\n            obj[fnName](arg1, arg2, arg3);\n        }\n    } catch (e) {\n        this.handleWickError(e,obj);\n    }\n\n}\n\nWickProject.prototype.regenAssetReferences = function () {\n\n    var self = this;\n\n    self.getAllObjects().forEach(function (obj) {\n        obj.asset = self.library.getAsset(obj.assetUUID);\n    });\n\n}\n\nWickProject.prototype.loadFonts = function () {\n    var self = this;\n    var fontsInProject = [];\n    self.getAllObjects().forEach(function (o) {\n        if(o.isText)\n            fontsInProject.push(o.textData.fontFamily);\n    });\n    loadGoogleFonts(fontsInProject, function () {\n        wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n        wickEditor.syncInterfaces();\n    });\n}\n\nWickProject.prototype.prepareForPlayer = function () {\n    var self = this;\n\n    self.regenAssetReferences();\n\n    self.rootObject.prepareForPlayer();\n    self.loadFonts();\n\n    self.getAllObjects().forEach(function (obj) {\n        self.loadScriptOfObject(obj);\n    });\n    self.getAllFrames().forEach(function (obj) {\n        self.loadScriptOfObject(obj);\n    });\n}\n\nWickProject.prototype.tick = function () {\n    this.applyTweens();\n\n    var allObjectsInProject = this.rootObject.getAllChildObjectsRecursive();\n\n    // Make sure all playhead positions are up to date \n    // (this is deferred to outside the main tick code so things don't get confusing)\n    allObjectsInProject.forEach(function (obj) {\n        if(obj._newPlayheadPosition !== undefined)\n            obj.playheadPosition = obj._newPlayheadPosition;\n    });\n\n    allObjectsInProject.forEach(function (obj) {\n        obj._newPlayheadPosition = undefined;\n    });\n    allObjectsInProject.forEach(function (obj) {\n        obj.getAllFrames().forEach(function (frame) {\n            frame._wasActiveLastTick = frame._active;\n            frame._active = frame.isActive();\n        });\n    });\n    allObjectsInProject.forEach(function (obj) {\n        obj._wasActiveLastTick = obj._active;\n        obj._active = obj.isActive();\n    });\n    \n    this.rootObject.tick();\n    this.updateCamera();\n}\n\nWickProject.prototype.applyTweens = function () {\n    this.getAllFrames().forEach(function (frame) {\n        frame.applyTween();\n    });\n}\n\nWickProject.prototype.updateCamera = function () {\n    var camera = window.camera;\n    if(!camera) return;\n\n    camera.update();\n\n    var camPos = camera.getPosition();\n    this.rootObject.x = -camPos.x+this.width/2;\n    this.rootObject.y = -camPos.y+this.height/2;\n}\n</script>\n<script>/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar WickCamera = function (project) {\n\n    var self = this;\n\n    var x = project.width/2;\n    var y = project.height/2;\n\n    var followingObject = null;\n    var followingSmoothness = 1;\n\n    this.followObject = function (object, smoothness) {\n    \tfollowingObject = object;\n    \tfollowingSmoothness = smoothness || 1;\n    }\n\n    this.getPosition = function () {\n    \treturn {\n    \t\tx: x, \n    \t\ty: y\n    \t};\n    }\n\n    this.setPosition = function (_x,_y) {\n    \tx = _x;\n    \ty = _y;\n    }\n\n    this.update = function () {\n    \tif(followingObject) {\n    \t\tvar dx = followingObject.x - x;\n    \t\tvar dy = followingObject.y - y;\n    \t\tself.setPosition(\n    \t\t\tx + dx*followingSmoothness, \n    \t\t\ty + dy*followingSmoothness\n    \t\t);\n    \t}\n    }\n\n};\n\n</script>\n<script>/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n    \nvar AssetLibrary = function () {\n\n    this.assets = {};\n\n};\n\nAssetLibrary.prototype.addAsset = function (asset) {\n\n    if(asset.uuid) {\n        this.assets[asset.uuid] = asset;\n    } else {\n        var uuid = random.uuid4();\n        this.assets[uuid] = asset;\n        asset.uuid = uuid;\n\n        return uuid;\n    }\n\n}\n\nAssetLibrary.prototype.deleteAsset = function (uuid) {\n\n    this.assets[uuid] = null;\n    delete this.assets[uuid];\n\n}\n\nAssetLibrary.prototype.getAsset = function (uuid) {\n\n    return this.assets[uuid];\n\n}\n\nAssetLibrary.prototype.getAllAssets = function (type) {\n\n    var allAssets = [];\n\n    for (assetUUID in this.assets) {\n        var asset = this.assets[assetUUID];\n        if(!type || asset.type === type) {\n            allAssets.push(asset);\n        }\n    }\n\n    return allAssets;\n\n}\n\nAssetLibrary.prototype.getAssetByName = function (filename) {\n\n    var foundAsset = null;\n    this.getAllAssets().forEach(function (asset) {\n        if (asset.filename === filename)\n            foundAsset = asset;\n    });\n    return foundAsset\n\n}\n\n/* For backwards compatibility... */\nAssetLibrary.prototype.regenAssetUUIDs = function () {\n\n    for (assetUUID in this.assets) {\n        var asset = this.assets[assetUUID];\n        asset.uuid = assetUUID;\n    }\n\n}\n\nAssetLibrary.prototype.printInfo = function () {\n\n    var totalSize = 0;\n    for (assetUUID in this.assets) {\n        var asset = this.assets[assetUUID];\n        totalSize += asset.data.length;\n\n        console.log(\"Filename: \"+asset.filename);\n        console.log(\"Type: \"+asset.type);\n        console.log(\"Size: \"+asset.data.length);\n        console.log(\"---\")\n    }\n    console.log(\"Total library size: \" + totalSize)\n\n}\n\nAssetLibrary.addPrototypes = function (library) {\n\n    for (assetUUID in library.assets) {\n        library.assets[assetUUID].__proto__ = WickAsset.prototype;\n    }\n\n}\n</script>\n<script>/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nWickProject.Compressor = (function () {\n\n    var projectCompressor = { };\n\n    var printFilesize = false;\n\n    var compressionRoutines = {\n        'LZSTRING-BASE64': {\n            compress:LZString.compressToBase64, \n            decompress:LZString.decompressFromBase64\n        },\n        'LZSTRING-UTF16': {\n            compress:LZString.compressToUTF16, \n            decompress:LZString.decompressFromUTF16\n        }\n    }\n\n    projectCompressor.compressProject = function (projectJSON, compressionRoutineName) {\n        if(printFilesize) console.log(\"Compressing project of size \" + projectJSON.length);\n\n        var compressionRoutine = compressionRoutines[compressionRoutineName];\n        var compressedProjectJSON = compressionRoutineName+compressionRoutine.compress(projectJSON)\n\n        if(printFilesize) console.log(\"Done! Result size \" + compressedProjectJSON.length);\n        return compressedProjectJSON;\n    }\n\n    projectCompressor.decompressProject = function (compressedProjectJSON) {\n        if(printFilesize) console.log(\"Decompressing project...\")\n\n        var projectJSON = compressedProjectJSON;\n\n        for (var compressionRoutineName in compressionRoutines) {\n            if(compressedProjectJSON.startsWith(compressionRoutineName)) {\n                console.log(\"Project compressed with \" + compressionRoutineName)\n                var compressionRoutine = compressionRoutines[compressionRoutineName];\n                var rawCompressedProjectJSON = compressedProjectJSON.substring(compressionRoutineName.length, compressedProjectJSON.length);\n                projectJSON = compressionRoutine.decompress(rawCompressedProjectJSON);\n            }\n        }\n\n        if(printFilesize) console.log(\"Done!\");\n        return projectJSON;\n    }\n    \n    projectCompressor.encodeString = function (str) {\n        var newStr = str;\n        newStr = encodeURI(str);\n        newStr = newStr.replace(/'/g, \"%27\");\n        return newStr;\n    }\n\n    projectCompressor.decodeString = function (str) {\n        var newStr = str;\n        newStr = newStr.replace(/%27/g, \"'\");\n        newStr = decodeURI(str);\n        return newStr;\n    }\n\n    return projectCompressor;\n\n})();</script>\n<script>/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar WickPixiRenderer = function (canvasContainer) {\n\n    var self = this;\n\n    var SVG_SCALE = 1.4;\n\n    var renderer = PIXI.autoDetectRenderer(100, 100, {\n        backgroundColor : \"#FFFFFF\", \n        resolution: window.devicePixelRatio,\n        preserveDrawingBuffer: true,\n        antialias: true,\n        transparent: true,\n    });\n    renderer.clearBeforeRender = true;\n    renderer.roundPixels = false;\n    renderer.view.setAttribute('tabindex', 0);\n\n    canvasContainer.appendChild(renderer.view);\n    renderer.view.focus();\n\n    var currentProjectUUID = null;\n    var container = new PIXI.Container();\n    var pixiSprites = {};\n    var pixiTextures = {};\n\n    var wickProject;\n\n    var graphics = new PIXI.Graphics();\n    \n    container.addChild(graphics);\n\n    _cached_w = 0;\n    _cached_h = 0;\n\n    self.preloadAllAssets = function (project, callback) {\n        currentProjectUUID = project.uuid;\n\n        var assetsToLoad = [];\n        project.getAllObjects().forEach(function (o) {\n            if((o.isPath && o.pathData) || o.isImage || o.isText) {\n                assetsToLoad.push(o);\n            }\n        });\n\n        var loadedAssetCount = 0;\n        assetsToLoad.forEach(function (o) {\n            function checkIfDone () {\n                if(loadedAssetCount === assetsToLoad.length) {\n                    callback();\n                }\n            }\n\n            if (!pixiSprites[o.uuid]) {\n                createPixiSprite(o, function () {\n                    loadedAssetCount++;\n                    checkIfDone()\n                });\n            } else if(o._renderDirty) {\n                regenPixiPath(o, pixiSprites[o.uuid], function () {\n                    loadedAssetCount++;\n                    checkIfDone()\n                });\n                o._renderDirty = false;\n            } else if(pixiTextures[o.uuid]) {\n                loadedAssetCount++;\n                checkIfDone()\n            } else {\n                loadedAssetCount++;\n                checkIfDone();\n            }\n        });\n    }\n\n    self.renderWickObjects = function (project, wickObjects, renderExtraSpace, fitToScreen) {\n        window._lastRender = {\n            project: project,\n            wickObjects: wickObjects, \n            renderExtraSpace: renderExtraSpace\n        }\n        if(!renderExtraSpace) renderExtraSpace = 1;\n\n        if(renderExtraSpace === 1) {\n            graphics.clear();\n            graphics.beginFill(parseInt(project.backgroundColor.replace(\"#\",\"0x\")));\n            graphics.moveTo(0, 0);\n            graphics.lineTo(project.width, 0);\n            graphics.lineTo(project.width, project.height);\n            graphics.lineTo(0, project.height);\n            graphics.endFill();\n        }\n\n        wickProject = project;\n\n        if(currentProjectUUID !== project.uuid) {\n            currentProjectUUID = project.uuid;\n            loadAllAssets(project);\n        }\n\n        if(fitToScreen) {\n            var w = window.innerWidth;\n            var h = window.innerHeight;\n            canvasContainer.style.width  = w + 'px';\n            canvasContainer.style.height = h + 'px';\n            if(_cached_w !== w || _cached_h !== h) {\n                renderer.resize(w, h);\n                _cached_w = w;\n                _cached_h = h;\n                renderer.view.style.width  = w + \"px\";\n                renderer.view.style.height = h + \"px\";\n                container.scale.x = 1//w / project.width;\n                container.scale.y = 1//h / project.height;\n            }\n        } else {\n            container.position.x = 0;\n            container.position.y = 0;\n            renderer.resize(project.width*renderExtraSpace, project.height*renderExtraSpace);\n            renderer.view.style.width  = project.width*renderExtraSpace  + \"px\";\n            renderer.view.style.height = project.height*renderExtraSpace + \"px\";\n            if(renderer.width !== project.width || renderer.height !== project.height) {\n                renderer.resize(project.width*renderExtraSpace, project.height*renderExtraSpace);\n                renderer.view.style.width  = project.width*renderExtraSpace  + \"px\";\n                renderer.view.style.height = project.height*renderExtraSpace + \"px\";\n\n                if(renderExtraSpace !== 1) {\n                    container.position.x = project.width/renderExtraSpace;\n                    container.position.y = project.height/renderExtraSpace;\n                }\n            }\n        }\n\n        for (uuid in pixiSprites) {\n            pixiSprites[uuid].visible = false;\n        }\n\n        wickObjects.forEach(function (wickObject) {\n            renderWickObject(wickObject);\n        });\n        renderer.render(container);\n    }\n\n    self.reorderAllObjects = function (project) {\n        var objectsToReorder = container.removeChildren(0, container.children.length);\n        var allWickObjects = project.getAllObjects();\n\n        container.addChild(graphics);\n        allWickObjects.forEach(function (wickObject) {\n            objectsToReorder.forEach(function (pixiObject) {\n                if(pixiSprites[wickObject.uuid] === pixiObject) {\n                    container.addChild(pixiObject);\n                }\n            });\n        });\n    }\n\n    self.cleanupObjectTextures = function (wickObj) {\n        var sprite = pixiSprites[wickObj.uuid];\n        if(sprite)\n            sprite.parent.removeChild(sprite);\n    }\n\n    function renderWickObject (wickObject) {\n        var sprite = pixiSprites[wickObject.uuid];\n        if(!sprite && !wickObject.isSymbol) {\n            createPixiSprite(wickObject);\n        }\n        if(sprite && wickObject._renderDirty && wickObject.isPath) {\n            regenPixiPath(wickObject, sprite);\n            wickObject._renderDirty = false;\n        }\n        if(sprite && wickObject._renderDirty && wickObject.isText) {\n            sprite = regenPixiText(wickObject, sprite);\n            wickObject._renderDirty = false;\n        }\n        if(sprite) {\n            sprite.visible = !wickObject.parentFrame.parentLayer.hidden;\n            sprite.anchor = new PIXI.Point(0.5, 0.5);\n            var textureScale = (wickObject.pathData || wickObject.isText ? SVG_SCALE : 1);\n\n            var absTransforms = wickObject.getAbsoluteTransformations();\n            var textOffset = wickObject.isText ? \n                rotate_point(sprite.textboxOffset, 0, 0, 0, absTransforms.rotation) :\n                {x:0,y:0};\n            sprite.position.x = absTransforms.position.x - textOffset.x;\n            sprite.position.y = absTransforms.position.y - textOffset.y;\n            sprite.rotation = absTransforms.rotation/360*2*3.14159;\n            sprite.scale.x = absTransforms.scale.x/textureScale;\n            sprite.scale.y = absTransforms.scale.y/textureScale;\n            sprite.alpha = absTransforms.opacity;\n            sprite.scale.x *= (absTransforms.flip.x ? -1 : 1);\n            sprite.scale.y *= (absTransforms.flip.y ? -1 : 1);\n        }\n\n        wickObject.getAllActiveChildObjects().forEach(function (child) {\n            renderWickObject(child);\n        });\n    }\n\n    function loadAllAssets (project) {\n        project.getAllObjects().forEach(function (wickObject) {\n            createPixiSprite(wickObject);\n        });\n    }\n\n    function createPixiSprite (wickObject, callback) {\n        if(wickObject.sourceUUID) {\n            var pixiTexture = pixiTextures[wickObject.sourceUUID];\n            if(pixiTexture) {\n                var pixiSprite = new PIXI.Sprite(pixiTexture);\n                wickObject.alphaMask = wickProject.getObjectByUUID(wickObject.sourceUUID).alphaMask\n                var sourceIndex = container.children.indexOf(pixiSprites[wickObject.sourceUUID])\n                container.addChildAt(pixiSprite, sourceIndex);\n                pixiSprites[wickObject.uuid] = pixiSprite;\n                pixiSprite.visible = false;\n                return;\n            }\n        }\n\n        var type;\n\n        if (wickObject.asset && wickObject.asset.type === 'image') {\n            type = 'image';\n        } else if (wickObject.isPath && wickObject.pathData) {\n            type = 'svg';\n        } else if (wickObject.isText) {\n            type = 'text';\n        }\n\n        if(type) {\n            var newPixiSprite = WickToPixiSprite[type](wickObject, callback);\n            container.addChild(newPixiSprite);\n            pixiSprites[wickObject.uuid] = newPixiSprite;\n\n            var textureSrc = newPixiSprite.texture.baseTexture.imageUrl;\n            if(textureSrc)\n                wickObject.generateAlphaMask(textureSrc);\n        }\n    }\n\n    function regenPixiPath (wickObject, pixiSprite, callback) {\n        var base64svg = getBase64SVG(wickObject);\n        var texture = PIXI.Texture.fromImage(base64svg, undefined, undefined, SVG_SCALE);\n        pixiSprite.setTexture(texture);\n        texture.baseTexture.on('loaded', function(){\n            if(callback) callback();\n        });\n    }\n\n    function regenPixiText (wickObject, pixiSprite) {\n        container.removeChild(pixiSprite);\n        var newPixiText = WickToPixiSprite['text'](wickObject);\n        container.addChild(newPixiText);\n        pixiSprites[wickObject.uuid] = newPixiText;\n        return newPixiText;\n    }\n\n    var WickToPixiSprite = {\n        'image': function (wickObject, callback) {\n            var pixiTexture = PIXI.Texture.fromImage(wickObject.asset.getData());\n            var pixiSprite = new PIXI.Sprite(pixiTexture);\n            pixiSprite.texture.baseTexture.on('loaded', function(){\n                if(window._lastRender) {\n                    self.renderWickObjects(\n                        window._lastRender.project, \n                        window._lastRender.wickObjects, \n                        window._lastRender.renderExtraSpace);\n                }\n                if(callback) callback();\n            });\n            pixiTextures[wickObject.uuid] = pixiTexture;\n            return pixiSprite;\n        },\n        'svg': function (wickObject, callback) {\n            var base64svg = getBase64SVG(wickObject);\n            var pixiTexture = PIXI.Texture.fromImage(base64svg, undefined, undefined, SVG_SCALE);\n            var newSprite = new PIXI.Sprite(pixiTexture);\n            newSprite.texture.baseTexture.on('loaded', function(){\n                if(window._lastRender) {\n                    self.renderWickObjects(\n                        window._lastRender.project, \n                        window._lastRender.wickObjects, \n                        window._lastRender.renderExtraSpace);\n                }\n                if(callback) callback();\n            });\n            pixiTextures[wickObject.uuid] = pixiTexture;\n            return newSprite;\n        },\n        'text': function (wickObject, callback) {\n            var textData = wickObject.textData;\n            var style = {\n                font : textData.fontWeight + \" \" + textData.fontStyle + \" \" + (textData.fontSize*SVG_SCALE) + \"px \" + textData.fontFamily,\n                fill : textData.fill,\n                wordWrap : false,\n                wordWrapWidth : wickObject.width*SVG_SCALE,\n                align: textData.textAlign,\n            };\n            var pixiText = new PIXI.Text(textData.text, style);\n            var textWidth = pixiText.width/SVG_SCALE;\n            var textboxWidth = wickObject.width;\n            if(textData.textAlign === 'left') {\n                pixiText.textboxOffset = (textboxWidth-textWidth)/2;\n            } else if (textData.textAlign === 'center') {\n                pixiText.textboxOffset = 0;\n            } else if (textData.textAlign === 'right') {\n                pixiText.textboxOffset = -(textboxWidth-textWidth)/2;\n            }\n            if(callback) callback();\n            return pixiText;\n        }\n    }\n\n    function getBase64SVG (wickObject) {\n        var parser = new DOMParser();\n        var x = (wickObject.svgX || 0);\n        var y = (wickObject.svgY || 0);\n        if(!wickObject.svgStrokeWidth) wickObject.svgStrokeWidth = 0;\n        x -= wickObject.svgStrokeWidth/2;\n        y -= wickObject.svgStrokeWidth/2;\n        var w = (wickObject.width  + wickObject.svgStrokeWidth*1);\n        var h = (wickObject.height + wickObject.svgStrokeWidth*1);\n        var svgDoc = parser.parseFromString('<svg id=\"svg\" viewBox=\"'+x+' '+y+' '+w+' '+h+'\" version=\"1.1\" width=\"'+w+'\" height=\"'+h+'\" xmlns=\"http://www.w3.org/2000/svg\">'+wickObject.pathData+'</svg>', \"image/svg+xml\");\n        var s = new XMLSerializer().serializeToString(svgDoc);\n        var base64svg = 'data:image/svg+xml;base64,' + window.btoa(s);\n        return base64svg;\n    }\n\n};\n\n</script>\n<script>/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar WickHowlerAudioPlayer = function (project) {\n\n    var self = this;\n\n    var sounds = {};\n\n    var muted;\n\n    self.setup = function () {\n\n        muted = false;\n\n        project.library.getAllAssets('audio').forEach(function (asset) {\n            var audioData = asset.getData();\n\n            sounds[asset.uuid] = new Howl({\n                src: [audioData],\n                loop: false,\n                volume: 1.0,\n                onend: function(id) { self.onSoundEnd(id); },\n                onStop: function(id) { self.onSoundStop(id); },\n                onPlay: function(id) { self.onSoundPlay(id); }\n            });\n        });\n\n    }\n\n    self.makeSound = function (assetUUID, objLoop, objVolume) {\n        var asset = project.library.getAsset(assetUUID);\n        if (!asset) return; \n        var audioData = asset.getData();\n\n        howl = new Howl({\n            src: [audioData],\n            loop: objLoop,\n            volume: objVolume,\n            onend: function(id) { self.onSoundEnd(id); },\n            onStop: function(id) { self.onSoundStop(id); },\n            onPlay: function(id) { self.onSoundPlay(id); }\n        });\n\n        return howl;\n    }\n\n    self.playSound = function (assetUUID) {\n        if(muted) return;\n        if(!sounds[assetUUID]) return;\n        var howlerID = sounds[assetUUID].play();\n    }\n\n    // TODO : Do this only for playing sounds\n    this.stopAllSounds = function () {\n        for (var sound in sounds) {\n            sounds[sound].stop();\n        }\n    }\n\n    self.cleanup = function () {\n\n    }\n\n    self.onSoundEnd = function (howlid) {\n\n    }\n\n    self.onSoundStop = function (howlid) {\n\n    }\n\n    self.onSoundPlay = function (howlid) {\n\n    }\n\n    window.playSound = function (assetFilename) {\n        var asset = project.library.getAssetByName(assetFilename);\n        if(asset) {\n            self.playSound(asset.uuid);\n        }\n    }\n\n    window.stopAllSounds = function () {\n        self.stopAllSounds();\n    }\n\n    window.mute = function () {\n        self.stopAllSounds();\n        muted = true;\n    }\n\n    window.unmute = function () {\n        muted = false;\n    }\n\n}</script>\n<script>/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n    \nWickPlayerInputHandler = function (canvasContainer, wickProject) {\n\n    var self = this;\n\n    var mouse;\n    var mouseDiff;\n    var lastMouse;\n    var newMouse;\n    var keys;\n    var keysJustPressed; \n    var keysJustReleased;\n\n    var _cachedKeysDown;\n    var _cachedKeysJustPressed;\n    var _cachedKeysJustReleased;\n\n    var project;\n\n    var canvas = canvasContainer.children[0];\n\n    self.setup = function () {\n        mouse = null;\n        keys = [];\n        keysJustPressed = [];\n        keysJustReleased = [];\n\n        if(bowser.mobile || bowser.tablet) {\n            // Touch event (one touch = like a mouse click)\n            document.body.addEventListener(\"touchstart\", onTouchStart, false);\n            document.body.addEventListener(\"touchmove\", onTouchMove, false);\n\n            // Squash gesture events\n            document.body.addEventListener('gesturestart',  function(e) { e.preventDefault(); });\n            document.body.addEventListener('gesturechange', function(e) { e.preventDefault(); });\n            document.body.addEventListener('gestureend',    function(e) { e.preventDefault(); });\n        } else {\n            document.body.addEventListener('mousemove', onMouseMove, false);\n            document.body.addEventListener(\"mousedown\", onMouseDown, false);\n            document.body.addEventListener(\"mouseup\",   onMouseUp,   false);\n\n            document.body.addEventListener(\"keydown\", onKeyDown);\n            document.body.addEventListener(\"keyup\", onKeyUp);\n        }\n    }\n\n    self.update = function () {\n        keysJustPressed = [];\n        keysJustReleased = [];\n\n        _cachedKeysDown = null;\n        _cachedKeysJustPressed = null;\n        _cachedKeysJustReleased = null;\n\n        lastMouse = mouse;\n        if(newMouse) mouse = newMouse;\n\n        if(mouse && lastMouse) {\n            mouseDiff = {\n                x: mouse.x - lastMouse.x,\n                y: mouse.y - lastMouse.y\n            }\n        }\n        if(mouse && lastMouse) {\n            lastMouse.x = mouse.x;\n            lastMouse.y = mouse.y;\n        }\n    }\n\n    self.cleanup = function () {\n        document.body.removeEventListener(\"mousedown\", onMouseDown);\n        document.body.removeEventListener(\"mousemove\", onMouseMove);\n        document.body.removeEventListener(\"mouseup\", onMouseUp);\n\n        document.body.removeEventListener(\"touchstart\", onTouchStart);\n        document.body.removeEventListener(\"touchmove\", onTouchMove);\n\n        document.body.removeEventListener(\"keydown\", onKeyDown);\n        document.body.removeEventListener(\"keyup\", onKeyUp);\n    }\n    \n    self.getMouse = function () {\n        return mouse || {x:0,y:0};\n    }\n\n    self.getMouseDiff = function () {\n        return mouseDiff || {x:0,y:0};\n    }\n\n    self.getKeys = function () {\n        return keys || [];\n    }\n\n    self.getKeysJustPressed = function () {\n        return keysJustPressed || [];\n    }\n\n    self.getKeysJustReleased = function () {\n        return keysJustReleased || [];\n    }\n\n    self.keyIsDown = function (keyString) {\n        return self.getKeys()[keyCharToCode[keyString.toUpperCase()]];\n    }\n\n    self.keyJustPressed = function (keyString) {\n        return self.getKeysJustPressed()[keyCharToCode[keyString.toUpperCase()]];\n    }\n\n    self.getAllKeysDown = function () {\n        if(_cachedKeysDown) return _cachedKeysDown;\n\n        _cachedKeysDown = [];\n\n        var _keys = self.getKeys();\n        for(var i = 0; i < _keys.length; i++) {\n            if(_keys[i]) {\n                var c = codeToKeyChar[i];\n                _cachedKeysDown.push(c);\n            }\n        }\n\n        return _cachedKeysDown;\n    }\n\n    self.getAllKeysJustPressed = function () {\n        if(_cachedKeysJustPressed) return _cachedKeysJustPressed;\n\n        _cachedKeysJustPressed = [];\n\n        var _keys = self.getKeysJustPressed();\n        for(var i = 0; i < _keys.length; i++) {\n            if(_keys[i]) {\n                var c = codeToKeyChar[i];\n                _cachedKeysJustPressed.push(c);\n            }\n        }\n\n        return _cachedKeysJustPressed;\n    }\n\n    self.getAllKeysJustReleased = function () {\n        if(_cachedKeysJustReleased) return _cachedKeysJustReleased;\n\n        _cachedKeysJustReleased = [];\n\n        var _keys = self.getKeysJustReleased();\n        for(var i = 0; i < _keys.length; i++) {\n            if(_keys[i]) {\n                var c = codeToKeyChar[i];\n                _cachedKeysJustReleased.push(c);\n            }\n        }\n\n        return _cachedKeysJustReleased;\n    }\n\n    self.hideCursor = function () {\n        canvasContainer.className = 'hideCursor'\n    }\n\n    self.showCursor = function () {\n        canvasContainer.className = ''\n    }\n\n\n    var onMouseMove = function (evt) {\n\n        setMousePos(calcMousePos(canvasContainer, evt));\n\n        canvasContainer.style.cursor = \"default\";\n\n        // Check if we're hovered over a clickable object...\n        var hoveredOverObj = null;\n        wickProject.rootObject.getAllActiveChildObjectsRecursive(true).forEachBackwards(function(child) {\n            if(!child.isSymbol) return;\n\n            if(!(hoveredOverObj && hoveredOverObj.isButton) && child.isPointInside(self.getMouse())) {\n                if(!child.hoveredOver) {\n                    child._wasHoveredOver = true;\n                }\n                if(child.isButton) canvasContainer.style.cursor = child.cursor || \"pointer\";\n                child.hoveredOver = true;\n                hoveredOverObj = child;\n            } else {\n                if(child.hoveredOver) {\n                    child._mouseJustLeft = true;\n                }\n                child.hoveredOver = false;\n            }\n        });\n\n    }\n\n    var onMouseDown = function (evt) {\n\n        canvasContainer.focus();\n\n        // Hack to avoid \"'requestFullscreen' can only be initiated by a user gesture.\" error\n        if(wickPlayer.fullscreenRequested) {\n            wickPlayer.enterFullscreen();\n            wickPlayer.fullscreenRequested = false;\n        }\n\n        var currFrame = wickProject.getCurrentFrame();\n        if(currFrame) {\n            currFrame._wasClicked = true;\n            currFrame._beingClicked = true;\n        }\n        \n        var clickedObj;\n        wickProject.rootObject.getAllActiveChildObjectsRecursive(true).forEachBackwards(function(child) {\n            if(!(clickedObj && clickedObj.isButton) && child.isPointInside(self.getMouse())) {\n                child._wasClicked = true;\n                child._beingClicked = true;\n                clickedObj = child;\n            }\n        });\n\n    }\n\n    var onMouseUp = function (evt) {\n        var currFrame = wickProject.getCurrentFrame();\n        if(currFrame) {\n            currFrame._beingClicked = false;\n            currFrame._wasClickedOff = true;\n        }\n\n        wickProject.rootObject.getAllActiveChildObjectsRecursive(true).forEachBackwards(function(child) {\n            child._beingClicked = false;\n\n            if(child.isPointInside(self.getMouse())) {\n                child._wasClickedOff = true;\n            }\n        });\n    }\n\n    var onKeyDown = function (event) {\n        event.preventDefault();\n\n        // Quit builtin editor\n        if(window.wickEditor && event.keyCode === 27) {\n            window.wickEditor.guiActionHandler.doAction('stopRunningProject')\n        }\n\n        // Check for new keyDown...\n        if (!keys[event.keyCode]) {\n            keysJustPressed[event.keyCode] = true; \n        }\n\n        keys[event.keyCode] = true;\n    }\n\n    var onKeyUp = function (event) {\n        event.preventDefault();\n\n        keysJustReleased[event.keyCode] = true;\n        \n        keys[event.keyCode] = false;\n    }\n\n    var onTouchStart = function (evt) {\n\n        document.getElementById('rendererCanvas').focus();\n\n        evt.preventDefault();\n\n        // on iOS, WebAudio context only gets 'unmuted' after first user interaction\n        if(!audioContext) {\n            wickPlayer.audioPlayer.setup(wickProject);\n        }\n\n        var touchPos = getTouchPos(canvasContainer, evt);\n        setMousePos(touchPos);\n\n        wickProject.rootObject.getAllActiveChildObjects().forEach(function(child) {\n            if(child.isPointInside(touchPos)) {\n                child._wasClicked = true;\n            }\n        });\n        \n\n    }\n\n    var onTouchMove = function (evt) {\n\n        evt.preventDefault();\n        \n        var touchPos = getTouchPos(canvasContainer, evt);\n        setMousePos(touchPos);\n\n    }\n\n    var calcMousePos = function (canvas, evt) {\n        var canvasBoundingClientRect = canvas.getBoundingClientRect();\n\n        var mouseX = evt.clientX;\n        var mouseY = evt.clientY;\n\n        return {\n            x: mouseX,\n            y: mouseY\n        };\n    }\n\n    var getTouchPos = function (canvas, evt) {\n        var canvasBoundingClientRect = canvas.getBoundingClientRect();\n\n        var touch = evt.targetTouches[0];\n\n        var touchX = touch.pageX;\n        var touchY = touch.pageY;\n\n        return {\n            x: touchX,\n            y: touchY\n        };\n    }\n\n    var setMousePos = function (newPos) {\n        var windowScale = getWindowScale();\n        newMouse = {\n            x: newPos.x * windowScale.x,\n            y: newPos.y * windowScale.y\n        }\n    }\n\n    var getWindowScale = function () {\n        // Fit to screen disabled for now.\n        return {\n            x:1,\n            y:1\n        }\n        /*return {\n            x: wickProject.width / window.innerWidth,\n            y: wickProject.height / window.innerHeight\n        }*/\n    }\n\n}</script>\n<script>/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n    \nvar WickPlayer = function () {\n\n    var self = this;\n\n    self.running = false;\n\n    var initialStateProject;\n    var stats;\n\n    self.runProject = function (projectJSON) {\n\n        if(localStorage.enableStats) {\n            stats = new Stats();\n            stats.showPanel(1);\n            document.body.appendChild(stats.dom);\n        }\n\n        try {\n            if(window.parent && window.parent.wickEditor) window.wickEditor = window.parent.wickEditor;\n        } catch (e) {\n            console.log(e)\n        }\n\n        self.running = true;\n\n        self.canvasContainer = document.getElementById('playerCanvasContainer');\n\n        resetElapsedTime();\n\n        // Load the project!\n        self.project = WickProject.fromJSON(projectJSON);\n        initialStateProject = WickProject.fromJSON(projectJSON);\n\n        self.canvasContainer.style.width = self.project.width+'px';\n        self.canvasContainer.style.height = self.project.height+'px';\n        self.canvasContainer.style.backgroundColor = self.project.backgroundColor;\n\n        self.project.rootObject.generateObjectNameReferences(self.project.rootObject);\n        initialStateProject.rootObject.generateObjectNameReferences(initialStateProject.rootObject);\n\n        self.project.prepareForPlayer();\n        initialStateProject.prepareForPlayer();\n\n        // Make the camera\n        window.camera = new WickCamera(self.project);\n\n        // Setup renderer/input/audio player\n        self.renderer = new WickPixiRenderer(self.canvasContainer);\n        self.inputHandler = new WickPlayerInputHandler(self.canvasContainer, self.project);\n        self.audioPlayer = new WickHowlerAudioPlayer(self.project);\n\n        self.inputHandler.setup(); \n        if(!bowser.mobile && !bowser.tablet) self.audioPlayer.setup();\n\n        self.renderer.preloadAllAssets(self.project, function () {\n            startUpdate();\n        });\n    }\n\n    window.runProject = function (projectJSON) {\n        self.runProject(projectJSON)\n    }\n\n    self.stopRunningProject = function () {\n\n        self.running = false;\n\n        update();\n        clearTimeout(loopTimeout);\n\n        self.project = null;\n\n        self.inputHandler.cleanup();\n        self.audioPlayer.cleanup();\n    }\n\n    function startUpdate(fps) {\n        then = Date.now();\n        startTime = then;\n        update(false);\n    }\n\n    var loopTimeout;\n    var update = function (firstTick) {\n\n        if(!self.running) return;\n\n        if(stats) stats.begin();\n\n        requestAnimationFrame(function() { update(false); });\n\n        now = Date.now();\n        elapsed = now - then;\n\n        var fpsInterval = 1000/self.project.framerate;\n        if (self.project.framerate === 60 || elapsed > fpsInterval) {\n            then = now - (elapsed % fpsInterval);\n            \n            deleteObjects = [];\n            if(!firstTick) self.project.tick();\n            deleteObjects.forEach(function (d) {\n                self.renderer.cleanupObjectTextures(d);\n                d.remove();\n                if(d.objectClonedFrom) {\n                    var removeIndex = d.objectClonedFrom.clones.indexOf(d);\n                    if(removeIndex !== -1) {\n                        d.objectClonedFrom.clones.splice(removeIndex, 1);\n                    }\n                }\n            });\n            self.renderer.renderWickObjects(self.project, self.project.rootObject.getAllActiveChildObjects(), null, true);\n            self.inputHandler.update();\n        }\n\n        if(stats) stats.end();\n\n    }\n\n    self.cloneObject = function (wickObj, args) {\n        var clone = wickObj.copy();\n        clone.name = undefined;\n        clone.isClone = true;\n        for(key in args) {\n            clone[key] = args[key];\n        }\n        clone.asset = wickObj.asset;\n\n        wickObj.clones.push(clone);\n\n        clone.objectClonedFrom = wickObj;\n\n        clone.prepareForPlayer()\n\n        clone.parentObject = wickObj.parentObject;\n        clone.parentFrame = wickObj.parentFrame;\n        clone.parentObject.getCurrentLayer().getCurrentFrame().wickObjects.push(clone);\n        clone.generateParentObjectReferences();\n\n        return clone;\n    }\n\n    self.deleteObject = function (wickObj) {\n        deleteObjects.push(wickObj);\n        \n    }\n\n    self.resetStateOfObject = function (wickObject) {\n\n        // Clones go away because they have no original state! :O\n        if(wickObject.isClone) {\n            self.deleteObject(wickObject)\n            return;\n        }\n\n        var initialStateObject = initialStateProject.getObjectByUUID(wickObject.uuid);\n        if(!initialStateObject) return;\n\n        // TOXXXIC\n        //console.log(\"-------------\");\n        var blacklist = ['_hitBox', 'asset', 'alphaMask', 'pixiSprite', 'pixiContainer', 'pixiText', 'audioData', 'wickScripts', 'parentObject', 'layers', '_active', '_wasActiveLastTick', '_scopeWrapper', 'parentFrame', 'bbox', 'tweens'];\n        for (var name in wickObject) {\n            if (name !== 'undefined' && wickObject.hasOwnProperty(name) && blacklist.indexOf(name) === -1) {\n                if(initialStateObject[name] !== wickObject[name]) {\n                    wickObject[name] = initialStateObject[name];\n                }\n            }\n        }\n        \n        wickObject.hoveredOver = false;\n        wickObject.playheadPosition = 0;\n        wickObject._playing = true;\n\n        // Don't forget to reset the childrens states\n        if(wickObject.isSymbol) {\n            wickObject.getAllChildObjects().forEach(function (child) {\n                if(child.isSymbol)\n                    wickPlayer.resetStateOfObject(child);\n            });\n        }\n\n    }\n\n}\n\n// this is temporary, need a better system for this...\nfunction runProject (json) {\n    window.wickPlayer = new WickPlayer(); \n    window.wickPlayer.runProject(json);\n}\n\nfunction tryToLoadProjectFromWindowHash () {\n    if(window.location.hash) {\n        var projectPath = window.location.hash.slice(1); // remove first char (the hash)\n\n        var xhr = new XMLHttpRequest();\n        xhr.open('GET', projectPath, true);\n        xhr.responseType = 'arraybuffer';\n\n        xhr.onload = function(e) {\n          if (this.status == 200) {\n            var byteArray = new Uint8Array(this.response);\n            var wickProjectJSON = LZString.decompressFromUint8Array(byteArray);\n            runProject(wickProjectJSON);\n          }\n        };\n\n        xhr.send();\n    }\n}\ntryToLoadProjectFromWindowHash();\n</script>\n"
  },
  {
    "path": "resources/credits.html",
    "content": "wowowowo"
  },
  {
    "path": "src/editor/WickEditor.GuiActionHandler.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\n/* GuiActionHandler.js - Interface for routines that don't need undo/redo functionality */\n\nvar GuiActionHandler = function (wickEditor) {\n\n    var that = this;\n\n    /* Initialize list of GuiActions. */\n    this.guiActions = {};\n\n    var registerAction = function (name, hotkeys, title, requiredParams, action) {\n        that.guiActions[name] = new GuiAction(hotkeys, title, requiredParams, action);\n    }\n\n    this.doAction = function (name, args) {\n        if(!this.guiActions[name]) {\n            console.error(\"Error: No GUI action called \" + name);\n        }\n\n        if(args) \n            this.guiActions[name].doAction(args);\n        else\n            this.guiActions[name].doAction({});\n    }\n\n    /* GuiAction definition. All possible actions performable through interacting\n    with the Wick Editor GUI are expected to be well defined by this structure .*/\n    var GuiAction = function (hotkeys, title, requiredParams, action) {\n\n        var that = this;\n\n        /* Function to be called when either a hotkey or element fires. */\n        this.doAction = action;\n\n        /* What this action should be labeled as in the hotkeys window */\n        this.title = title;\n\n        /* Options for special cases */\n        this.requiredParams = requiredParams;\n\n        /* Array of key strings which trigger the action function. */\n        this.hotkeys = hotkeys;\n        this.specialKeys = [];\n        if(this.hotkeys.indexOf(\"MODIFIER\") !== -1) {\n            this.modifierKey = true;\n            this.hotkeys.splice(this.hotkeys.indexOf(\"MODIFIER\"), 1);\n        } else {\n            this.modifierKey = false;\n        }\n\n        if(this.hotkeys.indexOf(\"SHIFT\") !== -1) {\n            this.shiftKey = true;\n            this.hotkeys.splice(this.hotkeys.indexOf(\"SHIFT\"), 1);\n        } else {\n            this.shiftKey = false;\n        }\n    }\n\n/****************************\n    GuiAction Definitions\n*****************************/\n\n    registerAction('previewToggle',\n        ['Enter'],\n        'Play/Pause Preview',\n        {},\n        function(args) {\n            wickEditor.canvas.getFastCanvas().togglePreviewPlaying();\n            wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n        });\n\n    registerAction('previewToggleAndLoop',\n        ['SHIFT','Enter'],\n        'Loop Preview',\n        {},\n        function(args) {\n            wickEditor.guiActionHandler.doAction('previewPlay', {loop:true});\n            wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n        });\n\n    registerAction('previewPlay',\n        [],\n        [],\n        {},\n        function(args) {\n            wickEditor.canvas.getFastCanvas().startPreviewPlaying(args.loop);\n        });\n\n    registerAction('previewPause',\n        [],\n        [],\n        {},\n        function(args) {\n            wickEditor.canvas.getFastCanvas().stopPreviewPlaying();\n            wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n        });\n\n    registerAction('stopRunningProject',\n        ['Escape'],\n        'Stop Running Project',\n        {builtinplayerRunning:true},\n        function(args) {\n            if(!wickEditor.builtinplayer.running) return;\n            wickEditor.builtinplayer.stopRunningProject();\n            $('#editorCanvasContainer').focus().select();\n        });\n\n    registerAction('redo',\n        ['MODIFIER','SHIFT','KeyZ'],\n        'Redo',\n        {},\n        function(args) {\n            wickEditor.actionHandler.redoAction();\n        });\n\n    registerAction('undo',\n        ['MODIFIER','KeyZ'],\n        'Undo',\n        {},\n        function(args) {\n            wickEditor.actionHandler.undoAction();\n        });\n\n    registerAction('runProject',\n        ['MODIFIER','Enter'],\n        'Run Project',\n        {usableInTextBoxes:true},\n        function(args) {\n            $(\":focus\").blur();\n            \n            that.keys = [];\n            that.specialKeys = [];\n\n            wickEditor.project.rootObject.getAllChildObjectsRecursive().forEach(function (child) {\n                child.causedAnException = false;\n            });\n            wickEditor.scriptingide.clearError();\n            \n            WickProject.Exporter.autosaveProject(wickEditor.project);\n            wickEditor.project.getAsJSON(function (JSONProject) {\n                wickEditor.project.unsaved = false;\n                wickEditor.builtinplayer.runProject(JSONProject);\n            });\n\n        });\n\n    registerAction('openProjectAsNewWindow',\n        ['MODIFIER','SHIFT','Enter'],\n        'Run Project in New Window',\n        {usableInTextBoxes:true},\n        function(args) {\n            that.keys = [];\n            that.specialKeys = [];\n            WickProject.Exporter.exportProject(wickEditor.project, {asNewWindow:true});\n        });\n\n    registerAction('recenterCanvas',\n        ['MODIFIER','Digit0'],\n        'Recenter Canvas',\n        {},\n        function(args) {\n            wickEditor.canvas.recenterCanvas();\n            wickEditor.syncInterfaces();\n        });\n\n    registerAction('exportProjectZIP',\n        [],\n        ['Export Project as ZIP'],\n        {usableInTextBoxes:true},\n        function(args) {\n            that.keys = [];\n            that.specialKeys = [];\n            WickProject.Exporter.autosaveProject(wickEditor.project);\n            WickProject.Exporter.exportProject(wickEditor.project, {zipped:true});\n        });\n  \n    registerAction('openProjectExportWindow',\n                   [],\n                   [],\n                   {usableInTextBoxes:true},\n                   function (args) {\n                      wickEditor.videoExporter.open();\n                   });\n\n    registerAction('saveProject',\n        ['MODIFIER','SHIFT','KeyS'],\n        'Force autosave',\n        {usableInTextBoxes:true},\n        function(args) {\n            that.keys = [];\n            that.specialKeys = [];\n            WickProject.Exporter.autosaveProject(wickEditor.project);\n            //wickEditor.guiActionHandler.doAction('exportProjectJSON');\n        });\n\n    registerAction('exportProjectWick',\n        ['MODIFIER','KeyS'],\n        ['Save Project'],\n        {usableInTextBoxes:true},\n        function(args) {\n            that.keys = [];\n            that.specialKeys = [];\n            WickProject.Exporter.autosaveProject(wickEditor.project);\n            WickProject.Exporter.exportProject(wickEditor.project, {wick:true});\n        });\n\n    registerAction('exportProjectHTML',\n        [],\n        [],\n        {usableInTextBoxes:true},\n        function(args) {\n            that.keys = [];\n            that.specialKeys = [];\n            WickProject.Exporter.autosaveProject(wickEditor.project);\n            WickProject.Exporter.exportProject(wickEditor.project);\n        });\n\n    registerAction('exportProjectJSON',\n        [],\n        'Save As',\n        {},\n        function(args) {\n            WickProject.Exporter.autosaveProject(wickEditor.project);\n            WickProject.Exporter.exportProject(wickEditor.project, {json:true});\n        });\n\n    registerAction('exportProjectGIF',\n        [],\n        [],\n        {},\n        function (args) {\n            wickEditor.canvas.getCanvasRenderer().renderProjectAsGIF(function (blob) {\n                saveAs(blob, wickEditor.project.name+\".gif\");\n            });\n        });\n\n    registerAction('exportFrameSVG',\n        [],\n        [],\n        {},\n        function (args) {\n            wickEditor.guiActionHandler.doAction('useTools.cursor')\n            wickEditor.canvas.getInteractiveCanvas().pathRoutines.getProjectAsSVG()\n        });\n\n    registerAction('exportProjectPNG',\n        [],\n        [],\n        {},\n        function (args) {\n            wickEditor.canvas.getCanvasRenderer().renderProjectAsPNG(function (blob) {\n                saveAs(blob, wickEditor.project.name+\".png\");\n            });\n        });\n\n    registerAction('exportProjectWebM',\n        [],\n        [],\n        {},\n        function (args) {\n            alert(\"NYI\")\n        });\n\n    registerAction('openFile',\n        ['MODIFIER','KeyO'],\n        'Open',\n        {},\n        function(args) {\n            that.keys = [];\n            $('#importButton').click();\n        });\n\n    registerAction('importFile',\n        [],\n        [],\n        {},\n        function(args) {\n            that.keys = [];\n            $('#importButton').click();\n        });\n\n    registerAction('moveSelection',\n        [],\n        [],\n        {},\n        function (args) {\n            var modifiedStates = [];\n            var objs = wickEditor.project.getSelectedObjects();\n            objs.forEach(function (obj) {\n                var wickObj = obj;\n                modifiedStates.push({\n                    x : wickObj.x + args.x,\n                    y : wickObj.y + args.y,\n                    scaleX : obj.isPath ? 1 : obj.scaleX,\n                    scaleY : obj.isPath ? 1 : obj.scaleY,\n                    rotation : obj.isPath ? 0 : obj.rotation,\n                    flipX : obj.isPath ? false : obj.flipX,\n                    flipY : obj.isPath ? false : obj.flipY\n                });\n            });\n\n            wickEditor.actionHandler.doAction('modifyObjects', {\n                objs: objs,\n                modifiedStates: modifiedStates\n            });\n        });\n\n    registerAction('selectAll',\n        ['MODIFIER','KeyA'],\n        'Select All',\n        {},\n        function(args) {\n            if(!(wickEditor.currentTool instanceof Tools.SelectionCursor)\n            && !(wickEditor.currentTool instanceof Tools.VectorCursor))\n                wickEditor.currentTool = wickEditor.tools.selectioncursor;\n\n            wickEditor.project.clearSelection();\n            wickEditor.project.currentObject.getAllActiveChildObjects().forEach(function (obj) {\n                if(obj.parentFrame.parentLayer !== wickEditor.project.getCurrentLayer()) return;\n                if(obj.parentFrame.parentLayer.locked || obj.parentFrame.parentLayer.hidden) return;\n                wickEditor.project.selectObject(obj);\n            });\n            wickEditor.syncInterfaces();\n        });\n\n    registerAction('deselectAll',\n        ['MODIFIER','SHIFT','KeyA'],\n        'Deselect All',\n        {},\n        function(args) {\n            wickEditor.project.clearSelection();\n            wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n            wickEditor.syncInterfaces();\n        });\n\n    registerAction('moveSelectionUp',\n        ['ArrowUp'],\n        'Move selection up 1px',\n        {},\n        function(args) {\n            wickEditor.guiActionHandler.doAction('moveSelection', {\n                x:0, y:-1\n            })\n        });\n\n    registerAction('moveSelectionDown',\n        ['ArrowDown'],\n        'Move selection down 1px',\n        {},\n        function(args) {\n            wickEditor.guiActionHandler.doAction('moveSelection', {\n                x:0, y:1\n            })\n        });\n\n    registerAction('moveSelectionLeft',\n        ['ArrowLeft'],\n        'Move selection left 1px',\n        {},\n        function(args) {\n            wickEditor.guiActionHandler.doAction('moveSelection', {\n                x:-1, y:0\n            })\n        });\n\n    registerAction('moveSelectionRight',\n        ['ArrowRight'],\n        'Move selection right 1px',\n        {},\n        function(args) {\n            wickEditor.guiActionHandler.doAction('moveSelection', {\n                x:1, y:0\n            })\n        });\n\n    registerAction('moveSelectionUp10x',\n        ['SHIFT', 'ArrowUp'],\n        'Move selection up 10px',\n        {},\n        function(args) {\n            wickEditor.guiActionHandler.doAction('moveSelection', {\n                x:0, y:-10\n            })\n        });\n\n    registerAction('moveSelectionDown10x',\n        ['SHIFT', 'ArrowDown'],\n        'Move selection down 10px',\n        {},\n        function(args) {\n            wickEditor.guiActionHandler.doAction('moveSelection', {\n                x:0, y:10\n            })\n        });\n\n    registerAction('moveSelectionLeft10x',\n        ['SHIFT', 'ArrowLeft'],\n        'Move selection left 10px',\n        {},\n        function(args) {\n            wickEditor.guiActionHandler.doAction('moveSelection', {\n                x:-10, y:0\n            })\n        });\n\n    registerAction('moveSelectionRight10x',\n        ['SHIFT', 'ArrowRight'],\n        'Move selection right 10px',\n        {},\n        function(args) {\n            wickEditor.guiActionHandler.doAction('moveSelection', {\n                x:10, y:0\n            })\n        });\n\n    registerAction('movePlayheadLeft',\n        ['Comma'],\n        'Previous frame',\n        {},\n        function(args) {\n            wickEditor.actionHandler.doAction(\"movePlayhead\", {\n                obj: wickEditor.project.currentObject,\n                newPlayheadPosition: wickEditor.project.currentObject.playheadPosition-1\n            })\n        });\n\n    registerAction('movePlayheadRight',\n        ['Period'],\n        'Next frame',\n        {},\n        function(args) {\n            wickEditor.actionHandler.doAction(\"movePlayhead\", {\n                obj: wickEditor.project.currentObject,\n                newPlayheadPosition: wickEditor.project.currentObject.playheadPosition+1\n            })\n        });\n\n    registerAction('deleteSelectedObjects',\n        [],\n        'Delete Selection',\n        {},\n        function(args) {\n            var selection = wickEditor.project.getSelectedObjects();\n            if(selection.length === 0) {\n                // Ignore\n            } else if (selection[0] instanceof WickFrame) {\n                wickEditor.actionHandler.doAction('deleteFrames', {\n                    frames: wickEditor.project.getSelectedObjectsByType(WickFrame)\n                });\n            } else if (selection[0] instanceof WickObject) {\n                wickEditor.actionHandler.doAction('deleteObjects', {\n                    objects: wickEditor.project.getSelectedObjectsByType(WickObject)\n                });\n            }\n        });\n\n    registerAction('deleteSelectedObjectsBackspace',\n        ['Backspace'],\n        null,\n        {},\n        function(args) {\n           wickEditor.guiActionHandler.doAction('deleteSelectedObjects');\n        });\n\n    registerAction('deleteSelectedObjectsDelete',\n        ['Delete'],\n        null,\n        {},\n        function(args) {\n            wickEditor.guiActionHandler.doAction('deleteSelectedObjects');\n        });\n\n    var copyKeys  = isChrome ? [] : ['MODIFIER',\"KeyC\"];\n    var cutKeys   = isChrome ? [] : ['MODIFIER',\"KeyX\"];\n    var pasteKeys = isChrome ? [] : ['MODIFIER',\"KeyV\"];\n\n    registerAction('copy',\n        copyKeys,\n        'Copy',\n        {},\n        function(args) {\n            wickEditor.rightclickmenu.open = false;\n            that.keys = [];\n\n            var copyData = wickEditor.project.getCopyData();\n            var copyType\n            if(wickEditor.project.getSelectedObjects()[0] instanceof WickObject) {\n                copyType = 'text/wickobjectsjson';\n            } else {\n                copyType = 'text/wickframesjson';\n            }\n            polyfillClipboardData.setData(copyType, copyData);\n        });\n\n    registerAction('cut',\n        cutKeys,\n        'Cut',\n        {},\n        function(args) {\n            wickEditor.guiActionHandler.doAction('copy');\n            wickEditor.guiActionHandler.doAction('deleteSelectedObjects');\n        });\n    \n    registerAction('paste',\n        pasteKeys,\n        'Paste',\n        {},\n        function(args) {\n            wickEditor.rightclickmenu.open = false;\n            that.keys = [];\n\n            var clipboardData = window.polyfillClipboardData;\n            if(args.clipboardData) clipboardData = args.clipboardData;\n            if(!clipboardData) return;\n            var items = clipboardData.items || clipboardData.types;\n\n            for (i=0; i<items.length; i++) {\n\n                var fileType = items[i].type || items[i];\n                var file = clipboardData.getData(fileType);\n                \n                if(fileType === 'text/wickobjectsjson') {\n                    var objs = WickObject.fromJSONArray(JSON.parse(file));\n                    objs.forEachBackwards(function (obj) {\n                        wickEditor.project.currentObject.getAllActiveChildObjects().forEach(function (c) {\n                            if(c.name === obj.name) obj.name = undefined;\n                        });\n                        obj.getAllChildObjectsRecursive().forEach(function (child) {\n                            child.uuid = random.uuid4();\n                            (child.layers||[]).forEach(function (layer) {\n                                layer.frames.forEach(function (frame) {\n                                    frame.uuid = random.uuid4();\n                                })\n                            });\n                        });\n                        obj.getAllFrames().forEach(function (frame) {\n                            frame.uuid = random.uuid4();\n                        });\n                    });\n                    wickEditor.actionHandler.doAction('addObjects', {\n                        wickObjects:objs\n                    });\n                } else if (fileType === 'text/wickframesjson') {\n                    var frames = WickFrame.fromJSONArray(JSON.parse(file));\n                    var firstPlayheadPosition = null;\n                    frames.forEach(function (frame) {\n                        if(!firstPlayheadPosition || frame.playheadPosition < firstPlayheadPosition) \n                            firstPlayheadPosition = frame.playheadPosition;\n                    });\n                    frames.forEach(function (frame) {\n                        frame.uuid = random.uuid4();\n                        if(frame.name) frame.name = frame.name;\n                        frame.playheadPosition -= firstPlayheadPosition;\n                        frame.playheadPosition += wickEditor.project.getCurrentObject().playheadPosition;\n\n                        frame.wickObjects.forEach(function (wickObject) {\n                            wickObject.getAllChildObjectsRecursive().forEach(function (child) {\n                                child.uuid = random.uuid4();\n                            });\n                        });\n                    });\n                    wickEditor.actionHandler.doAction('addFrames', {\n                        frames:frames\n                    });\n                } else if (fileType.includes('image')) {\n                    reader = new FileReader();\n                    reader.onload = function(evt) {\n                        var asset = new WickAsset(evt.target.result, 'image', 'Pasted Image');\n                        var wickObj = new WickObject();\n                        wickObj.assetUUID = wickEditor.project.library.addAsset(asset);\n                        wickObj.isImage = true;\n                        wickObj.name = 'Pasted Image';\n                        wickEditor.actionHandler.doAction('addObjects', {\n                            wickObjects:[wickObj]\n                        });\n                    };\n                    reader.readAsDataURL(items[i].getAsFile());\n                } else {\n                    console.error(\"Pasting files with type \" + fileType + \"NYI.\")\n                }\n\n            }\n        });\n\n    registerAction('newProject',\n        [],\n        [],\n        {},\n        function(args) {\n            if(!args.dontWarn && !confirm(\"Create a new project? All unsaved changes to the current project will be lost!\")) {\n                return;\n            }\n            \n            var project = new WickProject();\n            project.name = window.prompt(\"Enter a name for your new project:\", \"New Project\") || \"New Project\";\n            \n            wickEditor.guiActionHandler.doAction('openProject', {project:project, dontWarn:true});\n        });\n\n    registerAction('openProject',\n        [],\n        [],\n        {},\n        function(args) {\n            if(!args.dontWarn && !confirm(\"Open a new project? All unsaved changes to the current project will be lost!\")) {\n                return;\n            }\n\n            var project = args.project;\n\n            wickEditor.project = project;\n            wickEditor.project.loadFonts();\n\n            wickEditor.actionHandler.clearHistory();\n\n            wickEditor.canvas.recenterCanvas();\n            wickEditor.guiActionHandler.doAction(\"openProjectSettings\");\n            wickEditor.project.currentObject.framesDirty = true;\n            wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n            wickEditor.library.dirty = true;\n            wickEditor.syncInterfaces();\n        });\n\n    registerAction('useTools.selectioncursor',\n        ['KeyC'],\n        'Switch to Selection Cursor',\n        {},\n        function(args) {\n            wickEditor.changeTool(wickEditor.tools.selectioncursor);\n        });\n\n    registerAction('useTools.vectorcursor',\n        ['KeyP'],\n        'Switch to Path Cursor',\n        {},\n        function (args) {\n            wickEditor.changeTool(wickEditor.tools.vectorcursor);\n        });\n\n    registerAction('useTools.pencil',\n        ['KeyV'],\n        'Switch to Pencil',\n        {},\n        function(args) {\n            wickEditor.changeTool(wickEditor.tools.pencil);\n        });\n\n    registerAction('useTools.paintbrush',\n        ['KeyB'],\n        'Switch to Brush',\n        {},\n        function(args) {\n            wickEditor.changeTool(wickEditor.tools.paintbrush);\n        });\n\n    registerAction('useTools.line',\n        ['KeyL'],\n        'Switch to Line',\n        {},\n        function(args) {\n            wickEditor.changeTool(wickEditor.tools.line);\n        });\n\n    registerAction('useTools.eraser',\n        ['KeyE'],\n        'Switch to Eraser',\n        {},\n        function(args) {\n            wickEditor.changeTool(wickEditor.tools.eraser);\n        });\n\n    registerAction('useTools.fillbucket',\n        ['KeyG'],\n        'Switch to Fill Bucket',\n        {},\n        function(args) {\n            wickEditor.changeTool(wickEditor.tools.fillbucket);\n        });\n\n    registerAction('useTools.rectangle',\n        ['KeyR'],\n        'Switch to Rectangle',\n        {},\n        function(args) {\n            wickEditor.changeTool(wickEditor.tools.rectangle);\n        });\n\n    registerAction('useTools.ellipse',\n        ['KeyS'],\n        'Switch to Ellipse',\n        {},\n        function(args) {\n            wickEditor.changeTool(wickEditor.tools.ellipse);\n        });\n\n    registerAction('useTools.pen',\n        ['KeyO'],\n        'Switch to Pen',\n        {},\n        function(args) {\n            wickEditor.changeTool(wickEditor.tools.pen);\n        });\n\n    registerAction('useTools.dropper',\n        ['KeyD'],\n        'Switch to Eyedropper',\n        {},\n        function(args) {\n            wickEditor.changeTool(wickEditor.tools.dropper);\n        });\n\n    registerAction('useTools.text',\n        ['KeyT'],\n        'Switch to Text',\n        {},\n        function(args) {\n            wickEditor.changeTool(wickEditor.tools.text);\n        });\n\n    registerAction('useTools.zoom',\n        ['KeyZ'],\n        'Switch to Zoom',\n        {},\n        function(args) {\n            wickEditor.changeTool(wickEditor.tools.zoom);\n        });\n\n    registerAction('useTools.pan',\n        [],\n        [],\n        {},\n        function(args) {\n            wickEditor.changeTool(wickEditor.tools.pan);\n        });\n\n    registerAction('panWithSpace',\n        ['Space'],\n        'Pan',\n        {},\n        function(args) {\n            if(!(wickEditor.currentTool instanceof Tools.Pan)) {\n                wickEditor.lastTool = wickEditor.currentTool;\n                wickEditor.currentTool = wickEditor.tools.pan;\n                wickEditor.canvas.updateCursor();\n                wickEditor.syncInterfaces();\n            }\n        });\n\n    var ZOOM_PLUS_MINUS_KEY_AMT = 1.2;\n\n    registerAction('zoomIn',\n        ['Equal'],\n        'Zoom In',\n        {},\n        function(args) {\n            wickEditor.canvas.zoomToPoint(ZOOM_PLUS_MINUS_KEY_AMT, window.innerWidth/2, window.innerHeight/2);\n        });\n\n    registerAction('zoomOut',\n        ['Minus'],\n        'Zoom Out',\n        {},\n        function(args) {\n            wickEditor.canvas.zoomToPoint(1/ZOOM_PLUS_MINUS_KEY_AMT, window.innerWidth/2, window.innerHeight/2);\n        });\n\n    registerAction('editScripts',\n        ['Backquote'],\n        'Open Scripting Window',\n        {},\n        function(args) {\n            wickEditor.scriptingide.open = !wickEditor.scriptingide.open;\n            wickEditor.scriptingide.aceEditor.focus()\n            wickEditor.syncInterfaces();\n        });\n\n    registerAction('bringToFront',\n        ['MODIFIER', \"SHIFT\", \"ArrowUp\"],\n        'Bring to Front',\n        {},\n        function(args) {\n            wickEditor.actionHandler.doAction('moveObjectToZIndex', {\n                objs:wickEditor.project.getSelectedObjects(),\n                newZIndex: wickEditor.project.getCurrentFrame().wickObjects.length-1\n            });\n        });\n\n    registerAction('sendToBack',\n        ['MODIFIER', \"SHIFT\", \"ArrowDown\"],\n        'Send to Back',\n        {},\n        function(args) {\n            wickEditor.actionHandler.doAction('moveObjectToZIndex', {\n                objs:wickEditor.project.getSelectedObjects(),\n                newZIndex: 0\n            });\n        });\n\n    registerAction('moveBackwards',\n        ['MODIFIER', \"ArrowDown\"],\n        'Move Backwards',\n        {},\n        function(args) {\n            wickEditor.actionHandler.doAction('moveObjectBackwards', {\n                objs: wickEditor.project.getSelectedObjects()\n            });\n        });\n\n    registerAction('moveForwards',\n        ['MODIFIER', \"ArrowUp\"],\n        'Move Forwards',\n        {},\n        function(args) {\n            wickEditor.actionHandler.doAction('moveObjectForwards', {\n                objs: wickEditor.project.getSelectedObjects()\n            });\n        });\n\n    registerAction('flipHorizontally',\n        [],\n        [],\n        {},\n        function(args) {\n            var modifiedStates = [];\n            var objs = wickEditor.project.getSelectedObjects();\n\n            var centerX = 0;\n            objs.forEach(function (obj) {\n                centerX += obj.x;\n            });\n            centerX /= objs.length;\n\n            objs.forEach(function (obj) {\n                var wickObj = obj;\n                modifiedStates.push({\n                    scaleX : -obj.scaleX,\n                    rotation: -obj.rotation,\n                    x: -(obj.x-centerX)+centerX,\n                });\n            });\n\n            wickEditor.actionHandler.doAction('modifyObjects', {\n                objs: objs,\n                modifiedStates: modifiedStates\n            });\n        });\n\n    registerAction('flipVertically',\n        [],\n        [],\n        {},\n        function(args) {\n            var modifiedStates = [];\n            var objs = wickEditor.project.getSelectedObjects();\n\n            var centerY = 0;\n            objs.forEach(function (obj) {\n                centerY += obj.y;\n            });\n            centerY /= objs.length;\n\n            objs.forEach(function (obj) {\n                var wickObj = obj;\n                modifiedStates.push({\n                    scaleY : -obj.scaleY,\n                    rotation: -obj.rotation,\n                    y: -(obj.y-centerY)+centerY,\n                });\n            });\n\n            wickEditor.actionHandler.doAction('modifyObjects', {\n                objs: objs,\n                modifiedStates: modifiedStates\n            });\n        });\n\n    registerAction('editObject',\n        [],\n        [],\n        {},\n        function(args) {\n            var selectedObject = wickEditor.project.getSelectedObject();\n            wickEditor.project.clearSelection()\n            wickEditor.actionHandler.doAction('editObject', { objectToEdit: selectedObject });\n        });\n\n    registerAction('finishEditingObject',\n        [],\n        [],\n        {},\n        function(args) {\n            wickEditor.actionHandler.doAction('finishEditingCurrentObject', {});\n        });\n\n    registerAction('convertToSymbol',\n        [],\n        [],\n        {},\n        function(args) {\n            wickEditor.actionHandler.doAction('convertObjectsToSymbol', {\n                objects: wickEditor.project.getSelectedObjects()\n            });\n        });\n\n    registerAction('convertToButton',\n        [],\n        [],\n        {},\n        function(args) {\n            wickEditor.actionHandler.doAction('convertObjectsToSymbol', {\n                objects: wickEditor.project.getSelectedObjects(),\n                button: true\n            });\n        });\n\n    registerAction('convertToGroup',\n        ['MODIFIER', 'KeyG'],\n        'Group Selection',\n        {},\n        function(args) {\n            wickEditor.actionHandler.doAction('convertObjectsToSymbol', {\n                objects: wickEditor.project.getSelectedObjects(),\n                group: true\n            });\n        });\n\n    registerAction('convertFramesToSymbol',\n        [],\n        [],\n        {},\n        function (args) {\n            wickEditor.actionHandler.doAction('convertFramesToSymbol', {\n                frames: wickEditor.project.getSelectedObjects()\n            });\n        })\n\n    registerAction('breakApart',\n        [\"MODIFIER\", \"KeyB\"],\n        'Break Apart Selection',\n        {},\n        function(args) {\n            var selectedObject = wickEditor.project.getSelectedObject();\n            wickEditor.actionHandler.doAction('breakApartSymbol', {\n                obj:selectedObject\n            });\n        });\n\n    registerAction('downloadObject',\n        [],\n        [],\n        {},\n        function(args) {\n            wickEditor.project.getSelectedObject().downloadAsFile();\n            wickEditor.syncInterfaces();\n        });\n\n    registerAction('addFrame',\n        [],\n        [],\n        {},\n        function(args) {\n            wickEditor.actionHandler.doAction('addNewFrame');\n        });\n    \n    registerAction('copyFrame',\n        [],\n        [],\n        {},\n        function(args) {\n            wickEditor.rightclickmenu.open = false;\n            polyfillClipboardData.setData('text/wickobjectsframe', wickEditor.project.getCurrentFrame().getAsJSON());\n            wickEditor.syncInterfaces()\n        });\n\n    registerAction('pasteFrame',\n        [],\n        [],\n        {},\n        function(args) {\n            var frameJSON = polyfillClipboardData.getData('text/wickobjectsframe');\n            var frame = WickFrame.fromJSON(frameJSON);\n            wickEditor.actionHandler.doAction('addFrame', {\n                frame:frame\n            });\n        });\n\n    registerAction('shrinkFrame',\n        ['SHIFT', 'Comma'],\n        'Shrink Frame',\n        {},\n        function(args) {\n            var frame = wickEditor.project.getCurrentFrame();\n\n            wickEditor.actionHandler.doAction('shrinkFrame', {\n                nFramesToShrinkBy: 1,\n                frame: frame\n            });\n        });\n\n    registerAction('addLayer',\n        [],\n        [],\n        {},\n        function(args) {\n            wickEditor.actionHandler.doAction('addNewLayer');\n        });\n\n    registerAction('removeLayer',\n        [],\n        [],\n        {},\n        function(args) {\n            wickEditor.actionHandler.doAction('removeLayer', {\n                layer: wickEditor.project.getCurrentObject().getCurrentLayer()\n            });\n        });\n\n    registerAction('moveLayerUp',\n        [],\n        [],\n        {},\n        function(args) {\n            wickEditor.actionHandler.doAction('moveLayerUp', {});\n        });\n\n    registerAction('moveLayerDown',\n        [],\n        [],\n        {},\n        function(args) {\n            wickEditor.actionHandler.doAction('moveLayerDown', {});\n        });\n\n    registerAction('createMotionTween',\n        [],\n        [],\n        {},\n        function(args) {\n            var frame = wickEditor.project.getSelectedObject();\n            var currentObject = wickEditor.project.getCurrentObject()\n\n            if(frame.wickObjects.length > 0) {\n                wickEditor.actionHandler.doAction('createMotionTween', {\n                    frame: frame,\n                    playheadPosition: currentObject.playheadPosition-frame.playheadPosition\n                });\n            }\n        });\n    \n    registerAction('deleteMotionTween',\n        [],\n        [],\n        {},\n        function(args) {\n            var frame = wickEditor.project.getSelectedObject();\n            var currentObject = wickEditor.project.getCurrentObject()\n\n            wickEditor.actionHandler.doAction('deleteMotionTween', {\n                frame: frame,\n                playheadPosition: currentObject.playheadPosition-frame.playheadPosition\n            });\n        });\n\n    registerAction('addNewText',\n        [],\n        [],\n        {},\n        function (args) {\n            var newWickObject = WickObject.createTextObject('Click to edit text');\n            newWickObject.x = wickEditor.project.width/2;\n            newWickObject.y = wickEditor.project.height/2;\n            wickEditor.actionHandler.doAction('addObjects', {wickObjects:[newWickObject]});\n        });\n\n    registerAction('finishEditingTextbox',\n        ['Enter'],\n        'Finish editing text box',\n        {usableInTextBoxes:true, disabledInScriptingIDE:true},\n        function (args) {\n            $(\":focus\").blur();\n        });\n\n    registerAction('openProjectSettings',\n        [],\n        [],\n        {},\n        function (args) {\n            wickEditor.project.clearSelection();\n            wickEditor.inspector.openProjectSettings();\n            wickEditor.syncInterfaces();\n        });\n\n    registerAction('openEditorSettings',\n        [],\n        [],\n        {},\n        function (args) {\n            wickEditor.editorSettings.open();\n            wickEditor.syncInterfaces();\n        });\n\n    registerAction('openEditorCredits',\n        [],\n        [],\n        {},\n        function (args) {\n            wickEditor.editorCredits.open();\n            wickEditor.syncInterfaces();\n        });\n\n    registerAction('toggleProjectSettings',\n        [],\n        [],\n        {},\n        function (args) {\n            wickEditor.project.clearSelection();\n            wickEditor.inspector.toggleProjectSettings();\n            wickEditor.syncInterfaces();\n        });\n\n    registerAction('copyFrameForward', \n        [],\n        [],\n        {},\n        function (args) {\n            wickEditor.actionHandler.doAction('copyFrameForward');\n        });\n\n    registerAction('extendFrameToPlayhead',\n        [],\n        [],\n        {},\n        function (args) {\n            var frame = wickEditor.project.getSelectedObject()\n            var length = wickEditor.project.getCurrentObject().playheadPosition - frame.playheadPosition + 1;\n            wickEditor.actionHandler.doAction('changeFrameLength', {\n                frame: frame,\n                newFrameLength: length\n            });\n        });\n\n    registerAction('duplicateSelection',\n        ['MODIFIER', 'KeyD'],\n        'Duplicate Selection',\n        {},\n        function (args) {\n            var selectedObjects = wickEditor.project.getSelectedObjects();\n            var duplicates = [];\n\n            selectedObjects.forEach(function (selectedObject) {\n                var copy = selectedObject.copy();\n                copy.x += 50;\n                copy.y += 50;\n                duplicates.push(copy);\n            });\n\n            wickEditor.actionHandler.doAction('addObjects', {\n                wickObjects:duplicates\n            });\n        })\n\n    registerAction('doBooleanOperation',\n        [],\n        [],\n        {},\n        function (args) {\n            wickEditor.actionHandler.doAction('doBooleanOperation', {\n                boolFnName: args.boolFnName,\n                objs: wickEditor.project.getSelectedObjects()\n            });\n        });\n\n    registerAction('resetSettings',\n        [],\n        [],\n        {},\n        function (args) {\n            wickEditor.settings.setDefaults();\n            wickEditor.syncInterfaces();\n        });\n\n    registerAction('deleteAsset',\n        [],\n        [],\n        {},\n        function (args) {\n            var asset = wickEditor.library.getSelectedAsset(); \n\n            wickEditor.library.dirty = true;\n\n            if (asset == null) return; \n            wickEditor.actionHandler.doAction('deleteAsset', {\n                asset: asset,\n            });\n\n        });\n\n    registerAction('renameAsset',\n        [],\n        [],\n        {},\n        function (args) {\n            var asset = wickEditor.library.getSelectedAsset(); \n            if (asset == null) return; // No asset selected\n            \n            var oldAssetName = asset.filename; \n            var newName = prompt(\"Rename \" + oldAssetName + \" to:\");\n\n            wickEditor.library.dirty = true;\n\n            if (newName == null) return; // No name input\n            wickEditor.actionHandler.doAction('renameAsset', {\n                asset: wickEditor.library.getSelectedAsset(),\n                newFilename: newName,\n            });\n\n        });\n\n    registerAction('createAssetFromSelection',\n        [],\n        [],\n        {},\n        function (args) {\n            var json = wickEditor.project.getSelectedObject().getAsJSON();\n            var asset = new WickAsset(json, 'symbol', prompt('Name ur new thing'));\n            wickEditor.project.library.addAsset(asset);\n            wickEditor.project.getSelectedObject().assetUUID = asset.uuid;\n        });\n\n    registerAction('createObjectFromAsset',\n        [],\n        [],\n        {},\n        function (args) {\n            var asset = args.asset;\n            if (!asset) return;\n\n            var screenPos = wickEditor.canvas.screenToCanvasSpace(args.x, args.y)\n            var wickObj = new WickObject();\n\n            if(asset.type === 'image') {\n                var wickObj = new WickObject();\n                wickObj.isImage = true;\n            } else if (asset.type === 'symbol') {\n                var wickObj = WickObject.fromJSON(asset.data);\n                wickObj.getAllChildObjectsRecursive().forEach(function (child) {\n                    child.uuid = random.uuid4();\n                    (child.layers||[]).forEach(function (layer) {\n                        layer.frames.forEach(function (frame) {\n                            frame.uuid = random.uuid4();\n                        })\n                    });\n                });\n                wickObj.getAllFrames().forEach(function (frame) {\n                    frame.uuid = random.uuid4();\n                });\n            }\n\n            wickObj.assetUUID = asset.uuid;\n            wickObj.x = screenPos.x;\n            wickObj.y = screenPos.y;\n\n            wickEditor.actionHandler.doAction('addObjects', {\n                wickObjects:[wickObj]\n            });\n        });\n\n    registerAction('changePathProperties',\n        [],\n        [],\n        {},\n        function (args) {\n            var objs = args.objs || wickEditor.project.getSelectedObjects();\n            var modifiedStates = [];\n            objs.forEach(function (wickObject) {\n                if(!wickObject.isPath) {\n                    modifiedStates.push({});\n                } else {\n                    for(key in args) {\n                        wickObject.paper[key] = args[key];\n                    }\n                    modifiedStates.push({\n                        pathData : wickObject.paper.exportSVG({asString:true}),\n                        svgX : wickObject.paper.bounds._x,\n                        svgY : wickObject.paper.bounds._y\n                    })\n                }\n            })\n            wickEditor.actionHandler.doAction('modifyObjects', {\n                objs: objs,\n                modifiedStates: modifiedStates\n            });\n        })\n\n    registerAction('printBrowserInfo', \n        [],\n        [],\n        {},\n        function (args) {\n            var myWindow = window.open(\"\", \"MsgWindow\", \"width=500,height=300\");\n            var info = getBrowserAndOSInfo()\n            myWindow.document.write('Browser: ' + info.browser + '<br />');\n            myWindow.document.write('Browser version: ' + info.browserVersion + '<br />');\n            myWindow.document.write('Navigator App Name: ' + info.navigatorAppName + '<br />');\n            myWindow.document.write('Navigator User Agent: ' + info.navigatorUserAgent + '<br />');\n            myWindow.document.write('devicePixelRatio: ' + info.devicePixelRatio + '<br />');\n            myWindow.document.write('WickEditor Version: ' + wickEditor.version + '<br />');\n        });\n\n}"
  },
  {
    "path": "src/editor/WickEditor.InputHandler.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar InputHandler = function (wickEditor) {\n\n    this.mouse = {};\n\n    var that = this;\n\n/*************************\n    Pressure\n*************************/\n\n    this.penPressure = 1; \n\n    Pressure.set(\".paperCanvas\", { \n        change: function(force, event) { \n            that.penPressure = force; \n        } \n    }, {polyfill: false});\n\n    this.getPenPressure = function() {\n        return that.penPressure; \n    }\n\n/*************************\n     Mouse\n*************************/\n\n    // Disable images in the GUI from being dragged around\n    $('img').on('dragstart', function(event) { event.preventDefault(); });\n\n    document.addEventListener('mousemove', function(e) { \n        that.mouse.x = e.clientX;\n        that.mouse.y = e.clientY;\n    }, false );\n\n    document.addEventListener('mousedown', function(e) { \n        that.mouse.down = true;\n    }, false );\n\n    document.addEventListener('mouseup', function(e) { \n        that.mouse.down = false;\n    }, false );\n\n/*************************\n     Keyboard\n*************************/\n\n    var modifierKeys = ['Shift','Control']\n\n    /* Set up vars needed for input listening. */\n    this.keys = [];\n\n    document.body.addEventListener(\"keydown\", function (event) {\n        handleKeyEvent(event, \"keydown\");\n    });\n    document.body.addEventListener(\"keyup\", function (event) {\n        // Why is this here\n        if(event.keyCode == 32 && !activeElemIsTextBox()) {\n            wickEditor.useLastUsedTool();\n            wickEditor.canvas.updateCursor();\n            wickEditor.syncInterfaces();\n        }\n    });\n\n    var handleKeyEvent = function (event) {\n\n        if(event.key === 'Tab' && document.activeElement.nodeName !== \"INPUT\") event.preventDefault()\n\n        for(actionName in wickEditor.guiActionHandler.guiActions) {\n            var hotkeysMatch = true;\n            var action = wickEditor.guiActionHandler.guiActions[actionName];\n\n            if(action.hotkeys.length < 1 || action.hotkeys[0] !== event.code) hotkeysMatch=false;\n\n            if(action.modifierKey) {\n                if(!event.metaKey && !event.ctrlKey) hotkeysMatch=false;\n            } else {\n                if(event.metaKey || event.ctrlKey) hotkeysMatch=false;\n            }\n\n            if(action.shiftKey) {\n                if(!event.shiftKey) hotkeysMatch=false;\n            } else {\n                if(event.shiftKey) hotkeysMatch=false;\n            }\n\n            if(hotkeysMatch) {\n                var specialParamsMatch = true;\n\n                if(activeElemIsTextBox() && !action.requiredParams.usableInTextBoxes) specialParamsMatch=false;\n                if(document.activeElement.className === 'canvasTextEdit') specialParamsMatch=false;\n                if(action.requiredParams.disabledInScriptingIDE && (document.activeElement.className === 'ace_text-input')) specialParamsMatch=false;\n\n                if(specialParamsMatch) {\n                    wickEditor.rightclickmenu.open = false;\n\n                    event.preventDefault();\n                    action.doAction({});\n                }\n            }\n        }\n    };\n\n    // In order to ensure that the browser will fire clipboard events, we always need to have something selected\n    var focusHiddenArea = function () {\n        if($(\"#scriptingGUI\").css('visibility') === 'hidden') {\n            $(\"#hidden-input\").val(' ');\n            $(\"#hidden-input\").focus().select();\n        }\n    }\n\n    var activeElemIsTextBox = function () {\n        var activeElem = document.activeElement.nodeName;\n        editingTextBox = activeElem == 'TEXTAREA' || activeElem == 'INPUT';\n        return editingTextBox;\n    }\n\n/*************************\n    Copy/paste\n*************************/\n\n    // clipboard\n    //https://www.lucidchart.com/techblog/2014/12/02/definitive-guide-copying-pasting-javascript/\n    //http://jsfiddle.net/vtjnr6ea/\n    //var textToCopy = 'Lucidchart: Diagrams Done Right';\n    //var htmlToCopy = '<div hiddenContent=\"This is a great place to put whatever you want\">Lucidchart: Diagrams Done Right</div>';\n\n    var ieClipboardDiv = $('#ie-clipboard-contenteditable');\n    var hiddenInput = $(\"#hidden-input\");\n\n    var userInput = \"\";\n    var hiddenInputListener = function(text) {};\n\n    var focusHiddenArea = function() {\n        // In order to ensure that the browser will fire clipboard events, we always need to have something selected\n        //hiddenInput.val(' ');\n        //hiddenInput.focus().select();\n    };\n\n    // Focuses an element to be ready for copy/paste (used exclusively for IE)\n    var focusIeClipboardDiv = function() {\n        ieClipboardDiv.focus();\n        var range = document.createRange();\n        range.selectNodeContents((ieClipboardDiv.get(0)));\n        var selection = window.getSelection();\n        selection.removeAllRanges();\n        selection.addRange(range);\n    };\n\n    // For IE, we can get/set Text or URL just as we normally would, but to get HTML, we need to let the browser perform the copy or paste\n    // in a contenteditable div.\n    var ieClipboardEvent = function(clipboardEvent) {\n        var clipboardData = window.clipboardData;\n        if (clipboardEvent == 'cut' || clipboardEvent == 'copy') {\n            clipboardData.setData('Text', wickEditor.project.getCopyData(wickEditor.project.getSelectedObjects(WickObject)));\n            ieClipboardDiv.html(htmlToCopy);\n            focusIeClipboardDiv();\n            setTimeout(function() {\n                focusHiddenArea();\n                ieClipboardDiv.empty();\n            }, 0);\n        }\n        if (clipboardEvent == 'paste') {\n            var clipboardText = clipboardData.getData('Text');\n            ieClipboardDiv.empty();\n            setTimeout(function() {\n                //console.log('Clipboard Plain Text: ' + clipboardText);\n                //console.log('Clipboard HTML: ' + ieClipboardDiv.html());\n                ieClipboardDiv.empty();\n                focusHiddenArea();\n            }, 0);\n        }\n    };\n\n    // For every broswer except IE, we can easily get and set data on the clipboard\n    var standardClipboardEvent = function(clipboardEvent, event) {\n        wickEditor.guiActionHandler.keys = [];\n        wickEditor.guiActionHandler.specialKeys = [];\n        \n        var clipboardData = event.clipboardData;\n\n        if (clipboardEvent == 'cut' || clipboardEvent == 'copy') {\n            //clipboardData.setData('text/wickobjectsjson', wickEditor.project.getCopyData());\n            \n            var copyData = wickEditor.project.getCopyData();\n            var copyType;\n            if(wickEditor.project.getSelectedObjects()[0] instanceof WickObject) {\n                copyType = 'text/wickobjectsjson';\n            } else {\n                copyType = 'text/wickframesjson';\n            }\n            clipboardData.setData(copyType, copyData);\n\n            if(clipboardEvent == 'cut') {\n                wickEditor.guiActionHandler.doAction('deleteSelectedObjects');\n            }\n        }\n        if (clipboardEvent == 'paste') {\n            //console.log('Clipboard Plain Text: ' + clipboardData.getData('text/plain'));\n            //console.log('Clipboard HTML: ' + clipboardData.getData('text/html'));\n            wickEditor.guiActionHandler.doAction('paste', {clipboardData:clipboardData});\n        }\n    };\n\n    // For IE, the broswer will only paste HTML if a contenteditable div is selected before paste. Luckily, the browser fires \n    // a before paste event which lets us switch the focuse to the appropraite element\n    if (isIe) {\n        document.addEventListener('beforepaste', function() {\n            if (hiddenInput.is(':focus')) {\n                focusIeClipboardDiv();\n            }\n        }, true);\n    }\n\n    // We need the hidden input to constantly be selected in case there is a copy or paste event. It also recieves and dispatches input events\n    hiddenInput.on('input', function(e) {\n        var value = hiddenInput.val();\n        userInput += value;\n        hiddenInputListener(userInput);\n\n        // There is a bug (sometimes) with Safari and the input area can't be updated during\n        // the input event, so we update the input area after the event is done being processed\n        if (isSafari) {\n            hiddenInput.focus();\n            setTimeout(focusHiddenArea, 0);\n        } else {\n            focusHiddenArea();\n        }\n    });\n\n    var activeElemIsTextBox = function () {\n        var activeElem = document.activeElement.nodeName;\n        var editingTextBox = activeElem == 'TEXTAREA' || activeElem == 'INPUT';\n        return editingTextBox;\n    };\n\n    // Set clipboard event listeners on the document. \n    ['cut', 'copy', 'paste'].forEach(function(event) {\n        window.addEventListener(event, function(e) {\n            if (isIe) {\n                ieClipboardEvent(event);\n            } else {\n                if(activeElemIsTextBox()) return;\n                standardClipboardEvent(event, e);\n                focusHiddenArea();\n                e.preventDefault();\n                $('#editorCanvasContainer').focus().select();\n                //console.log(document.activeElement.nodeName)\n            }\n        });\n    });\n\n/*************************\n     Tooltips\n*************************/\n\n    setTimeout(function () {\n        $('.tooltipElem').on(\"mousemove\", function(e) {\n            document.getElementById('tooltipGUI').innerHTML = e.currentTarget.getAttribute('alt');\n            document.getElementById('tooltipGUI').style.display = 'block';\n            document.getElementById('tooltipGUI').style.opacity = 1.0;\n            var mouseX = wickEditor.inputHandler.mouse.x+10;\n            var mouseY = wickEditor.inputHandler.mouse.y+5;\n            var tooltipX = Math.min(mouseX, window.innerWidth  - $(\"#tooltipGUI\").width()  - 10)\n            var tooltopY = Math.min(mouseY, window.innerHeight - $(\"#tooltipGUI\").height() - 3);\n            $(\"#tooltipGUI\").css('top', tooltopY+'px');\n            $(\"#tooltipGUI\").css('left', tooltipX+'px');\n        });\n        $('.tooltipElem').on(\"mouseout\", function(e) {\n            document.getElementById('tooltipGUI').style.display = 'block';\n            document.getElementById('tooltipGUI').style.opacity = 0.0;\n        });\n    }, 1500);\n\n/*************************\n     File Import\n*************************/\n\n    var loadSVG = function (svg, filename, callback) {\n        var xmlString = svg\n          , parser = new DOMParser()\n          , doc = parser.parseFromString(xmlString, \"text/xml\");\n        var paperObj = paper.project.importSVG(doc, {insert:false});\n        \n        var allPaths = [];\n\n        function importPaperGroup (paperGroup) {\n            paperGroup.children.forEach(function (child) {\n                if(child instanceof paper.Group) {\n                    importPaperGroup(child);\n                } else {\n                    importPaperPath(child);\n                }\n            })\n        }\n        function importPaperPath (paperPath) {\n            var svgRaw = paperPath.exportSVG({asString:true})\n            var svgString = '<svg id=\"svg\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">'+svgRaw+'</svg>';\n            var wickPath = WickObject.createPathObject(svgString);\n            wickPath.x = paperPath.position.x;\n            wickPath.y = paperPath.position.y;\n            wickPath.width = paperPath.bounds._width;\n            wickPath.height = paperPath.bounds._height;\n            allPaths.push(wickPath);\n        }\n\n        if(paperObj instanceof paper.Group) {\n            importPaperGroup(paperObj);\n        } else {\n            importPaperPath(paperObj);\n        }\n\n        wickEditor.actionHandler.doAction('addObjects', {wickObjects:allPaths});\n    }\n    \n    var loadAnimatedGIF = function (dataURL, filename, callback) {\n        //console.log(dataURL)\n\n        var gifSymbol = WickObject.createNewSymbol(filename);\n        gifSymbol.layers[0].frames = [];\n\n        var newGifEl = document.createElement(\"img\");\n\n        newGifEl.onload = function () {\n            document.body.appendChild(newGifEl)\n            \n            var framesDataURLs;\n            var gifWidth;\n            var gifHeight;\n            var superGif = new SuperGif({ gif: newGifEl } );\n            superGif.load(function () {\n\n                gifWidth = superGif.get_canvas().width;\n                gifHeight = superGif.get_canvas().height;\n                framesDataURLs = superGif.getFrameDataURLs();\n                proceed();\n\n            });\n\n            var proceed = function () {\n\n                for(var i = 0; i < framesDataURLs.length; i++) {\n                    var asset = new WickAsset(framesDataURLs[i], 'image', filename+\"_frame_\"+i);\n                    var frameWickObj = new WickObject();\n                    frameWickObj.assetUUID = wickEditor.project.library.addAsset(asset);\n                    frameWickObj.width = gifWidth;\n                    frameWickObj.height = gifHeight;\n                    frameWickObj.isImage = true;\n                    frameWickObj.name = filename+\"_frame_\"+i;\n\n                    gifSymbol.layers[0].addFrame(new WickFrame());\n                    gifSymbol.layers[0].frames[i].playheadPosition = i;\n                    gifSymbol.layers[0].frames[i].wickObjects.push(frameWickObj);\n                }\n\n                gifSymbol.width = gifWidth;\n                gifSymbol.height = gifHeight;\n\n                callback(gifSymbol);\n            }\n        }\n\n        newGifEl.src = dataURL;\n    }\n\n    var loadImage = function (src, filename, callback) {\n        var asset = new WickAsset(src, 'image', filename);\n        var wickObj = new WickObject();\n        wickObj.assetUUID = wickEditor.project.library.addAsset(asset);\n        wickObj.isImage = true;\n        wickObj.name = filename;\n        callback(wickObj);\n    }\n\n    var loadAudio = function (src, filename, callback) {\n        // Firefox reads Ogg files as video/ogg which breaks howler. \n        // This forces howler to not think ogg files are videos in firefox.\n        if(src.includes('video/ogg')) {\n            src = src.replace('video/ogg', 'audio/ogg');\n        }\n\n        var asset = new WickAsset(src, 'audio', filename);\n        var assetUUID = wickEditor.project.library.addAsset(asset);\n        wickEditor.syncInterfaces();\n    }\n\n    var loadUncompressedAudio = function (src, filename, callback) {\n        var asset = new WickAsset(src, 'audio', filename, true);\n        var assetUUID = wickEditor.project.library.addAsset(asset);\n        wickEditor.syncInterfaces();\n    }\n\n    var loadPlaintext = function (text, filename, callback) {\n        loadJSON(text, filename, callback);\n    }\n\n    var loadWickFile = function (arrayBuffer, filename, callback) {\n        var byteArray = new Uint8Array(arrayBuffer);\n        var wickProjectJSON = LZString.decompressFromUint8Array(byteArray);\n        loadJSON(wickProjectJSON, filename, callback);\n    }\n\n    var loadJSON = function (json, filename, callback) {\n        var tempJsonObj = JSON.parse(json);\n        if(tempJsonObj.rootObject) {\n            var project = WickProject.fromJSON(json);\n            var filenameParts = filename.split('-');\n            var name = filenameParts[0];\n            if(name.includes('.json')) {\n                name = name.split('.json')[0];\n            }\n            if(name.includes('.wick')) {\n                name = name.split('.wick')[0];\n            }\n            project.name = name || 'New Project';\n            wickEditor.guiActionHandler.doAction('openProject', {project:project})\n        } else {\n            callback(WickObject.fromJSON(json));\n        }\n    }\n\n    var loadHTML = function (file) {\n        WickProject.fromFile(file, function(project) {\n            wickEditor.guiActionHandler.doAction('openProject', {project:project})\n        });\n    }\n\n    var loadZIP = function (file) {\n        WickProject.fromZIP(file, function(project) {\n            wickEditor.guiActionHandler.doAction('openProject', {project:project})\n        });\n    } \n\n    var loadJS = function (file) {\n        var fr = new FileReader();\n        fr.onloadend = function() {\n            var asset = new WickAsset(fr.result, 'script', file.name, true);\n            wickEditor.project.library.addAsset(asset);\n            wickEditor.syncInterfaces();\n        };\n        fr.readAsText(file); \n    } \n\n    var loadFileIntoWickObject = function (e,file,fileType) {\n\n        if(file.name.endsWith('.wick')) {\n            fileType = 'wickfile'\n        }\n\n        if(fileType === 'text/html') {\n            loadHTML(file)\n            return;\n        }\n\n        if(fileType === 'application/zip' || fileType === 'application/x-zip-compressed') {\n            loadZIP(file)\n            return;\n        }\n\n        if(fileType === 'text/javascript') {\n            loadJS(file);\n            return;\n        }\n\n        var fromContstructors = {\n            'image/png'        : loadImage,\n            'image/jpeg'       : loadImage,\n            'application/jpg'  : loadImage,\n            'image/bmp'        : loadImage,\n            'image/svg+xml'    : loadSVG,\n            'image/gif'        : loadAnimatedGIF,\n            'audio/mp3'        : loadAudio,\n            'audio/wav'        : loadUncompressedAudio,\n            'audio/wave'       : loadUncompressedAudio,\n            'audio/x-wav'      : loadUncompressedAudio,\n            'audio/x-pn-wav'   : loadUncompressedAudio,\n            'audio/ogg'        : loadAudio,\n            'video/ogg'        : loadAudio,\n            'application/ogg'  : loadAudio,\n            'audio/flac'       : loadAudio,\n            'audio/x-flac'     : loadAudio,\n            \"audio/x-m4a\"      : loadAudio,\n            'audio/mpeg'       : loadAudio,\n            \"application/json\" : loadJSON,\n            \"text/plain\"       : loadPlaintext,\n            \"wickfile\"         : loadWickFile,\n        }\n        \n        var fr = new FileReader();\n        fr.onloadend = function() {\n            if(!fromContstructors[fileType]) { \n                alert(\"Wick cannot import '\" + file.name + \"'\\n\\nWick does not support '\" + fileType + \"' files yet.\"); \n                console.error(fileType + \" has no constructor!\");\n                return;\n            }\n\n            fromContstructors[fileType](fr.result, file.name, function (newWickObject) {\n                var m\n                if(e && e.originalEvent && e.originalEvent.clientX) {\n                    m = wickEditor.canvas.screenToCanvasSpace(e.originalEvent.clientX, e.originalEvent.clientY);\n                } else {\n                    m = wickEditor.canvas.screenToCanvasSpace(window.innerWidth/2, window.innerHeight/2);\n                }\n                newWickObject.x = m.x;\n                newWickObject.y = m.y;\n                wickEditor.actionHandler.doAction('addObjects', {wickObjects:[newWickObject]});\n            })\n        };\n        if(fileType === \"application/json\" || fileType === \"image/svg+xml\" || fileType === \"text/plain\") { \n            fr.readAsText(file); \n        } else if (fileType === 'wickfile') {\n            fr.readAsArrayBuffer(file);\n        } else {\n            fr.readAsDataURL(file);\n        }\n    }\n\n/*************************\n     Drag-to-upload\n*************************/\n    \n    var dropMessageDiv = document.getElementById('dropFileMessage');\n    dropMessageDiv.addEventListener('mousemove', function (e) {\n        dropMessageDiv.style.display = 'none';\n    })\n    $(\"#editor\").on('dragover', function(e) {\n        dropMessageDiv.style.display = 'block';\n        return false;\n    });\n    $(\"#editor\").on('dragleave', function(e) {\n        //dropMessageDiv.style.display = 'none';\n        return false;\n    });\n    $(\"#editor\").on('drop', function(e) {\n\n        dropMessageDiv.style.display = 'none';\n\n        // prevent browser from opening the file\n        e.stopPropagation();\n        e.preventDefault();\n\n        var files = e.originalEvent.dataTransfer.files;\n\n        // Retrieve uploaded files data\n        for (var i = 0; i < files.length; i++) {\n\n            var file = files[i];\n            var fileType = file.type;\n\n            if(fileType === '') {\n                var parts = file.name.split('.');\n                ext = parts[parts.length-1];\n                if(ext === 'json') fileType = 'application/json';\n            }\n\n            loadFileIntoWickObject(e,file,fileType);\n\n        }\n\n        return false;\n    });\n\n/*************************\n     Import Files\n*************************/\n\n    function importFile (e) {\n        var filePath = document.getElementById(\"importButton\");\n        if(filePath.files && filePath.files[0]) {\n            var reader = new FileReader();\n            var file = filePath.files[0];\n            var fileType = file.type;\n\n            loadFileIntoWickObject(null,file,fileType);\n        }\n\n        $(\"#importButton\").replaceWith($(\"<input>\", {id : \"importButton\", type: \"file\", \"class\": \"hidden\"}));\n        document.getElementById('importButton').onchange = importFile;\n    }\n\n    document.getElementById('importButton').onchange = importFile;\n\n/*************************\n    Leave page warning\n*************************/\n\n    window.onbeforeunload = function(event) {\n        if(wickEditor.actionHandler.getHistoryLength() === 0) return;\n        \n        var confirmationMessage = 'Warning: All unsaved changes will be lost!';\n        (event || window.event).returnValue = confirmationMessage; //Gecko + IE\n        return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.\n    };\n\n}\n"
  },
  {
    "path": "src/editor/WickEditor.Settings.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n    \nvar WickEditorSettings = function () {\n\n    if(localStorage.wickEditorSettings) {\n\n        this.load();\n\n    } else {\n\n        this.setDefaults();\n        this.save();\n\n    }\n\n}\n\nWickEditorSettings.prototype.getDefaults = function () {\n    return {\n        brushThickness : 5,\n        brushSmoothing : 0,\n        pencilSmoothing : 1,\n        strokeWidth : 5,\n        strokeColor : \"#000000\",\n        fillColor : \"#9999FF\",\n        rectangleCornerRadius : 0,\n        strokeCap : 'round',\n        strokeJoin : 'round',\n        scriptingIDEHeight: 300,\n    }\n}\n\nWickEditorSettings.prototype.setDefaults = function () {\n\n    var defaults = this.getDefaults();\n    for(key in defaults) {\n        this[key] = defaults[key];\n    }\n\n    this.save();\n\n}\n\nWickEditorSettings.prototype.setValue = function (key, val) {\n\n    this[key] = val;\n    this.save();\n\n}\n\nWickEditorSettings.prototype.save = function () {\n\n    localStorage.wickEditorSettings = JSON.stringify(this);\n\n};\n\nWickEditorSettings.prototype.load = function () {\n\n    var savedSettings = JSON.parse(localStorage.wickEditorSettings);\n\n    for (key in savedSettings) {\n        this[key] = savedSettings[key];\n    }\n\n    var defaults = this.getDefaults();\n    for(key in defaults) {\n        if(this[key] === undefined) {\n            this[key] = defaults[key];\n        }\n    }\n\n}\n\n"
  },
  {
    "path": "src/editor/WickEditor.WickActionHandler.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\n/* WickActionHandler - General Logic for how undo and redo is handled in the Wick editor. */\n/* Only add routines to WickActionHandler if they:\n     (1) Change the state of the project and\n     (2) Can be undone/redone */\n\nvar WickActionHandler = function (wickEditor) {\n\n    var self = this;\n\n// Class definitions\n\n    /* Class to define WickActions */\n    var WickAction = function (name, doFn, undoFn) {\n\n        this.name = name;\n\n        /* To be called when an action is committed by the user. */\n        this.doFn = doFn;\n\n        /* To be called when this the user undoes this action. This should revert\n           the state of the wickEditor or wickObject back to its original state. */\n        this.undoFn = undoFn;\n\n    }\n\n    /* Class to store data of actions done, stored in the undo/redo stacks */\n    var StackAction = function (name, args) {\n        /* name is used as a key to the dict of action definitions */\n        this.name = name;\n\n        /* 'args' is used to pass any data that the action needs.\n           'args' also saves anything that the undo will use later,\n           For example, to undo a delete we need to bring back that deleted object...\n           In this case the object that gets deleted gets stored in args! */\n        this.args = args;\n\n        this.doAction = function () {\n            //console.log(\"StackAction: do \" + this.name);\n            actions[this.name].doFn(this.args);\n        }\n\n        this.undoAction = function () {\n            //console.log(\"StackAction: undo \" + this.name);\n            actions[this.name].undoFn(this.args);\n        }\n    }\n\n// Private vars\n\n    // Actions dict, stores action definitions\n    var actions = {};\n\n    // Undo/redo action stacks\n    var undoStack = [];\n    var redoStack = [];\n\n    /* Call this to define a new action! */\n    var registerAction = function(name, doFunction, undoFunction) {\n        actions[name] = new WickAction(name, doFunction, undoFunction);\n    }\n\n    // done function, call when a WickAction is finished\n    function done (args) {\n        // Sync interfaces + do other post-action cleanup\n        wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n        if(args && args.dontAddToStack) return;\n        wickEditor.project.unsaved = true;\n        wickEditor.project.rootObject.regenerateAssetLinkedSymbols();\n        wickEditor.project.rootObject.generateParentObjectReferences();\n        wickEditor.project.regenAssetReferences();\n        if(!args || !args.dontSync) wickEditor.syncInterfaces();\n        if(args) args.dontSync = null;\n    }\n\n    // scrap function, call if you need to cancel an action for some reason\n    function scrap (dontUndo) {\n        actionBeingDone = false;\n\n        if(!dontUndo) {\n            self.undoAction();\n        }\n        redoStack.pop();\n\n        done();\n    }\n\n// API\n\n    this.doAction = function (actionName, args) {\n        if(!args) args = {};\n\n        // Check for invalid action\n        if(!actions[actionName]) {\n            console.error(actionName + \" is not a defined WickAction!\");\n            return;\n        }\n\n        // Put the action on the undo stack to be undone later\n        var newAction = new StackAction(actionName, args);\n\n        newAction._selectionAtState = wickEditor.project.getSelectedObjectsUUIDs();\n        if(!args.dontAddToStack) undoStack.push(newAction);\n        newAction.doAction();\n\n        redoStack = [];\n\n        return newAction;\n\n    }\n\n    this.undoAction = function () {\n\n        // Nothing to undo!\n        if (undoStack.length == 0) {\n            console.log(\"undoAction(): No actions on the undo stack.\");\n            return;\n        }\n\n        // Get last action on the undo stack\n        var action = undoStack.pop();\n\n        wickEditor.project.clearSelection();\n        action._selectionAtState.forEach(function (uuid) {\n            wickEditor.project.selectObjectByUUID(uuid);\n        })\n\n        // Do the action and put it on the redo stack to be redone later\n        action.undoAction();\n        redoStack.push(action);\n        \n    }\n\n    this.redoAction = function () {\n\n        // Nothing to redo!\n        if (redoStack.length == 0) {\n            console.log(\"redoAction(): No actions on the redo stack.\");\n            return;\n        }\n\n        // Get last action on the redo stack\n        var action = redoStack.pop();\n\n        // Do the action and put it back onto the undo stack\n        action.doAction();\n        undoStack.push(action);\n\n    }\n\n    this.clearHistory = function () {\n        undoStack = [];\n        redoStack = [];\n    }\n\n    this.printHistory =  function () {\n        console.log(undoStack)\n    }\n\n    this.getHistoryLength =  function () {\n        return undoStack.length\n    }\n\n// Register all actions\n\n    registerAction('addObjects',\n        function (args) {\n            wickEditor.project.clearSelection();\n\n            // Make a new frame if one doesn't exist at the playhead position\n            var currentFrame = wickEditor.project.getCurrentFrame();\n            if(!currentFrame) {\n                args.addFrameAction = wickEditor.actionHandler.doAction('addNewFrame', {\n                    dontAddToStack: true\n                });\n            } else {\n                if(currentFrame.tweens.length > 0) {\n                    args.addLayerAction = wickEditor.actionHandler.doAction('addNewLayer', {\n                        dontAddToStack: true\n                    });\n                    wickEditor.project.rootObject.generateParentObjectReferences()\n                    args.addFrameAction = wickEditor.actionHandler.doAction('addNewFrame', {\n                        dontAddToStack: true\n                    });\n                }\n            }\n            \n            // Save references to added wick objects so they can be removed on undo\n            if(args.addedObjects) {\n                args.addedObjects.forEach(function (wickObj) {\n                    wickEditor.project.addObject(wickObj, args.sendToBack ? 0 : null, true);\n                });\n            } else {\n                args.addedObjects = [];\n                args.wickObjects.forEach(function (wickObj) {\n                    args.addedObjects.push(wickObj);\n                });\n\n                // Add all the new wick objects\n                args.wickObjects.forEach(function (wickObj) {\n                    wickEditor.project.addObject(wickObj, args.sendToBack ? 0 : null);\n                    if(!args.dontSelectObjects) wickEditor.project.selectObject(wickObj)\n                });\n            }\n            \n            done(args);\n        },\n        function (args) {\n            // Remove objects we added\n            args.wickObjects.forEach(function (wickObject) {\n                wickEditor.project.currentObject.removeChild(wickObject);\n            });\n\n            if(args.addFrameAction) args.addFrameAction.undoAction();\n            if(args.addLayerAction) args.addLayerAction.undoAction();\n\n            done(args);\n        });\n\n    registerAction('deleteObjects',\n        function (args) {\n            args.restoredObjects = [];\n            args.oldZIndices = [];\n\n            // Store the old z index vars for each object.\n            // Must do this before removing them all.\n            args.objects.forEach(function (object) {\n                if(object instanceof WickObject) {\n                    var zIndex = wickEditor.project.getCurrentFrame().wickObjects.indexOf(object);\n                    args.oldZIndices.push(zIndex);\n                }\n            });\n\n            // Now remove them\n            args.objects.forEach(function (object) {\n                args.restoredObjects.push(object);\n                wickEditor.project.currentObject.removeChild(object);\n            });\n\n            // Clear selection after deletion.\n            wickEditor.project.clearSelection()\n            done(args);\n        },\n        function (args) {\n            for(var i = 0; i < args.restoredObjects.length; i++) {\n                wickEditor.project.addObject(args.restoredObjects[i], args.oldZIndices[i], true, args.restoredObjects[i].parentFrame);\n            }\n\n            done(args);\n        });\n\n    registerAction('deleteFrames',\n        function (args) {\n            args.restoredFrames = [];\n            args.frames.forEach(function (frame) {\n                args.restoredFrames.push(frame);\n                frame.parentLayer.removeFrame(frame);\n            });\n\n            wickEditor.project.getCurrentObject().framesDirty = true;\n            wickEditor.project.clearSelection()\n            done(args);\n        },\n        function (args) {\n            for(var i = 0; i < args.restoredFrames.length; i++) {\n                var frame = args.restoredFrames[i];\n                frame.parentLayer.addFrame(frame);\n            }\n\n            wickEditor.project.getCurrentObject().framesDirty = true;\n            done(args);\n        });\n\n    var modifyableAttributes = [\"x\",\"y\",\"scaleX\",\"scaleY\",\"rotation\",\"opacity\",\"flipX\",\"flipY\",\"pathData\",\"svgX\",\"svgY\",\"width\",\"height\",\"volume\", \"loop\"];\n\n    registerAction('modifyObjects',\n        function (args) {\n            \n            args.originalStates = [];\n\n            for(var i = 0; i < args.objs.length; i++) {\n                var wickObj = args.objs[i];\n\n                args.originalStates[i] = {};\n                modifyableAttributes.forEach(function(attrib) {\n                    args.originalStates[i][attrib] = deepCopy(wickObj[attrib]);\n                });\n\n                modifyableAttributes.forEach(function(attrib) {\n                    if(args.modifiedStates[i][attrib] !== undefined) {\n                        wickObj[attrib] = deepCopy(args.modifiedStates[i][attrib]);\n                    }\n                });\n\n                if(wickObj.pathData && args.modifiedStates[i]['pathData']) {\n                    wickObj._renderDirty = true;\n                }\n\n                var frame = wickObj.parentFrame;\n                if(frame && frame.tweens.length > 0) {\n                    if(!frame.getTweenAtFrame(wickObj.parentObject.playheadPosition)) {\n                        args.createTweenAction = wickEditor.actionHandler.doAction('createMotionTween', { \n                            dontAddToStack: true,\n                            frame: frame,\n                            playheadPosition: wickEditor.project.getCurrentObject().playheadPosition-frame.playheadPosition,\n                        });\n                    }\n                }\n\n                if(wickObj.updateFrameTween) wickObj.updateFrameTween();\n            };\n\n            var source = wickObj.getSourceInside();\n            if(source) {\n                var asset = wickEditor.project.library.getAsset(source.assetUUID);\n                asset.data = source.getAsJSON();\n            }\n\n            done(args);\n        },\n        function (args) {\n            for(var i = 0; i < args.objs.length; i++) {\n                var wickObj = args.objs[i];\n\n                if(args.createTweenAction) args.createTweenAction.undoAction();\n\n                // Revert the object's state to it's original pre-transformation state\n                modifyableAttributes.forEach(function(attrib) {\n                    if(args.originalStates[i][attrib] !== undefined) {\n                        wickObj[attrib] = deepCopy(args.originalStates[i][attrib]);\n                    }\n                });\n\n                if(wickObj.pathData) {\n                    wickObj._renderDirty = true;\n                }\n                \n                wickObj.updateFrameTween();\n            }\n\n            done(args);\n        });\n\n    registerAction('convertObjectsToSymbol',\n        function (args) {\n            var objects = args.objects.concat([]);//make sure we dont modify the original array\n\n            objects.forEach(function(obj) {\n                obj._tempZIndex = wickEditor.project.getCurrentFrame().wickObjects.indexOf(obj);\n            })\n            objects.sort(function (a,b) {\n                return a._tempZIndex - b._tempZIndex;\n            });\n\n            // Create symbol out of objects\n            objects.forEach(function (obj) {\n                obj.uuid = random.uuid4();\n            })\n\n            var symbol = new WickObject.createSymbolFromWickObjects(objects);\n            args.createdSymbol = symbol;\n\n            symbol.name = args.symbolName;\n            if(args.button) {\n                //symbol.layers[0].frames.push(symbol.layers[0].frames[0].copy());\n                //symbol.layers[0].frames.push(symbol.layers[0].frames[0].copy());\n\n                /*symbol.layers[0].frames[0].name = 'mouseReleased';\n                symbol.layers[0].frames[0].playheadPosition = 0;\n                symbol.layers[0].frames[1].name = 'mouseHover';\n                symbol.layers[0].frames[1].playheadPosition = 1;\n                symbol.layers[0].frames[2].name = 'mousePressed';\n                symbol.layers[0].frames[2].playheadPosition = 2;*/\n                symbol.name = 'New Button'\n\n                symbol.isButton = true;\n            } else if(args.group) {\n                symbol.isGroup = true;\n                symbol.layers[0].frames[0].wickScript = 'stop();';\n                symbol.name = 'New Group'\n            } else {\n                symbol.name = 'New Clip'\n            }\n\n            // Remove objects from original parent (they are inside the symbol now.)\n            objects.forEach(function (wickObject) {\n                wickEditor.project.currentObject.removeChild(wickObject);\n            });\n            wickEditor.project.addObject(symbol, undefined, true);\n\n            wickEditor.project.clearSelection()\n            wickEditor.project.selectObject(symbol)\n\n            done(args);\n        },\n        function (args) {\n            var children = args.createdSymbol.getObjectsOnFirstFrame();\n            children.forEach(function (child) {\n                child.x += child.parentObject.x;\n                child.y += child.parentObject.y;\n                child.uuid = random.uuid4();\n                wickEditor.project.addObject(child, null, true);\n            });\n\n            wickEditor.project.currentObject.removeChild(args.createdSymbol);\n\n            done(args);\n        });\n\n    registerAction('breakApartSymbol',\n        function (args) {\n            args.symbol = args.obj;\n\n            args.children = args.symbol.getObjectsOnFirstFrame();\n            args.children.forEach(function (child) {\n                args.origOffsetX = child.parentObject.x;\n                args.origOffsetY = child.parentObject.y;\n                child.x += child.parentObject.x;\n                child.y += child.parentObject.y;\n                wickEditor.project.addObject(child, null, true);\n            });\n\n            wickEditor.project.currentObject.removeChild(args.obj);\n\n            done(args);\n        },\n        function (args) {\n            args.children.forEach(function (child) {\n                child.x -= args.origOffsetX;\n                child.y -= args.origOffsetY;\n                wickEditor.project.currentObject.removeChild(child);\n            });\n\n            wickEditor.project.addObject(args.symbol);\n\n            done(args);\n        });\n\n    registerAction('addFrame',\n        function (args) {\n            var currentObject = wickEditor.project.currentObject;\n\n            if (args.layer.getFrameAtPlayheadPosition(args.frame.playheadPosition)) {\n                scrap(true); return;\n            }\n\n            // Add frame\n            args.layer.addFrame(args.frame);\n            wickEditor.project.clearSelection();\n            wickEditor.project.selectObject(args.frame);\n\n            // Move to that new frame\n            args.movePlayheadAction = wickEditor.actionHandler.doAction('movePlayhead', {\n                obj:currentObject,\n                newPlayheadPosition:args.frame.playheadPosition,\n                newLayer:args.layer,\n                dontAddToStack: true\n            });\n\n            currentObject.framesDirty = true;\n\n            done(args);\n        },\n        function (args) {\n            var currentObject = wickEditor.project.currentObject;\n            args.layer.removeFrame(args.frame);\n\n            if(args.movePlayheadAction) args.movePlayheadAction.undoAction();\n\n            currentObject.framesDirty = true;\n\n            done(args);\n        });\n\n    registerAction('addFrames',\n        function (args) {\n            var currentObject = wickEditor.project.getCurrentObject();\n            var currentLayer = currentObject.getCurrentLayer();\n\n            wickEditor.project.clearSelection();\n            args.frames.forEach(function (frame) {\n                frame.playheadPosition = currentLayer.getNextOpenPlayheadPosition(frame.playheadPosition);\n                currentLayer.addFrame(frame);\n                wickEditor.project.selectObject(frame);\n            });\n\n            currentObject.framesDirty = true;\n            wickEditor.project.rootObject.generateParentObjectReferences();\n\n            done(args);\n        },\n        function (args) {\n            var currentObject = wickEditor.project.getCurrentObject();\n            var currentLayer = currentObject.getCurrentLayer();\n            \n            args.frames.forEach(function (frame) {\n                currentLayer.removeFrame(frame);\n            });\n\n            currentObject.framesDirty = true;\n        })\n\n    registerAction('addNewFrame',\n        function (args) {\n            var currentObject = wickEditor.project.currentObject;\n\n            // Add an empty frame\n            var newFrame = new WickFrame();\n            newFrame.playheadPosition = wickEditor.project.getCurrentObject().playheadPosition\n            currentObject.getCurrentLayer().addFrame(newFrame);\n\n            currentObject.framesDirty = true;\n\n            done(args);\n        },\n        function (args) {\n            var currentObject = wickEditor.project.currentObject;\n            currentObject.getCurrentLayer().frames.pop();\n\n            currentObject.framesDirty = true;\n\n            done(args);\n        });\n\n    registerAction('addNewLayer',\n        function (args) {\n            var currentObject = wickEditor.project.currentObject;\n\n            // Add an empty frame\n            var newLayer = new WickLayer();\n            newLayer.frames = []; // Make sure the layer has no frames \n\n            currentObject.addLayer(newLayer);\n\n            // Go to last added layer\n            currentObject.currentLayer = currentObject.layers.length-1;\n\n            currentObject.framesDirty = true;\n\n            done(args);\n        },\n        function (args) {\n            var currentObject = wickEditor.project.currentObject;\n\n            // Remove last layer added\n            currentObject.layers.pop();\n\n            // Go to last added layer\n            currentObject.currentLayer = currentObject.layers.length-1;\n\n            currentObject.framesDirty = true;\n\n            done(args);\n        });\n\n    registerAction('removeLayer',\n        function (args) {\n            var currentObject = wickEditor.project.currentObject;\n            if(currentObject.layers.length > 1) {\n                args.removedLayer = args.layer;\n                args.removedLayerPosition = currentObject.layers.indexOf(args.removedLayer);\n                currentObject.removeLayer(args.removedLayer);\n                currentObject.currentLayer = currentObject.layers.length-1;\n            }\n\n            currentObject.framesDirty = true;\n\n            done(args);\n        },\n        function (args) {\n            if(args.removedLayer) {\n                var currentObject = wickEditor.project.currentObject;\n                //currentObject.addLayer(args.removedLayer);\n                currentObject.layers.splice(args.removedLayerPosition, 0, args.removedLayer);\n            }\n\n            currentObject.framesDirty = true;\n\n            done(args);\n        });\n\n    registerAction('moveLayer',\n        function (args) {\n            args.oldIndex = wickEditor.project.currentObject.layers.indexOf(args.layer);\n            wickEditor.project.currentObject.layers.move(args.oldIndex, args.newIndex);\n            wickEditor.project.currentObject.currentLayer = args.newIndex;\n\n            wickEditor.project.currentObject.framesDirty = true;\n\n            done(args);\n        },\n        function (args) {\n            wickEditor.project.currentObject.layers.move(args.newIndex, args.oldIndex);\n            wickEditor.project.currentObject.currentLayer = args.oldIndex;\n\n            wickEditor.project.currentObject.framesDirty = true;\n\n            done(args);\n        });\n\n    registerAction('moveFrame',\n        function (args) {\n            args.oldPlayheadPosition = args.frame.playheadPosition;\n            args.oldLayer = args.frame.parentLayer;\n\n            args.frame.playheadPosition = args.newPlayheadPosition;\n            args.oldLayer.removeFrame(args.frame);\n            args.newLayer.addFrame(args.frame);\n\n            wickEditor.project.currentObject.framesDirty = true;\n            done(args);\n        },\n        function (args) {\n            args.frame.playheadPosition = args.oldPlayheadPosition;\n\n            args.newLayer.removeFrame(args.frame);\n            args.oldLayer.addFrame(args.frame);\n\n            wickEditor.project.currentObject.framesDirty = true;\n            done(args);\n        });\n\n    registerAction('moveFrames', \n        function (args) {\n            var fixNegativeOffset = 0;\n            for (var i = 0; i < args.framesMoveActionData.length; i++) {\n                var frameMoveData = args.framesMoveActionData[i]\n                if(frameMoveData.newPlayheadPosition < 0) {\n                    fixNegativeOffset = -Math.min(fixNegativeOffset, frameMoveData.newPlayheadPosition)\n                }\n            }\n\n            var newPlayheadPosition = 0;\n            var newLayer = wickEditor.project.getCurrentLayer();\n\n            args.moveFrameActions = [];\n            for (var i = 0; i < args.framesMoveActionData.length; i++) {\n                var frameMoveData = args.framesMoveActionData[i]\n                newPlayheadPosition = frameMoveData.newPlayheadPosition+fixNegativeOffset;\n                newLayer = frameMoveData.newLayer;\n                args.moveFrameActions.push(wickEditor.actionHandler.doAction('moveFrame', {\n                    frame: frameMoveData.frame, \n                    newPlayheadPosition: newPlayheadPosition,\n                    newLayer: newLayer,\n                    dontAddToStack: true\n                }));\n            }\n\n            for (var i = 0; i < args.framesMoveActionData.length; i++) {\n                var currFrame = args.framesMoveActionData[i].frame\n                var touching = false;\n                args.framesMoveActionData[i].newLayer.frames.forEach(function (frame) {\n                    if(frame!==currFrame && frame.touchesFrame(currFrame)) {\n                        touching = true;\n                    }\n                    if(frame.playheadPosition < 0) {\n                        touching = true;\n                    }\n                });\n                if(touching) {\n                    scrap();\n                }\n            }\n\n            args.movePlayheadAction = wickEditor.actionHandler.doAction('movePlayhead', {\n                obj: wickEditor.project.getCurrentObject(),\n                newPlayheadPosition: newPlayheadPosition,\n                newLayer: frameMoveData.newLayer,\n                dontAddToStack: true\n            });\n\n            wickEditor.project.currentObject.framesDirty = true;\n            done(args);\n        },\n        function (args) {\n            args.moveFrameActions.forEach(function (moveFrameAction) {\n                moveFrameAction.undoAction();\n            })\n\n            if(args.movePlayheadAction) args.movePlayheadAction.undoAction();\n\n            wickEditor.project.currentObject.framesDirty = true;\n            done(args);\n        });\n\n    registerAction('changeFrameLength',\n        function (args) {\n            args.oldFrameLength = args.frame.length;\n            args.frame.length = Math.max(1, args.newFrameLength);\n\n            var touching = false;\n            args.frame.parentLayer.frames.forEach(function (frame) {\n                if(frame!==args.frame && frame.touchesFrame(args.frame)) {\n                    var overlap = frame.getFramesDistance(args.frame).distB;\n                    args.frame.length -= overlap;\n                }\n            });\n\n            wickEditor.project.currentObject.framesDirty = true;\n            done(args);\n        },\n        function (args) {\n            args.frame.length = args.oldFrameLength;\n            wickEditor.project.currentObject.framesDirty = true;\n            done(args);\n        });\n\n    registerAction('movePlayhead',\n        function (args) {\n            wickEditor.project.deselectObjectType(WickObject);\n            \n            args.newPlayheadPosition = Math.max(0, args.newPlayheadPosition)\n            \n            var currentObject = wickEditor.project.currentObject;\n\n            args.oldPlayheadPosition = args.obj.playheadPosition;\n            args.oldLayer = args.obj.currentLayer;\n\n            if(args.newPlayheadPosition !== undefined) {\n                var oldFrame = wickEditor.project.getCurrentFrame();\n                args.obj.playheadPosition = args.newPlayheadPosition;\n                var newFrame = wickEditor.project.getCurrentFrame();\n            }\n\n            if(args.newLayer) {\n                args.obj.currentLayer = args.obj.layers.indexOf(args.newLayer)\n            }\n\n            done(args);\n            \n        },\n        function (args) {\n            args.obj.playheadPosition = args.oldPlayheadPosition;\n            args.obj.currentLayer = args.oldLayer;\n\n            done(args);\n        });\n\n    registerAction('editObject',\n        function (args) {\n            wickEditor.project.clearSelection();\n\n            //wickEditor.project.currentObject.playheadPosition = 0;\n\n            // Set the editor to be editing this object at its first frame\n            args.prevEditedObject = wickEditor.project.currentObject;\n            wickEditor.project.currentObject = args.objectToEdit;\n\n            wickEditor.timeline.resetScrollbars();\n\n            done(args);\n        },\n        function (args) {\n            wickEditor.project.clearSelection();\n            wickEditor.project.currentObject = args.prevEditedObject;\n\n            wickEditor.timeline.resetScrollbars();\n\n            done(args);\n        });\n\n    registerAction('finishEditingCurrentObject',\n        function (args) {\n            wickEditor.project.clearSelection();\n            wickEditor.project.currentObject.playheadPosition = 0;\n            args.prevEditedObject = wickEditor.project.currentObject;\n            wickEditor.project.currentObject = wickEditor.project.currentObject.parentObject;\n\n            wickEditor.timeline.resetScrollbars();\n\n            done(args);\n        },\n        function (args) {\n            wickEditor.project.clearSelection();\n            wickEditor.project.currentObject = args.prevEditedObject;\n\n            wickEditor.timeline.resetScrollbars();\n\n            done(args);\n        });\n\n    registerAction('moveObjectToZIndex',\n        function (args) {\n            var currFrame = args.objs[0].parentFrame;\n\n            args.oldZIndexes = [];\n            args.objs.forEach(function (obj) {\n                args.oldZIndexes.push(currFrame.wickObjects.indexOf(obj));\n            });\n\n            args.objs.sort(function (a,b) {\n                if(args.newZIndex === 0)\n                    return currFrame.wickObjects.indexOf(a) < currFrame.wickObjects.indexOf(b);\n                else \n                    return currFrame.wickObjects.indexOf(a) > currFrame.wickObjects.indexOf(b);\n            });\n\n            args.objs.forEach(function (obj) {\n                var oldIndex = currFrame.wickObjects.indexOf(obj);\n                currFrame.wickObjects.move(oldIndex, args.newZIndex);\n            });\n\n            done(args);\n        },\n        function (args) {\n            var currFrame = wickEditor.project.getCurrentFrame();\n\n            args.objs.sort(function (a,b) {\n                if(args.newZIndex === 0)\n                    return currFrame.wickObjects.indexOf(a) < currFrame.wickObjects.indexOf(b);\n                else \n                    return currFrame.wickObjects.indexOf(a) > currFrame.wickObjects.indexOf(b);\n            });\n\n            args.objs.forEach(function (obj) {\n                var oldIndex = currFrame.wickObjects.indexOf(obj);\n                var newIndex = args.oldZIndexes[args.objs.indexOf(obj)];\n                currFrame.wickObjects.move(oldIndex, newIndex);\n            });\n\n            done(args);\n        });\n\n    registerAction('moveObjectForwards',\n        function (args) {\n            var newZIndex = 0;\n            args.objs.forEach(function (obj) {\n                var z = obj.getZIndex();\n                if(z+1 > newZIndex) {\n                    newZIndex = z+1;\n                }\n            });\n\n            var len = args.objs[0].parentFrame.wickObjects.length-1;\n            if(newZIndex >= len) newZIndex = len;\n\n            args.moveAction = wickEditor.actionHandler.doAction('moveObjectToZIndex', {\n                objs: args.objs,\n                newZIndex: newZIndex,\n                dontAddToStack: true\n            });\n\n            done(args);\n        },\n        function (args) {\n            args.moveAction.undoAction();\n\n            done(args);\n        });\n\n    registerAction('moveObjectBackwards',\n        function (args) {\n            var newZIndex = args.objs[0].parentFrame.wickObjects.length-1;\n            args.objs.forEach(function (obj) {\n                var z = obj.getZIndex();\n                if(z-1 < newZIndex) {\n                    newZIndex = z-1;\n                }\n            });\n\n            if(newZIndex < 0) newZIndex = 0;\n\n            args.moveAction = wickEditor.actionHandler.doAction('moveObjectToZIndex', {\n                objs: args.objs,\n                newZIndex: newZIndex,\n                dontAddToStack: true\n            });\n\n            done(args);\n        },\n        function (args) {\n            args.moveAction.undoAction();\n\n            done(args);\n        });\n\n    registerAction('deleteAsset', \n        function (args) {\n            var asset = args.asset;\n            args.recoverAsset = args.asset;\n\n            var objectsWithAsset = [];\n            wickEditor.project.getAllObjects().forEach(function (wickObject) {\n                if(wickObject.assetUUID === asset.uuid) {\n                    objectsWithAsset.push(wickObject);\n                }\n            })\n            wickEditor.project.getAllFrames().forEach(function (wickFrame) {\n                if(wickFrame.audioAssetUUID === asset.uuid) {\n                    wickFrame.audioAssetUUID = null;\n                }\n            })\n\n            args.deleteAction = wickEditor.actionHandler.doAction('deleteObjects', {\n                objects: objectsWithAsset,\n                dontAddToStack: true\n            });\n\n            wickEditor.project.library.deleteAsset(asset.uuid);\n\n            done(args);\n        },\n        function (args) {\n            wickEditor.project.library.addAsset(args.recoverAsset);\n\n            args.deleteAction.undoAction();\n\n            done(args);\n        });\n\n    registerAction('renameAsset', \n        function (args) {\n            var asset = args.asset;\n            \n            args.oldName =  args.asset.filename;\n            args.asset.filename = args.newFilename; \n\n            done(args);\n        },\n        function (args) {\n            args.asset.filename = args.oldName;\n\n            done(args);\n        });\n\n    registerAction('addSoundToFrame', \n        function (args) {\n            args.oldAudioAssetUUID = args.frame.audioAssetUUID;\n            args.oldFrameLength = args.frame.length;\n\n            args.frame.audioAssetUUID = args.asset.uuid;\n            args.frame.volume = 1; \n            args.frame._soundDataForPreview = null;\n            wickEditor.audioPlayer.clearCacheForFrame(args.frame)\n\n            var frameLengthInSeconds = wickEditor.audioPlayer.getDurationOfSound(args.asset.uuid)\n            var frameLengthInFrames = Math.ceil(frameLengthInSeconds*wickEditor.project.framerate);\n            \n            args.changeLengthAction = wickEditor.actionHandler.doAction('changeFrameLength', {\n                frame: args.frame, \n                newFrameLength: frameLengthInFrames,\n                dontAddToStack: true,\n            });\n\n            wickEditor.project.getCurrentObject().framesDirty = true;\n            done(args);\n        },\n        function (args) {\n            args.frame.audioAssetUUID = args.oldAudioAssetUUID;\n            args.frame.length = args.oldFrameLength;\n\n            wickEditor.project.getCurrentObject().framesDirty = true;\n            done(args);\n        });\n\n    registerAction('createMotionTween', \n        function (args) {\n            var frame = args.frame;\n\n            if(frame.wickObjects.length > 1 || frame.wickObjects[0].isPath) {\n                args.createClipAction = wickEditor.actionHandler.doAction('convertObjectsToSymbol', {\n                    objects: frame.wickObjects,\n                    dontAddToStack: true,\n                    group: true,\n                    symbolName: 'Tweened Objects'\n                });\n            }\n            \n            var wickObj = frame.wickObjects[0];\n            var tween = WickTween.fromWickObjectState(wickObj);\n            tween.playheadPosition = args.playheadPosition;\n\n            frame.addTween(tween);\n            args.addedTween = tween;\n            wickEditor.project.getCurrentObject().framesDirty = true;\n\n            done(args);\n        },\n        function (args) {\n            var frame = args.frame;\n            frame.removeTween(args.addedTween);\n            wickEditor.project.getCurrentObject().framesDirty = true;\n\n            if(args.createClipAction) args.createClipAction.undoAction();\n\n            done(args);\n        });\n\n    registerAction('addKeyframe',\n        function (args) {\n            args.frame.addTween(args.tween);\n\n            wickEditor.project.getCurrentObject().framesDirty = true;\n            done(args);\n        },\n        function (args) {\n            args.frame.removeTween(args.tween);\n\n            wickEditor.project.getCurrentObject().framesDirty = true;\n            done(args);\n        })\n\n    registerAction('deleteMotionTween', \n        function (args) {\n            var frame = args.frame;\n            args.removedTween = frame.getCurrentTween();\n            frame.removeTween(args.removedTween);\n            wickEditor.project.getCurrentObject().framesDirty = true;\n\n            done(args);\n        },\n        function (args) {\n            var frame = args.frame;\n            frame.addTween(args.removedTween);\n            wickEditor.project.getCurrentObject().framesDirty = true;\n\n            done(args);\n        });\n\n    registerAction('moveMotionTween',\n        function (args) {\n            args.oldPlayheadPosition = args.tween.playheadPosition;\n            var boundPlayheadPosition = Math.min(Math.max(0, args.newPlayheadPosition), args.frame.length-1);\n            if(args.frame.getTweenAtPlayheadPosition(boundPlayheadPosition)) {\n                boundPlayheadPosition = args.oldPlayheadPosition;\n            }\n            args.tween.playheadPosition = boundPlayheadPosition;\n            \n            wickEditor.project.currentObject.framesDirty = true;\n            done(args);\n        }, \n        function (args) {\n            args.tween.playheadPosition = args.oldPlayheadPosition\n\n            wickEditor.project.currentObject.framesDirty = true;\n            done(args);\n        });\n\n    registerAction('copyFrameForward',\n        function (args) {\n            var frame = wickEditor.project.getSelectedObject() || wickEditor.project.getCurrentFrame();\n            var copiedFrame = frame.copy();\n            copiedFrame.playheadPosition = frame.getNextOpenPlayheadPosition();\n\n            args.movePlayheadAction = wickEditor.actionHandler.doAction('movePlayhead', {\n                obj:wickEditor.project.getCurrentObject(),\n                newPlayheadPosition:copiedFrame.playheadPosition,\n                newLayer:copiedFrame.parentLayer,\n                dontAddToStack: true\n            });\n\n            wickEditor.project.getCurrentLayer().addFrame(copiedFrame);\n            wickEditor.project.clearSelection();\n            wickEditor.project.selectObject(copiedFrame);\n\n            args.addedFrame = copiedFrame;\n\n            wickEditor.project.currentObject.framesDirty = true;\n            done(args);\n        }, \n        function (args) {\n            wickEditor.project.getCurrentLayer().removeFrame(args.copiedFrame);\n\n            args.movePlayheadAction.undoAction();\n\n            wickEditor.project.currentObject.framesDirty = true;\n            done(args);\n        });\n\n    registerAction('doBooleanOperation',\n        function (args) {\n            args.objs.forEach(function(obj) {\n                obj._tempZIndex = wickEditor.project.getCurrentFrame().wickObjects.indexOf(obj);\n            })\n            args.objs.sort(function (a,b) {\n                return b._tempZIndex - a._tempZIndex;\n            });\n\n            if(args.boolFnName === 'unite') {\n                var removeObjs = [];\n                for (var i = 1; i < args.objs.length; i++) {\n                    removeObjs.push(args.objs[i]);\n                }\n                var superPath = args.objs[0];\n                removeObjs.forEach(function (ro) {\n                    superPath.paper = superPath.paper.unite(ro.paper);\n                });\n                var parentAbsPos = wickEditor.project.currentObject.getAbsolutePosition();\n                args.modAction = wickEditor.actionHandler.doAction('modifyObjects', {\n                    objs: [superPath],\n                    modifiedStates: [{\n                        x: superPath.paper.position.x - parentAbsPos.x,\n                        y: superPath.paper.position.y - parentAbsPos.y,\n                        svgX: superPath.paper.bounds._x,\n                        svgY: superPath.paper.bounds._y,\n                        width: superPath.paper.bounds._width,\n                        height: superPath.paper.bounds._height,\n                        pathData: superPath.paper.exportSVG({asString:true}),\n                    }],\n                    dontAddToStack: true,\n                });\n                args.deleteAction = wickEditor.actionHandler.doAction('deleteObjects', {\n                    objects: removeObjs,\n                    dontAddToStack: true\n                });\n            } else if (args.boolFnName === 'subtract') {\n                var cuttingPath = args.objs[0];\n                var cutPaths = [];\n                for (var i = 1; i < args.objs.length; i++) {\n                    cutPaths.push(args.objs[i]);\n                }\n                var modifiedStates = [];\n                var modifiedObjects = [];\n                cutPaths.forEach(function (cp) {\n                    cp.paper = cp.paper.subtract(cuttingPath.paper);\n                    modifiedObjects.push(cp);\n                    var parentAbsPos = wickEditor.project.currentObject.getAbsolutePosition();\n                    modifiedStates.push({\n                        x: cp.paper.position.x - parentAbsPos.x,\n                        y: cp.paper.position.y - parentAbsPos.y,\n                        svgX: cp.paper.bounds._x,\n                        svgY: cp.paper.bounds._y,\n                        width: cp.paper.bounds._width,\n                        height: cp.paper.bounds._height,\n                        pathData: cp.paper.exportSVG({asString:true}),\n                    });\n                });\n                args.modAction = wickEditor.actionHandler.doAction('modifyObjects', {\n                    objs: modifiedObjects,\n                    modifiedStates: modifiedStates,\n                    dontAddToStack: true,\n                });\n            }\n\n            done(args);\n        }, \n        function (args) {\n            if(args.modAction) args.modAction.undoAction();\n            if(args.deleteAction) args.deleteAction.undoAction();\n\n            done(args);\n        });\n\n}"
  },
  {
    "path": "src/editor/WickEditor.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick.\n\n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\n/* This is the entry point for the whole editor */\n\nvar WickEditor = function () {\n\n    var self = this;\n\n    self.version = \"0.15\";\n    document.getElementById('wick-editor-version').innerHTML = 'Wick Editor ' + self.version;\n    console.log(\"Wick Editor version \" + self.version)\n    window.wickVersion = self.version;\n\n    // Friendly console message ~~~\n    console.log('%cWelcome to the javascript console! ', 'color: #ff99bb; font-size: 20px; font-weight: bold; text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;');\n    console.log('%cYou are free to change any of the internal editor stuff from here.', 'color: #7744bb; font-size: 12px;');\n    console.log('%cTry typing \"wickEditor\" into the console to see some stuff!.', 'color: #22bb99; font-size: 12px;');\n\n    // Setup init project\n    this.project = new WickProject();\n\n    // Load settings\n    this.settings = new WickEditorSettings();\n\n    // Load audio player and renderer\n    this.fastRenderer = new WickPixiRenderer(document.getElementById('previewRenderContainer'));\n    this.audioPlayer = new WickHowlerAudioPlayer(this.project);\n\n    // Load all interfaces\n    this.interfaces = [];\n    function registerInterface (interface) {\n        self.interfaces.push(interface);\n        return interface;\n    }\n    this.builtinplayer = registerInterface(new BuiltinPlayerInterface(this));\n    this.scriptingide = registerInterface(new ScriptingIDEInterface(this));\n    this.timeline = registerInterface(new TimelineInterface(this));\n    this.library = registerInterface(new LibraryInterface(this));\n    this.toolbar = registerInterface(new ToolbarInterface(this));\n    this.canvas = registerInterface(new CanvasInterface(this));\n    this.inspector = registerInterface(new InspectorInterface(this));\n    this.rightclickmenu = registerInterface(new RightClickMenuInterface(this));\n    this.menubar = registerInterface(new MenuBarInterface(this));\n    this.breadcrumbs = registerInterface(new BreadcrumbsInterface(this));\n    this.alertbox = registerInterface(new AlertBoxInterface(this));\n    this.cursorIcon = registerInterface(new CursorIconInterface(this));\n    this.colorPicker = registerInterface(new ColorPickerInterface(this));\n    this.editorSettings = registerInterface(new EditorSettings(this));\n    this.editorCredits = registerInterface(new EditorCredits(this));\n    this.textEditBox = registerInterface(new TextEditBox(this));\n    this.videoExporter = registerInterface(new VideoExporterInterface(this)); \n\n    // Setup editor logic handlers\n    this.actionHandler = new WickActionHandler(this);\n    this.guiActionHandler = new GuiActionHandler(this);\n\n    // Load all tools\n    this.tools = {};\n    this.tools.selectioncursor = new Tools.SelectionCursor(this);\n    this.tools.vectorcursor = new Tools.VectorCursor(this);\n    this.tools.paintbrush = new Tools.Paintbrush(this);\n    this.tools.pencil = new Tools.Pencil(this);\n    this.tools.eraser = new Tools.Eraser(this);\n    this.tools.fillbucket = new Tools.FillBucket(this);\n    this.tools.rectangle = new Tools.Rectangle(this);\n    this.tools.ellipse = new Tools.Ellipse(this);\n    this.tools.line = new Tools.Line(this);\n    this.tools.pen = new Tools.Pen(this);\n    this.tools.dropper = new Tools.Dropper(this);\n    this.tools.text = new Tools.Text(this);\n    this.tools.zoom = new Tools.Zoom(this);\n    this.tools.pan = new Tools.Pan(this);\n    \n    this.currentTool = this.tools.selectioncursor;\n    this.lastTool = this.currentTool;\n\n    // Setup all tools + interfaces\n    this.interfaces.forEach(function (interface) {\n        interface.setup();\n    });\n    for(tool in this.tools) {\n        this.tools[tool].setup();\n    };\n\n    // Setup inputhandler\n    this.inputHandler = new InputHandler(this);\n\n    self.syncInterfaces();\n\n    // This is put after the first sync so the page loads before the editor asks to load a project\n    // (and we gotta wait a little bit before loading it ... we want to make sure the editor is ready)\n    setTimeout(function () {\n        self.tryToLoadProject();\n    }, 100);\n\n}\n\nWickEditor.prototype.syncInterfaces = function () {\n    var enablePerfTests = false;\n    if(enablePerfTests) {\n        console.log('---------Begin timing sync-------')\n    }\n\n    //startTiming();\n\n    this.project.applyTweens();\n\n    if(!this.tools) return;\n    this.interfaces.forEach(function (interface) {\n        if(enablePerfTests) startTiming();\n        interface.syncWithEditorState();\n        if(enablePerfTests) {\n            stopTiming('interface:');\n            console.log(interface.__proto__.constructor)\n            //console.log(' ')\n        }\n    });\n\n    //console.log(new Error())\n    //stopTiming('total sync')\n}\n\nWickEditor.prototype.changeTool = function (newTool) {\n    this.lastTool = this.currentTool;\n    if(this.lastTool.onDeselected) this.lastTool.onDeselected();\n    this.currentTool = newTool;\n    if(newTool.onSelected) newTool.onSelected();\n\n    this.syncInterfaces();\n\n    this.guiActionHandler.doAction('previewPause');\n}\n\nWickEditor.prototype.useLastUsedTool = function () {\n    this.currentTool = this.lastTool;\n}\n\nWickEditor.prototype.tryToLoadProject = function () {\n    // Load .wick from hash - for new site \n    /*if(window.location.hash) {\n        var projectPath = window.location.hash.slice(1); // remove first char (the hash)\n\n        var xhr = new XMLHttpRequest();\n        xhr.open('GET', projectPath, true);\n        xhr.responseType = 'arraybuffer';\n\n        xhr.onload = function(e) {\n          if (this.status == 200) {\n            var byteArray = new Uint8Array(this.response);\n            var wickProjectJSON = LZString.decompressFromUint8Array(byteArray);\n            var wickProject = WickProject.fromJSON(wickProjectJSON, true);\n            wickEditor.guiActionHandler.doAction('openProject', {\n                project:wickProject,\n                dontWarn: true\n            });\n          }\n        };\n\n        xhr.send();\n    } else {\n        WickProject.Exporter.getAutosavedProject(function (project) {\n            wickEditor.guiActionHandler.doAction('openProject', {\n                project: project,\n                dontWarn: true\n            })\n        });\n    }\n    window.location.hash = '';*/\n\n    var demoName = URLParameterUtils.getParameterByName(\"demo\");\n    if(demoName) {\n        console.log(\"Trying to load demo:\");\n        console.log(\"demoName: \" + demoName);\n\n        $.ajax({\n            url: \"../examples/\" + demoName,\n            type: 'GET',\n            data: {},\n            success: function(data) {\n                console.log(\"ajax: success\");\n                if(data === \"NEW_PROJECT\") {\n                    wickEditor.project = new WickProject();\n                } else {\n                    //wickEditor.project = WickProject.fromWebpage(data);\n                    wickEditor.guiActionHandler.doAction('openProject', {\n                        project:WickProject.fromJSON(JSON.stringify(data)),\n                        dontWarn: true\n                    })\n                }\n                wickEditor.syncInterfaces();\n            },\n            error: function () {\n                console.log(\"ajax: error\");\n                wickEditor.syncInterfaces();\n            },\n            complete: function(response, textStatus) {\n                console.log(\"ajax: complete\")\n                console.log(response)\n                console.log(textStatus)\n                URLParameterUtils.clearURLParam(\"demo\")\n            }\n        });\n    } else {\n        WickProject.Exporter.getAutosavedProject(function (project) {\n            wickEditor.guiActionHandler.doAction('openProject', {\n                project: project,\n                dontWarn: true\n            })\n        });\n    }\n}\n"
  },
  {
    "path": "src/editor/interfaces/Interfaces.AlertBox.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar AlertBoxInterface = function (wickEditor) {\n\n    var self = this;\n\n    var alertBoxDiv;\n    var alertBoxText;\n    var alertBoxIcon;\n\n    var fadeTimeout;\n\n    self.setup = function () {\n        alertBoxDiv = document.getElementById('alert-box');\n        alertBoxText = document.getElementsByClassName('alert-box-text')[0];\n        alertBoxIcon = document.getElementsByClassName('alert-box-icon')[0];\n\n        alertBoxDiv.style.pointerEvents = 'none'\n\n        alertBoxDiv.onclick = function () {\n            self.hide();\n        }\n    }\n\n    self.syncWithEditorState = function () {\n        if(!alertBoxDiv) return;\n    }\n\n    self.showMessage = function (message) {\n        alertBoxText.innerHTML = message;\n        self.show();\n\n        clearTimeout(fadeTimeout);\n        fadeTimeout = setTimeout(function () {\n            self.hide();\n        }, 3000);\n    }\n\n    self.showProjectSavedMessage = function () {\n        self.showMessage(\"Project autosaved!\");\n    }\n\n    self.hide = function () {\n        alertBoxDiv.style.opacity = 0.0;\n        setTimeout(function () {\n            alertBoxDiv.style.pointerEvents = 'none'\n        }, 500);\n    }\n\n    self.show = function () {\n        alertBoxDiv.style.pointerEvents = 'all'\n        alertBoxDiv.style.opacity = 1.0;\n    }\n\n}"
  },
  {
    "path": "src/editor/interfaces/Interfaces.Breadcrumbs.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n    \nvar BreadcrumbsInterface = function (wickEditor) {\n\n    var breadcrumbsDiv = document.getElementById('breadcrumbsGUI');\n\n    this.setup = function () {\n        \n    }\n\n    this.syncWithEditorState = function () {\n\n        breadcrumbsDiv.innerHTML = \"\";\n\n        wickEditor.project.getCurrentObject().getParents().forEach(function (object) {\n            createButton(object);\n        })\n\n    }\n\n    var createButton = function (wickObject) {\n\n        var title;\n        if(wickObject.isRoot) {\n            title = \"Project\";\n        } else {\n            var spacer = document.createElement('div');\n            spacer.className = \"breadcrumbs-spacer\";\n            spacer.innerHTML = \"/\";\n            breadcrumbsDiv.appendChild(spacer);\n\n            title = wickObject.name;\n        }\n\n        var button = document.createElement('div');\n        button.className = 'breadcrumbs-button';\n        button.onclick = function () {\n            wickEditor.actionHandler.doAction('editObject', { objectToEdit: wickObject });\n        }\n        button.innerHTML = title;\n\n        breadcrumbsDiv.appendChild(button);\n\n    }\n\n}"
  },
  {
    "path": "src/editor/interfaces/Interfaces.BuiltinPlayer.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar BuiltinPlayerInterface = function (wickEditor) {\n\n    var that = this;\n\n    var closeButton;\n\n    this.setup = function () {\n        this.running = false;\n\n        closeButton = document.getElementById('closeBuiltinPlayerButton')\n        closeButton.addEventListener(\"mousedown\", function (e) {\n            that.stopRunningProject(); \n        });\n\n        window.addEventListener('resize', resize, false);\n    }\n\n    this.syncWithEditorState = function () {\n        if(this.running) {\n            showBuiltinPlayer();\n        } else {\n            hideBuiltinPlayer();\n        }\n    }\n\n    this.runProject = function (JSONProject) {\n        if(wickEditor.project.hasSyntaxErrors()) {\n            if(!confirm(\"There are syntax errors in the code of this project! Are you sure you want to run it?\")) {\n                return;\n            }\n        }\n\n        that.running = true;\n        wickEditor.syncInterfaces();\n\n        WickProject.Exporter.bundleProjectToHTML(wickEditor.project, function (result) {\n            var oldIframe = document.getElementById('builtinPlayerViewer');\n            if(oldIframe) {\n                oldIframe.remove();\n            }\n\n            var iframe = document.createElement('iframe');\n            iframe.id = 'builtinPlayerViewer';\n            document.getElementById('builtinPlayer').appendChild(iframe);\n            iframe.contentWindow.document.write(result);\n\n            resize();\n        });\n    }\n\n    this.stopRunningProject = function () {\n        document.getElementById('builtinPlayerViewer').remove();\n        hideBuiltinPlayer();\n        that.running = false;\n    }\n\n    var showBuiltinPlayer = function () {\n        document.getElementById(\"builtinPlayer\").style.display = \"block\";\n    }\n\n    var hideBuiltinPlayer = function () {\n        document.getElementById(\"builtinPlayer\").style.display = \"none\";\n    }\n\n    var resize = function () {\n        var title = document.getElementById('builtinPlayerProjectInfo');\n        title.innerHTML = wickEditor.project.name;\n        title.style.width = (wickEditor.project.width-16)+'px';\n        title.style.height = 16+'px';\n        title.style.left = ((window.innerWidth -wickEditor.project.width) /2)+'px';\n        title.style.top  = ((window.innerHeight-wickEditor.project.height)/2-16-6)+'px';\n\n        closeButton.style.left = ((window.innerWidth -wickEditor.project.width) /2+wickEditor.project.width-16)+'px';\n        closeButton.style.top  = ((window.innerHeight-wickEditor.project.height)/2-16-4)+'px';\n\n        var viewer = document.getElementById('builtinPlayerViewer');\n        if(viewer) {\n            viewer.style.left = ((window.innerWidth -wickEditor.project.width) /2)+'px';\n            viewer.style.top  = ((window.innerHeight-wickEditor.project.height)/2)+'px';\n            viewer.style.width  = (wickEditor.project.width)+'px';\n            viewer.style.height = (wickEditor.project.height)+'px';\n        }\n    }\n\n}"
  },
  {
    "path": "src/editor/interfaces/Interfaces.Canvas.Backdrop.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar CanvasBackdrop = function (wickEditor, canvasContainer) {\n\n    var self = this;\n\n    var backdropDiv = document.createElement('div');\n    backdropDiv.style.position = 'absolute';\n    backdropDiv.style.top = '0px';\n    backdropDiv.style.left = '0px';\n    canvasContainer.prepend(backdropDiv);\n\n    self.update = function () {\n        self.updateViewTransforms();\n    }\n\n    self.updateViewTransforms = function () {\n        var pan = wickEditor.canvas.getPan();\n        var zoom = wickEditor.canvas.getZoom();\n\n        var width = wickEditor.project.width;\n        var height = wickEditor.project.height;\n\n        var tx = (pan.x)+width*(zoom-1)/2;\n        var ty = (pan.y)+height*(zoom-1)/2;\n        var transform = 'translate('+tx+'px,'+ty+'px) scale('+zoom+', '+zoom+')';\n        backdropDiv.style.width = width+'px';\n        backdropDiv.style.height = height+'px';\n        backdropDiv.style[\"-ms-transform\"] = transform;\n        backdropDiv.style[\"-webkit-transform\"] = transform;\n        backdropDiv.style[\"transform\"] = transform;\n\n        self.setColor(wickEditor.project.backgroundColor);\n    }\n\n    self.setColor = function (color) {\n        backdropDiv.style.backgroundColor = color;\n    }\n\n}"
  },
  {
    "path": "src/editor/interfaces/Interfaces.Canvas.Fast.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n    \nvar FastCanvas = function (wickEditor) {\n\n\tvar self = this;\n\n    var canvasContainer;\n\n    var fastRenderIntervalID;\n    var previewPlayIntervalID;\n\n    var fastRendering;\n    var previewPlaying;\n\n    this.setup = function () {\n        fastRendering = false;\n        previewPlaying = false;\n\n        canvasContainer = document.getElementById('previewRenderContainer');\n    }\n\n    this.update = function () {\n        wickEditor.audioPlayer.reloadSoundsInProject(wickEditor.project);\n\n        updateCanvasTransforms();\n        canvasContainer.style.display = 'block';\n        canvasContainer.style.opacity = 0.5;\n\n        var inactiveObjects = wickEditor.project.currentObject.getAllInactiveSiblings();\n        if (wickEditor.project.onionSkinning) {\n            var onionSkinObjects = wickEditor.project.currentObject.getNearbyObjects(1,1);\n            inactiveObjects = inactiveObjects.concat(onionSkinObjects);\n        }\n        wickEditor.fastRenderer.renderWickObjects(wickEditor.project, inactiveObjects, 2);\n    }\n\n    this.startFastRendering = function () {\n        wickEditor.fastRenderer.reorderAllObjects(wickEditor.project)\n\n        clearInterval(fastRenderIntervalID);\n        \n        fastRendering = true;\n\n        wickEditor.canvas.getInteractiveCanvas().hide();\n\n        function proceed () {\n            canvasContainer.style.opacity = 1.0;\n            wickEditor.project.applyTweens();\n            var renderObjects = wickEditor.project.rootObject.getAllActiveChildObjects();\n            renderObjects.forEach(function (o) {\n                o._renderAsBGObject = false;\n            });\n            wickEditor.fastRenderer.renderWickObjects(wickEditor.project, renderObjects, 2);\n        }\n\n        proceed();\n        fastRenderIntervalID = setInterval(proceed, 1000/60);\n    }\n\n    this.stopFastRendering = function () {\n        fastRendering = true;\n\n        wickEditor.canvas.getInteractiveCanvas().show();\n\n        clearInterval(fastRenderIntervalID);\n    }\n\n    this.startPreviewPlaying = function (loop) {\n        clearInterval(previewPlayIntervalID);\n\n        previewPlaying = true;\n        self.startFastRendering();\n\n        var currObj = wickEditor.project.currentObject;\n        if(currObj.playheadPosition >= currObj.getTotalTimelineLength()-1) {\n            currObj.playheadPosition = 0;\n        }\n\n        wickEditor.audioPlayer.reloadSoundsInProject(wickEditor.project);\n        currObj.getActiveFrames().forEach(function (frame) {\n            if(frame.hasSound() && frame.playheadPosition !== currObj.playheadPosition) {\n                wickEditor.audioPlayer.playSoundOnFrame(frame);\n            }\n        });\n\n        function proceed () {\n            var currObj = wickEditor.project.currentObject;\n            currObj.getAllFrames().forEach(function (frame) {\n                if(frame.hasSound()) { \n                    if(frame.playheadPosition === currObj.playheadPosition) {\n                        wickEditor.audioPlayer.playSoundOnFrame(frame);\n                    } else if (frame.playheadPosition+frame.length === currObj.playheadPosition) {\n                        wickEditor.audioPlayer.stopSoundOnFrame(frame);\n                    }\n                }\n            });\n\n            currObj.playheadPosition ++;\n\n            if(currObj.playheadPosition >= currObj.getTotalTimelineLength()) {\n                if(loop) {\n                    currObj.playheadPosition = 0;\n                    wickEditor.audioPlayer.stopAllSounds()\n                } else {\n                    currObj.playheadPosition -= 1;\n                    self.stopPreviewPlaying();\n                }\n            }\n\n            wickEditor.timeline.getElem().playhead.update();\n        }\n\n        wickEditor.timeline.getElem().playhead.update();\n        previewPlayIntervalID = setInterval(proceed, 1000/wickEditor.project.framerate);\n    }\n\n    this.stopPreviewPlaying = function () {\n        previewPlaying = false;\n        self.stopFastRendering();\n        wickEditor.audioPlayer.stopAllSounds();\n\n        clearInterval(previewPlayIntervalID);\n\n        wickEditor.syncInterfaces();\n    }\n\n    this.togglePreviewPlaying = function () {\n        if(previewPlaying) {\n            self.stopPreviewPlaying();\n        } else {\n            self.startPreviewPlaying();\n        }\n    }\n\n    this.getRenderer = function () {\n        return {\n            renderer: wickEditor.fastRenderer,\n            canvasContainer: canvasContainer\n        };\n    }\n\n    this.updateViewTransforms = function () {\n        updateCanvasTransforms();\n    }\n\n    this.getWaveformForFrameSound = function (frame) {\n        return wickEditor.audioPlayer.getWaveformOfFrame(frame)\n    }\n\n    function updateCanvasTransforms () {\n        var pan = wickEditor.canvas.getPan();\n        var zoom = wickEditor.canvas.getZoom();\n\n        var width = wickEditor.project.width;\n        var height = wickEditor.project.height;\n        \n        var tx = (pan.x)+width *2*(zoom-1)/2;\n        var ty = (pan.y)+height*2*(zoom-1)/2;\n        tx -= width /2*(zoom);\n        ty -= height/2*(zoom);\n        var transform = 'translate('+tx+'px,'+ty+'px) scale('+zoom+', '+zoom+')';\n        canvasContainer.style.width = (width*2)+'px';\n        canvasContainer.style.height = (height*2)+'px';\n        canvasContainer.style.paddingLeft = '0px';//(pan.x*zoom)+'px';\n        canvasContainer.style.paddingRight = '0px';\n        canvasContainer.style.paddingTop = '0px';//(pan.y*zoom)+'px';\n        canvasContainer.style.paddingBottom = '0px';\n        canvasContainer.style[\"-ms-transform\"] = transform;\n        canvasContainer.style[\"-webkit-transform\"] = transform;\n        canvasContainer.style[\"transform\"] = transform;\n    }\n\t\n}"
  },
  {
    "path": "src/editor/interfaces/Interfaces.Canvas.ImageRenderer.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n    \nvar ImageRenderer = function () {\n\n\tvar self = this;\n\n    self.renderProjectAsGIF = function (callback) {\n\n        retrieveCanvas();\n\n        self.renderer.reorderAllObjects(wickEditor.project)\n\n        self.renderer.preloadAllAssets(wickEditor.project, function () {\n\n            function buildAndSaveGIF () {\n                gifFrameImages.forEach(function (gifFrameImage) {\n                    gif.addFrame(gifFrameImage, {delay: 1000/wickEditor.project.framerate});\n                });\n\n                gif.render();\n\n                gif.on('finished', function(blob) {\n                    callback(blob);\n                    self.renderer.renderWickObjects(wickEditor.project, [], 2);\n                    wickEditor.canvas.getInteractiveCanvas().show();\n                });\n            }\n\n            var gifFrameDataURLs = [];\n\n            wickEditor.project.currentObject = wickEditor.project.rootObject;\n            var len = wickEditor.project.rootObject.getTotalTimelineLength();\n            for (var i = 0; i < len; i++) {\n                wickEditor.project.rootObject.playheadPosition = i;\n                wickEditor.project.applyTweens();\n                self.renderer.renderWickObjects(wickEditor.project, wickEditor.project.rootObject.getAllActiveChildObjects(), 1);\n                var canvas = self.canvasContainer.children[0];\n                gifFrameDataURLs.push(canvas.toDataURL());\n            }\n\n            gif = new GIF({\n                workers: 2,\n                quality: 10,\n                workerScript: 'lib/gif.worker.js',\n                background: '#FF0000',\n                width: wickEditor.project.width,\n                height: wickEditor.project.height,\n            });\n\n            var gifFrameImages = [];\n\n            gifFrameDataURLs.forEach(function (gifFrameDataURL) {\n                resizedataURL(gifFrameDataURL, wickEditor.project.width, wickEditor.project.height, function (resizedGifFrameDataURL) {\n                    var gifFrameImage = new Image();\n                    gifFrameImage.onload = function () {\n                        gifFrameImages.push(gifFrameImage);\n                        if(gifFrameImages.length === gifFrameDataURLs.length) {\n                            buildAndSaveGIF();\n                        }\n                    }\n\n                    gifFrameImage.src = resizedGifFrameDataURL;\n                })\n            });\n        });\n\n    }\n\n    self.getProjectFrames = function (callback) {\n        console.log('Rendering frames...');\n        wickEditor.videoExporter.setSparkText('Rendering frames...');\n\n        retrieveCanvas();\n\n        wickEditor.project.currentObject = wickEditor.project.rootObject;\n        var len = wickEditor.project.rootObject.getTotalTimelineLength();\n        imgs = [];\n\n        self.renderer.reorderAllObjects(wickEditor.project);\n        self.renderer.preloadAllAssets(wickEditor.project, function () {\n            function proceed (i) {\n                if(i === len) {\n                    console.log(imgs)\n                    callback(imgs);\n                    return;\n                }\n\n                getFrameAsDataURL(i, function (img) {\n                    imgs.push(img);\n                    // Force next frame render to be scheduled later so the DOM can update\n                    setTimeout(function () {\n                        proceed(i+1)\n                    });\n                });\n                \n                wickEditor.videoExporter.setProgressBarPercent(i/len);\n            }\n            proceed(0);\n        });\n    }\n\n    function getFrameAsDataURL (i, callback) {\n        wickEditor.project.rootObject.playheadPosition = i;\n        wickEditor.project.applyTweens();\n        self.renderer.renderWickObjects(wickEditor.project, wickEditor.project.rootObject.getAllActiveChildObjects(), 1);\n        var canvas = self.canvasContainer.children[0];\n        var canvasDataURL = canvas.toDataURL();\n\n        resizedataURL(canvasDataURL, wickEditor.project.width, wickEditor.project.height, function (resizedFrameDataURL) {\n            var frameImage = new Image();\n            frameImage.onload = function () {\n                setTimeout(function () {\n                    callback(frameImage)\n                })\n            }\n            frameImage.src = resizedFrameDataURL;\n        }, true)\n    }\n\n    self.renderProjectAsPNG = function (callback) {\n        retrieveCanvas()\n\n        wickEditor.project.currentObject = wickEditor.project.rootObject;\n        self.renderer.renderWickObjects(wickEditor.project, wickEditor.project.rootObject.getAllActiveChildObjects());\n        var canvas = self.canvasContainer.children[0];\n        callback(dataURItoBlob(canvas.toDataURL()))\n        //callback(canvas.toDataURL())\n    }\n\n    self.getCanvasAsDataURL = function (callback) {\n        retrieveCanvas()\n\n        wickEditor.project.currentObject = wickEditor.project.rootObject;\n        self.renderer.renderWickObjects(wickEditor.project, wickEditor.project.rootObject.getAllActiveChildObjects(), 2);\n        var canvas = self.canvasContainer.children[0];\n        \n        callback(canvas.toDataURL())\n    }\n\n    function retrieveCanvas () {\n        if(!self.canvasContainer) {\n            var otherRenderer = wickEditor.canvas.getFastCanvas().getRenderer();\n            self.renderer = otherRenderer.renderer;\n            self.canvasContainer = otherRenderer.canvasContainer;\n        }\n        self.canvasContainer.style.width = wickEditor.project.width+'px';\n        self.canvasContainer.style.height = wickEditor.project.height+'px';\n    }\n\n    return self;\n\n};\n"
  },
  {
    "path": "src/editor/interfaces/Interfaces.Canvas.Interactive.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n    \nvar InteractiveCanvas = function (wickEditor) {\n\n    var self = this;\n\n    var paperCanvas;\n\n    self.setup = function () {\n        self.needsUpdate = true;\n\n        // Create the canvas to be used with paper.js and init the paper.js instance.\n        paperCanvas = document.createElement('canvas');\n        paperCanvas.className = 'paperCanvas';\n        paperCanvas.style.backgroundColor = \"rgb(0,0,0,0)\";\n        paperCanvas.style.position = 'absolute';\n        paperCanvas.style.top = \"0px\";\n        paperCanvas.style.left = \"0px\";\n        paperCanvas.style.width  = window.innerWidth+'px';\n        paperCanvas.style.height = window.innerHeight+'px';\n        paper.setup(paperCanvas);\n        \n        paper.view.viewSize.width  = window.innerWidth;\n        paper.view.viewSize.height = window.innerHeight;\n        window.addEventListener('resize', function () {\n            paperCanvas.style.width  = window.innerWidth+'px';\n            paperCanvas.style.height = window.innerHeight+'px';\n            paper.view.viewSize.width  = window.innerWidth;\n            paper.view.viewSize.height = window.innerHeight;\n        }, false);\n        paper.view.viewSize.width  = window.innerWidth;\n        paper.view.viewSize.height = window.innerHeight;\n        document.getElementById('editorCanvasContainer').appendChild(paperCanvas);\n\n        paper._mainLayer = new paper.Layer();\n        paper._guiLayer = new paper.Layer();\n        paper._guiLayer.locked = true;\n        paper._mainLayer.activate();\n\n        //paper.install(window)\n\n    }\n\n    self.show = function () {\n        paperCanvas.style.display = 'block'\n    }\n\n    self.hide = function () {\n        paperCanvas.style.display = 'none'\n    }\n\n    self.update = function () {\n\n        self.updateViewTransforms();\n\n        if(wickEditor.currentTool.paperTool) wickEditor.currentTool.paperTool.activate();\n        self.show();\n\n        if(self.needsUpdate) {\n            function createPathForWickobject (wickObject) {\n                function proceed () {\n                    wickObject.paper.position.x = wickObject.x;\n                    wickObject.paper.position.y = wickObject.y;\n                    if(wickObject.isPath) {\n                        wickObject.paper.applyMatrix = true;\n                    } else {\n                        wickObject.paper.applyMatrix = false;\n                    }\n                    wickObject.paper.rotation = wickObject.rotation;\n                    wickObject.paper.scaling.x = wickObject.scaleX;\n                    wickObject.paper.scaling.y = wickObject.scaleY;\n\n                    wickObject.paper.opacity = wickObject.opacity;\n                    wickObject.svgStrokeWidth = wickObject.paper.strokeWidth;\n                    \n                    wickObject.paper.wick = wickObject;\n                    return wickObject.paper;\n                }\n\n                if(wickObject.isPath) {\n                    var xmlString = wickObject.pathData\n                      , parser = new DOMParser()\n                      , doc = parser.parseFromString(xmlString, \"text/xml\");\n                    wickObject.paper = paper.project.importSVG(doc, {insert:false});\n                    if(wickObject.paper._class === 'Group') {\n                        wickObject.paper = wickObject.paper.children[0]\n                    }\n                    return proceed();\n                } else if (wickObject.isImage) {\n                    var raster = new paper.Raster(wickObject.asset.data);\n                    wickObject.paper = raster;\n                    /*wickObject.paper = new paper.Group();\n                    wickObject.paper.addChild(raster);\n                    wickObject.width = wickObject.paper.bounds._width;\n                    wickObject.height = wickObject.paper.bounds._height;*/\n                    wickObject.width = wickObject.paper.bounds._width;\n                    wickObject.height = wickObject.paper.bounds._height;\n                    return proceed();\n                } else if (wickObject.isText) {\n                    wickObject.paper = new paper.PointText({\n                        point: paper.view.center,\n                        justification: wickObject.textData.textAlign,\n                        fontSize: wickObject.textData.fontSize,\n                        fillColor: wickObject.textData.fill,\n                        fontFamily: wickObject.textData.fontFamily,\n                        content: wickObject.textData.text,\n                        fontWeight: wickObject.textData.fontWeight + ' ' + wickObject.textData.fontStyle,\n                    });\n                    wickObject.width = wickObject.paper.bounds.width;\n                    wickObject.height = wickObject.paper.bounds.height;\n                    return proceed();\n                } else if (wickObject.isSymbol) {\n                    wickObject.paper = new paper.Group();\n                    wickObject.getAllActiveChildObjects().forEach(function (child) {\n                        createPathForWickobject(child)\n                        wickObject.paper.addChild(child.paper);\n                        child.paper._isPartOfGroup = true;\n                    });\n                    wickObject.paper._inLockedLayer = wickObject.parentFrame.parentLayer.locked;\n                    wickObject.paper.pivot = new paper.Point(0,0);\n                    return proceed();\n                }\n            }\n\n            paper.project.activeLayer.removeChildren();\n\n            var currentObj = wickEditor.project.getCurrentObject();\n            if(!currentObj.isRoot) {\n                var fullscreenRect = new paper.Path.Rectangle(\n                    new paper.Point(-10000,-10000),\n                    new paper.Point(10000,10000))\n                fullscreenRect.fillColor = 'rgba(0,0,0,0.2)';\n                fullscreenRect._isGUI = 'gui';\n\n                var originPos = currentObj.getAbsolutePosition();\n                var path = new paper.Path([100, 100], [100, 200]);\n                var path2 = new paper.Path([50, 150], [150, 150]);\n                var group = new paper.Group([path, path2]);\n                group.strokeColor = '#777777';\n                group._isGUI = 'gui';\n                path._isGUI = 'gui';\n                path2._isGUI = 'gui';\n\n                group.position.x = originPos.x;\n                group.position.y = originPos.y;\n            }\n\n            var activeObjects = currentObj.getAllActiveChildObjects();\n            activeObjects.forEach(function (wickObject) {\n                var layer = wickObject.parentFrame.parentLayer;\n                if(layer.hidden) return;\n\n                if(createPathForWickobject(wickObject)) {\n                    var originPos = wickEditor.project.getCurrentObject().getAbsolutePosition();\n                    wickObject.paper.position.x += originPos.x\n                    wickObject.paper.position.y += originPos.y\n                    wickObject.paper._inLockedLayer = layer.locked;\n                    paper.project.activeLayer.addChild(wickObject.paper);\n                    wickObject.paper._isPartOfGroup = false;\n                }\n            });\n        }\n\n        if(wickEditor.currentTool.forceUpdateSelection) {\n            wickEditor.currentTool.forceUpdateSelection()\n        }\n        \n        self.needsUpdate = false;\n    }\n\n    self.updateViewTransforms = function () {\n        var zoom = wickEditor.canvas.getZoom();\n        var pan = wickEditor.canvas.getPan();\n        paper.view.matrix = new paper.Matrix();\n        paper.view.matrix.translate(new paper.Point(pan.x,pan.y))\n        paper.view.matrix.scale(zoom)\n    }\n\n    self.getColorAtPoint = function (point) {\n        var hitResult = paper.project.hitTest(point, {\n            segments: false,\n            fill: true,\n            curves: true,\n            handles: false,\n            stroke: true,\n        });\n        if(hitResult) {\n            var item = hitResult.item;\n            if(hitResult.type === 'stroke' && item.strokeColor) {\n                return { type: 'stroke', color:item.strokeColor.toCSS() };\n            } else if(hitResult.type === 'fill' && item.fillColor) {\n                return { type: 'fill', color:item.fillColor.toCSS() };\n            }\n        }\n    }\n\n    self.getItemAtPoint = function (point, hitOptions) {\n        if(!hitOptions) hitOptions = {};\n\n        options = JSON.parse(JSON.stringify(hitOptions));\n        if(!options.tolerance) options.tolerance = paper.settings.hitTolerance;\n        options.tolerance /= wickEditor.canvas.getZoom();\n        var hitResult = paper.project.hitTest(point, options);\n\n        if(hitResult && (hitResult.item._isPartOfGroup || hitResult.item.parent._isPartOfGroup)) {\n            if(hitOptions.allowGroups) {\n                function getRootParent (item) {\n                    if(item.parent._class === 'Layer') {\n                        return item;\n                    } else {\n                        return getRootParent(item.parent)\n                    }\n                }\n                hitResult.item = getRootParent(hitResult.item);\n            } else {\n                hitResult = null;\n            }\n        }\n\n        if(hitResult && hitResult.item && hitResult.item._isGUI) {\n            hitResult = null;\n        }\n\n        if(hitResult && hitResult.item && (hitResult.item._inLockedLayer || hitResult.item.parent._inLockedLayer)) {\n            hitResult = null;\n        }\n\n        return hitResult;\n    }\n\n }\n"
  },
  {
    "path": "src/editor/interfaces/Interfaces.Canvas.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar CanvasInterface = function (wickEditor) {\n\n    var self = this;\n\n    var ZOOM_MIN = 0.1;\n    var ZOOM_MAX = 50;\n\n    var pan;\n    var zoom;\n\n    var interactiveCanvas;\n    var fastCanvas;\n\n    var imageRenderer;\n\n    var canvasBackdrop;\n    var canvasContainer;\n\n    self.setup = function () {\n        canvasContainer = document.getElementById('editorCanvasContainer')\n\n        canvasBackdrop = new CanvasBackdrop(wickEditor, canvasContainer);\n        interactiveCanvas = new InteractiveCanvas(wickEditor);\n        fastCanvas = new FastCanvas(wickEditor);\n\n        fastCanvas.setup();\n        interactiveCanvas.setup();\n\n        imageRenderer = new ImageRenderer();\n\n        pan = {x:0,y:0};\n        zoom = 1.0;\n    }\n\n    self.syncWithEditorState = function () {\n        interactiveCanvas.update();\n        fastCanvas.update();\n        canvasBackdrop.update();\n        self.updateCursor();\n    }\n\n    self.getCanvasContainer = function () {\n        return canvasContainer;\n    }\n\n    self.getInteractiveCanvas = function () {\n        return interactiveCanvas;\n    }\n\n    self.getFastCanvas = function () {\n        return fastCanvas;\n    }\n\n    self.getCanvasRenderer = function () {\n        return imageRenderer;\n    }\n\n    self.getBackdrop = function () {\n        return canvasBackdrop;\n    }\n\n    self.getZoom = function () {\n        return zoom;\n    }\n\n    self.getPan = function () {\n        return pan;\n    }\n\n    self.updateCursor = function () {\n        canvasContainer.style.cursor = wickEditor.currentTool.getCursorImage();\n    }\n\n    self.recenterCanvas = function () {\n        var guiOffsetX = -85;\n        var guiOffsetY = 47;\n        var windowW = window.innerWidth;\n        var windowH = window.innerHeight;\n        var projectW = wickEditor.project.width\n        var projectH = wickEditor.project.height\n        var centerX = (windowW/2) - (projectW/2) + guiOffsetX;\n        var centerY = (windowH/2) - (projectH/2) + guiOffsetY;\n\n        pan.x = centerX;\n        pan.y = centerY;\n        zoom = 1.0;\n\n        updateViewTransforms()\n    }\n\n    self.panByAmount = function (x, y) {\n        pan.x += x;\n        pan.y += y;\n\n        updateViewTransforms();\n    }\n\n    self.setZoom = function (newZoom) {\n        var oldZoom = zoom;\n        zoom = newZoom;\n        lockZoomToRange();\n        \n        var zoomAmount = zoom / oldZoom;\n\n        pan.x += ((window.innerWidth/2) -pan.x)*(1-zoomAmount);\n        pan.y += ((window.innerHeight/2)-pan.y)*(1-zoomAmount);\n\n        updateViewTransforms();\n    }\n\n    self.zoomToPoint = function (zoomFactor, x, y) {\n        var oldZoom = zoom;\n        var newZoom = zoom * zoomFactor;\n        zoom = newZoom;\n        lockZoomToRange();\n\n        var zoomAmount = zoom / oldZoom;\n\n        pan.x += (x-pan.x)*(1-zoomAmount);\n        pan.y += (y-pan.y)*(1-zoomAmount);\n\n        updateViewTransforms()\n    }\n\n    self.screenToCanvasSpace = function (x,y) {\n        return {\n            x: (x - pan.x)/zoom,\n            y: (y - pan.y)/zoom\n        }\n    }\n\n    self.canvasToScreenSpace = function (x,y) {\n        return {\n            x: (x * zoom) + pan.x,\n            y: (y * zoom) + pan.y\n        }\n    }\n\n    function lockZoomToRange () {\n        if(zoom < ZOOM_MIN) \n            zoom = ZOOM_MIN;\n        if(zoom > ZOOM_MAX)\n            zoom = ZOOM_MAX;\n    }\n\n    function updateViewTransforms () {\n        interactiveCanvas.updateViewTransforms();\n        fastCanvas.updateViewTransforms();\n        canvasBackdrop.updateViewTransforms();\n        wickEditor.timeline.updateZoomBox();\n    }\n\n}\n"
  },
  {
    "path": "src/editor/interfaces/Interfaces.ColorPicker.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar ColorPickerInterface = function (wickEditor) {\n\n    var self = this;\n\n    var spectrumContainer;\n\n    var colorPickerContainer;\n    var currentColor;\n    var currentDoneFn;\n    var previewType;\n\n    var isOpen;\n\n    self.setup = function () {\n        isOpen = false;\n\n        colorPickerContainer = document.getElementById('colorPickerGUI');\n        colorPickerContainer.style.display = 'none';\n\n        var closeButton = document.createElement('div');\n        closeButton.className = 'color-picker-close-button';\n        closeButton.onclick = function () {\n            self.close();\n        }\n        colorPickerContainer.appendChild(closeButton);\n\n        colorPicker = document.createElement('input');\n        colorPicker.type = 'text';\n        colorPicker.id = random.uuid4();\n        colorPickerContainer.appendChild(colorPicker);\n\n        spectrumContainer = $(\"#\"+colorPicker.id);\n        spectrumContainer.spectrum({\n            flat: true,\n            //color: \"rgba(0,0,0,1.0)\",\n            showInput: true,\n            showButtons: false,\n            className: \"full-spectrum\",\n            showInitial: true,\n            showPalette: true,\n            showSelectionPalette: true,\n            maxSelectionSize: 10,\n            preferredFormat: \"hex\",\n            localStorageKey: \"spectrum.demo\",\n            showAlpha: true,\n            maxSelectionSize: 6,\n            move: function (color) {\n                var colorString = color.toString();\n                if(previewType && previewType === 'background-color') {\n                    wickEditor.canvas.getBackdrop().setColor(colorString)\n                } else if (previewType) {\n                    wickEditor.project.getSelectedObjects().forEach(function (o) {\n                        if(!o.paper || o.isSymbol) return;\n                        o.paper[previewType] = colorString;\n                    });\n                }\n                currentColor = colorString;\n            },\n            show: function () {\n\n            },\n            beforeShow: function () {},\n            hide: function (color) {},\n            change: function(color) { \n                currentColor = color.toString();\n            },\n            palette: [\n                [\"rgba(0,0,0,1)\",   \n                 \"rgba(50,50,50,1)\",  \n                 \"rgba(100,100,100,1)\", \n                 \"rgba(150,150,150,1)\", \n                 \"rgba(200,200,200,1)\", \n                 \"rgba(255,255,255,1)\"],\n                [\"rgba(255,0,0,1,1)\", \n                 \"rgba(255,153,0,1,1)\", \n                 \"rgba(255,255,0,1,1)\",    \n                 \"rgba(0,255,0,1,1)\",      \n                 \"rgba(0,181,255,1,1)\",    \n                 \"rgba(181,0,255,1)\"], \n                [\"rgba(0,0,0,0)\"], \n            ]\n        });\n\n        var dropperButton = document.createElement('div');\n        dropperButton.className = 'color-picker-dropper-button';\n        dropperButton.onclick = function () {\n            wickEditor.changeTool(wickEditor.tools.dropper);\n        }\n        colorPickerContainer.appendChild(dropperButton);\n\n        window.addEventListener('mousedown', function(e) { \n            if(!isOpen) return;\n\n            var t = e.target;\n            if (t.className === 'paperCanvas' && wickEditor.currentTool === wickEditor.tools.dropper) {\n                \n            } else if(!elementInsideElement(t, colorPickerContainer)) {\n                self.close();\n            }\n        });\n\n        window.addEventListener('mouseup', function(e) { \n            if(!isOpen) return;\n\n            var t = e.target;\n            if (t.className === 'sp-thumb-inner') {\n                setTimeout(function () {\n                    self.close();\n                }, 10);\n            }\n        });\n    }\n\n    self.open = function (doneFn,color,x,y,pt) {\n        previewType = pt;\n        if(!x) x = wickEditor.inputHandler.mouse.x;\n        if(!y) y = wickEditor.inputHandler.mouse.y;\n\n        wickEditor.syncInterfaces();\n\n        isOpen = true;\n\n        currentDoneFn = doneFn;\n\n        spectrumContainer.spectrum(\"set\", color);\n\n        colorPickerContainer.style.display = 'block';\n        var buffer = 10;\n        var bbox = colorPickerContainer.getBoundingClientRect();\n        var boundX = Math.min(x, window.innerWidth - bbox.width - buffer);\n        var boundY = Math.min(y, window.innerHeight - bbox.height - buffer);\n        colorPickerContainer.style.left = boundX+\"px\";\n        colorPickerContainer.style.top = boundY+\"px\";\n    }\n\n    self.close = function () {\n        isOpen = false;\n        currentDoneFn(currentColor);\n        colorPickerContainer.style.display = 'none';\n    }\n\n    self.syncWithEditorState = function () {\n\n    }\n\n    self.setColor = function (color) {\n        spectrumContainer.spectrum(\"set\", color);\n    }\n\n    self.isOpen = function () {\n        return isOpen;\n    }\n\n}\n"
  },
  {
    "path": "src/editor/interfaces/Interfaces.Credits.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar EditorCredits = function (wickEditor) {\n\n    var self = this;\n    var creditsWindow = document.getElementById('editorCreditsGUI');\n    var closeButton = document.getElementsByClassName('editorCreditsCloseButton')[0];\n    var creditsContent = document.getElementsByClassName('editorCreditsContent')[0];\n\n    self.setup = function () {\n        closeButton.onclick = function () {\n            self.close();\n        }\n\n        $('.editorCreditsContent').load('resources/credits.html');\n    }\n\n    self.syncWithEditorState = function () {\n\n    }\n\n    self.open = function () {\n        creditsWindow.style.display = 'block';\n    }\n\n    self.close = function () {\n        creditsWindow.style.display = 'none';\n    }\n\n}"
  },
  {
    "path": "src/editor/interfaces/Interfaces.CursorIcon.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n    \nvar CursorIconInterface = function (wickEditor) {\n\n    var self = this;\n\n    var cursorIconDiv = document.getElementById('cursorIcon');\n\n    this.setup = function () {\n        document.body.addEventListener('mousemove', function(e) { \n\n            var imgOffset = {x:5, y:15}\n\n            if(wickEditor.currentTool instanceof Tools.FillBucket) {\n                imgOffset.x = 0;\n                imgOffset.y = 2;\n            } else if (wickEditor.currentTool instanceof Tools.Dropper) {\n                imgOffset.x = 15;\n                imgOffset.y = -29;\n            }\n\n            cursorIconDiv.style.top = e.y + imgOffset.y + 'px';\n            cursorIconDiv.style.left = e.x + imgOffset.x + 'px';\n        });\n    }\n\n    this.syncWithEditorState = function () {\n\n    }\n\n    this.hide = function () {\n        cursorIconDiv.style.display = 'none';\n    }\n\n    this.setImageForPaperEvent = function (event) {\n        hitResult = wickEditor.canvas.getInteractiveCanvas().getItemAtPoint(event.point);\n\n        if(hitResult && hitResult.item && hitResult.item._cursor)\n            wickEditor.canvas.getCanvasContainer().style.cursor = hitResult.item._cursor;\n        else\n            wickEditor.canvas.updateCursor();\n\n        if(hitResult && hitResult.item) {\n            if (hitResult.item._wickInteraction) {\n                self.hide()\n            } else if(hitResult.item.parent && hitResult.item.parent._isPartOfGroup) {\n                self.hide()\n            } else if(hitResult.type === 'curve' || hitResult.type === 'stroke') {\n                console.log('curve'); \n                self.setImage('resources/cursor-curve.png')\n\n            } else if(hitResult.type === 'fill') {\n                self.setImage('resources/cursor-fill.png')\n                console.log('fill'); \n            } else if(hitResult.type === 'segment' ||\n                      hitResult.type === 'handle-in' ||\n                      hitResult.type === 'handle-out') {\n                console.log('segment'); \n                self.setImage('resources/cursor-segment.png')\n            } else {\n                self.hide()\n            }\n        } else {\n            self.hide()\n        }\n    }\n\n    this.setImage = function (url, color) {\n        if(color) {\n            cursorIconDiv.style.backgroundColor = color;\n        } else {\n            cursorIconDiv.style.backgroundColor = 'rgba(0,0,0,0)';\n        }\n        cursorIconDiv.style.backgroundImage = 'url('+url+')'\n        cursorIconDiv.style.display = \"block\";\n    }\n\n}"
  },
  {
    "path": "src/editor/interfaces/Interfaces.EditorSettings.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar EditorSettings = function (wickEditor) {\n\n    var self = this;\n    var settingsWindow = document.getElementById('editorSettingsGUI');\n    var closeButton = document.getElementsByClassName('editorSettingsGUICloseButton')[0];\n    var hotkeysContainer = document.getElementsByClassName('editorSettingsGUIHotkeys')[0];\n\n    self.setup = function () {\n        closeButton.onclick = function () {\n            self.close();\n        }\n\n        var guiActions = wickEditor.guiActionHandler.guiActions;\n        for(key in guiActions) {\n            var action = guiActions[key];\n            if(action.hotkeys.length === 0 || !action.title) continue;\n            var hotkeysString = action.hotkeys.map(function (k) {\n                // Remove extra words from key string\n                var splitByKey = k.split('Key')\n                k = splitByKey[splitByKey.length-1]\n                var splitByArrow = k.split('Arrow')\n                k = splitByArrow[splitByArrow.length-1]\n                var splitByDigit = k.split('Digit')\n                k = splitByDigit[splitByDigit.length-1]\n                return k;\n            }).join(' + ');\n            if(action.shiftKey) hotkeysString = 'Shift + ' + hotkeysString;\n            if(action.modifierKey) hotkeysString = 'Control + ' + hotkeysString;\n\n            var hotkeyDiv = document.createElement('div');\n            hotkeyDiv.className = 'hotkey';\n\n            var hotkeyTitle = document.createElement('div');\n            hotkeyTitle.className = 'hotkey-title';\n            hotkeyTitle.innerHTML = action.title;\n            hotkeyDiv.appendChild(hotkeyTitle);\n\n            var hotkeyDesc = document.createElement('div');\n            hotkeyDesc.className = 'hotkey-description';\n            hotkeyDesc.innerHTML = hotkeysString;\n            hotkeyDiv.appendChild(hotkeyDesc);\n\n            hotkeysContainer.appendChild(hotkeyDiv);\n\n            var hr = document.createElement('hr');\n            hr.className = 'hotkeyhr';\n            hotkeysContainer.appendChild(hr);\n        };\n    }\n\n    self.syncWithEditorState = function () {\n\n    }\n\n    self.open = function () {\n        settingsWindow.style.display = 'block';\n    }\n\n    self.close = function () {\n        settingsWindow.style.display = 'none';\n    }\n\n}"
  },
  {
    "path": "src/editor/interfaces/Interfaces.Inspector.InputTypes.js",
    "content": "InspectorInterface.StringInput = function (args) {\n\n    var self = this;\n    self.getValueFn = args.getValueFn;\n    self.onChangeFn = args.onChangeFn;\n    self.isActiveFn = args.isActiveFn;\n\n    self.updateViewValue = function () {\n        if(self.isActiveFn()) {\n            self.propertyDiv.style.display = 'block';\n            self.valueDiv.value = self.getValueFn();\n        } else {\n            self.propertyDiv.style.display = 'none';\n        }\n    }\n    self.updateModelValue = function () {\n        try {\n            self.onChangeFn(self.valueDiv.value);\n        } catch (e) {\n            console.log(e)\n            self.updateViewValue();\n        }\n    }\n\n    self.isFocused = function () {\n        return document.activeElement === self.valueDiv;\n    }\n\n    self.propertyDiv;\n    self.valueDiv;\n    self.getPropertyDiv = function () {\n        var title = document.createElement('span');\n        title.className = \"inspector-input-title\";\n        if(args.tooltip) {\n            title.className += ' tooltipElem';\n            title.setAttribute('alt', args.tooltip);\n        }\n        title.innerHTML = args.title;\n\n        self.valueDiv = document.createElement('input');\n        self.valueDiv.className = 'inspector-input inspector-input-string ' + args.className;\n        self.valueDiv.onchange = function (e) {\n            self.updateModelValue();\n        }\n\n        self.propertyDiv = document.createElement('div');\n        self.propertyDiv.className = 'inspector-property';\n        self.propertyDiv.appendChild(title);\n        self.propertyDiv.appendChild(self.valueDiv);\n\n        if(args.type === 'right-input') {\n            self.propertyDiv.className += ' inspector-property-right';\n            title.className += ' inspector-input-title-right'\n        } else if (args.type === 'left-input') {\n            self.propertyDiv.className += ' inspector-property-left';\n            title.className += ' inspector-input-title-left'\n        }\n\n        return self.propertyDiv;\n    }\n\n}\n\nInspectorInterface.SliderInput = function (args) {\n\n    var self = this;\n    self.getValueFn = args.getValueFn;\n    self.onChangeFn = args.onChangeFn;\n    self.isActiveFn = args.isActiveFn;\n\n    self.updateViewValue = function () {\n        if(self.isActiveFn()) {\n            self.propertyDiv.style.display = 'block';\n            self.valueDiv.value = self.getValueFn();\n            self.sliderDiv.value = self.getValueFn();\n        } else {\n            self.propertyDiv.style.display = 'none';\n        }\n    }\n    self.updateModelValue = function () {\n        try {\n            self.valueDiv.value = Math.min(self.valueDiv.value, args.max)\n            self.valueDiv.value = Math.max(self.valueDiv.value, args.min)\n            self.onChangeFn(self.valueDiv.value);\n        } catch (e) {\n            console.log(e)\n            self.updateViewValue();\n        }\n    }\n\n    self.isFocused = function () {\n        return document.activeElement === self.valueDiv;\n    }\n\n    self.propertyDiv;\n    self.valueDiv;\n    self.getPropertyDiv = function () {\n        var title = document.createElement('span');\n        title.className = \"inspector-input-title tooltipElem\";\n        title.setAttribute('alt', args.tooltip);\n        title.innerHTML = args.title;\n\n        self.valueDiv = document.createElement('input');\n        self.valueDiv.className = 'inspector-input inspector-input-string inspector-input-string-tiny ' + args.className;\n        self.valueDiv.onchange = function (e) {\n            self.updateModelValue();\n        }\n\n        self.sliderDiv = document.createElement('input');\n        self.sliderDiv.type = 'range';\n        self.sliderDiv.min = args.min;\n        self.sliderDiv.max = args.max;\n        if(args.step) self.sliderDiv.step = args.step;\n        self.sliderDiv.onchange = function (e) {\n            self.updateModelValue(self.valueDiv.value);\n            $('.inspector-input').blur()\n        }\n        self.sliderDiv.oninput = function (e) {\n            self.valueDiv.value = self.sliderDiv.value;\n            if(args.liveUpdateType) {\n                wickEditor.project.getSelectedObjects().forEach(function (o) {\n                    if(!o.paper || o.isSymbol) return;\n                    o.paper[args.liveUpdateType] = self.valueDiv.value;\n                });\n            }\n        }\n        self.sliderDiv.className = 'inspector-input inspector-input-slider';\n\n        self.propertyDiv = document.createElement('div');\n        self.propertyDiv.className = 'inspector-property';\n        self.propertyDiv.appendChild(title);\n        self.propertyDiv.appendChild(self.valueDiv);\n        self.propertyDiv.appendChild(self.sliderDiv);\n\n        return self.propertyDiv;\n    }\n\n}\n\nInspectorInterface.TwoStringInput = function (args) {\n\n    var self = this;\n    self.getValueFn = args.getValueFn;\n    self.onChangeFn = args.onChangeFn;\n    self.isActiveFn = args.isActiveFn;\n\n    self.updateViewValue = function () {\n        if(self.isActiveFn()) {\n            self.propertyDiv.style.display = 'block';\n            self.leftValueDiv.value = self.getValueFn().left;\n            self.rightValueDiv.value = self.getValueFn().right;\n        } else {\n            self.propertyDiv.style.display = 'none';\n        }\n    }\n    self.updateModelValue = function () {\n        try {\n            self.onChangeFn({\n                left: self.leftValueDiv.value,\n                right: self.rightValueDiv.value\n            });\n        } catch (e) {\n            console.log(e)\n            self.updateViewValue();\n        }\n    }\n\n    self.isFocused = function () {\n        return document.activeElement === self.leftValueDiv\n            || document.activeElement === self.rightValueDiv;\n    }\n\n    self.propertyDiv;\n    self.leftValueDiv;\n    self.rightValueDiv;\n    self.getPropertyDiv = function () {\n        var title = document.createElement('span');\n        title.className = \"inspector-input-title\";\n        if(args.tooltip) {\n            title.className += ' tooltipElem';\n            title.setAttribute('alt', args.tooltip);\n        }\n        title.innerHTML = args.title;\n\n        self.leftValueDiv = document.createElement('input');\n        self.leftValueDiv.className = 'inspector-input inspector-input-string inspector-input-string-small ' + args.className;\n        self.leftValueDiv.onchange = function (e) {\n            self.updateModelValue();\n        }\n\n        var otherTitle = document.createElement('span');\n        otherTitle.className = \"inspector-input-title inspector-input-title-small\";\n        if(args.otherTooltip) {\n            otherTitle.className += ' tooltipElem';\n            otherTitle.setAttribute('alt', args.otherTooltip);\n        }\n        otherTitle.innerHTML = args.otherTitle;\n\n        self.rightValueDiv = document.createElement('input');\n        self.rightValueDiv.className = 'inspector-input inspector-input-string inspector-input-string-small ' + args.className;\n        self.rightValueDiv.onchange = function (e) {\n            self.updateModelValue();\n        }\n\n        self.propertyDiv = document.createElement('div');\n        self.propertyDiv.className = 'inspector-property';\n        self.propertyDiv.appendChild(title);\n        self.propertyDiv.appendChild(self.leftValueDiv);\n        self.propertyDiv.appendChild(otherTitle);\n        self.propertyDiv.appendChild(self.rightValueDiv);\n\n        return self.propertyDiv;\n    }\n\n}\n\nInspectorInterface.ColorPickerInput = function (args) {\n\n    var self = this;\n    self.getValueFn = args.getValueFn;\n    self.onChangeFn = args.onChangeFn;\n    self.isActiveFn = args.isActiveFn;\n    self.previewType = args.previewType;\n\n    self.updateViewValue = function () {\n        if(self.isActiveFn()) {\n            self.propertyDiv.style.display = 'block';\n            self.valueDiv.style.backgroundColor = self.getValueFn();\n        } else {\n            self.propertyDiv.style.display = 'none';\n        }\n    }\n    self.updateModelValue = function () {\n        try {\n            self.onChangeFn(self.valueDiv.value);\n        } catch (e) {\n            console.log(e)\n            self.updateViewValue();\n        }\n    }\n\n    self.propertyDiv;\n    self.valueDiv;\n    self.getPropertyDiv = function () {\n        var title = document.createElement('span');\n        title.className = \"inspector-input-title tooltipElem\";\n        title.setAttribute('alt', args.tooltip);\n        title.innerHTML = args.title;\n\n        self.valueDiv = document.createElement('div');\n        self.valueDiv.className = 'inspector-input inspector-color-picker';\n        self.valueDiv.onclick = function () {\n            wickEditor.colorPicker.open(function (color) {\n                self.onChangeFn(color)\n                wickEditor.syncInterfaces();\n            }, \n            self.getValueFn(),\n            self.valueDiv.getBoundingClientRect().left,\n            self.valueDiv.getBoundingClientRect().top,\n            self.previewType)\n        }\n\n        self.propertyDiv = document.createElement('div');\n        self.propertyDiv.className = 'inspector-property';\n        self.propertyDiv.appendChild(title);\n        self.propertyDiv.appendChild(self.valueDiv);\n\n        return self.propertyDiv;\n    }\n\n}\n\nInspectorInterface.TwoColorPickerInput = function (args) {\n\n    var self = this;\n    self.getValueFn = args.getValueFn;\n    self.onChangeFn = args.onChangeFn;\n    self.isActiveFn = args.isActiveFn;\n    self.previewTypeLeft = args.previewTypeLeft;\n    self.previewTypeRight = args.previewTypeRight;\n\n    self.updateViewValue = function () {\n        if(self.isActiveFn()) {\n            self.propertyDiv.style.display = 'block';\n            self.leftValueDiv.style.backgroundColor = self.getValueFn().left;\n            self.rightValueDiv.style.backgroundColor = self.getValueFn().right;\n        } else {\n            self.propertyDiv.style.display = 'none';\n        }\n    }\n    self.updateModelValue = function () {\n        try {\n            self.onChangeFn({\n                left : self.leftValueDiv.value, \n                right : self.rightValueDiv.value\n            });\n        } catch (e) {\n            console.log(e)\n            self.updateViewValue();\n        }\n    }\n\n    self.propertyDiv;\n    self.leftValueDiv;\n    self.rightValueDiv;\n    self.getPropertyDiv = function () {\n        var titleLeft = document.createElement('span');\n        titleLeft.className = \"inspector-input-title inspector-input-title tooltipElem\";\n        titleLeft.setAttribute('alt', args.rightTooltip);\n        titleLeft.innerHTML = args.titleLeft;\n\n        var titleRight = document.createElement('span');\n        titleRight.className = \"inspector-input-title inspector-input-title-small tooltipElem\";\n        titleRight.setAttribute('alt', args.leftTooltip);\n        titleRight.innerHTML = args.titleRight;\n\n        self.leftValueDiv = document.createElement('div');\n        self.leftValueDiv.className = 'inspector-input inspector-color-picker inspector-color-picker-small';\n        self.leftValueDiv.onclick = function () {\n            wickEditor.colorPicker.open(function (color) {\n                self.onChangeFn({left:color})\n                wickEditor.syncInterfaces();\n            }, \n            self.getValueFn().left,\n            self.leftValueDiv.getBoundingClientRect().left,\n            self.leftValueDiv.getBoundingClientRect().top,\n            self.previewTypeLeft)\n        }\n\n        self.rightValueDiv = document.createElement('div');\n        self.rightValueDiv.className = 'inspector-input inspector-color-picker inspector-color-picker-small';\n        self.rightValueDiv.onclick = function () {\n            wickEditor.colorPicker.open(function (color) {\n                self.onChangeFn({right:color})\n                wickEditor.syncInterfaces();\n            }, \n            self.getValueFn().right,\n            self.rightValueDiv.getBoundingClientRect().left,\n            self.rightValueDiv.getBoundingClientRect().top,\n            self.previewTypeRight)\n        }\n\n        self.propertyDiv = document.createElement('div');\n        self.propertyDiv.className = 'inspector-property';\n        self.propertyDiv.appendChild(titleLeft);\n        self.propertyDiv.appendChild(self.leftValueDiv);\n        self.propertyDiv.appendChild(titleRight);\n        self.propertyDiv.appendChild(self.rightValueDiv);\n\n        return self.propertyDiv;\n    }\n\n}\n\nInspectorInterface.SelectInput = function (args) {\n\n    var self = this;\n    self.getValueFn = args.getValueFn;\n    self.onChangeFn = args.onChangeFn;\n    self.isActiveFn = args.isActiveFn;\n    self.options    = args.options;\n    self.optionsFn  = args.optionsFn;\n\n    self.updateViewValue = function () {\n        self.valueDiv.innerHTML = '';\n        (self.options || self.optionsFn()).forEach(function (optionText) {\n            var option = document.createElement(\"option\");\n            option.text = optionText;\n            self.valueDiv.add(option);\n        });\n        if(self.isActiveFn()) {\n            self.propertyDiv.style.display = 'block';\n            self.valueDiv.value = self.getValueFn();\n        } else {\n            self.propertyDiv.style.display = 'none';\n        }\n    }\n    self.updateModelValue = function () {\n        try {\n            self.onChangeFn(self.valueDiv.value);\n        } catch (e) {\n            console.log(e)\n            self.updateViewValue();\n        }\n    }\n\n    self.propertyDiv;\n    self.valueDiv;\n    self.getPropertyDiv = function () {\n        var title = document.createElement('span');\n        title.className = \"inspector-input-title tooltipElem\";\n        title.setAttribute('alt', args.tooltip);\n        title.innerHTML = args.title;\n\n        self.valueDiv = document.createElement('SELECT');\n        self.valueDiv.className = 'inspector-input inspector-input-select ' + args.className;\n        (self.options || self.optionsFn()).forEach(function (optionText) {\n            var option = document.createElement(\"option\");\n            option.text = optionText;\n            self.valueDiv.add(option);\n        });\n        self.valueDiv.onchange = function (e) {\n            self.updateModelValue();\n        }\n\n        self.propertyDiv = document.createElement('div');\n        self.propertyDiv.className = 'inspector-property';\n        self.propertyDiv.appendChild(title);\n        self.propertyDiv.appendChild(self.valueDiv);\n        return self.propertyDiv;\n    }\n\n}\n\nInspectorInterface.CheckboxInput = function (args) {\n\n    var self = this;\n    self.getValueFn = args.getValueFn;\n    self.onChangeFn = args.onChangeFn;\n    self.isActiveFn = args.isActiveFn;\n\n    self.updateViewValue = function () {\n        if(self.isActiveFn()) {\n            self.propertyDiv.style.display = 'block';\n            self.valueDiv.checked = self.getValueFn();\n        } else {\n            self.propertyDiv.style.display = 'none';\n        }\n    }\n    self.updateModelValue = function () {\n        try {\n            self.onChangeFn(self.valueDiv.checked);\n        } catch (e) {\n            console.log(e)\n            self.updateViewValue();\n        }\n    }\n\n    self.propertyDiv;\n    self.valueDiv;\n    self.getPropertyDiv = function () {\n        var title = document.createElement('span');\n        title.className = \"inspector-input-title tooltipElem\";\n        title.setAttribute('alt', args.tooltip);\n        title.innerHTML = args.title;\n\n        self.valueDiv = document.createElement('input');\n        self.valueDiv.type = 'checkBox';\n        self.valueDiv.className = 'inspector-input inspector-input-checkbox ' + args.className;\n        self.valueDiv.onchange = function (e) {\n            self.updateModelValue();\n        }\n\n        self.propertyDiv = document.createElement('div');\n        self.propertyDiv.className = 'inspector-property';\n        self.propertyDiv.appendChild(title);\n        self.propertyDiv.appendChild(self.valueDiv);\n        return self.propertyDiv;\n    }\n}\n\nInspectorInterface.MultiCheckboxInput = function (args) {\n\n    var self = this;\n    self.getValueFn = args.getValueFn;\n    self.onChangeFn = args.onChangeFn;\n    self.isActiveFn = args.isActiveFn;\n\n    self.updateViewValue = function () {\n        if(self.isActiveFn()) {\n            self.propertyDiv.style.display = 'block';\n            var vals = self.getValueFn();\n            for(var i = 0; i < self.valueDivs.length; i++) {\n                var activated = vals[i];\n                var valueDiv = self.valueDivs[i];\n                valueDiv.activated = activated;\n                valueDiv.className = activated ? \n                    'inspector-input inspector-input-togglebutton inspector-input-togglebutton-activated' : \n                    'inspector-input inspector-input-togglebutton ' ;\n            }\n        } else {\n            self.propertyDiv.style.display = 'none';\n        }\n    }\n    self.updateModelValue = function () {\n        try {\n            var vals = [];\n            self.valueDivs.forEach(function (valueDiv) {\n                vals.push(valueDiv.activated);\n            });\n            self.onChangeFn(vals);\n        } catch (e) {\n            console.log(e);\n            self.updateViewValue();\n        }\n    }\n\n    self.propertyDiv;\n    self.valueDivs;\n    self.getPropertyDiv = function () {\n        var title = document.createElement('span');\n        title.className = \"inspector-input-title tooltipElem\";\n        title.setAttribute('alt', args.tooltip);\n        title.innerHTML = args.title;\n\n        self.valueDivs = [];\n        args.icons.forEach(function (icon) {\n            var valueDiv = document.createElement('div');\n            valueDiv.className = 'inspector-input inspector-input-togglebutton ';\n            valueDiv.style.backgroundImage = 'url('+icon+')';\n            valueDiv.onmousedown = function (e) {\n                valueDiv.activated = !valueDiv.activated;\n                self.updateModelValue();\n            }\n            self.valueDivs.push(valueDiv);\n        })\n\n        self.propertyDiv = document.createElement('div');\n        self.propertyDiv.className = 'inspector-property';\n        self.propertyDiv.appendChild(title);\n        self.valueDivs.forEach(function (valueDiv) {\n            self.propertyDiv.appendChild(valueDiv);\n        });\n        return self.propertyDiv;\n    }\n}\n\nInspectorInterface.InspectorButton = function (args) {\n\n    var self = this;\n    self.isActiveFn = args.isActiveFn;\n    self.buttonAction = args.buttonAction;\n\n    self.name = args.tooltipTitle;\n    self.icon = \"url(\"+args.icon+\")\";\n\n    self.updateViewValue = function () {\n        if(self.isActiveFn()) {\n            self.buttonDiv.style.display = 'block';\n        } else {\n            self.buttonDiv.style.display = 'none';\n        }\n    }\n\n    self.buttonDiv;\n    self.getButtonDiv = function () {\n        self.buttonDiv = document.createElement('div');\n        self.buttonDiv.className = 'inspector-button tooltipElem inspector-button-' + args.colorClass;\n        self.buttonDiv.style.backgroundImage = self.icon;\n        self.buttonDiv.onclick = function () {\n            self.buttonAction();\n        }\n        self.buttonDiv.setAttribute('alt', args.tooltipTitle);\n        return self.buttonDiv;\n    }\n\n}\n\nInspectorInterface.Divider = function (args) {\n\n    var self = this;\n    self.isActiveFn = function () { return true; };\n    self.buttonAction = function () { return true; };\n\n    self.name = '';\n    self.icon = '';\n\n    self.updateViewValue = function () { return true; };\n\n    var elem = document.createElement('div');\n    elem.className = 'inspector-divider';\n\n    self.buttonDiv;\n    self.getButtonDiv = function () {\n        self.buttonDiv = document.createElement('div');\n        self.buttonDiv.className = 'inspector-divider';\n        return self.buttonDiv;\n    }\n\n}\n"
  },
  {
    "path": "src/editor/interfaces/Interfaces.Inspector.Properties.js",
    "content": "InspectorInterface.getProperties = function (wickEditor, inspector) {\n\n\tvar properties = [];\n\n    selectionInfo = inspector.selectionInfo;\n\n    properties.push(new InspectorInterface.StringInput({\n        title: '<img src=\"resources/inspector-icons/name.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Name',\n        isActiveFn: function () {\n            return selectionInfo.numObjects === 1 \n                && selectionInfo.type == 'wickobject'\n                && !selectionInfo.object.isPath;\n        },\n        getValueFn: function () {\n            return selectionInfo.object.name || \"\";\n        }, \n        onChangeFn: function (val) {\n            selectionInfo.object.name = val;\n        }\n    }));\n\n    properties.push(new InspectorInterface.TwoStringInput({\n        title: '<img src=\"resources/inspector-icons/position.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Position (x,y)',\n        otherTitle: 'x',\n        isActiveFn: function () {\n            return selectionInfo.numObjects === 1 \n                && selectionInfo.type == 'wickobject';\n        },\n        getValueFn: function () {\n            return {\n                left:  roundToHundredths(selectionInfo.object.x),\n                right: roundToHundredths(selectionInfo.object.y)\n            };\n        }, \n        onChangeFn: function (vals) {\n            wickEditor.actionHandler.doAction('modifyObjects', {\n                objs: [selectionInfo.object],\n                modifiedStates: [{\n                    x: eval(vals.left),\n                    y: eval(vals.right)\n                }]\n            });\n        }\n    }));\n\n    properties.push(new InspectorInterface.TwoStringInput({\n        title: '<img src=\"resources/inspector-icons/size.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Width / Height',\n        otherTitle: 'x',\n        isActiveFn: function () {\n            return selectionInfo.numObjects === 1 \n                && selectionInfo.type == 'wickobject'\n                && selectionInfo.dataType !== 'text';\n        },\n        getValueFn: function () {\n            return {\n                left:  roundToHundredths(selectionInfo.object.scaleX*selectionInfo.object.width),\n                right: roundToHundredths(selectionInfo.object.scaleY*selectionInfo.object.height)\n            };\n        }, \n        onChangeFn: function (vals) {\n            wickEditor.actionHandler.doAction('modifyObjects', {\n                objs: [selectionInfo.object],\n                modifiedStates: [{\n                    scaleX: eval(vals.left) /selectionInfo.object.width,\n                    scaleY: eval(vals.right)/selectionInfo.object.height\n                }]\n            });\n        }\n    }));\n\n    properties.push(new InspectorInterface.TwoStringInput({\n        title: '<img src=\"resources/inspector-icons/scale.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Scale',\n        otherTitle: 'x',\n        isActiveFn: function () {\n            return selectionInfo.numObjects === 1 \n                && selectionInfo.type == 'wickobject'\n                && selectionInfo.dataType !== 'text';\n        },\n        getValueFn: function () {\n            return {\n                left:  roundToHundredths(selectionInfo.object.scaleX),\n                right: roundToHundredths(selectionInfo.object.scaleY)\n            };\n        }, \n        onChangeFn: function (vals) {\n            wickEditor.actionHandler.doAction('modifyObjects', {\n                objs: [selectionInfo.object],\n                modifiedStates: [{\n                    scaleX: eval(vals.left),\n                    scaleY: eval(vals.right)\n                }]\n            });\n        }\n    }));\n\n    properties.push(new InspectorInterface.SliderInput({\n        title: '<img src=\"resources/inspector-icons/rotation.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Rotation',\n        className: 'inspector-input-string-small',\n        max: 360,\n        min: 0,\n        isActiveFn: function () {\n            return selectionInfo.numObjects === 1 \n                && selectionInfo.type == 'wickobject'\n                && selectionInfo.dataType !== 'text';\n            },\n        getValueFn: function () {\n            return selectionInfo.object.rotation;\n        }, \n        onChangeFn: function (val) {\n            wickEditor.actionHandler.doAction('modifyObjects', {\n                objs: [selectionInfo.object],\n                modifiedStates: [{rotation: eval(val)}]\n            });\n        }\n    }));\n\n    properties.push(new InspectorInterface.SliderInput({\n        title: '<img src=\"resources/inspector-icons/opacity.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Opacity',\n        className: 'inspector-input-string-small',\n        max: 1,\n        min: 0,\n        step: 0.01,\n        liveUpdateType: 'opacity',\n        isActiveFn: function () {\n            return selectionInfo.numObjects === 1 \n                && selectionInfo.type == 'wickobject'\n                && selectionInfo.dataType !== 'text';\n            },\n        getValueFn: function () {\n            return selectionInfo.object.opacity;\n        }, \n        onChangeFn: function (val) {\n            wickEditor.actionHandler.doAction('modifyObjects', {\n                objs: [selectionInfo.object],\n                modifiedStates: [{opacity: eval(val)}]\n            });\n        }\n    }));\n\n    properties.push(new InspectorInterface.SelectInput({\n        title: '<img src=\"resources/image.png\" class=\"inspector-icon\"/>',\n        tooltip: 'Image Resource',\n        optionsFn: function () {\n            var imageAssetFilenames = wickEditor.project.library.getAllAssets().filter(function (asset) {\n                return asset.type === 'image';\n            }).map(function (asset) {\n                return asset.filename;\n            });\n            return imageAssetFilenames;\n        },\n        isActiveFn: function () {\n            return selectionInfo.type == 'wickobject'\n                && selectionInfo.dataType == 'image'\n                && selectionInfo.numObjects === 1;\n        },\n        getValueFn: function () {\n            return wickEditor.project.library.getAsset(selectionInfo.object.assetUUID).filename; \n        },\n        onChangeFn: function (val) {\n            console.error('!! Need action for this !!')\n            selectionInfo.object.assetUUID = wickEditor.project.library.getAssetByName(val).uuid\n        }\n    }));\n\n    properties.push(new InspectorInterface.SelectInput({\n        title: '<img src=\"resources/inspector-icons/fontfamily.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Font Family',\n        options: getAllGoogleFonts(),\n        isActiveFn: function () {\n            return selectionInfo.numObjects === 1 \n                && selectionInfo.type == 'wickobject' \n                && selectionInfo.object.isText;\n        },\n        getValueFn: function () {\n            return selectionInfo.object.textData.fontFamily;\n        }, \n        onChangeFn: function (val) {\n            loadGoogleFonts([val], function () {\n                selectionInfo.object.textData.fontFamily = val;\n                wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n                wickEditor.syncInterfaces();\n            });\n        }\n    }));\n\n    properties.push(new InspectorInterface.SliderInput({\n        title: '<img src=\"resources/inspector-icons/fontsize.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Font Size',\n        liveUpdateType: 'fontSize',\n        min: 1,\n        max: 150,\n        isActiveFn: function () {\n            return selectionInfo.numObjects === 1 && selectionInfo.type == 'wickobject' && selectionInfo.object.isText;\n        },\n        getValueFn: function () {\n            return selectionInfo.object.textData.fontSize;\n        },\n        onChangeFn: function (val) {\n            selectionInfo.object.textData.fontSize = eval(val);\n            wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n            wickEditor.syncInterfaces();\n        }\n    }));\n\n    properties.push(new InspectorInterface.MultiCheckboxInput({\n        title: '',\n        icons: [\n            'resources/align-left.svg', \n            'resources/align-center.svg',\n            'resources/align-right.svg',\n            'resources/text-bold.svg',\n            'resources/text-italic.svg'\n        ],\n        isActiveFn: function () {\n            return selectionInfo.numObjects === 1 && selectionInfo.type == 'wickobject' && selectionInfo.object.isText;\n        },\n        getValueFn: function () {\n            return [\n                selectionInfo.object.textData.textAlign === 'left',\n                selectionInfo.object.textData.textAlign === 'center',\n                selectionInfo.object.textData.textAlign === 'right',\n                selectionInfo.object.textData.fontWeight === 'bold',\n                selectionInfo.object.textData.fontStyle === 'italic'\n            ];\n        }, \n        onChangeFn: function (vals) {\n            var currentAlign = selectionInfo.object.textData.textAlign;\n            if(vals[0]) {\n                if(currentAlign !== 'left') selectionInfo.object.textData.textAlign = 'left';\n            }\n            if(vals[1]) {\n                if(currentAlign !== 'center') selectionInfo.object.textData.textAlign = 'center';\n            }\n            if(vals[2]) {\n                if(currentAlign !== 'right') selectionInfo.object.textData.textAlign = 'right';\n            }\n            selectionInfo.object.textData.fontWeight = vals[3] ? 'bold' : '';\n            selectionInfo.object.textData.fontStyle = vals[4] ? 'italic' : '';\n            wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n            wickEditor.syncInterfaces();\n        }\n    }));\n\n    properties.push(new InspectorInterface.ColorPickerInput({\n        title: '<img src=\"resources/inspector-icons/paint.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Font Color',\n        isActiveFn: function () {\n            return selectionInfo.numObjects === 1 && selectionInfo.type == 'wickobject' && selectionInfo.object.isText;\n        },\n        getValueFn: function () {\n            return selectionInfo.object.textData.fill;\n        }, \n        onChangeFn: function (val) {\n            selectionInfo.object.textData.fill = val;\n            wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n            wickEditor.syncInterfaces();\n        }\n    }));\n\n    properties.push(new InspectorInterface.SliderInput({\n        title: '<img src=\"resources/inspector-icons/strokewidth.png\" class=\"inspector-icon\"/>',\n        tooltip: 'Stroke Width',\n        className: 'inspector-input-string-small',\n        max: 30,\n        min: 0,\n        liveUpdateType: 'strokeWidth',\n        isActiveFn: function () {\n            return selectionInfo.numObjects === 1 && selectionInfo.type == 'wickobject' && selectionInfo.object.isPath;\n        },\n        getValueFn: function () {\n            return selectionInfo.object.paper && selectionInfo.object.paper.strokeWidth;\n        }, \n        onChangeFn: function (val) {\n            wickEditor.guiActionHandler.doAction(\"changePathProperties\", {\n                strokeWidth: eval(val)\n            });\n            wickEditor.syncInterfaces();\n        }\n    }));\n\n    properties.push(new InspectorInterface.TwoColorPickerInput({\n        previewTypeLeft: 'fillColor',\n        previewTypeRight: 'strokeColor',\n        titleRight: '<img src=\"resources/inspector-icons/strokecolor.svg\" class=\"inspector-icon\"/>',\n        leftTooltip: 'Stroke Color',\n        titleLeft: '<img src=\"resources/inspector-icons/fillcolor.svg\" class=\"inspector-icon\"/>',\n        rightTooltip: 'Fill Color',\n        isActiveFn: function () {\n            return selectionInfo.numObjects === 1 \n                && selectionInfo.type == 'wickobject' \n                && selectionInfo.object.isPath;\n        },\n        getValueFn: function () {\n            if(!selectionInfo.object.paper) {\n                return {left:null,right:null};\n            }\n            var left;\n            var right;\n            if(selectionInfo.object.paper.fillColor) {\n                left = selectionInfo.object.paper.fillColor.toCSS()\n            }\n            if(selectionInfo.object.paper.strokeColor) {\n                right = selectionInfo.object.paper.strokeColor.toCSS()\n            }\n            return {\n                left: left,\n                right: right\n            };\n        }, \n        onChangeFn: function (val) {\n            var modifyState = {};\n            if(val.left) modifyState.fillColor = val.left;\n            if(val.right) modifyState.strokeColor = val.right;\n            wickEditor.guiActionHandler.doAction(\"changePathProperties\", modifyState);\n            wickEditor.syncInterfaces();\n        }\n    }));\n\n    properties.push(new InspectorInterface.StringInput({\n        title: '<img src=\"resources/inspector-icons/name.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Name',\n        isActiveFn: function () {\n            return selectionInfo.type === 'project';\n        },\n        getValueFn: function () {\n            return wickEditor.project.name;\n        }, \n        onChangeFn: function (val) {\n            wickEditor.project.name = val;\n            wickEditor.syncInterfaces();\n        }\n    }));\n\n    properties.push(new InspectorInterface.TwoStringInput({\n        title: '<img src=\"resources/inspector-icons/size.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Project Size',\n        otherTitle: 'x',\n        isActiveFn: function () {\n            return selectionInfo.type === 'project';\n        },\n        getValueFn: function () {\n            return {\n                left: wickEditor.project.width,\n                right: wickEditor.project.height\n            };\n        }, \n        onChangeFn: function (vals) {\n            wickEditor.project.width = eval(vals.left);\n            wickEditor.project.height = eval(vals.right);\n            wickEditor.syncInterfaces();\n        }\n    }));\n\n    properties.push(new InspectorInterface.StringInput({\n        title: '<img src=\"resources/inspector-icons/framerate.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Framerate',\n        isActiveFn: function () {\n            return selectionInfo.type === 'project';\n        },\n        getValueFn: function () {\n            return wickEditor.project.framerate;\n        }, \n        onChangeFn: function (val) {\n            wickEditor.project.framerate = eval(val);\n            wickEditor.syncInterfaces();\n        }\n    }));\n\n    properties.push(new InspectorInterface.ColorPickerInput({\n        title: '<img src=\"resources/inspector-icons/paint.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Background Color',\n        previewType: 'background-color',\n        isActiveFn: function () {\n            return selectionInfo.type === 'project';\n        },\n        getValueFn: function () {\n            return wickEditor.project.backgroundColor;\n        }, \n        onChangeFn: function (val) {\n            wickEditor.project.backgroundColor = val;\n            wickEditor.syncInterfaces();\n        }\n    }));\n\n    properties.push(new InspectorInterface.SliderInput({\n        title: '<img src=\"resources/inspector-icons/brushsmoothness.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Brush Smoothness',\n        max: 100,\n        min: 0,\n        isActiveFn: function () {\n            return selectionInfo.type === 'paintbrush';\n        },\n        getValueFn: function () {\n            return wickEditor.settings.brushSmoothing;\n        }, \n        onChangeFn: function (val) {\n            wickEditor.settings.setValue('brushSmoothing', eval(val));\n            wickEditor.syncInterfaces();\n        }\n    }));\n\n    properties.push(new InspectorInterface.SliderInput({\n        title: '<img src=\"resources/inspector-icons/brushsize.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Brush Size',\n        max: 100,\n        min: 1,\n        isActiveFn: function () {\n            return selectionInfo.type === 'paintbrush';\n        },\n        getValueFn: function () {\n            return wickEditor.settings.brushThickness;\n        }, \n        onChangeFn: function (val) {\n            wickEditor.settings.setValue('brushThickness', eval(val));\n            wickEditor.syncInterfaces();\n        }\n    }));\n\n    properties.push(new InspectorInterface.SliderInput({\n        title: '<img src=\"resources/inspector-icons/brushsmoothness.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Line Smoothness',\n        max: 100,\n        min: 0,\n        isActiveFn: function () {\n            return selectionInfo.type === 'pencil';\n        },\n        getValueFn: function () {\n            return wickEditor.settings.pencilSmoothing;\n        }, \n        onChangeFn: function (val) {\n            wickEditor.settings.setValue('pencilSmoothing', eval(val));\n            wickEditor.syncInterfaces();\n        }\n    }));\n\n    properties.push(new InspectorInterface.SliderInput({\n        title: '<img src=\"resources/inspector-icons/strokewidth.png\" class=\"inspector-icon\"/>',\n        tooltip: 'Stroke Width',\n        max: 100,\n        min: 0,\n        isActiveFn: function () {\n            return selectionInfo.type === 'pencil'\n                || selectionInfo.type === 'rectangle'\n                || selectionInfo.type === 'ellipse'\n                || selectionInfo.type === 'pen'\n                || selectionInfo.type === 'line';\n        },\n        getValueFn: function () {\n            return wickEditor.settings.strokeWidth;\n        }, \n        onChangeFn: function (val) {\n            wickEditor.settings.setValue('strokeWidth', eval(val));\n            wickEditor.syncInterfaces();\n        }\n    }));\n\n    properties.push(new InspectorInterface.SliderInput({\n        title: '<img src=\"resources/inspector-icons/brushsize.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Eraser Size',\n        max: 100,\n        min: 1,\n        isActiveFn: function () {\n            return selectionInfo.type === 'eraser';\n        },\n        getValueFn: function () {\n            return wickEditor.settings.brushThickness;\n        }, \n        onChangeFn: function (val) {\n            wickEditor.settings.setValue('brushThickness', eval(val));\n            wickEditor.syncInterfaces();\n        }\n    }));\n\n    properties.push(new InspectorInterface.SliderInput({\n        title: '<img src=\"resources/inspector-icons/cornerroundness.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Corner Roundess',\n        max: 100,\n        min: 0,\n        isActiveFn: function () {\n            return selectionInfo.type === 'rectangle';\n        },\n        getValueFn: function () {\n            return wickEditor.settings.rectangleCornerRadius;\n        }, \n        onChangeFn: function (val) {\n            wickEditor.settings.setValue('rectangleCornerRadius', eval(val));\n            wickEditor.syncInterfaces();\n        }\n    }));\n\n    properties.push(new InspectorInterface.StringInput({\n        title: '<img src=\"resources/inspector-icons/name.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Name',\n        isActiveFn: function () {\n            return selectionInfo.type === 'frame' && selectionInfo.numObjects === 1;\n        },\n        getValueFn: function () {\n            return selectionInfo.object.name || \"\";\n        }, \n        onChangeFn: function (val) {\n            selectionInfo.object.name = val;\n            wickEditor.syncInterfaces()\n        }\n    }));\n\n    properties.push(new InspectorInterface.StringInput({\n        title: '<img src=\"resources/inspector-icons/framelength.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Frame Length',\n        isActiveFn: function () {\n            return selectionInfo.type === 'frame' && selectionInfo.numObjects === 1;\n        },\n        getValueFn: function () {\n            return selectionInfo.object.length;\n        }, \n        onChangeFn: function (val) {\n            wickEditor.actionHandler.doAction('changeFrameLength', {\n\t\t        frame: selectionInfo.object, \n\t\t        newFrameLength: eval(val)\n\t\t    });\n        }\n    }));\n    \n    properties.push(new InspectorInterface.StringInput({\n        title: '<img src=\"resources/inspector-icons/rotation.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Rotations',\n        isActiveFn: function () {\n            return selectionInfo.type === 'frame' \n                && selectionInfo.numObjects === 1 \n                && selectionInfo.object.getCurrentTween();\n        },\n        getValueFn: function () {\n            return selectionInfo.object.getCurrentTween().rotations;\n        }, \n        onChangeFn: function (val) {\n            var tween = selectionInfo.object.getCurrentTween();\n            tween.rotations = parseInt(val);\n        }\n    }));\n\n    properties.push(new InspectorInterface.SelectInput({\n        title: '<img src=\"resources/inspector-icons/sound.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Sound Resource',\n        optionsFn: function () {\n            var audioAssetFilenames = wickEditor.project.library.getAllAssets().filter(function (asset) {\n                return asset.type === 'audio';\n            }).map(function (asset) {\n                return asset.filename;\n            });\n            return ['None'].concat(audioAssetFilenames);\n        },\n        isActiveFn: function () {\n            return selectionInfo.type === 'frame' \n                && selectionInfo.numObjects === 1;\n        },\n        getValueFn: function () {\n            if(selectionInfo.object.hasSound()) {\n                return wickEditor.project.library.getAsset(selectionInfo.object.audioAssetUUID).filename; \n            } else {\n                return 'None'\n            }\n        },\n        onChangeFn: function (val) {\n            wickEditor.actionHandler.doAction('addSoundToFrame', {\n                frame: selectionInfo.object,\n                asset: wickEditor.project.library.getAssetByName(val),\n            });\n        }\n    }));\n\n    /*properties.push(new InspectorInterface.SliderInput({\n        title: '<img src=\"resources/inspector-icons/volume.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Volume',\n        min: 0,\n        max: 1,\n        step:.01,\n        isActiveFn: function () {\n            return selectionInfo.type === 'frame' \n                && selectionInfo.numObjects === 1 \n                && selectionInfo.object.hasSound()\n        },\n        getValueFn: function () {\n            return selectionInfo.object.volume; \n        },\n        onChangeFn: function (val) {\n            selectionInfo.object.volume = parseFloat(val);\n        }\n    }));*/\n\n    properties.push(new InspectorInterface.MultiCheckboxInput({\n        title: '<img src=\"resources/inspector-icons/ease.svg\" class=\"inspector-icon\"/>',\n        tooltip: 'Easing Direction',\n        icons: [\n            'resources/ease-none.png',\n            'resources/ease-in.png', \n            'resources/ease-out.png',\n            'resources/ease-in-out.png',\n        ],\n        isActiveFn: function () {\n            return selectionInfo.type === 'frame' \n                && selectionInfo.numObjects === 1 \n                && selectionInfo.object.getCurrentTween();\n        },\n        getValueFn: function () {\n            var tweenDir = selectionInfo.object.getCurrentTween().tweenDir\n            return [\n                tweenDir === 'None',\n                tweenDir === 'In',\n                tweenDir === 'Out',\n                tweenDir === 'InOut',\n            ];\n        }, \n        onChangeFn: function (vals) {\n            var tween = selectionInfo.object.getCurrentTween();\n\n            if(vals[0] && tween.tweenDir !== 'None') {\n                tween.tweenDir = 'None';\n                tween.tweenType = 'Linear'\n            } else if (vals[1] && tween.tweenDir !== 'In') {\n                tween.tweenDir = 'In';\n                tween.tweenType = 'Quadratic';\n            } else if (vals[2] && tween.tweenDir !== 'Out') {\n                tween.tweenDir = 'Out';\n                tween.tweenType = 'Quadratic';\n            } else if (vals[3] && tween.tweenDir !== 'InOut') {\n                tween.tweenDir = 'InOut';\n                tween.tweenType = 'Quadratic';\n            }\n            wickEditor.syncInterfaces();\n        }\n    }));\n\n/* Buttons */\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Flip Horizontally\",\n        icon: \"./resources/inspector-flip-horizontally.svg\",\n        colorClass: 'common',\n        isActiveFn: function () {\n            return (selectionInfo.numObjects > 0 && selectionInfo.type === 'wickobject');\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction('flipHorizontally');\n        }\n    }));\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Flip Vertically\",\n        icon: \"./resources/inspector-flip-vertically.svg\",\n        colorClass: 'common',\n        isActiveFn: function () {\n            return (selectionInfo.numObjects > 0 && selectionInfo.type === 'wickobject');\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction('flipVertically');\n        }\n    }));\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Delete\",\n        icon: \"./resources/inspector-delete.svg\",\n        colorClass: 'common',\n        isActiveFn: function () {\n            return (selectionInfo.numObjects > 0 && selectionInfo.type === 'wickobject');\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction(\"deleteSelectedObjects\")\n        }\n    }));\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Duplicate\",\n        icon: \"./resources/inspector-duplicate.svg\",\n        colorClass: 'common',\n        isActiveFn: function () {\n            return (selectionInfo.numObjects > 0 && selectionInfo.type === 'wickobject');\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction(\"duplicateSelection\")\n        }\n    }));\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Send to Back\",\n        icon: \"./resources/inspector-send-to-back.png\",\n        colorClass: 'common',\n        isActiveFn: function () {\n            return (selectionInfo.numObjects > 0 && selectionInfo.type === 'wickobject');\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction(\"sendToBack\")\n        }\n    }));\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Bring to Front\",\n        icon: \"./resources/inspector-bring-to-front.png\",\n        colorClass: 'common',\n        isActiveFn: function () {\n            return (selectionInfo.numObjects > 0 && selectionInfo.type === 'wickobject');\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction(\"bringToFront\")\n        }\n    }));\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Move Forwards\",\n        icon: \"./resources/inspector-move-up.svg\",\n        colorClass: 'common',\n        isActiveFn: function () {\n            return (selectionInfo.numObjects > 0 && selectionInfo.type === 'wickobject');\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction(\"moveForwards\")\n        }\n    }));\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Move Backwards\",\n        icon: \"./resources/inspector-move-back.svg\",\n        colorClass: 'common',\n        isActiveFn: function () {\n            return (selectionInfo.numObjects > 0 && selectionInfo.type === 'wickobject');\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction(\"moveBackwards\")\n        }\n    }));\n\n    properties.push(new InspectorInterface.Divider());\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Group Objects\",\n        icon: \"./resources/group.svg\",\n        colorClass: 'multiple',\n        isActiveFn: function () {\n            return selectionInfo.numObjects > 0 \n                && (selectionInfo.type === 'wickobject' || selectionInfo.type === 'multiple') \n                && selectionInfo.dataType !== 'symbol';\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction(\"convertToGroup\");\n        }\n    }));\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Create Clip from Objects\",\n        icon: \"./resources/inspector-edit-timeline.svg\",\n        colorClass: 'multiple',\n        isActiveFn: function () {\n            return selectionInfo.numObjects > 0 \n                && (selectionInfo.type === 'wickobject' || selectionInfo.type === 'multiple') \n                && selectionInfo.dataType !== 'symbol';\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction(\"convertToSymbol\")\n        }\n    }));\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Create Button from Objects\",\n        icon: \"./resources/inspector-button.svg\",\n        colorClass: 'multiple',\n        isActiveFn: function () {\n            return selectionInfo.numObjects > 0 \n                && (selectionInfo.type === 'wickobject' || selectionInfo.type === 'multiple') \n                && selectionInfo.dataType !== 'symbol';\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction(\"convertToButton\")\n        }\n    }));\n\n    properties.push(new InspectorInterface.Divider());\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Edit JavaScript\",\n        icon: \"./resources/javascript.png\",\n        colorClass: 'symbol',\n        isActiveFn: function () {\n            return selectionInfo.numObjects === 1 \n                && selectionInfo.type === 'wickobject'\n                && selectionInfo.dataType === 'symbol'\n                && (!selectionInfo.object.isGroup);\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction(\"editScripts\");\n        }\n    }));\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Edit Frames\",\n        icon: \"./resources/inspector-edit-timeline.svg\",\n        colorClass: 'symbol',\n        isActiveFn: function () {\n            return selectionInfo.numObjects === 1 \n                && selectionInfo.type === 'wickobject'\n                && selectionInfo.dataType === 'symbol'\n                && (!selectionInfo.object.isGroup);\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction(\"editObject\")\n        }\n    }));\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Edit Group\",\n        icon: \"./resources/group.svg\",\n        colorClass: 'symbol',\n        isActiveFn: function () {\n            return selectionInfo.numObjects === 1 \n                && selectionInfo.type === 'wickobject'\n                && selectionInfo.dataType === 'symbol'\n                && selectionInfo.object.isGroup;\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction(\"editObject\")\n        }\n    }));\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Break Apart\",\n        icon: \"./resources/inspector-break-apart.svg\",\n        colorClass: 'symbol',\n        isActiveFn: function () {\n            return selectionInfo.numObjects === 1 \n                && selectionInfo.type === 'wickobject'\n                && selectionInfo.dataType === 'symbol'\n                && selectionInfo.object.parentFrame.tweens.length === 0;\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction(\"breakApart\")\n        }\n    }));\n\n    properties.push(new InspectorInterface.Divider());\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Add Tween Keyframe\",\n        icon: \"./resources/add-tween.png\",\n        colorClass: 'tweens',\n        isActiveFn: function () {\n            return selectionInfo.numObjects === 1 \n                && selectionInfo.dataType === 'frame'\n                && !selectionInfo.object.getCurrentTween()\n                && selectionInfo.object.wickObjects.length > 0;\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction('createMotionTween');\n        }\n    }));\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Paste Tween Keyframe\",\n        icon: \"./resources/paste-tween.png\",\n        colorClass: 'tweens',\n        isActiveFn: function () {\n            return selectionInfo.numObjects === 1 \n                && selectionInfo.dataType === 'frame'\n                && !selectionInfo.object.getCurrentTween()\n                && selectionInfo.object.wickObjects.length > 0;\n        },\n        buttonAction: function () {\n            if(wickEditor.project.tweenClipboardData) {\n                var pastedTween = JSON.parse(wickEditor.project.tweenClipboardData);\n                pastedTween.__proto__ = WickTween.prototype;\n                pastedTween.playheadPosition = wickEditor.project.getCurrentObject().playheadPosition - selectionInfo.object.playheadPosition;\n                wickEditor.actionHandler.doAction('addKeyframe', {\n                    frame: selectionInfo.object,\n                    tween: pastedTween\n                })\n            }\n        }\n    }));\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Copy Tween Keyframe\",\n        icon: \"./resources/copy-tween.png\",\n        colorClass: 'tweens',\n        isActiveFn: function () {\n            return selectionInfo.numObjects === 1 \n                && selectionInfo.dataType === 'frame'\n                && selectionInfo.object.getCurrentTween();\n        },\n        buttonAction: function () {\n            wickEditor.project.tweenClipboardData = JSON.stringify(selectionInfo.object.getCurrentTween());\n        }\n    }));\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Delete Tween Keyframe\",\n        icon: \"./resources/delete-tween.png\",\n        colorClass: 'tweens',\n        isActiveFn: function () {\n            return selectionInfo.numObjects === 1 \n                && selectionInfo.dataType === 'frame'\n                && selectionInfo.object.getCurrentTween();\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction('deleteMotionTween');\n        }\n    }));\n\n    properties.push(new InspectorInterface.Divider());\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Clone Frame\",\n        icon: \"./resources/inspector-duplicate.svg\",\n        colorClass: 'frames',\n        isActiveFn: function () {\n            return selectionInfo.numObjects > 0 \n                && selectionInfo.dataType === 'frame';\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction('copyFrameForward')\n        }\n    }));\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Delete Frame(s)\",\n        icon: \"./resources/inspector-delete.svg\",\n        colorClass: 'frames',\n        isActiveFn: function () {\n            return selectionInfo.numObjects > 0 \n                && selectionInfo.dataType === 'frame';\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction(\"deleteSelectedObjects\")\n        }\n    }));\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Extend Frame to Playhead\",\n        icon: \"./resources/inspector-edit-timeline.svg\",\n        colorClass: 'frames',\n        isActiveFn: function () {\n            return selectionInfo.numObjects > 0 \n                && selectionInfo.dataType === 'frame';\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction(\"extendFrameToPlayhead\")\n        }\n    }));\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Edit JavaScript\",\n        icon: \"./resources/javascript.png\",\n        colorClass: 'frames',\n        isActiveFn: function () {\n            return selectionInfo.numObjects === 1 \n                && selectionInfo.dataType === 'frame';\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction(\"editScripts\");\n        }\n    }));\n\n    properties.push(new InspectorInterface.Divider());\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Unite Paths\",\n        icon: \"./resources/inspector-unite.png\",\n        colorClass: 'all-paths',\n        isActiveFn: function () {\n            return selectionInfo.numObjects > 1 \n                && selectionInfo.special.allPaths;\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction('doBooleanOperation', {boolFnName:'unite'});\n        }\n    }));\n\n    properties.push(new InspectorInterface.InspectorButton({\n        tooltipTitle: \"Subtract Paths\",\n        icon: \"./resources/inspector-subtract.png\",\n        colorClass: 'all-paths',\n        isActiveFn: function () {\n            return selectionInfo.numObjects > 1 \n                && selectionInfo.special.allPaths;\n        },\n        buttonAction: function () {\n            wickEditor.guiActionHandler.doAction('doBooleanOperation', {boolFnName:'subtract'});\n        }\n    }));\n\n    return properties;\n}"
  },
  {
    "path": "src/editor/interfaces/Interfaces.Inspector.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar InspectorInterface = function (wickEditor) {\n\n    var inputs;\n\n    var selectionIcon;\n    var selectionTitle;\n    var inspectorTitle;\n\n    var specialMode;\n\n    this.selectionInfo = {\n        objects: [],\n        object: null,\n        numObjects: 0,\n        type: null,\n        dataType: null,\n        special: {},\n    }\n    var selectionInfo = this.selectionInfo;\n\n    this.setup = function () {\n        selectionTitleBar = document.getElementById('inspector-title-bar');\n        selectionIcon = document.getElementsByClassName('inspector-selection-icon')[0];\n        selectionTitle = document.getElementsByClassName('inspector-selection-title')[0];\n        inspectorTitle = document.getElementById('inspector-title');\n\n        allItemsContainer = document.getElementsByClassName('inspector-allitems-container')[0];\n        propertiesContainer = document.getElementsByClassName('inspector-properties-container')[0];\n        buttonsContainer = document.getElementsByClassName('inspector-buttons-container')[0];\n\n        specialMode = 'project';\n\n        inputs = InspectorInterface.getProperties(wickEditor, this);\n        inputs.forEach(function (input) {\n            if(input.getPropertyDiv) {\n                propertiesContainer.appendChild(input.getPropertyDiv());\n            }\n            if(input.getButtonDiv) {\n                buttonsContainer.appendChild(input.getButtonDiv());\n            }\n        });\n    }\n\n    this.syncWithEditorState = function () {\n\n        inputs.forEach(function (input) {\n            if(input.isFocused && input.isFocused()) {\n                $('.inspector-input').blur()\n                input.updateModelValue();\n            }\n        });\n\n        // Recalc selection vars\n        selectionInfo.numObjects = wickEditor.project.getNumSelectedObjects();\n        selectionInfo.objects = wickEditor.project.getSelectedObjects();\n        selectionInfo.object = wickEditor.project.getSelectedObject();\n        selectionInfo.uuids = wickEditor.project.getSelectedObjectsUUIDs();\n        selectionInfo.dataType = null;\n        selectionInfo.special = {};\n\n        // Show current frame if nothing is selected\n        if(selectionInfo.numObjects === 0) {\n            selectionInfo.object = wickEditor.project.getCurrentFrame();\n            if(!selectionInfo.object) {\n                selectionInfo.numObjects = 0;\n            } else {\n                selectionInfo.numObjects = 1;\n            }\n        }\n\n        if(specialMode) {\n            selectionInfo.type = specialMode;\n            selectionInfo.dataType = null;\n        } else if(selectionInfo.object) {\n            if(selectionInfo.object.isImage) {\n                selectionInfo.type = 'wickobject';\n                selectionInfo.dataType = 'image';\n            } else if (selectionInfo.object.isPath) {\n                selectionInfo.type = 'wickobject';\n                selectionInfo.dataType = 'path';\n            } else if (selectionInfo.object.isText) {\n                selectionInfo.type = 'wickobject';\n                selectionInfo.dataType = 'text';\n            } else if (selectionInfo.object.isSymbol) {\n                selectionInfo.type = 'wickobject';\n                selectionInfo.dataType = 'symbol';\n            } else if (selectionInfo.object instanceof WickFrame) {\n                selectionInfo.type = 'frame';\n                selectionInfo.dataType = 'frame';\n            }\n        } else {\n            if(selectionInfo.numObjects === 0) {\n                selectionInfo.type = 'none';\n                selectionInfo.dataType = null;\n            } else {\n                if(selectionInfo.objects[0] instanceof WickObject) {\n                    selectionInfo.type = 'wickobject'\n                } else if(selectionInfo.objects[0] instanceof WickFrame) {\n                    selectionInfo.type = 'frame'\n                    selectionInfo.dataType = 'frame';\n                }\n\n                // Check for special selection cases\n                selectionInfo.special.allPaths = true;\n                selectionInfo.objects.forEach(function (object) {\n                    if(!object.isPath) {\n                        selectionInfo.special.allPaths = false;\n                    }\n                })\n            }\n        }\n\n        updateSelectonTypeTitle();\n\n        // Update values in view\n        inputs.forEach(function (input) {\n            input.updateViewValue();\n        });\n    }\n\n    this.clearSpecialMode = function () {\n        specialMode = undefined;\n    }\n\n    this.toggleProjectSettings = function () {\n        if(specialMode === 'project') {\n            specialMode = null;\n        } else {\n            specialMode = 'project';\n        }\n    }\n\n    this.openProjectSettings = function () {\n        specialMode = 'project';\n    }\n\n    this.openToolSettings = function (tool) {\n        specialMode = tool;\n    }\n\n    this.getButtons = function () {\n        var buttons = [];\n        inputs.forEach(function (input) {\n            if(input instanceof InspectorInterface.InspectorButton) {\n                buttons.push(input);\n            }\n        });\n        return buttons;\n    }\n\n    var updateSelectonTypeTitle = function () {\n\n        var noSelectionTitle = \"Inspector\";\n        var title; \n        var image;\n\n        if(selectionInfo.type === 'project') {\n\n            title = \"Project Settings\"\n            image = \"./resources/settings.png\";\n\n        } else if(selectionInfo.type === 'paintbrush') {\n\n            title = \"Brush Options\"\n            image = \"./resources/tools/Paintbrush.svg\";\n\n        } else if(selectionInfo.type === 'pencil') {\n\n            title = \"Pencil Options\"\n            image = \"./resources/tools/Pencil.svg\";\n\n        } else if(selectionInfo.type === 'fillbucket') {\n\n            title = \"Fill Options\"\n            image = \"./resources/tools/Bucket.svg\";\n\n        } else if(selectionInfo.type === 'eraser') {\n\n            title = \"Eraser Options\"\n            image = \"./resources/tools/Erase.svg\";\n\n        } else if(selectionInfo.type === 'rectangle') {\n\n            title = \"<p style='font-size:18px;'>Rectangle Options</p>\"\n            image = \"./resources/tools/Square.svg\";\n\n        } else if(selectionInfo.type === 'ellipse') {\n\n            title = \"Ellipse Options\"\n            image = \"./resources/tools/Circle.svg\";\n\n        } else if(selectionInfo.type === 'pen') {\n\n            title = \"Pen Options\"\n            image = \"./resources/tools/Path.svg\";\n\n        } else if(selectionInfo.type === 'line') {\n\n            title = \"Line Options\"\n            image = \"./resources/tools/Line.svg\";\n\n        } else if(selectionInfo.type === 'none') {\n\n            noSelectionTitle = \"Inspector (No Selection)\"\n            title = \"\"\n            image = null;\n\n        } else if(selectionInfo.numObjects > 1) {\n\n            if(selectionInfo.type === 'wickobject') {\n                title = \"<p style='font-size:18px;'>Multiple Objects</p>\"\n                image = './resources/inspector-icons/multipleobjects.svg';\n            } else if (selectionInfo.type === 'frame') {\n                title = \"Multiple Frames\"\n                image = \"./resources/inspector-edit-timeline.svg\"\n            }\n\n        } else if(selectionInfo.type === 'wickobject') {\n\n            if(selectionInfo.dataType === 'symbol' && selectionInfo.object.isButton) {\n                title = \"Button\"; \n                image = \"./resources/inspector-button.svg\"\n            } else if(selectionInfo.dataType === 'symbol' && selectionInfo.object.isGroup) {\n                title = \"Group\"; \n                image = \"./resources/group.svg\"\n            } else if(selectionInfo.dataType === 'symbol' && !selectionInfo.object.isButton) {\n                title = \"Clip\"; \n                image = \"./resources/inspector-edit-timeline.svg\"\n            } else if (selectionInfo.dataType === 'path') {\n                title = \"Path\";\n                image = \"./resources/tools/Path.svg\"\n            } else if (selectionInfo.dataType === 'image') {\n                title = \"Image\"; \n                image = \"./resources/image.png\"\n            } else if (selectionInfo.dataType === 'text') {\n                title = \"Text\"; \n                image = \"./resources/text.png\"\n            } else if (selectionInfo.dataType === 'sound') {\n                title = \"Sound\";\n                image = \"./resources/icon_sound_white.png\"; \n            }\n\n        } else if (selectionInfo.type === 'frame') {\n            title = \"Frame\";  \n            image = \"./resources/inspector-edit-timeline.svg\"\n        }\n\n        selectionTitle.innerHTML = title;\n        inspectorTitle.innerHTML = noSelectionTitle;\n        if(image)\n            selectionIcon.style.backgroundImage = 'url('+image+')';\n        else\n            selectionIcon.style.backgroundImage = 'none';\n\n    }\n\n}"
  },
  {
    "path": "src/editor/interfaces/Interfaces.Library.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n    \nvar LibraryInterface = function (wickEditor) {\n\n    var self = this;\n\n    self.dirty = false;\n\n    var selectedNode;\n    var draggedNode;\n\n    var draggedAssetElem;\n    var isDraggingAsset = false; \n\n    this.setup = function () {\n        $(\"#tree\").mousedown(function() {\n            wickEditor.project.clearSelection();\n        });\n        \n        $(\"#tree\").fancytree({\n            extensions: [\"filter\"],\n            filter: { \n                counter: false, \n                mode: \"hide\",\n            },\n            selectMode: 1,\n            activate: function(event, data) {\n                selectedNode = data.node;\n            },\n            select: function(event, data) {\n            },\n            dblclick: function(event, data) {\n            },\n        });\n\n        // Setup the filter\n        var filterInput = $('#treeFilterInput');\n        filterInput.bind(\"propertychange change click keyup input paste\", function(event){\n            $(\"#tree\").fancytree(\"getTree\").filterNodes(filterInput.val());\n        });\n\n        // Enable the delete asset button\n        var deleteAssetButton = $('#deleteAssetButton');\n        deleteAssetButton.bind(\"mouseup\", function(event) {\n            wickEditor.guiActionHandler.doAction('deleteAsset'); \n        });\n\n        // Enable rename asset button\n        var renameAssetButton = $('#renameAssetButton');\n        renameAssetButton.bind(\"mouseup\", function(event) {\n            wickEditor.guiActionHandler.doAction('renameAsset'); \n        });\n\n        draggedAssetElem = document.createElement('div');\n        draggedAssetElem.id = 'draggedAsset';\n        document.getElementById('tree').addEventListener('mousedown', function (e) {\n            draggedNode = selectedNode;\n            draggedAssetElem.style.display = 'block';\n            var asset = self.getSelectedAsset();\n            if (!asset) return; \n\n            var assetURL;\n            if(asset.type === 'image') {\n                assetURL = asset.data;\n            } else if(asset.type === 'audio') {\n                assetURL = 'resources/icon_sound_canvas.png';\n            } else if (asset.type === 'symbol') {\n                assetURL = 'resources/icon_sound_canvas.png';\n            }\n            draggedAssetElem.style.backgroundImage = 'url('+assetURL+')';\n            isDraggingAsset = true; \n        });\n        window.addEventListener('mouseup', function (e) {\n            if(!draggedNode) return;\n            draggedNode = null;\n            draggedAssetElem.style.display = 'none';\n            if(e.target.className === 'frame') {\n                wickEditor.actionHandler.doAction('addSoundToFrame', {\n                    frame: e.target.wickData.wickFrame,\n                    asset: self.getSelectedAsset()\n                });\n            } else if(e.target.nodeName === 'CANVAS' && (self.getSelectedAsset().type === 'image' || self.getSelectedAsset().type === 'symbol')) {\n                wickEditor.guiActionHandler.doAction(\"createObjectFromAsset\", {\n                    asset: self.getSelectedAsset(),\n                    x: e.x,\n                    y: e.y\n                });\n            }\n            isDraggingAsset = false; \n        });\n        window.addEventListener('mousemove', function (e) {\n            if(!draggedAssetElem) return;\n            draggedAssetElem.style.left = e.x + 'px';\n            draggedAssetElem.style.top = e.y + 'px';\n        });\n        document.body.appendChild(draggedAssetElem);\n    }\n\n    this.syncWithEditorState = function () {\n        //if(this.dirty) {\n            this.dirty = false;\n            this.clear();\n            this.populate();\n        //}\n    }\n\n    this.populate = function () {\n\n        var newTreeChildren = [];\n\n        var library = wickEditor.project.library;\n        for (uuid in library.assets) {\n            var asset = library.assets[uuid];\n            var iconSrc = {\n                image : 'resources/library-image.png',\n                audio : 'resources/icon_sound.png',\n            }[asset.type]\n            newTreeChildren.push({ \n                title: asset.filename,\n                data: {uuid:asset.uuid},\n                icon: iconSrc,\n            });\n        }\n\n        $(\"#tree\").fancytree(\"getRootNode\").addChildren(newTreeChildren);\n\n    }\n\n    this.clear = function () {\n\n        var node = $(\"#tree\").fancytree(\"getRootNode\");\n\n        while( node.hasChildren() ) {\n            node.getFirstChild().remove();\n        }\n        \n    }\n\n    this.isSelected = function () {\n        return (document.activeElement.className.includes('fancytree'));\n    }\n\n    this.getSelectedAsset = function () {\n        if (!selectedNode) return; \n        return wickEditor.project.library.getAsset(selectedNode.data.uuid)\n    }\n\n    this.isDraggingAsset = function () {\n        return isDraggingAsset; \n    }\n\n}\n"
  },
  {
    "path": "src/editor/interfaces/Interfaces.MenuBar.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick.\n\n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar MenuBarInterface = function (wickEditor) {\n\n    var editorElem;\n    var menuElem;\n    var tabContainer;\n    var projectNameElem;\n    var projectSettingsElem;\n\n    var tabs;\n\n\tvar Tab = function (name, buttons, func) {\n        this.buttons = buttons;\n        this.name = name;\n\n        this.generateElem = function () {\n            var self = this;\n\n            var tabElem = document.createElement('div');\n            tabElem.className = \"menubarTab\";\n            tabElem.id = 'menubarMenu' + this.name;\n            tabElem.innerHTML = this.name;\n            tabElem.onclick = function () {\n                if(func) {\n                    func();\n                    return;\n                }\n                var visible = self.elem.style.display === \"block\";\n                closeAllMenus();\n                if(visible) {\n                    self.elem.style.display = \"none\";\n                } else {\n                    self.elem.style.display = \"block\";\n                }\n                self.elem.style.left = (tabElem.offsetLeft-8) + 'px';\n            }\n            tabContainer.appendChild(tabElem);\n\n            this.elem = document.createElement('div');\n            this.elem.className ='GUIBox menubarMenu';\n            this.elem.id = 'menubarMenuDropdown' + this.name;\n            this.elem.style.display = 'none';\n\n            this.buttons.forEach(function (button) {\n                button.generateElem();\n                self.elem.appendChild(button.elem);\n            });\n            editorElem.appendChild(this.elem);\n        }\n    }\n\n    var TabButton = function (name, func) {\n        this.name = name;\n        this.func = func;\n\n        this.generateElem = function () {\n            this.elem = document.createElement('div');\n            this.elem.className ='menubarButton';\n            this.elem.id = 'menubarMenu' + this.name;\n            this.elem.innerHTML = this.name;\n            this.elem.onclick = function () {\n                closeAllMenus();\n                func();\n            }\n        }\n    }\n\n    var TabSpacer = function () {\n        this.generateElem = function () {\n            this.elem = document.createElement('hr');\n        }\n    }\n\n    this.setup = function () {\n        editorElem = document.getElementById('editor');\n\n        menuElem = document.createElement('div');\n        menuElem.id = \"menuBarGUI\";\n        menuElem.className = \"GUIBox\";\n        editorElem.appendChild(menuElem);\n\n        tabContainer = document.createElement('div');\n        tabContainer.className = \"tab-container\";\n        menuElem.appendChild(tabContainer);\n\n        projectNameElem = document.createElement('div');\n        projectNameElem.className = \"menuBarProjectTitle\";\n        projectNameElem.onclick = function () {\n            wickEditor.guiActionHandler.doAction('saveProject')\n        }\n\n        projectSettingsElem = document.createElement('div');\n        projectSettingsElem.className = 'tooltipElem menuBarProjectSettingsButton';\n        projectSettingsElem.setAttribute('alt', \"Project settings\");\n        projectSettingsElem.onclick = function () {\n            wickEditor.guiActionHandler.doAction(\"toggleProjectSettings\");\n        }\n\n        var menuBarProjectControls = document.createElement('div');\n        menuBarProjectControls.className = \"menuBarProjectControls\";\n        menuBarProjectControls.appendChild(projectNameElem);\n        menuBarProjectControls.appendChild(projectSettingsElem);\n        menuElem.appendChild(menuBarProjectControls);\n\n        tabs = [];\n\n        wickEditor.canvas.getCanvasContainer().addEventListener('mousedown', function (e) {\n            closeAllMenus();\n        });\n\n        addTab('File', [\n            new TabButton('New Project', function () {\n                wickEditor.guiActionHandler.doAction(\"newProject\");\n            }),\n            new TabButton('Open Project', function () {\n                wickEditor.guiActionHandler.doAction(\"openFile\");\n            }),\n            new TabButton('Save Project', function () {\n                wickEditor.guiActionHandler.doAction(\"exportProjectWick\");\n            }),\n            new TabSpacer(),\n\n            /*new TabButton('Export SVG', function () {\n                wickEditor.guiActionHandler.doAction(\"exportFrameSVG\");\n            }),\n            new TabButton('Export PNG', function () {\n                wickEditor.guiActionHandler.doAction(\"exportProjectPNG\");\n            }),*/\n            new TabButton('Export HTML', function () {\n                wickEditor.guiActionHandler.doAction(\"exportProjectHTML\");\n            }),\n            new TabButton('Export ZIP', function () {\n                wickEditor.guiActionHandler.doAction(\"exportProjectZIP\");\n            }),\n            /*new TabButton('Export Project as JSON', function () {\n                wickEditor.guiActionHandler.doAction(\"exportProjectJSON\");\n            }),*/\n            new TabButton('Export Animated GIF', function () {\n                wickEditor.guiActionHandler.doAction(\"exportProjectGIF\");\n            }),\n            new TabButton('Export Video', function () {\n                wickEditor.guiActionHandler.doAction(\"openProjectExportWindow\");\n            }),\n            new TabSpacer(),\n\n            new TabButton('Run project', function () {\n                wickEditor.guiActionHandler.doAction(\"runProject\");\n            }),\n            new TabButton('Project settings', function () {\n                wickEditor.guiActionHandler.doAction(\"openProjectSettings\");\n            }),\n        ]);\n\n        addTab('Edit', [\n            new TabButton('Undo', function () {\n                wickEditor.guiActionHandler.doAction(\"undo\")\n            }),\n            new TabButton('Redo', function () {\n                wickEditor.guiActionHandler.doAction(\"redo\")\n            }),\n            new TabSpacer(),\n\n            new TabButton('Cut', function () {\n                wickEditor.guiActionHandler.doAction(\"cut\")\n            }),\n            new TabButton('Copy', function () {\n                wickEditor.guiActionHandler.doAction(\"copy\")\n            }),\n            new TabButton('Paste', function () {\n                wickEditor.guiActionHandler.doAction(\"paste\")\n            }),\n            new TabButton('Delete', function () {\n                wickEditor.guiActionHandler.doAction(\"deleteSelectedObjects\")\n            }),\n            new TabSpacer(),\n\n            new TabButton('Select All', function () {\n                wickEditor.guiActionHandler.doAction(\"selectAll\")\n            }),\n            new TabButton('Deselect All', function () {\n                wickEditor.guiActionHandler.doAction(\"deselectAll\")\n            }),\n        ]);\n\n        addTab('Import', [\n            new TabButton('Image', function () {\n                wickEditor.guiActionHandler.doAction(\"importFile\");\n            }),\n            new TabButton('Sound', function () {\n                wickEditor.guiActionHandler.doAction(\"importFile\");\n            }),\n            new TabButton('SVG', function () {\n                wickEditor.guiActionHandler.doAction(\"importFile\");\n            }),\n            /*new TabButton('JSON', function () {\n                wickEditor.guiActionHandler.doAction(\"importFile\");\n            }),\n            new TabButton('Script', function () {\n                wickEditor.guiActionHandler.doAction(\"importFile\");\n            }),*/\n        ]);\n\n        addTab('Help', [\n            new TabButton('Hotkeys', function () {\n                wickEditor.guiActionHandler.doAction(\"openEditorSettings\");\n            }),\n            new TabButton('Examples', function () {\n                window.open('http://www.wickeditor.com/#examples')\n            }),\n            new TabButton('Tutorials', function () {\n                window.open('http://www.wickeditor.com/#tutorials')\n            }),\n            new TabButton('Forums', function () {\n                window.open('http://forum.wickeditor.com/')\n            }),\n            new TabButton('Browser Info', function () {\n                wickEditor.guiActionHandler.doAction('printBrowserInfo');\n            }),\n        ]);\n\n        addTab('About', [\n            new TabButton('Source code', function () {\n                window.open('https://www.github.com/zrispo/wick/');\n            }),\n            new TabButton('Credits', function () {\n                window.open('http://www.wickeditor.com/#about');\n            }),\n        ]);\n\n        addTab('Run', [], function () {\n                wickEditor.guiActionHandler.doAction(\"runProject\");\n            });\n    }\n\n    var addTab = function (name, buttons, func) {\n        var tab = new Tab(name, buttons, func);\n        tab.generateElem();\n        tabs.push(tab);\n    }\n\n    var closeAllMenus = function () {\n        tabs.forEach(function (tab) {\n            tab.elem.style.display = \"none\";\n        })\n    }\n\n    this.syncWithEditorState = function () {\n        document.title = \"Wick Editor: \" + wickEditor.project.name\n\n        if(projectNameElem) {\n            if(wickEditor.project.unsaved) {\n                projectNameElem.innerHTML = wickEditor.project.name + ' <span class=\"unsavedText\">(unsaved)</span>';\n            } else {\n                projectNameElem.innerHTML = wickEditor.project.name;\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/editor/interfaces/Interfaces.RightClickMenu.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar RightClickMenuInterface = function (wickEditor) {\n\n    var self = this;\n\n    var menu;\n\n    var enabled = true;\n    var timelineMode = false;\n\n// menu object definitions\n\n    var RightClickMenu = function (buttonGroups) {\n        var self = this;\n\n        this.open = false;\n\n        this.buttonGroups = buttonGroups;\n\n        this.elem = null;\n\n        this.generateElem = function () {\n\n            this.elem = document.createElement('div');\n            this.elem.id = 'rightClickMenu';\n            this.elem.className = \"GUIBox\";\n            document.getElementById('editor').appendChild(this.elem);\n\n            this.buttonGroups.forEach(function (buttonGroup) {\n                buttonGroup.generateElem();\n                self.elem.appendChild(buttonGroup.elem);\n            });\n\n            var textboxSelected = function (e) {\n                return e.target.tagName === 'INPUT' || e.target.className === 'ace_content' || e.target.tagName === 'TEXTAREA';\n            } \n\n            var mouseEventHandler = function (e) {\n                if(!enabled) return;\n\n                if(e.button == 2) {\n                    if(textboxSelected(e)) {\n                        self.open = false;\n                        return;\n                    }\n                    self.open = true;\n                    timelineMode = e.target.className.includes('frame');\n                } else {\n                    self.open = false;\n                }\n\n                self.updateElem(e);\n            }\n\n            window.addEventListener('mousedown', function(e) { \n                mouseEventHandler(e);\n            });\n            document.addEventListener('contextmenu', function (e) { \n                if(enabled && !textboxSelected(e)) e.preventDefault();\n            }, false);\n\n        }\n\n        this.updateElem = function (e) {\n\n            if(this.open) {\n\n                self.buttonGroups.forEach(function (buttonGroup) {\n                    buttonGroup.updateElem();\n                });\n\n                this.elem.style.display = 'block';\n\n                var newX = wickEditor.inputHandler.mouse.x;\n                var newY = wickEditor.inputHandler.mouse.y;\n                if(newX+this.elem.offsetWidth > window.innerWidth) {\n                    newX = window.innerWidth - this.elem.offsetWidth;\n                }\n                if(newY+this.elem.offsetHeight > window.innerHeight) {\n                    newY = window.innerHeight - this.elem.offsetHeight;\n                }\n                this.elem.style.left = newX+'px';\n                this.elem.style.top  = newY+'px';\n            \n            } else {\n\n                this.elem.style.display = 'none';\n                this.elem.style.top = '0px';\n                this.elem.style.left = '0px';\n\n            }\n\n        }\n\n    }\n\n    var RightClickMenuButtonGroup = function (buttons, isActiveFn, isLibraryGroup) {\n        var self = this;\n\n        this.buttons = buttons;\n        this.isActiveFn = isActiveFn;\n        this.elem = null;\n        this.isLibraryGroup = isLibraryGroup;\n\n        this.generateElem = function () {\n            this.elem = document.createElement('div');\n\n            this.buttons.forEach(function (button) {\n                button.generateElem();\n                self.elem.appendChild(button.elem);\n            });\n            //this.elem.appendChild(document.createElement('hr'));\n        }\n\n        this.updateElem = function () {\n            if(wickEditor.library.isSelected() && !this.isLibraryGroup) {\n                this.elem.style.display = 'none';\n            } else if(this.isActiveFn()) {\n                this.elem.style.display = 'block';\n            } else {\n                this.elem.style.display = 'none';\n            }\n        }\n\n    }\n\n    var RightClickMenuButton = function (title, icon, action) {\n        var self = this;\n\n        this.title = title;\n        this.action = action;\n        this.elem = null;\n\n        this.generateElem = function () {\n            this.elem = document.createElement('div');\n            this.elem.className = 'rightClickMenuButton';\n            this.elem.innerHTML = title;\n\n            var iconElem = document.createElement('div');\n            iconElem.className = 'rightClickMenuButtonIcon';\n            iconElem.style.backgroundImage = icon;\n            this.elem.appendChild(iconElem)\n\n            this.elem.addEventListener('mousedown', function (e) {\n                menu.open = false;\n                self.action();\n            });\n        }\n\n        this.updateElem = function () {\n\n        }\n\n    }\n\n// Interface API\n\n    self.setup = function () {\n        var buttons = []\n\n        buttons.push(new RightClickMenuButtonGroup([\n            new RightClickMenuButton(\n                \"Add Frame\", \n                'url(./resources/inspector-duplicate.svg)', \n                function () { wickEditor.actionHandler.doAction('addNewFrame'); }),\n            ], function () {return wickEditor.project.getSelectedObjects().length < 1 && timelineMode && !wickEditor.library.isSelected()}, false ));\n\n        wickEditor.inspector.getButtons().forEach(function (button) {\n            var group = new RightClickMenuButtonGroup([\n                new RightClickMenuButton(button.name, button.icon, button.buttonAction),\n            ], button.isActiveFn, false);\n            buttons.push(group);\n        });\n\n        buttons.push(new RightClickMenuButtonGroup([\n            new RightClickMenuButton(\n                \"Copy\", \n                'url(./resources/copy.svg)', \n                function () { wickEditor.guiActionHandler.doAction(\"copy\") }),\n            ], function () {return !wickEditor.library.isSelected()}, false ));\n\n        buttons.push(new RightClickMenuButtonGroup([\n            new RightClickMenuButton(\n                \"Cut\", \n                'url(./resources/cut.svg)', \n                function () { wickEditor.guiActionHandler.doAction(\"cut\") }),\n            ], function () {return !wickEditor.library.isSelected()}, false ));\n\n        buttons.push(new RightClickMenuButtonGroup([\n            new RightClickMenuButton(\n                \"Paste\", \n                'url(./resources/paste.svg)', \n                function () { wickEditor.guiActionHandler.doAction(\"paste\") }),\n            ], function () {return !wickEditor.library.isSelected()}, false ));\n\n        /*buttons.push(new RightClickMenuButtonGroup([\n            new RightClickMenuButton(\n                \"Create Object from Asset\", \n                'url(./resources/inspector-duplicate.svg)', \n                function () { wickEditor.guiActionHandler.doAction(\"createObjectFromAsset\") }),\n            ], function () {return wickEditor.library.isSelected()}, true ));*/\n\n        buttons.push(new RightClickMenuButtonGroup([\n            new RightClickMenuButton(\n                \"Delete Asset\", \n                'url(./resources/delete-layer.svg)', \n                function () { wickEditor.guiActionHandler.doAction(\"deleteAsset\") }),\n            ], function () {return wickEditor.library.isSelected()}, true ));\n\n        buttons.push(new RightClickMenuButtonGroup([\n            new RightClickMenuButton(\n                \"Rename Asset\", \n                'url(./resources/pen.png)', \n                function () { wickEditor.guiActionHandler.doAction(\"renameAsset\") }),\n            ], function () {return wickEditor.library.isSelected()}, true ));\n\n        menu = new RightClickMenu(buttons);\n\n        menu.generateElem();\n    }\n\n    self.syncWithEditorState = function () {\n        menu.updateElem();\n    }\n\n    self.openMenu = function (specialMode, _timelineMode) {\n        if(!enabled) return;\n        timelineMode = _timelineMode;\n        menu.open = true;\n        self.syncWithEditorState();\n    }\n\n    self.closeMenu = function () {\n        if(!enabled) return;\n        menu.open = false;\n        self.syncWithEditorState();\n    }\n\n    window.disableWickRightClickMenu = function () { enabled = false; };\n\n}"
  },
  {
    "path": "src/editor/interfaces/Interfaces.ScriptingIDE.Reference.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar ScriptingIDEReference = function (scriptingIDE, wickEditor) {\n\n// API\n\n    var propButtons = {};\n\n    this.setup = function () {\n        var reference = document.getElementById('scriptEditorReference');\n\n        window.wickDocs.forEach(function (section) {\n            var referenceGroup = document.createElement('div');\n            referenceGroup.className = \"sidebarGroup\"\n            reference.appendChild(referenceGroup);\n\n            var referenceTitle = document.createElement('div');\n            referenceTitle.className = 'sidebarTitle';\n            referenceTitle.innerHTML = section.name;\n            referenceTitle.onclick = function () {\n                if(referenceGroup.style.height === 'auto') {\n                    referenceGroup.style.height = '16px';\n                } else {\n                    referenceGroup.style.height = 'auto';\n                }\n            }\n            referenceGroup.appendChild(referenceTitle);\n\n            section.properties.forEach(function (prop) {\n                var propertyButton = document.createElement('div');\n                propButtons[stripFunctionParams(prop.name)] = propertyButton;\n                propertyButton.sectionLabel = referenceTitle;\n\n                propertyButton.className = 'sidebarGroupElement tooltipElem';\n                propertyButton.innerHTML = stripFunctionParams(prop.name);\n                propertyButton.setAttribute('alt', getPropertyHTML(prop));\n                propertyButton.onclick = function () {\n                    var cursorPos = scriptingIDE.aceEditor.getCursorPosition();\n                    scriptingIDE.aceEditor.session.insert(cursorPos, formatSnippet(prop.snippet));\n                    scriptingIDE.aceEditor.focus();\n                }\n                referenceGroup.appendChild(propertyButton);\n            })\n        })\n    }\n\n    this.highlightPropButton = function (name) {\n        for(key in propButtons) {\n            propButtons[key].style.boxShadow = '';\n            propButtons[key].sectionLabel.style.boxShadow = '';\n        }\n\n        var propButton = propButtons[name];\n        if(propButton) {\n            var borderStyle = 'inset 0px 0px 2px #31E19C'\n            propButton.style.boxShadow = borderStyle;\n            propButton.sectionLabel.style.boxShadow = borderStyle;\n        }\n    }\n\n// Helper functions\n\n    var stripFunctionParams = function (name) {\n        if(name.indexOf('(') === -1) {\n            return name;\n        } else {\n            return name.split('(')[0];\n        }\n    }\n\n    var getPropertyHTML = function (prop) {\n        return \"<strong>\" + prop.name + \"</strong>\" + \"<br />\" + prop.description;\n    }\n\n    var formatSnippet = function (snippet) {\n        var cursorCol = scriptingIDE.aceEditor.getCursorPosition().column;\n\n        var shiftOverString = \"\";\n        var i = 0;\n        while(i < cursorCol) {\n            shiftOverString += ' ';\n            i++;\n        }\n\n        var snippetLines = snippet.split('\\n');\n        for(var i = 1; i < snippetLines.length; i++) {\n            snippetLines[i] = shiftOverString + snippetLines[i];\n        }\n\n        var rebuiltSnippet = snippetLines.join(\"\\n\");\n\n        return rebuiltSnippet;\n    }\n\n}"
  },
  {
    "path": "src/editor/interfaces/Interfaces.ScriptingIDE.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar ScriptingIDEInterface = function (wickEditor) {\n\n    var self = this;\n\n    var openLast;\n\n    var maximized;\n    var objectBeingScripted;\n\n    var changeAnnotationTimer;\n    var SYNTAX_ERROR_MSG_DELAY = 800;\n\n    var reference;\n\n    this.setup = function () {\n        maximized = false;\n        objectBeingScripted = null;\n\n        self.open = false;\n        openLast = false;\n\n        reference = new ScriptingIDEReference(this, wickEditor);\n        window.wickDocsKeywords = \"\";\n        window.wickDocsKeyworksArray = [];\n        window.wickDocs.forEach(function (doc) {\n            doc.properties.forEach(function (prop) {\n                window.wickDocsKeywords += prop.name.split('(')[0] + \"|\"\n                window.wickDocsKeyworksArray.push(prop.name.split('(')[0]);\n            });\n        });\n        reference.setup();\n\n        var beautify = ace.require(\"ace/ext/beautify\");\n        var langTools = ace.require('ace/ext/language_tools');\n\n        self.aceEditor = ace.edit(\"scriptEditor\");\n        self.aceEditor.setTheme(\"ace/theme/idle_fingers\");\n        self.aceEditor.getSession().setMode(\"ace/mode/javascript\");\n        self.aceEditor.$blockScrolling = Infinity;\n        self.aceEditor.setAutoScrollEditorIntoView(true);\n        self.aceEditor.setOptions({\n            enableBasicAutocompletion: true,\n            enableLiveAutocompletion: true,\n        })\n        self.aceEditor.completers = [{\n            getCompletions: function(editor, session, pos, prefix, callback) {\n                var wordList = window.wickDocsKeyworksArray;\n                callback(null, wordList.map(function(word) {\n                    return {\n                        caption: word,\n                        value: word,\n                        meta: \"static\"\n                    };\n                }));\n            }\n        }];\n\n        self.aceEditor.getSession().on('change', onChange);\n        self.aceEditor.getSession().on(\"changeAnnotation\", onChangeAnnotation);\n        self.aceEditor.on('changeSelection', onChangeSelection);\n\n        self.aceEditor.commands.addCommand({\n            name: \"...\",\n            exec: function() {\n                self.open = false;\n                self.syncWithEditorState();\n            },\n            bindKey: {mac: \"`\", win: \"`\"}\n        })\n\n        var resizer = document.getElementById('resizeScriptingGUIBar');\n        resizer.resizing = false;\n        resizer.addEventListener('mousedown', function (e) {\n            if(self.open && !maximized){\n                resizer.resizing = true;\n            } else {\n                self.open = true;\n                self.clearError();\n                self.syncWithEditorState();\n            }\n\n        });\n        window.addEventListener('mousemove', function (e) {\n            if(resizer.resizing) {\n                var newIDEHeight = wickEditor.settings.scriptingIDEHeight - e.movementY;\n                wickEditor.settings.setValue('scriptingIDEHeight', newIDEHeight)\n                document.getElementById('scriptingGUI').style.height = wickEditor.settings.scriptingIDEHeight+'px';\n                self.resize()\n            }\n        });\n        window.addEventListener('mouseup', function (e) {\n            resizer.resizing = false\n        });\n\n        self.resize = function () {\n            self.aceEditor.resize();\n        }\n\n        window.addEventListener('resize', function(e) {\n            self.resize();\n        });\n        self.resize();\n\n        $(\"#closeScriptingGUIButton\").on(\"click\", function (e) {\n            self.open = false;\n            self.clearError();\n            self.syncWithEditorState();\n        });\n        $(\"#openScriptingGUIButton\").on(\"click\", function (e) {\n            self.open = true;\n            self.clearError();\n            self.syncWithEditorState();\n        });\n\n        $(\"#beautifyButton\").on(\"click\", function (e) {\n            beautifyCode();\n        });\n\n        $(\"#expandScriptingGUIButton\").on(\"click\", function (e) {\n            maximized = true;\n            self.syncWithEditorState();\n        });\n        $(\"#minimizeScriptingGUIButton\").on(\"click\", function (e) {\n            maximized = false;\n            self.syncWithEditorState();\n        });\n        \n    }\n\n    this.syncWithEditorState = function () {\n        oldObjectBeingScripting = objectBeingScripted;\n        objectBeingScripted = wickEditor.project.getSelectedObject() || wickEditor.project.getCurrentFrame();\n\n        updateHeaderText()\n\n        if(this.open) {\n            $(\"#scriptEditor\").css('display', 'block');\n\n            if(maximized) {\n                document.getElementById('scriptingGUI').style.height = 'calc(100% - 24px)';\n            } else {\n                document.getElementById('scriptingGUI').style.height = wickEditor.settings.scriptingIDEHeight+'px';\n            }\n            \n            this.aceEditor.resize();\n            document.getElementById('closeScriptingGUIButton').style.display = 'block';\n            document.getElementById('openScriptingGUIButton').style.display = 'none';\n            document.getElementById('beautifyButton').style.display = 'block';\n            if(maximized) {\n                document.getElementById('expandScriptingGUIButton').style.display = 'none';\n                document.getElementById('minimizeScriptingGUIButton').style.display = 'block';\n            } else {\n                document.getElementById('expandScriptingGUIButton').style.display = 'block';\n                document.getElementById('minimizeScriptingGUIButton').style.display = 'none';\n            }\n\n            if(objectBeingScripted && wickEditor.project.getNumSelectedObjects() < 2 && ((objectBeingScripted instanceof WickObject && !objectBeingScripted.isPath && !objectBeingScripted.isImage) || objectBeingScripted instanceof WickFrame)) {\n                $(\"#noSelectionDiv\").css('display', 'none');\n                $(\"#scriptObjectDiv\").css('display', 'block');\n\n                var script = objectBeingScripted.wickScript;\n                if(self.aceEditor.getValue() !== objectBeingScripted.wickScript)\n                    self.aceEditor.setValue(script, -1);\n            } else {\n                $(\"#noSelectionDiv\").css('display', 'block');\n                $(\"#scriptObjectDiv\").css('display', 'none');\n\n                if(objectBeingScripted && objectBeingScripted.isPath) {\n                    document.getElementById('noSelectionText').innerHTML = \"Paths can't be scripted. <br />Group it, or convert it to a Clip or Button!\";\n                } else if(objectBeingScripted && objectBeingScripted.isImage) {\n                    document.getElementById('noSelectionText').innerHTML = \"Images can't be scripted. <br />Group it, or convert it to a Clip or Button!\";\n                } else if(wickEditor.project.getNumSelectedObjects() < 2) {\n                    document.getElementById('noSelectionText').innerHTML = \"No scriptable object selected!\";\n                } else {\n                    document.getElementById('noSelectionText').innerHTML = \"Multiple objects can't be scripted.<br />Group them, or convert them to a Clip or Button!\";\n                }\n            }\n\n        } else {\n            $(\"#scriptEditor\").css('display', 'none');\n            $(\"#noSelectionDiv\").css('display', 'none');\n            $(\"#scriptingGUI\").css('height', '24px');\n\n            document.getElementById('expandScriptingGUIButton').style.display = 'none';\n            document.getElementById('minimizeScriptingGUIButton').style.display = 'none';\n\n            document.getElementById('closeScriptingGUIButton').style.display = 'none';\n            document.getElementById('openScriptingGUIButton').style.display = 'block';\n\n            document.getElementById('beautifyButton').style.display = 'none';\n        }\n\n        if(objectBeingScripted !== oldObjectBeingScripting) {\n            self.aceEditor.getSession().setUndoManager(new ace.UndoManager())\n        }\n\n        if(openLast && !self.open) {\n            document.activeElement.blur();\n        }\n        openLast = self.open;\n    }\n\n    self.displayError = function (obj, scriptError) {\n        var object = wickEditor.project.getObjectByUUID(obj.uuid);\n        var frame = wickEditor.project.getFrameByUUID(obj.uuid);\n\n        wickEditor.project.clearSelection();\n        wickEditor.project.selectObject(object || frame);\n        (object || frame).scriptError = scriptError;\n\n        if(object) {\n            wickEditor.project.jumpToObject(object);\n        } else if (frame) {\n            wickEditor.project.jumpToFrame(frame);\n        }\n\n        this.open = true;\n\n        wickEditor.syncInterfaces();\n\n        this.aceEditor.selection.moveCursorToPosition({row: scriptError.line-1, column: 0});\n        this.aceEditor.selection.selectLine();\n    }\n\n    self.clearError = function () {\n        var framesAndObjects = (wickEditor.project.getAllFrames().concat(wickEditor.project.getAllObjects()));\n        framesAndObjects.forEach(function (obj) {\n            if(obj.scriptError && obj.scriptError.type === 'runtime') {\n                obj.scriptError = null;\n            }\n        })\n    }\n\n    function onChange (e) {\n        if(!objectBeingScripted) return;\n            objectBeingScripted.wickScript = self.aceEditor.getValue();\n    }\n\n    function onChangeAnnotation (e) {\n        if(objectBeingScripted && objectBeingScripted.scriptError && objectBeingScripted.scriptError.type === 'syntax')\n            objectBeingScripted.scriptError = null;\n        updateHeaderText()\n\n        clearTimeout(changeAnnotationTimer);\n        changeAnnotationTimer = setTimeout (function () {\n            if(!self.open)return;\n\n            var annot = self.aceEditor.getSession().getAnnotations();\n\n            // Look for errors\n            if(!objectBeingScripted) return;\n\n            if(objectBeingScripted.scriptError && objectBeingScripted.scriptError.type === 'syntax')\n                objectBeingScripted.scriptError = null;\n\n            for (var key in annot){\n                if (annot.hasOwnProperty(key)) {\n                    if(annot[key].type === 'error') {\n                        // There's a syntax error. Set the projectHasErrors flag so the project won't run.\n                        //self.projectHasErrors = true;\n                        if(!objectBeingScripted.scriptError || objectBeingScripted.scriptError.type === 'runtime') {\n                            objectBeingScripted.scriptError = {\n                                message: annot[key].text,\n                                line: annot[key].row+1,\n                                type: 'syntax'\n                            }\n                        }\n                    }\n                }\n            }\n            updateHeaderText()\n        },SYNTAX_ERROR_MSG_DELAY);\n    }\n\n    function onChangeSelection () {\n        var position = self.aceEditor.getCursorPosition();\n        var token = self.aceEditor.session.getTokenAt(position.row, position.column);\n        if(token) {\n            reference.highlightPropButton(token.value);\n        }\n    }\n\n    function beautifyCode () {\n        var val = self.aceEditor.session.getValue();\n        val = js_beautify(val);\n        self.aceEditor.session.setValue(val);\n        \n        var row = self.aceEditor.session.getLength() - 1;\n        var column = self.aceEditor.session.getLine(row).length;\n        self.aceEditor.gotoLine(row + 1, column);\n    }\n\n    function updateHeaderText () {\n        var header = document.getElementById('scriptingIDEHeader');\n\n        //header.style.color = 'white'\n        header.style.backgroundColor = 'rgba(0,0,0,0)';\n        header.style.fontWeight = 'normal';\n\n        //document.getElementById('scriptObjectDiv').style.backgroundColor  = 'rgba(0,0,0,0)';\n\n        if(!objectBeingScripted) {\n            header.innerHTML = \"\";\n        } else {\n            if(objectBeingScripted.scriptError) {\n                header.innerHTML = \"Line \" + objectBeingScripted.scriptError.line + \": \" + objectBeingScripted.scriptError.message;\n                //header.style.color = 'red';\n                header.style.backgroundColor = 'rgb(255,50,70)';\n                //document.getElementById('scriptObjectDiv').style.backgroundColor = 'red';\n                header.style.fontWeight = 'bold';\n            } else if(/*objectBeingScripted.isSymbol*/objectBeingScripted instanceof WickObject) {\n\n                var wickObjectType = \"object\"\n                if(objectBeingScripted.isText) {\n                    wickObjectType = 'text'\n                } else if(objectBeingScripted.isButton) {\n                    wickObjectType = 'button'\n                } else if(objectBeingScripted.isGroup) {\n                    wickObjectType = 'group'\n                } else if(objectBeingScripted.isSymbol) {\n                    wickObjectType = 'clip'\n                } else if(objectBeingScripted.isPath) {\n                    wickObjectType = 'path'\n                } else if(objectBeingScripted.isImage) {\n                    wickObjectType = 'image'\n                }\n\n                header.innerHTML = \"Edit scripts of \"+wickObjectType+\": <strong>\"+(objectBeingScripted.name || \"(no name)\")+\"</strong>\";\n            } else if (objectBeingScripted instanceof WickFrame) {\n                var framename = objectBeingScripted.name || (objectBeingScripted.playheadPosition+1)\n                header.innerHTML = \"Edit scripts of frame: <strong>\"+framename+\"</strong>\";\n            } else {\n                header.innerHTML = \"\"\n            }\n        }\n    }\n\n}"
  },
  {
    "path": "src/editor/interfaces/Interfaces.TextEditBox.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar TextEditBox = function (wickEditor) {\n\n    var self = this;\n\n    var box;\n\n    this.setup = function () {\n        box = document.createElement('textarea');\n        box.className = 'canvasTextEdit';\n        box.oninput = function () {\n            var selectedObj = wickEditor.project.getSelectedObject();\n            if(selectedObj) {\n                selectedObj.textData.text = box.value;\n                selectedObj._renderDirty = true;\n                wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n                wickEditor.syncInterfaces();\n            }\n        }\n        document.getElementById('editorCanvasContainer').appendChild(box);\n    }\n\n    this.syncWithEditorState = function () {\n        var selectedObj = wickEditor.project.getSelectedObject();\n\n        var textToolSelected = wickEditor.currentTool === wickEditor.tools.text;\n        var selectedObjIsText = selectedObj && selectedObj.isText;\n\n        if(selectedObjIsText && textToolSelected) {\n            var objAbsPos = selectedObj.getAbsolutePosition();\n            var screenSpacePos = wickEditor.canvas.canvasToScreenSpace(objAbsPos.x, objAbsPos.y);\n\n            var x = screenSpacePos.x;\n            var y = screenSpacePos.y;\n            var w = selectedObj.width;\n            var h = selectedObj.height;\n            var zoom = wickEditor.canvas.getZoom();\n            var TOP_OFFSET = -2;\n\n            box.style.left   = x-(w*zoom/2) + 'px';\n            box.style.top    = y-(h*zoom/2)+TOP_OFFSET + 'px';\n            box.style.width  = w*zoom+1 + 'px'; // Slightly increase text box size to avoid text box resizing issues.\n            box.style.height = h*zoom + 'px';\n\n            box.value = selectedObj.textData.text;\n\n            box.style.fontFamily = selectedObj.textData.fontFamily;\n            box.style.fontSize = (selectedObj.textData.fontSize*wickEditor.canvas.getZoom())+'px';\n            box.style.textAlign = selectedObj.textData.textAlign;\n            box.style.fontWeight = selectedObj.textData.fontWeight;\n            box.style.fontStyle = selectedObj.textData.fontStyle;\n            box.style.lineHeight = '1.2';\n            box.style.display = 'block';\n        } else {\n            box.style.display = 'none';\n        }\n    }\n}\n"
  },
  {
    "path": "src/editor/interfaces/Interfaces.Timeline.FramesContainer.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nTimelineInterface.FramesContainer = function (wickEditor, timeline) {\n    var that = this;\n\n    this.elem = null;\n\n    this.frames = null;\n    this.frameStrips = null;\n\n    this.addFrameOverlay = new TimelineInterface.AddFrameOverlay(wickEditor, timeline);\n    this.selectionBox = new TimelineInterface.SelectionBox(wickEditor, timeline);\n\n    var framesStrip;\n    var framesStripCellContainer;\n    this.hoverHighlightOverlay;\n\n    this.build = function () {\n        this.elem = document.createElement('div');\n        this.elem.className = 'frames-container';\n\n        this.elem.addEventListener('mousedown', function (e) {\n            timeline.interactions.start('dragSelectionBox', e, {});\n\n            var layerIndex = Math.round((e.clientY - timeline.framesContainer.elem.getBoundingClientRect().top - cssVar('--layer-height')/2) / cssVar('--layer-height'))\n            var layer = wickEditor.project.currentObject.layers[layerIndex];\n            wickEditor.actionHandler.doAction('movePlayhead', {\n                obj: wickEditor.project.currentObject,\n                newPlayheadPosition: Math.round((e.clientX - 9 - timeline.framesContainer.elem.getBoundingClientRect().left - cssVar('--frame-width')/2) / cssVar('--frame-width')),\n                newLayer: layer,\n            });\n\n            wickEditor.project.clearSelection();\n            if(e.button === 2) {\n                var layer = wickEditor.project.getCurrentLayer();\n                //var frame = layer.getLastFrame(wickEditor.project.getCurrentObject().playheadPosition);\n                var frame = layer.getFrameAtPlayheadPosition(wickEditor.project.getCurrentObject().playheadPosition)\n                if(frame) wickEditor.project.selectObject(frame);\n                wickEditor.syncInterfaces();\n            }\n            timeline.framesContainer.update();\n        });\n\n        timeline.elem.addEventListener('mousewheel', function(e) {\n            that.addFrameOverlay.elem.style.display = 'none'\n            var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));\n\n            /*if(wickEditor.inputHandler.specialKeys[\"SHIFT\"]) {\n                var currentFrameWidth = cssVar('--frame-width');\n\n                var newFrameWidth = currentFrameWidth + delta * 3;\n                newFrameWidth = Math.min(newFrameWidth, 100);\n                newFrameWidth = Math.max(newFrameWidth, 23);\n\n                document.body.style.setProperty('--frame-width', newFrameWidth+'px');\n\n                wickEditor.project.currentObject.framesDirty = true;\n                wickEditor.syncInterfaces();\n            } else {*/\n                if(timeline.verticalScrollBar.elem.style.display === 'none') return;\n                timeline.verticalScrollBar.scroll(-delta*10);\n                that.update();\n            //}\n        });\n\n        framesStripCellContainer = document.createElement('span');\n        framesStripCellContainer.className = 'frames-cell-container';\n        for(var i = 0; i < 70; i++) {\n            var framesStripCell = document.createElement('div');\n            framesStripCell.className = 'frames-cell';\n            framesStripCell.style.left = i*20 + 10 + 'px'\n            \n            framesStripCellContainer.appendChild(framesStripCell);\n        }\n        this.elem.appendChild(framesStripCellContainer)\n\n        this.hoverHighlightOverlay = document.createElement('div')\n        this.hoverHighlightOverlay.className = 'hover-highlight-overlay';\n\n        this.addFrameOverlay.build();\n        this.selectionBox.build();\n\n        this.rebuild();\n    }\n\n    this.rebuild = function () {\n        this.elem.innerHTML = \"\";\n        this.frames = [];\n        this.frameStrips = [];\n\n        this.elem.appendChild(framesStripCellContainer)\n        //this.elem.appendChild(this.hoverHighlightOverlay)\n\n        var wickLayers = wickEditor.project.currentObject.layers;\n        wickLayers.forEach(function (wickLayer) {\n            framesStrip = new TimelineInterface.FramesStrip(wickEditor, timeline);\n            framesStrip.wickLayer = wickLayer;\n            framesStrip.build();\n            framesStrip.wickLayer = wickLayer;\n            that.elem.appendChild(framesStrip.elem);\n            that.frameStrips.push(framesStrip)\n\n            wickLayer.frames.forEach(function(wickFrame) {\n                var frame = new TimelineInterface.Frame(wickEditor, timeline);\n\n                frame.wickFrame = wickFrame;\n                frame.wickLayer = wickLayer;\n                frame.build();\n\n                that.frames.push(frame);\n                that.elem.appendChild(frame.elem);\n            });\n        });\n\n        this.elem.appendChild(this.addFrameOverlay.elem);\n        this.elem.appendChild(this.selectionBox.elem);\n    }\n\n    this.update = function () {\n        this.frames.forEach(function (frame) {\n            frame.update();\n        });\n\n        this.frameStrips.forEach(function (frameStrip) {\n            frameStrip.update();\n        });\n\n        var shift = timeline.horizontalScrollBar.getScrollPosition();\n        framesStripCellContainer.style.left = (shift-shift%cssVar('--frame-width'))+'px';\n\n        var scrollX = -timeline.horizontalScrollBar.getScrollPosition();\n        var scrollY = -timeline.verticalScrollBar.getScrollPosition();\n        if(wickEditor.project.getCurrentObject().layers.length < 4) {\n            scrollY = 0;\n            timeline.verticalScrollBar.reset();\n        }\n        $('.frames-container').css('left', scrollX+cssVar('--layers-width')      +'px');\n        $('.frames-container').css('top',  scrollY+cssVar('--number-line-height')+'px');\n        $('.layers-container').css('top',  scrollY+cssVar('--number-line-height')+'px');\n    }\n\n    this.getFrames = function (wickFrames) {\n        var frames = [];\n        wickFrames.forEach(function (wickFrame) {\n            that.frames.forEach(function (frame) {\n                if(frame.wickFrame === wickFrame) {\n                    frames.push(frame);\n                }\n            })\n        });\n        return frames;\n    }\n}\n\nTimelineInterface.Frame = function (wickEditor, timeline) {\n    var self = this;\n\n    var selectionOverlayDiv = null;\n    var thumbnailDiv = null;\n    var waveformDiv = null;\n    var hasScriptsIconDiv = null;\n    var nameDiv = null;\n\n    this.wickFrame = null;\n    this.wickLayer = null;\n\n    var tweens = [];\n    var scriptIcon = null;\n\n    this.build = function () {\n        var wickLayers = wickEditor.project.getCurrentObject().layers;\n\n        this.elem = document.createElement('div');\n        this.elem.className = \"frame\";\n        this.elem.style.left = (self.wickFrame.playheadPosition * cssVar('--frame-width')) - 4 + 'px';\n        this.elem.style.top = (wickLayers.indexOf(self.wickLayer) * cssVar('--layer-height')) + 'px';\n        this.elem.style.width = (self.wickFrame.length * cssVar('--frame-width') - cssVar('--common-padding')/2) + 'px';\n        this.elem.style.height = cssVar('--layer-height')-cssVar('--common-padding')+'px'\n        this.elem.wickData = {wickFrame:self.wickFrame};\n        this.elem.addEventListener('mouseup', function (e) {\n            /*wickEditor.actionHandler.doAction('movePlayhead', {\n                obj: wickEditor.project.currentObject,\n                newPlayheadPosition: self.wickFrame.playheadPosition,\n                newLayer: self.wickFrame.parentLayer\n            });\n            wickEditor.project.clearSelection()\n            wickEditor.project.selectObject(self.wickFrame)\n            timeline.framesContainer.update();*/\n        });\n        this.elem.addEventListener('mousedown', function (e) {\n\n            if(e.button === 2)\n                wickEditor.rightclickmenu.openMenu(null, true);\n            else\n                wickEditor.rightclickmenu.closeMenu();\n\n            if(!wickEditor.project.isObjectSelected(self.wickFrame)) {\n                if(!e.shiftKey) wickEditor.project.clearSelection();\n                wickEditor.project.selectObject(self.wickFrame);\n                \n            }\n            wickEditor.actionHandler.doAction('movePlayhead', {\n                obj: wickEditor.project.currentObject,\n                newPlayheadPosition: self.wickFrame.playheadPosition + Math.floor((e.offsetX+2) / cssVar('--frame-width')),\n                newLayer: self.wickFrame.parentLayer\n            });\n            \n\n            timeline.interactions.start(\"dragFrame\", e, {\n                frames: timeline.framesContainer.getFrames(wickEditor.project.getSelectedObjects())\n            });\n\n            e.stopPropagation();\n        });\n        this.elem.addEventListener('dblclick', function (e) {\n            //wickEditor.guiActionHandler.doAction('copyFrameForward')\n        });\n        this.elem.addEventListener('mouseout', function (e) {\n            timeline.framesContainer.hoverHighlightOverlay.style.display = 'none';\n        });\n        this.elem.addEventListener('mousemove', function (e) {\n            if(e.target.className !== 'frame') {\n                timeline.framesContainer.hoverHighlightOverlay.style.display = 'none';\n                return;\n            }\n\n            var rect = self.elem.getBoundingClientRect();\n            var x = rect.left-193+12 + (e.offsetX - (e.offsetX%cssVar('--frame-width')));\n            x += timeline.horizontalScrollBar.getScrollPosition()\n            var y = rect.top-70+9;\n            timeline.framesContainer.hoverHighlightOverlay.style.left = x+'px';\n            timeline.framesContainer.hoverHighlightOverlay.style.top = y+'px';\n            timeline.framesContainer.hoverHighlightOverlay.style.display = 'block';\n        });\n\n        thumbnailDiv = document.createElement('img');\n        thumbnailDiv.className = \"frame-thumbnail\";\n        thumbnailDiv.style.marginLeft = cssVar('--frame-width')===20 ? '4px' : '11px';\n        this.elem.appendChild(thumbnailDiv);\n\n        waveformDiv = document.createElement('img');\n        waveformDiv.className = \"frame-waveform\";\n        this.elem.appendChild(waveformDiv);\n\n        nameDiv = document.createElement('div');\n        nameDiv.className = \"frame-name\";\n        this.elem.appendChild(nameDiv);\n\n        selectionOverlayDiv = document.createElement('div');\n        selectionOverlayDiv.className = \"selection-overlay\";\n        this.elem.appendChild(selectionOverlayDiv);\n\n        hasScriptsIconDiv = document.createElement('div');\n        hasScriptsIconDiv.className = \"has-scripts-icon\";\n        this.elem.appendChild(hasScriptsIconDiv);\n\n        var extenderHandleRight = document.createElement('div');\n        extenderHandleRight.className = \"frame-extender-handle frame-extender-handle-right\";\n        extenderHandleRight.addEventListener('mousedown', function (e) {\n            timeline.interactions.start(\"dragFrameWidth\", e, {frame:self});\n            e.stopPropagation();\n        });\n        this.elem.appendChild(extenderHandleRight);\n        \n//        var extenderHandleLeft = document.createElement('div');\n//        extenderHandleLeft.className = \"frame-extender-handle-left\";\n//        extenderHandleLeft.addEventListener('mousedown', function (e) {\n//            timeline.interactions.start(\"dragFrameWidth\", e, {frame:self});\n//            e.stopPropagation();\n//        });\n//        self.elem.appendChild(extenderHandleLeft);\n\n        tweens = [];\n        this.wickFrame.tweens.forEach(function (wickTween) {\n            var tween = new TimelineInterface.Tween(wickEditor, timeline);\n            tween.wickTween = wickTween;\n            tween.wickFrame = self.wickFrame;\n            tween.build();\n            self.elem.appendChild(tween.elem);\n            tweens.push(tween)\n        });\n    }\n\n    this.update = function () {\n        if(wickEditor.project.smallFramesMode) {\n            this.elem.style.borderRadius = '0px';\n        } else {\n            this.elem.style.borderRadius = '2px';\n        }\n\n        hasScriptsIconDiv.style.display = this.wickFrame.hasScript() ? 'block' : 'none';\n        hasScriptsIconDiv.onclick = function () {\n            wickEditor.guiActionHandler.doAction('editScripts')\n        }\n\n        nameDiv.innerHTML = this.wickFrame.name || '';\n        if(this.wickFrame.name === 'New Frame') {\n            nameDiv.innerHTML = '';\n        }\n\n        if(this.wickFrame.hasSound()) {\n            thumbnailDiv.style.display = 'none';\n            waveformDiv.style.display = 'block';\n            if(this.wickFrame.hasSound()) {\n                if(!this.wickFrame._soundDataForPreview) {\n                    self.wickFrame._soundDataForPreview = {};\n                    var canvas = document.createElement('canvas');\n                    canvas.width = 600;\n                    canvas.height = 40;\n                    //self.wickFrame._soundDataForPreview.howl.play();\n                } else {\n                    var waveform = wickEditor.canvas.getFastCanvas().getWaveformForFrameSound(self.wickFrame)\n                    if(waveform) {\n                        waveformDiv.src = waveform.src;\n                        var baseWidth = 200*(12.0/10.0);\n                        var waveformWidth = baseWidth;\n                        waveformWidth = waveformWidth/(12.0/wickEditor.project.framerate);\n                        waveformWidth = waveformWidth * (waveform.length)\n                        waveformDiv.style.width = waveformWidth + 'px';\n                    }\n                }\n                this.elem.style.backgroundColor = '#FFF';\n            } else {\n                this.wickFrame._soundDataForPreview = null;\n            }\n        } else {\n            //var src = this.wickFrame.thumbnail;\n            waveformDiv.style.display = 'none';\n            if(this.wickFrame.tweens.length > 0) {\n                thumbnailDiv.style.display = 'none';\n                this.elem.style.backgroundColor = '#e4eafb';\n            } else if(this.wickFrame.wickObjects.length > 0) {\n                this.elem.style.backgroundColor = '#EEE';\n                thumbnailDiv.src = 'resources/fullframe.svg';\n            } else {\n                this.elem.style.backgroundColor = '#FFF';\n                thumbnailDiv.src = 'resources/emptyframe.svg';\n            }\n            /* else if(!src || wickEditor.project.smallFramesMode) {\n                thumbnailDiv.style.display = 'block';\n                thumbnailDiv.src = '/resources/whitepage.png';\n                this.elem.style.backgroundColor = '#FFF';\n            } else if(src) {\n                thumbnailDiv.style.display = 'block';\n                thumbnailDiv.src = src;\n                this.elem.style.backgroundColor = wickEditor.project.backgroundColor;//'#FFF';\n            }*/\n        }\n        \n        if (wickEditor.project.isObjectSelected(this.wickFrame)) {\n            selectionOverlayDiv.style.display = 'block';\n            selectionOverlayDiv.className = 'selection-overlay'\n        } else if (this.wickFrame.scriptError) {\n            selectionOverlayDiv.style.display = 'block';\n            selectionOverlayDiv.className = 'selection-overlay selection-overlay-error'\n        } else {\n            selectionOverlayDiv.style.display = 'none';\n        }\n\n        tweens.forEach(function (tween) {\n            tween.update();\n        });\n    }\n}\n\nTimelineInterface.Tween = function (wickEditor, timeline) {\n    var self = this;\n\n    self.wickTween = null;\n    self.wickFrame = null;\n    self.wickObject = null;\n\n    this.build = function () {\n        /*console.log(self.wickTween)\n        console.log(self.wickFrame)*/\n\n        self.elem = document.createElement('div');\n        self.elem.className = 'tween';\n\n        self.elem.addEventListener('mousedown', function (e) {\n\n            if(e.button === 2)\n                wickEditor.rightclickmenu.openMenu(null, true);\n            else\n                wickEditor.rightclickmenu.closeMenu();\n\n            //console.log(e)\n            e.stopPropagation();\n\n            wickEditor.actionHandler.doAction('movePlayhead', {\n                obj: wickEditor.project.currentObject,\n                newPlayheadPosition: self.wickFrame.playheadPosition + self.wickTween.playheadPosition,\n                newLayer: wickEditor.project.getCurrentLayer()\n            });\n\n            /*wickEditor.project.deselectObjectType(WickTween);\n            wickEditor.project.selectObject(self.wickTween);\n            wickEditor.project.selectObject(self.wickObject);*/\n            wickEditor.project.clearSelection();\n            wickEditor.project.selectObject(self.wickFrame);\n            wickEditor.syncInterfaces();\n\n            timeline.interactions.start(\"dragTweens\", e, {\n                tweens: [self],\n                frame: self.wickFrame,\n            });\n        }); \n    }\n\n    this.update = function () {\n        //if(!wickEditor.project.isObjectSelected(self.wickObject)) {\n            //self.elem.style.display = 'none';\n            //return;\n        //}\n\n        /*if(wickEditor.project.isObjectSelected(self.wickTween)) {\n            //self.elem.style.backgroundColor = 'green';\n            self.elem.style.opacity = 1.0;\n        } else {\n            //self.elem.style.backgroundColor = 'rgba(0,0,0,0)';\n            self.elem.style.opacity = 0.3;\n        }*/\n        self.elem.style.opacity = 1.0;\n\n        //self.elem.style.display = 'block';\n\n        var baseX = self.wickTween.playheadPosition*cssVar('--frame-width');\n        var paddingX = cssVar('--frame-width')/2 - 10;\n        //if(!timeline.interactions.getCurrent())\n        self.elem.style.left = (baseX+paddingX)+\"px\";\n\n        var baseY = 0;\n        var paddingY = cssVar('--layer-height')/2 - 10 - 2;\n        self.elem.style.top = baseY+paddingY+\"px\";\n\n        //self.elem.style.width = cssVar('--frame-width')+\"px\";\n        //self.elem.style.height = cssVar('--layer-height')+'px';\n    }\n}\n\nTimelineInterface.FramesStrip = function (wickEditor, timeline) {\n    var that = this;\n\n    this.elem = null;\n\n    this.wickLayer = null;\n\n    var framesStripCellContainer;\n\n    this.build = function () {\n        var wickLayers = wickEditor.project.getCurrentObject().layers;\n\n        this.elem = document.createElement('div');\n        this.elem.className = 'frames-strip';\n        this.elem.style.top = (wickLayers.indexOf(this.wickLayer) * cssVar('--layer-height')) + 'px';\n        this.elem.addEventListener('mousemove', function (e) {\n            if(wickEditor.project.smallFramesMode) return;\n            \n            var px = Math.round((e.clientX - timeline.framesContainer.elem.getBoundingClientRect().left - cssVar('--frame-width')/2)      / cssVar('--frame-width'))\n            var py = Math.round((e.clientY - timeline.framesContainer.elem.getBoundingClientRect().top  - cssVar('--layer-height')/2) / cssVar('--layer-height'))\n\n            if(timeline.interactions.getCurrent()) return;\n            var layer = wickEditor.project.getCurrentObject().layers[py];\n            if(layer && layer.getFrameAtPlayheadPosition(px)) return;\n            \n            timeline.framesContainer.addFrameOverlay.elem.style.display = 'block';\n            timeline.framesContainer.addFrameOverlay.elem.style.left = roundToNearestN(e.clientX - timeline.framesContainer.elem.getBoundingClientRect().left - cssVar('--frame-width')/2 - 9, cssVar('--frame-width')) + \"px\";\n            timeline.framesContainer.addFrameOverlay.elem.style.top  = roundToNearestN(e.clientY - timeline.framesContainer.elem.getBoundingClientRect().top  - cssVar('--layer-height')/2, cssVar('--layer-height')) + \"px\";\n        });\n        this.elem.addEventListener('mouseup', function (e) {\n            if(e.button === 2) return;\n            if(wickEditor.project.smallFramesMode) return;\n\n            if(timeline.framesContainer.addFrameOverlay.elem.style.display === 'none') return;\n\n            var playheadPosition = Math.round((e.clientX - timeline.framesContainer.elem.getBoundingClientRect().left - cssVar('--frame-width')/2 - 9) / cssVar('--frame-width'));\n\n            /*if(wickEditor.library.isDraggingAsset()) { \n                var asset = wickEditor.library.getSelectedAsset(); \n\n                if (asset.type == 'audio') {\n                    wickEditor.actionHandler.doAction(\"addSoundToFrame\", {\n                        asset: asset,\n                        playheadPosition: playheadPosition\n                    });\n                }\n                return; \n            }*/\n            \n\n            if (playheadPosition < 0) return; // You're behind position 0!\n\n            var newFrame = new WickFrame();\n            newFrame.playheadPosition = playheadPosition; \n            \n            var layerIndex = Math.round((e.clientY - timeline.framesContainer.elem.getBoundingClientRect().top - cssVar('--layer-height')/2) / cssVar('--layer-height'))\n            var layer = wickEditor.project.currentObject.layers[layerIndex];\n\n            wickEditor.actionHandler.doAction('addFrame', {frame:newFrame, layer:layer});\n            timeline.framesContainer.addFrameOverlay.elem.style.display = 'none';\n\n            //e.stopPropagation();\n        });\n        this.elem.addEventListener('mouseout', function (e) {\n            timeline.framesContainer.addFrameOverlay.elem.style.display = 'none';\n        });\n\n        framesStripCellContainer = document.createElement('span');\n        framesStripCellContainer.className = 'frames-strip-cell-container';\n        for(var i = 1; i < 70; i++) {\n            var framesStripCell = document.createElement('div');\n            framesStripCell.className = 'frames-strip-cell';\n            if(i===0){\n                framesStripCell.className += \" frames-strip-cell-first\"\n                framesStripCell.style.left = i*cssVar('--frame-width') + 'px'\n            } else {\n                framesStripCell.style.left = i*cssVar('--frame-width') + 5 + 'px'\n            }\n            \n            framesStripCellContainer.appendChild(framesStripCell);\n        }\n        this.elem.appendChild(framesStripCellContainer)\n    }\n\n    this.update = function () {\n        var shift = timeline.horizontalScrollBar.getScrollPosition();\n        framesStripCellContainer.style.left = (shift-shift%cssVar('--frame-width'))+'px';\n        this.elem.style.cursor = wickEditor.project.smallFramesMode ? 'deafult' : 'pointer';\n    }\n}\n\nTimelineInterface.AddFrameOverlay = function (wickEditor, timeline) {\n    this.elem = null;\n\n    var that = this;\n\n    this.build = function () {\n        this.elem = document.createElement('div');\n        this.elem.className = 'add-frame-overlay';\n        this.elem.style.display = 'none';\n\n        var addFrameOverlayImg = document.createElement('img');\n        addFrameOverlayImg.className = 'add-frame-overlay-img';\n        addFrameOverlayImg.src = 'resources/plus-24-512.png';\n        this.elem.appendChild(addFrameOverlayImg);\n    }\n\n    this.update = function () {\n        \n    }\n}\n\nTimelineInterface.SelectionBox = function (wickEditor, timeline) {\n    this.elem = null;\n\n    this.build = function () {\n        this.elem = document.createElement('div');\n        this.elem.className = \"selection-box\";\n        this.elem.style.display = 'none';\n    }\n\n    this.update = function () {\n        \n    }\n}\n"
  },
  {
    "path": "src/editor/interfaces/Interfaces.Timeline.Interactions.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nTimelineInterface.Interactions = function (wickEditor, timeline) {\n\n    var self = this;\n\n    var currentInteraction;\n    var interactionData;\n\n    var interactions = {};\n\n    this.setup = function () {\n        currentInteraction = null;\n        window.addEventListener('mousemove', function (e) {\n            self.update(e);\n        });\n        window.addEventListener('mouseup', function (e) {\n            self.finish(e);\n        });\n    }\n\n    this.start = function (interactionName, e, interactiondata) {\n        interactionData = interactiondata;\n        currentInteraction = interactionName;\n\n        interactions[interactionName]['start'](e);\n        //updateInteraction(e);\n    }\n    this.update = function (e) {\n        if(!currentInteraction) return;\n        interactions[currentInteraction]['update'](e);\n    }\n    this.finish = function (e) {\n        if(!currentInteraction) return;\n        interactions[currentInteraction]['finish'](e);\n        currentInteraction = null;\n\n        timeline.framesContainer.addFrameOverlay.elem.style.display = 'none';\n    }\n\n    this.getCurrent = function () {\n        return currentInteraction;\n    }\n\n    interactions['dragFrame'] = {\n        'start' : (function (e) {\n            interactionData.movedDistance = {x:0, y:0};\n\n            interactionData.frames.forEach(function (frame) {\n                frame.origX = parseInt(frame.elem.style.left);\n                frame.origY = parseInt(frame.elem.style.top);\n                frame.currentX = 0;\n                frame.currentY = 0;\n            });\n        }), \n        'update' : (function (e) {\n            if(e.movementX !== 0 || e.movementY !== 0) interactionData.moved = true;\n\n            interactionData.movedDistance.x += e.movementX;\n            interactionData.movedDistance.y += e.movementY;\n\n            if(Math.abs(interactionData.movedDistance.x) < 0 &&\n               Math.abs(interactionData.movedDistance.y) < 0) {\n                return;\n            }\n\n            var frameWidth = cssVar('--frame-width');\n            var layerHeight = cssVar('--layer-height');\n            interactionData.frames.forEach(function (frame) {\n                frame.currentX += e.movementX;\n                frame.currentY += e.movementY;\n                //frame.elem.style.left = frame.origX + roundToNearestN(frame.currentX,frameWidth) + 'px';\n                //frame.elem.style.top  = frame.origY + roundToNearestN(frame.currentY,layerHeight) + 'px';\n                frame.elem.style.left = frame.origX + frame.currentX + 'px';\n                frame.elem.style.top  = frame.origY + frame.currentY + 'px';\n                frame.elem.style.zIndex = 10;\n            });\n        }),\n        'finish' : (function (e) {\n            if(!interactionData.moved) return;\n\n            //var frame = interactionData.frames[0];\n\n            /*interactionData.frames.forEach(function (frame) {\n                //if(!frame) return;\n                var newPlayheadPosition = Math.round(parseInt(frame.elem.style.left) / cssVar('--frame-width'));\n                var newLayerIndex       = Math.round(parseInt(frame.elem.style.top)  / cssVar('--layer-height'));\n                var newLayer = wickEditor.project.getCurrentObject().layers[newLayerIndex];\n                if(!newLayer) newLayer = wickEditor.project.getCurrentLayer();\n\n                wickEditor.actionHandler.doAction('moveFrame', {\n                    frame: frame.wickFrame, \n                    newPlayheadPosition: newPlayheadPosition,\n                    newLayer: newLayer\n                });\n            });*/\n\n            var framesMoveActionData = [];\n            interactionData.frames.forEach(function (frame) {\n                if(!frame) return;\n                var newPlayheadPosition = Math.round(parseInt(frame.elem.style.left) / cssVar('--frame-width'));\n                var newLayerIndex       = Math.round(parseInt(frame.elem.style.top)  / cssVar('--layer-height'));\n                var newLayer = wickEditor.project.getCurrentObject().layers[newLayerIndex];\n                if(!newLayer) newLayer = wickEditor.project.getCurrentLayer();\n\n                framesMoveActionData.push({\n                    frame: frame.wickFrame, \n                    newPlayheadPosition: newPlayheadPosition,\n                    newLayer: newLayer\n                });\n            });\n\n            wickEditor.actionHandler.doAction('moveFrames', {\n                framesMoveActionData: framesMoveActionData\n            });\n\n        })\n    }\n    interactions['dragFrameWidth'] = {\n        'start' : (function (e) {\n            \n        }), \n        'update' : (function (e) {\n            var wickFrame = interactionData.frame.wickFrame;\n            var frameDivLeft = interactionData.frame.elem.getBoundingClientRect().left;\n            var mouseLeft = e.x;\n\n            var newWidth = mouseLeft - frameDivLeft;\n            newWidth = roundToNearestN(newWidth, cssVar('--frame-width'));\n            newWidth = Math.max(newWidth, cssVar('--frame-width'));\n            interactionData.frame.elem.style.width = + newWidth + 'px';\n        }),\n        'finish' : (function (e) {\n            var newFrameDivLen = parseInt(interactionData.frame.elem.style.width);\n            var newLength = Math.round(newFrameDivLen / cssVar('--frame-width'));\n\n            wickEditor.actionHandler.doAction('changeFrameLength', {\n                frame: interactionData.frame.wickFrame, \n                newFrameLength: newLength\n            });\n        })\n    }\n    interactions['dragPlayRange'] = {\n        'start' : (function (e) {\n            interactionData.origWidth = parseInt(interactionData.playrange.elem.style.width);\n            interactionData.origLeft = parseInt(interactionData.playrange.elem.style.left);\n            interactionData.mouseMovement = 0;\n        }), \n        'update' : (function (e) {\n            var wickPlayrange = interactionData.playrange.wickPlayrange;\n\n            interactionData.mouseMovement += e.movementX;\n            var newLeft = interactionData.origLeft + interactionData.mouseMovement;\n\n            interactionData.playrange.elem.style.left = newLeft + 'px';\n        }),\n        'finish' : (function (e) {\n            var newDivLeft = parseInt(interactionData.playrange.elem.style.left);\n            var newLeft = Math.round(newDivLeft / cssVar('--frame-width'));\n            var newStart = newLeft;\n\n            var newDivLen = parseInt(interactionData.playrange.elem.style.width);\n            var newLength = Math.round(newDivLen / cssVar('--frame-width'));\n            var newEnd = newLength + newStart;\n\n            wickEditor.actionHandler.doAction('modifyPlayRange', {\n                playRange: interactionData.playrange.wickPlayrange,\n                end: newEnd,\n                start: newStart\n            });\n        })\n    }\n    interactions['dragPlayRangeStart'] = {\n        'start' : (function (e) {\n            interactionData.origWidth = parseInt(interactionData.playrange.elem.style.width);\n            interactionData.origLeft = parseInt(interactionData.playrange.elem.style.left);\n        }), \n        'update' : (function (e) {\n            var wickPlayrange = interactionData.playrange.wickPlayrange;\n\n            var mouseLeft = e.x;\n            var newLeft = mouseLeft - timeline.numberLine.elem.getBoundingClientRect().left;\n            var diffWidth = interactionData.origLeft - newLeft;\n\n            interactionData.playrange.elem.style.left = newLeft + 'px';\n            interactionData.playrange.elem.style.width = interactionData.origWidth + diffWidth + 'px';\n        }),\n        'finish' : (function (e) {\n            var newDivLeft = parseInt(interactionData.playrange.elem.style.left);\n            var newLeft = Math.round(newDivLeft / cssVar('--frame-width'));\n            var newStart = newLeft;\n\n            wickEditor.actionHandler.doAction('modifyPlayRange', {\n                playRange: interactionData.playrange.wickPlayrange,\n                start: newStart\n            });\n        })\n    }\n    interactions['dragPlayRangeEnd'] = {\n        'start' : (function (e) {\n            \n        }), \n        'update' : (function (e) {\n            var wickPlayrange = interactionData.playrange.wickPlayrange;\n\n            var origLeft = interactionData.playrange.elem.getBoundingClientRect().left;\n            var mouseLeft = e.x;\n\n            var newWidth = mouseLeft - origLeft;\n            interactionData.playrange.elem.style.width = newWidth + 'px';\n        }),\n        'finish' : (function (e) {\n            var newDivLen = parseInt(interactionData.playrange.elem.style.width);\n            var newLength = Math.round(newDivLen / cssVar('--frame-width'));\n            var newEnd = newLength + interactionData.playrange.wickPlayrange.getStart();\n\n            wickEditor.actionHandler.doAction('modifyPlayRange', {\n                playRange: interactionData.playrange.wickPlayrange,\n                end: newEnd\n            });\n        })\n    }\n    interactions['dragHorizontalScrollbarHead'] = {\n        'start' : (function (e) {\n            \n        }), \n        'update' : (function (e) {\n            timeline.horizontalScrollBar.scroll(e.movementX);\n        }),\n        'finish' : (function (e) {\n            \n        })\n    }\n    interactions['dragVerticalScrollbarHead'] = {\n        'start' : (function (e) {\n            \n        }), \n        'update' : (function (e) {\n            timeline.verticalScrollBar.scroll(e.movementY);\n        }),\n        'finish' : (function (e) {\n            \n        })\n    }\n    interactions['dragSelectionBox'] = {\n        'start' : (function (e) {\n            var mx = e.x-timeline.framesContainer.elem.getBoundingClientRect().left;\n            var my = e.y-timeline.framesContainer.elem.getBoundingClientRect().top;\n            interactionData.selectionBoxOrigX = mx;\n            interactionData.selectionBoxOrigY = my;\n            timeline.framesContainer.selectionBox.elem.style.left = '0px';\n            timeline.framesContainer.selectionBox.elem.style.top = '0px';\n            timeline.framesContainer.selectionBox.elem.style.width = '0px';\n            timeline.framesContainer.selectionBox.elem.style.height = '0px';\n        }), \n        'update' : (function (e) {\n            var mx = e.x-timeline.framesContainer.elem.getBoundingClientRect().left;\n            var my = e.y-timeline.framesContainer.elem.getBoundingClientRect().top;\n\n            var ox = interactionData.selectionBoxOrigX;\n            var oy = interactionData.selectionBoxOrigY;\n\n            if(mx-ox > 0) {\n                timeline.framesContainer.selectionBox.elem.style.left = ox+'px'\n                timeline.framesContainer.selectionBox.elem.style.width = mx-ox+'px';\n            } else {\n                timeline.framesContainer.selectionBox.elem.style.left = mx+'px';\n                timeline.framesContainer.selectionBox.elem.style.width = ox-mx+'px'\n            }\n            if(my-oy > 0) {\n                timeline.framesContainer.selectionBox.elem.style.top = oy+'px'\n                timeline.framesContainer.selectionBox.elem.style.height = my-oy+'px';\n            } else {\n                timeline.framesContainer.selectionBox.elem.style.top = my+'px';\n                timeline.framesContainer.selectionBox.elem.style.height = oy-my+'px'\n            }\n\n            timeline.framesContainer.selectionBox.elem.style.display = 'block';\n        }),\n        'finish' : (function (e) {\n            timeline.framesContainer.selectionBox.elem.style.display = 'none';\n\n            if(parseInt(timeline.framesContainer.selectionBox.elem.style.width)  === 0 \n            && parseInt(timeline.framesContainer.selectionBox.elem.style.height) === 0) return;\n\n            var frameDivs = document.getElementsByClassName('frame')\n            wickEditor.project.clearSelection();\n            for(var i = 0; i < frameDivs.length; i ++) {\n                var frameDiv = frameDivs[i]\n\n                var frameRect = {\n                    left:   parseInt(frameDiv.style.left) + 15,\n                    top:    parseInt(frameDiv.style.top),\n                    right:  parseInt(frameDiv.style.width)  + parseInt(frameDiv.style.left) + 15,\n                    bottom: parseInt(frameDiv.style.height) + parseInt(frameDiv.style.top)\n                }\n\n                var selectionBoxRect = {\n                    left:   parseInt(timeline.framesContainer.selectionBox.elem.style.left),\n                    top:    parseInt(timeline.framesContainer.selectionBox.elem.style.top),\n                    right:  parseInt(timeline.framesContainer.selectionBox.elem.style.width)  + parseInt(timeline.framesContainer.selectionBox.elem.style.left),\n                    bottom: parseInt(timeline.framesContainer.selectionBox.elem.style.height) + parseInt(timeline.framesContainer.selectionBox.elem.style.top)\n                }\n\n                if(intersectRect(frameRect, selectionBoxRect)) {\n                    wickEditor.project.selectObject(frameDiv.wickData.wickFrame);\n                } \n            }\n            timeline.framesContainer.update();\n            timeline.framesContainer.selectionBox.elem.style.width = '0px'\n            timeline.framesContainer.selectionBox.elem.style.height = '0px'\n            \n            wickEditor.syncInterfaces();\n        })\n    }\n    interactions['dragLayer'] = {\n        'start' : (function (e) {\n            interactionData.allLayerDivs = [];\n            interactionData.allLayerDivs.push(interactionData.layer.elem);\n\n            var currentLayer = wickEditor.project.getCurrentLayer();\n            timeline.framesContainer.frames.forEach(function (frame) {\n                if (frame.wickFrame.parentLayer === currentLayer) {\n                    interactionData.allLayerDivs.push(frame.elem)\n                }\n            });\n            timeline.framesContainer.frameStrips.forEach(function (frameStrip) {\n                if (frameStrip.wickLayer === currentLayer) {\n                    interactionData.allLayerDivs.push(frameStrip.elem)\n                }\n            });\n\n        }), \n        'update' : (function (e) {\n            interactionData.allLayerDivs.forEach(function (div) {\n                div.style.top = e.y - timeline.framesContainer.elem.getBoundingClientRect().top - cssVar('--layer-height')/2 + 'px';\n            });\n        }),\n        'finish' : (function (e) {\n            var newIndex = Math.round(parseInt(interactionData.allLayerDivs[0].style.top) / cssVar('--layer-height'));\n            newIndex = Math.max(newIndex, 0);\n            newIndex = Math.min(newIndex, wickEditor.project.currentObject.layers.length-1);\n\n            wickEditor.actionHandler.doAction('moveLayer', {\n                layer: interactionData.layer.wickLayer, \n                newIndex: newIndex\n            });\n        })\n    }\n\n    interactions['dragTweens'] = {\n        'start' : (function (e) {\n            interactionData.tweenElemOrigX = parseInt(interactionData.tweens[0].elem.style.left);\n            interactionData.startX = e.x;\n            interactionData.moveX = 0;\n            interactionData.tweens[0].elem.style.pointerEvents = 'none';\n        }), \n        'update' : (function (e) {\n            interactionData.moveX = e.x - interactionData.startX;\n\n            var tween = interactionData.tweens[0];\n            var newPos = interactionData.moveX//roundToNearestN(interactionData.moveX, cssVar('--frame-width'));\n            newPos = parseInt(newPos);\n            tween.elem.style.left = interactionData.tweenElemOrigX+newPos + 'px';\n            tween.elem.style.opacity = 0.5;\n        }),\n        'finish' : (function (e) {\n            var tween = interactionData.tweens[0];\n            tween.elem.style.opacity = 1.0;\n            interactionData.tweens[0].elem.style.pointerEvents = 'auto';\n            \n            var newPlayheadPosition = Math.round((parseInt(tween.elem.style.left)) / cssVar('--frame-width'));\n            wickEditor.actionHandler.doAction('moveMotionTween', {\n                frame: interactionData.frame,\n                tween: tween.wickTween,\n                newPlayheadPosition: newPlayheadPosition\n            });\n\n        })\n    }\n\n    var timelineOffset = 186;\n    interactions['dragPlayhead'] = {\n        'start' : (function (e) {\n            wickEditor.canvas.getFastCanvas().stopPreviewPlaying();\n            var shift = -timeline.horizontalScrollBar.getScrollPosition();\n            timeline.playhead.setPosition(e.pageX-timelineOffset-shift);\n            wickEditor.project.getCurrentObject().playheadPosition = timeline.playhead.getFramePosition();\n            wickEditor.canvas.getFastCanvas().startFastRendering();\n        }), \n        'update' : (function (e) {\n            var shift = -timeline.horizontalScrollBar.getScrollPosition();\n            timeline.playhead.setPosition(Math.max(0, e.pageX-timelineOffset-shift));\n            timeline.playhead.snap();\n            if(timeline.playhead.frameDidChange()) {\n                wickEditor.project.getCurrentObject().playheadPosition = timeline.playhead.getFramePosition();\n            }\n        }),\n        'finish' : (function (e) {\n            timeline.playhead.snap();\n            wickEditor.canvas.getFastCanvas().stopFastRendering();\n            wickEditor.actionHandler.doAction('movePlayhead', {\n                obj: wickEditor.project.getCurrentObject(),\n                newPlayheadPosition: timeline.playhead.getFramePosition(),\n                newLayer: wickEditor.project.getCurrentLayer()\n            });\n        })\n    }\n\n}"
  },
  {
    "path": "src/editor/interfaces/Interfaces.Timeline.LayersContainer.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nTimelineInterface.LayersContainer = function (wickEditor, timeline) {\n    var that = this;\n\n    this.elem = null;\n\n    this.layers = null;\n\n    this.build = function () {\n        this.elem = document.createElement('div');\n        this.elem.className = 'layers-container';\n\n        this.rebuild();\n    }\n\n    this.rebuild = function () {\n        this.layers = [];\n\n        this.elem.innerHTML = \"\";\n\n        var wickLayers = wickEditor.project.currentObject.layers;\n        wickLayers.forEach(function (wickLayer) {\n            var layer = new TimelineInterface.Layer(wickEditor, timeline);\n\n            layer.wickLayer = wickLayer;\n            layer.build();\n            layer.update();\n\n            that.elem.appendChild(layer.elem);\n            that.layers.push(layer);                \n        });\n    }\n\n    this.update = function () {\n        this.layers.forEach(function (layer) {\n            layer.update();\n        })\n    }\n}\n\nTimelineInterface.Layer = function (wickEditor, timeline) {\n    var that = this;\n\n    this.elem = null\n\n    this.wickLayer = null;\n\n    var lockLayerButton;\n    var hideLayerButton;\n\n    this.build = function () {\n        var wickLayers = wickEditor.project.currentObject.layers;\n\n        this.elem = document.createElement('div');\n        this.elem.className = \"layer\";\n        this.elem.style.top = (wickLayers.indexOf(this.wickLayer) * cssVar('--layer-height')) + 'px';\n        this.elem.wickData = {wickLayer:this.wickLayer};\n\n        this.elem.appendChild((function () {\n            that.nameElem = document.createElement('div');\n            that.nameElem.innerHTML = that.wickLayer.identifier;\n            that.nameElem.className = 'layer-name';\n            that.nameElem.addEventListener('mousedown', function (e) {\n                if(wickEditor.project.getCurrentLayer() === that.wickLayer) {\n                    renameLayerTextfield.select();\n                    renameLayerTextfield.value = that.wickLayer.identifier;\n                    renameLayerTextfield.style.display = 'block';\n                    e.stopPropagation();\n                } else {\n                    wickEditor.actionHandler.doAction('movePlayhead', {\n                        obj: wickEditor.project.currentObject,\n                        newPlayheadPosition: wickEditor.project.currentObject.playheadPosition,\n                        newLayer: that.wickLayer\n                    });\n                }\n            });\n            return that.nameElem;\n        })());\n\n        var renameLayerTextfield = document.createElement('input');\n        renameLayerTextfield.className = 'layer-rename-textfield';\n        renameLayerTextfield.type = 'text';\n        renameLayerTextfield.addEventListener('mouseup', function (e) {\n            this.select();\n            e.stopPropagation();\n        });\n        renameLayerTextfield.addEventListener('blur', function (e) {\n            that.wickLayer.identifier = renameLayerTextfield.value;\n            renameLayerTextfield.style.display = 'none';\n            wickEditor.project.currentObject.framesDirty = true;\n            wickEditor.syncInterfaces();\n        });\n        this.elem.appendChild(renameLayerTextfield);\n\n        //div creation block for selection overlay\n        var layerSelectionOverlayDiv = document.createElement('div');\n        layerSelectionOverlayDiv.className = 'layer-selection-overlay';\n        this.elem.appendChild(layerSelectionOverlayDiv);\n        \n        //div creation block for gnurl overlay\n        /*var gnurl = document.createElement('div');\n        gnurl.className = 'layer-gnurl';\n        this.elem.appendChild(gnurl);*/\n        \n        lockLayerButton = document.createElement('div');\n        lockLayerButton.className = 'layer-lock-button';\n        lockLayerButton.onclick = function (e) {\n            that.wickLayer.locked = !that.wickLayer.locked;\n            wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n            wickEditor.syncInterfaces();\n            e.stopPropagation();\n        }\n        this.elem.appendChild(lockLayerButton);\n\n        hideLayerButton = document.createElement('div');\n        hideLayerButton.className = 'layer-hide-button';\n        hideLayerButton.onclick = function (e) {\n            that.wickLayer.hidden = !that.wickLayer.hidden;\n            wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n            wickEditor.syncInterfaces();\n        }\n        this.elem.appendChild(hideLayerButton);\n\n        //hideLayerButton\n\n        this.elem.gnurl = document.createElement('div');\n        this.elem.gnurl.className = 'layer-gnurl'\n        this.elem.appendChild(this.elem.gnurl)\n\n        this.elem.gnurl.addEventListener('mousedown', function (e) {\n            //if(e.layerX < 30) return;\n            wickEditor.actionHandler.doAction('movePlayhead', {\n                obj: wickEditor.project.currentObject,\n                newPlayheadPosition: wickEditor.project.currentObject.playheadPosition,\n                newLayer: that.wickLayer\n            });\n            timeline.interactions.start('dragLayer', e, {layer:that});\n        });\n    }\n\n    this.update = function () {\n        var layerIsSelected = wickEditor.project.getCurrentLayer() === this.wickLayer;\n        var selectionOverlayDiv = this.elem.getElementsByClassName('layer-selection-overlay')[0];\n        selectionOverlayDiv.style.display = layerIsSelected ? 'block' : 'none';\n        \n        if(this.wickLayer.hidden) {\n            hideLayerButton.className = 'layer-hide-button layer-hidden';\n        } else {\n            hideLayerButton.className = 'layer-hide-button';\n        }\n\n        if(this.wickLayer.locked) {\n            lockLayerButton.className = 'layer-lock-button layer-locked';\n        } else {\n            lockLayerButton.className = 'layer-lock-button';\n        }\n\n        var layerDiv = this.elem;\n        if (layerIsSelected === true) {\n            layerDiv.className = 'layer active-layer';\n            that.nameElem.style.cursor = 'text';\n        } else {\n            layerDiv.className = 'layer';\n            that.nameElem.style.cursor = 'pointer';\n        }\n    }\n}\n"
  },
  {
    "path": "src/editor/interfaces/Interfaces.Timeline.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n    \nvar TimelineInterface = function (wickEditor) {\n\n    var self = this;\n\n    var lastObject;\n\n    var timeline;\n\n    //var cssVars;\n    //var cssVar;\n\n    self.setup = function () {\n\n        // Load style vars from CSS\n        window.cssVars = window.getComputedStyle(document.body);\n        window.cssVar = function (varName) {\n            return parseInt(cssVars.getPropertyValue(varName));\n        }\n\n        // Build timeline in DOM\n        timeline = new TimelineInterface.Timeline(wickEditor);\n        timeline.build();\n    }\n\n    self.syncWithEditorState = function () {\n\n        if (lastObject !== wickEditor.project.currentObject || wickEditor.project.currentObject.framesDirty) {\n            wickEditor.project.currentObject.framesDirty = false;\n            lastObject = wickEditor.project.currentObject;\n\n            timeline.rebuild();\n        }\n\n        timeline.update();\n\n    }\n\n    self.getElem = function () {\n        return timeline;\n    }\n\n    self.resetScrollbars = function () {\n        timeline.horizontalScrollBar.reset();\n        timeline.verticalScrollBar.reset();\n    }\n\n    self.updateZoomBox = function () {\n        timeline.updateZoomBox();\n    }\n\n}\n\nTimelineInterface.Timeline = function (wickEditor) {\n    var self = this;\n\n    this.elem = null;\n\n    this.layersContainer = new TimelineInterface.LayersContainer(wickEditor, this);\n    this.framesContainer = new TimelineInterface.FramesContainer(wickEditor, this);\n    this.horizontalScrollBar = new TimelineInterface.HorizontalScrollBar(wickEditor, this);\n    this.verticalScrollBar = new TimelineInterface.VerticalScrollBar(wickEditor, this);\n    this.numberLine = new TimelineInterface.NumberLine(wickEditor, this);\n    this.playhead = new TimelineInterface.Playhead(wickEditor, this);\n\n    this.interactions = new TimelineInterface.Interactions(wickEditor, this);\n    this.interactions.setup();\n\n    var onionSkinningButton;\n\n    this.build = function () {\n        this.elem = document.createElement('div');\n        document.getElementById('timelineGUI').appendChild(this.elem);\n\n        this.framesContainer.build();\n        this.elem.appendChild(this.framesContainer.elem);\n\n        this.layersContainer.build();\n        this.elem.appendChild(this.layersContainer.elem);\n\n        this.numberLine.build();\n        this.elem.appendChild(this.numberLine.elem);\n\n        this.playhead.build();\n        this.elem.appendChild(this.playhead.elem);\n\n        var hideNumberlinePiece = document.createElement('div');\n        hideNumberlinePiece.className = 'hide-number-line-piece';\n        this.elem.appendChild(hideNumberlinePiece);\n        \n        var hideLayersPiece = document.createElement('div');\n        hideLayersPiece.className = 'layer-toolbar';\n        this.elem.appendChild(hideLayersPiece);\n\n        var resizeTimelineBar = document.createElement('div');\n        resizeTimelineBar.className = 'resize-timeline-bar';\n        resizeTimelineBar.addEventListener('mousedown', function (e) {\n            resizeTimelineBar.beingDragged = true\n            resizeTimelineBar.origY = e.pageY\n        });\n        document.body.addEventListener('mouseup', function (e) {\n            resizeTimelineBar.beingDragged = false\n        });\n        document.body.addEventListener('mousemove', function (e) {\n            if(resizeTimelineBar.beingDragged) {\n                var diffY = resizeTimelineBar.origY - e.pageY;\n                resizeTimelineBar.origY = e.pageY\n                if(!wickEditor.project.timelineHeight) {\n                    wickEditor.project.timelineHeight = self.calculateHeight();\n                }\n                wickEditor.project.timelineHeight -= diffY\n                if(wickEditor.project.timelineHeight > 240 ) wickEditor.project.timelineHeight = 240;\n                if(wickEditor.project.timelineHeight < 70 ) wickEditor.project.timelineHeight = 70;\n\n                self.elem.style.height = self.calculateHeight() + \"px\";\n            }\n        });\n        this.elem.appendChild(resizeTimelineBar);\n\n        var addLayerButton = document.createElement('div');\n        addLayerButton.className = 'layer-tools-button add-layer-button tooltipElem';\n        addLayerButton.setAttribute('alt', \"Add Layer\");\n        addLayerButton.addEventListener('mousedown', function (e) {\n            wickEditor.guiActionHandler.doAction('addLayer');\n        });\n        this.elem.appendChild(addLayerButton);\n\n        var deleteLayerButton = document.createElement('div');\n        deleteLayerButton.className = 'layer-tools-button delete-layer-button tooltipElem';\n        deleteLayerButton.setAttribute('alt', \"Delete Layer\");\n        deleteLayerButton.addEventListener('mousedown', function (e) {\n            wickEditor.guiActionHandler.doAction('removeLayer', {\n                layer: wickEditor.project.getCurrentObject().getCurrentLayer()\n            });\n        });\n        this.elem.appendChild(deleteLayerButton);\n\n        onionSkinningButton = document.createElement('div');\n        onionSkinningButton.className = 'layer-tools-button onion-skin-button tooltipElem';\n        onionSkinningButton.setAttribute('alt', \"Toggle Onion Skinning\");\n        onionSkinningButton.style.backgroundColor = wickEditor.project.onionSkinning ? 'orange' : '#F0EFEF';\n        onionSkinningButton.addEventListener('mousedown', function (e) {\n            wickEditor.project.onionSkinning = !wickEditor.project.onionSkinning;\n            wickEditor.syncInterfaces();\n        });\n        this.elem.appendChild(onionSkinningButton);\n\n\n        var previewPlayButton = document.createElement('div');\n        previewPlayButton.className = 'layer-tools-button play-preview-button tooltipElem';\n        previewPlayButton.setAttribute('alt', \"Play Preview (Enter)<br/>(Shift+Click to loop)\");\n        previewPlayButton.addEventListener('mousedown', function (e) {\n            wickEditor.guiActionHandler.doAction('previewPlay', {loop:e.shiftKey});\n        });\n        this.elem.appendChild(previewPlayButton);\n\n        var previewPauseButton = document.createElement('div');\n        previewPauseButton.className = 'layer-tools-button pause-preview-button tooltipElem';\n        previewPauseButton.setAttribute('alt', \"Pause Preview (Enter)\");\n        previewPauseButton.addEventListener('mousedown', function (e) {\n            wickEditor.guiActionHandler.doAction('previewPause');\n        });\n        this.elem.appendChild(previewPauseButton);\n\n        this.horizontalScrollBar.build();\n        this.elem.appendChild(this.horizontalScrollBar.elem);\n\n        var zoomBox = document.createElement('div');\n        zoomBox.className = 'zoom-box';\n        this.elem.appendChild(zoomBox);\n        self.numberInput = new SlideyNumberInput({\n            onsoftchange: function (e) {\n                wickEditor.canvas.setZoom(e/100, true);\n            },\n            onhardchange: function (e) {\n                wickEditor.canvas.setZoom(e/100, true);\n            },\n            min: 1,\n            max: 500,\n            moveFactor: 0.5,\n            initValue: 100,\n        });\n        self.numberInput.className = 'timeline-number-input';\n        zoomBox.appendChild(self.numberInput);\n        var zoomIcon = document.createElement('div');\n        zoomIcon.className = 'timeline-zoom-icon';\n        zoomIcon.onclick = function () {\n            wickEditor.canvas.recenterCanvas();\n            wickEditor.syncInterfaces();\n        }\n        zoomBox.appendChild(zoomIcon);\n        var zoomPercentSign = document.createElement('div');\n        zoomPercentSign.className = 'timeline-zoom-percent-sign';\n        zoomPercentSign.innerHTML = '%'\n        zoomBox.appendChild(zoomPercentSign);\n\n        this.verticalScrollBar.build();\n        this.elem.appendChild(this.verticalScrollBar.elem);\n    }\n    \n    this.rebuild = function () {\n        resetFrameSize();\n\n        this.layersContainer.rebuild();\n        this.framesContainer.rebuild();\n        this.numberLine.rebuild();\n    }\n\n    this.update = function () {\n        this.layersContainer.update();\n        this.framesContainer.update();\n        this.elem.style.height = this.calculateHeight() + \"px\";\n\n        this.numberLine.update();\n        this.playhead.update();\n\n        this.horizontalScrollBar.update();\n        this.verticalScrollBar.update();\n\n        onionSkinningButton.style.backgroundColor = wickEditor.project.onionSkinning ? 'orange' : '#F0EFEF';\n\n        this.updateZoomBox();\n\n        resetFrameSize();\n    }\n\n    this.updateZoomBox = function () {\n        self.numberInput.value = Math.floor(wickEditor.canvas.getZoom() * 100);\n    }\n\n    this.calculateHeight = function () {\n        if(!wickEditor.project.timelineHeight) { \n            var maxTimelineHeight = cssVar(\"--max-timeline-height\");\n            var expectedTimelineHeight = this.layersContainer.layers.length * cssVar(\"--layer-height\") + 44; \n            return Math.min(expectedTimelineHeight, maxTimelineHeight); \n        } else {\n            return wickEditor.project.timelineHeight;\n        }\n    }\n\n    var resetFrameSize = function () {\n        var newFrameWidth = wickEditor.project.getCurrentObject().isButton ? 35 : 20;\n        var newHandleWidth = 5;\n        document.body.style.setProperty('--frame-width', newFrameWidth+'px');\n        document.body.style.setProperty('--frame-handle-width', newHandleWidth+'px');\n    }\n}\n\nTimelineInterface.HorizontalScrollBar = function (wickEditor, timeline) {\n    var that = this;\n\n    this.elem = null;\n\n    var leftButton;\n    var rightButton;\n    var head;\n\n    var scrollbar;\n\n    var heldDownInterval;\n\n    this.build = function () {\n        this.elem = document.createElement('div');\n        this.elem.className = 'scrollbar horizontal-scrollbar';\n\n        head = document.createElement('div');\n        head.className = 'scrollbar-head scrollbar-head-horizontal';\n        head.addEventListener('mousedown', function (e) {\n            timeline.interactions.start('dragHorizontalScrollbarHead')\n        })\n        this.elem.appendChild(head);\n\n        leftButton = document.createElement('div');\n        leftButton.className = 'scrollbar-button scrollbar-button-left';\n        leftButton.addEventListener('mousedown', function (e) {\n            //that.scroll(-10);\n            clearInterval(heldDownInterval);\n            heldDownInterval = setInterval(function () {\n                that.scroll(-3);\n            }, 1000/30)\n        });\n        leftButton.addEventListener('mouseup', function (e) {\n            clearInterval(heldDownInterval);\n        });\n        this.elem.appendChild(leftButton);\n\n        rightButton = document.createElement('div');\n        rightButton.className = 'scrollbar-button scrollbar-button-right';\n        rightButton.addEventListener('mousedown', function (e) {\n            //that.scroll(10);\n            clearInterval(heldDownInterval);\n            heldDownInterval = setInterval(function () {\n                that.scroll(3);\n            }, 1000/30)\n        });\n        rightButton.addEventListener('mouseup', function (e) {\n            clearInterval(heldDownInterval);\n        });\n        this.elem.appendChild(rightButton);\n\n        scrollbar = new Scrollbar(10, 20, 30);\n        setTimeout(function () {\n            scrollbar.setScrollbarContainerSize(that.elem.offsetWidth-30);\n            scrollbar.setViewboxSize(that.elem.offsetWidth);\n        }, 100);\n\n        $(window).resize(function() {\n            scrollbar.setScrollbarContainerSize(that.elem.offsetWidth-30);\n            scrollbar.setViewboxSize(that.elem.offsetWidth);\n            that.update()\n        });\n    }\n\n    this.update = function () {\n        var frameCount = wickEditor.project.getCurrentObject().getTotalTimelineLength();\n        var buffer = 1000 + window.innerWidth;\n        var contentSize = frameCount * cssVar('--frame-width') + buffer;\n        scrollbar.setContentSize(contentSize)\n        head.style.marginLeft = scrollbar.barPosition + cssVar('--scrollbar-thickness') + 'px';\n        head.style.width = scrollbar.barSize + 'px';\n    }\n\n    this.scroll = function (scrollAmt) {\n        scrollbar.setBarPosition(scrollbar.barPosition + scrollAmt);\n        timeline.framesContainer.update();\n        timeline.numberLine.update();\n        timeline.playhead.update();\n        that.update();\n    }\n\n    this.getScrollPosition = function () {\n        return scrollbar.viewboxPosition;\n    }\n\n    this.reset = function () {\n        scrollbar.setBarPosition(0);\n    }\n}\n\nTimelineInterface.VerticalScrollBar = function (wickEditor, timeline) {\n    var that = this;\n\n    this.elem = null;\n\n    var topButton;\n    var bottomButton\n    var head;\n\n    var scrollbar;\n\n    var heldDownInterval;\n\n    this.build = function () {\n        this.elem = document.createElement('div');\n        this.elem.className = 'scrollbar vertical-scrollbar';\n\n        head = document.createElement('div');\n        head.className = 'scrollbar-head scrollbar-head-vertical';\n        head.addEventListener('mousedown', function (e) {\n            timeline.interactions.start('dragVerticalScrollbarHead');\n        })\n        this.elem.appendChild(head);\n\n        topButton = document.createElement('div');\n        topButton.className = 'scrollbar-button scrollbar-button-top';\n        topButton.addEventListener('mousedown', function (e) {\n            //that.scroll(-20)\n            clearInterval(heldDownInterval);\n            heldDownInterval = setInterval(function () {\n                that.scroll(-3);\n            }, 1000/30)\n        });\n        topButton.addEventListener('mouseup', function (e) {\n            clearInterval(heldDownInterval);\n        });\n        this.elem.appendChild(topButton);\n\n        bottomButton = document.createElement('div');\n        bottomButton.className = 'scrollbar-button scrollbar-button-bottom';\n        bottomButton.addEventListener('mousedown', function (e) {\n            //that.scroll(20)\n            clearInterval(heldDownInterval);\n            heldDownInterval = setInterval(function () {\n                that.scroll(3);\n            }, 1000/30)\n        });\n        bottomButton.addEventListener('mouseup', function (e) {\n            clearInterval(heldDownInterval);\n        });\n        this.elem.appendChild(bottomButton);\n\n        scrollbar = new Scrollbar(10, 100, 300);\n    },\n\n    this.update = function () {\n        var nLayers = wickEditor.project.getCurrentObject().layers.length;\n\n        if(nLayers < 4) {\n            this.elem.style.display = 'none';\n            return;\n        }\n        this.elem.style.display = 'block';\n\n        //head.style.height = parseInt(timeline.elem.style.height)/4 + 'px';\n        //head.style.marginTop = scrollbar.barPosition + cssVar('--scrollbar-thickness') + cssVar('--number-line-height') + 'px';\n    \n        scrollbar.setScrollbarContainerSize(that.elem.offsetHeight);\n        scrollbar.setViewboxSize(that.elem.offsetHeight-10);\n        var contentSize = nLayers * cssVar('--layer-height');\n        scrollbar.setContentSize(contentSize);\n        head.style.marginTop = scrollbar.barPosition + cssVar('--scrollbar-thickness') + 'px';\n        head.style.height = scrollbar.barSize - 30 + 'px';\n    }\n\n    this.scroll = function (scrollAmt) {\n        scrollbar.setBarPosition(scrollbar.barPosition+scrollAmt);\n        timeline.framesContainer.update();\n        that.update();\n    }\n\n    this.getScrollPosition = function () {\n        return scrollbar.viewboxPosition;\n    }\n\n    this.reset = function () {\n        scrollbar.setBarPosition(0);\n    }\n}\n\nTimelineInterface.NumberLine = function (wickEditor, timeline) {\n    var that = this;\n\n    this.elem = null;\n\n    var numberlineContainer;\n    var numbers = [];\n    var bars = [];\n\n    this.build = function () {\n        this.elem = document.createElement('div');\n        this.elem.addEventListener('mousedown', function (e) {\n            timeline.interactions.start(\"dragPlayhead\", e, {});\n        })\n        this.elem.className = 'number-line';\n\n        numberlineContainer = document.createElement('span');\n        numberlineContainer.className = 'numberline-container';\n        this.elem.appendChild(numberlineContainer);\n    }\n\n    this.update = function () {\n        var shift = -timeline.horizontalScrollBar.getScrollPosition();\n\n        this.elem.style.left = shift+cssVar('--layers-width')+'px';\n\n        numberlineContainer.style.left = -shift+(shift%cssVar('--frame-width'))+'px';\n\n        for(var i = 0; i < numbers.length; i++) {\n            var num = i+1+Math.floor(-shift/cssVar('--frame-width'));\n            numbers[i].innerHTML = num;\n            numbers[i].className = 'number-line-cell-number';\n            if(wickEditor.project.getCurrentObject().isButton) {\n                var buttonNames = ['Up', 'Over', 'Down']\n                numbers[i].innerHTML = i < 3 ? buttonNames[i] : '';\n                numbers[i].style.fontSize = '12px';\n                bars[i].style.opacity = '0.2';\n            } else {\n                if(num % 5 !== 0 && num !== 1)  {\n                    numbers[i].innerHTML = '';\n                    bars[i].style.opacity = '0.2';\n                } else {\n                    bars[i].style.opacity = '1.0';\n                }\n                numbers[i].className += ' number-line-cell-number-small';\n            }\n        }\n    }\n\n    this.rebuild = function () {\n\n        this.elem.innerHTML = ''\n        this.elem.appendChild(numberlineContainer)\n        numberlineContainer.innerHTML = \"\"\n\n        numbers = []\n        bars = []\n        for(var i = 0; i < 70; i++) {\n            var numberLineCell = document.createElement('div');\n            numberLineCell.className = 'number-line-cell';\n            numberLineCell.style.left = i*cssVar('--frame-width') +cssVar('--frames-cell-first-padding') + 'px'\n            \n            var bar = document.createElement('div');\n            bar.className = 'number-line-cell-bar';\n            numberLineCell.appendChild(bar);\n            bars.push(bar);\n\n            var number = document.createElement('div');\n            number.className = 'number-line-cell-number';\n            numberLineCell.appendChild(number);\n            numbers.push(number);\n            \n            numberlineContainer.appendChild(numberLineCell);\n        }\n    }\n}\n\nTimelineInterface.Playhead = function (wickEditor, timeline) {\n    var self = this;\n\n    self.elem = null;\n    self.pos = null;\n\n    var framePosCached = 0;\n\n    self.build = function () {\n        self.elem = document.createElement('div');\n        self.elem.className = 'playhead';\n\n        var playheadNub = document.createElement('div');\n        playheadNub.className = 'playhead-nub';\n        self.elem.addEventListener('mousedown', function (e) {\n            timeline.interactions.start(\"dragPlayhead\", e, {});\n        });\n        self.elem.appendChild(playheadNub);\n\n        window.addEventListener('mousemove', function (e) {\n            self.elem.style.pointerEvents = (e.y>60) ? 'none' : 'auto';\n        });\n\n        var playheadBody = document.createElement('div');\n        playheadBody.className = 'playhead-body';\n        self.elem.appendChild(playheadBody);\n    }\n\n    self.update = function () {\n        self.setPosition(wickEditor.project.currentObject.playheadPosition * cssVar('--frame-width'));\n        snapPosition()\n        updateView();\n    }\n\n    self.setPosition = function (pos) {\n        self.pos = pos;\n        updateView();\n    }\n\n    self.snap = function () {\n        snapPosition();\n        updateView();\n    }\n\n    self.getFramePosition = function () {\n        var framePos = Math.floor(self.pos/cssVar('--frame-width'));\n        return framePos;\n    }\n\n    self.frameDidChange = function () {\n        if(!framePosCached) {\n            framePosCached = self.getFramePosition();\n            return true;\n        } else {\n            var newFramePos = self.getFramePosition();\n            var frameChanged = newFramePos !== framePosCached;\n            framePosCached = newFramePos;\n            return frameChanged;\n        }\n    }\n\n    function updateView () {\n        var shift = -timeline.horizontalScrollBar.getScrollPosition();\n        self.elem.style.left = (self.pos+132+shift)+'px';\n    }\n\n    function snapPosition () {\n        self.pos = Math.floor(self.pos/cssVar('--frame-width'))*cssVar('--frame-width')\n        self.pos += cssVar('--frame-width')/2;\n    }\n}\n"
  },
  {
    "path": "src/editor/interfaces/Interfaces.Toolbar.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar ToolbarInterface = function (wickEditor) {\n\n    var toolbarDiv;\n\n    var container;\n    var toolOptionInputs;\n\n    var colorPickerDivs = [];\n\n    var brushSizePreview;\n    var cornerRadiusPreview;\n\n    this.setup = function () {\n        toolbarDiv = document.getElementById('tools');\n\n        // Build tool button elements\n        for(toolName in wickEditor.tools) {\n            var toolButton = new ToolButton(toolName)\n            toolbarDiv.appendChild(toolButton);\n        }\n\n        toolbarDiv.appendChild(document.createElement('hr'));\n\n        // Build color pickers\n        var colorPickerContainer = document.createElement('div');\n        colorPickerContainer.className = 'toolbar-color-picker-container';\n        toolbarDiv.appendChild(colorPickerContainer);\n\n        var strokeColorBackground = document.createElement('div');\n        strokeColorBackground.className = 'toolbar-stroke-color-background';\n        colorPickerContainer.appendChild(strokeColorBackground);\n\n        var strokeColorPicker = new ColorPicker('strokeColor', 'toolbar-stroke-color', 'strokeColor');\n        colorPickerDivs.push(strokeColorPicker);\n        var strokeInnerRect = document.createElement('div');\n        strokeInnerRect.className = 'toolbar-stroke-color-inner-rect';\n        strokeColorPicker.appendChild(strokeInnerRect);\n        colorPickerContainer.appendChild(strokeColorPicker);\n\n        var fillColorBackground = document.createElement('div');\n        fillColorBackground.className = 'toolbar-fill-color-background';\n        colorPickerContainer.appendChild(fillColorBackground);\n\n        var fillColorPicker = new ColorPicker('fillColor', 'toolbar-fill-color', 'fillColor');\n        colorPickerDivs.push(fillColorPicker);\n        colorPickerContainer.appendChild(fillColorPicker);\n    }\n\n    this.syncWithEditorState = function () {\n\n        // Highlight select tool, unhighlight all other tools\n        for (toolName in wickEditor.tools) {\n            var buttonClassName = toolName + 'ToolButton';\n            if (wickEditor.tools[toolName] === wickEditor.currentTool) {\n                document.getElementById(buttonClassName).className = \"toolButton tooltipElem toolButtonActive\"\n            } else {\n                document.getElementById(buttonClassName).className = \"toolButton tooltipElem\"\n            }\n        };\n\n        // Update color picker preview colors\n        colorPickerDivs.forEach(function (colorPicker) {\n            colorPicker.style.backgroundColor = wickEditor.settings[colorPicker.wickSettingsVal];\n        });\n\n    }\n\n    var ToolButton = function (toolName) {\n        var tool = wickEditor.tools[toolName];\n\n        var toolDiv = document.createElement('div');\n        toolDiv.id = toolName + \"ToolButton\";\n        toolDiv.setAttribute('alt', tool.getTooltipName());\n\n        // nasty closure thing\n        var useToolFn = function (toolName) {\n            return function () { wickEditor.guiActionHandler.doAction('useTools.'+toolName); };\n        }\n        toolDiv.onclick = useToolFn(toolName);\n\n        var toolIcon = document.createElement('img');\n        toolIcon.src = tool.getToolbarIcon();\n        toolIcon.width = '28';\n        toolDiv.appendChild(toolIcon);\n\n        return toolDiv;\n    }\n\n    var ColorPicker = function (settingsVal, className, previewType) {\n        var colorPickerContainer = document.createElement('div');\n        colorPickerContainer.className = 'toolbar-color ' + className;\n        colorPickerContainer.wickSettingsVal = settingsVal;\n\n        colorPickerContainer.onclick = function () {\n            wickEditor.colorPicker.open(function (color) {\n                wickEditor.settings.setValue(settingsVal, color);\n                if(settingsVal === 'fillColor') {\n                    wickEditor.guiActionHandler.doAction(\"changePathProperties\", {\n                        fillColor: color\n                    });\n                } else if (settingsVal === 'strokeColor') {\n                    wickEditor.guiActionHandler.doAction(\"changePathProperties\", {\n                        strokeColor: color\n                    });\n                }\n                wickEditor.syncInterfaces();\n            }, \n                wickEditor.settings[settingsVal],\n                colorPickerContainer.getBoundingClientRect().left,\n                colorPickerContainer.getBoundingClientRect().top,\n                previewType)\n        }\n\n        return colorPickerContainer;\n    }\n\n}\n"
  },
  {
    "path": "src/editor/interfaces/Interfaces.VideoExporter.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar VideoExporterInterface = function (wickEditor) {\n    var self = this;\n    var videoExportWindow = document.getElementById('videoExportGUI');\n    var closeButton; \n    var sparkText; \n    var progressBar; \n    var downloadButton;\n\n    var videoExporter;\n\n    var qualityOptions = {\n        \"Ultra\" : 1, \n        \"High\" : 5, \n        \"Medium\" : 15, \n        \"Low\" : 31,\n    }; \n    var defaultQuality = \"High\"; \n    var chosenQuality = defaultQuality; \n    var qualityDropdown; \n\n    self.setup = function () {\n        // Add title\n        /*var title = document.createElement('div');\n        title.className = \"GUIBoxTitle\"; \n        title.id = \"videoExportGUITitle\";\n        title.innerHTML = \"Wick Video Exporter\"; \n        videoExportWindow.appendChild(title); */\n\n        // Add Close Button\n        closeButton = document.createElement('div'); \n        closeButton.className = \"GUIBoxCloseButton\"; \n        closeButton.id = \"videoExportGUICloseButton\"; \n        closeButton.addEventListener('click', self.close);\n        videoExportWindow.appendChild(closeButton);\n\n        // Add Spark Text\n        sparkText = document.createElement('div'); \n        sparkText.id = \"videoExportSparkText\"; \n        sparkText.className = \"sparkText\"; \n        sparkText.innerHTML = \"Exporting Your Video...\";\n        videoExportWindow.appendChild(sparkText); \n\n        // Add Progress Bar\n        var progressBarContainer = document.createElement('div'); \n        progressBarContainer.className = \"meter animate wickGreen\"; \n        progressBarContainer.id = \"videoExportProgressBarContainer\"; \n        progressBar = document.createElement('span');\n        progressBar.id = \"videoExportProgressBar\";\n        progressBar.style.width = \"1%\";\n        progressBarContainer.appendChild(progressBar); \n        var extraSpan = document.createElement('span'); \n        progressBar.appendChild(extraSpan); \n        videoExportWindow.appendChild(progressBarContainer); \n\n        // Add Settings Menu\n        var settingsContainer = document.createElement('div');\n        settingsContainer.id = \"videoExportSettingsContainer\";\n        videoExportWindow.appendChild(settingsContainer); \n\n        var qualityContainer = document.createElement('div');\n        qualityContainer.className = \"quality-container\"; \n        settingsContainer.appendChild(qualityContainer);\n\n        var qualitySettingTitle = document.createElement('div'); \n        qualitySettingTitle.innerText = \"Quality: \";  \n        qualitySettingTitle.id = \"qualitySettingTitle\"; \n        qualityContainer.appendChild(qualitySettingTitle); \n\n        qualityDropdown = document.createElement('div'); \n        qualityDropdown.id=\"videoExportQualityDropdown\";\n        qualityDropdown.className=\"dropbtn\"; \n        qualityDropdown.onclick = function () {\n            dropdownContainer.classList.toggle(\"show\")\n        };\n        qualityContainer.appendChild(qualityDropdown); \n\n        var dropdownTitleDiv = document.createElement('div'); \n        dropdownTitleDiv.id = \"videoExportQualityTitleDiv\"; \n        dropdownTitleDiv.innerText=chosenQuality;\n        dropdownTitleDiv.class=\"title-div\";\n        qualityDropdown.appendChild(dropdownTitleDiv); \n\n        var dropdownContainer = document.createElement('div'); \n        dropdownContainer.className = \"dropdown-content\"; \n\n        for(quality in qualityOptions) {\n            var elem = document.createElement('div'); \n            elem.innerHTML = quality; \n            elem.className = \"dropdown-item\";\n            (function (q) {\n                elem.onclick = function () {\n                    self.setVideoQuality(q); \n                };\n            })(quality); \n            dropdownContainer.appendChild(elem); \n        }\n        qualityDropdown.appendChild(dropdownContainer); \n\n        // Add Download Button\n        downloadButton = document.createElement('div'); \n        downloadButton.className = \"videoDownloadButton\"; \n        downloadButton.innerHTML = \"Export Video\"; \n        downloadButton.addEventListener('click', self.exportVideo);\n        settingsContainer.appendChild(downloadButton); \n    }\n    \n    self.setVideoQuality = function (qualitySetting) {\n        var titleDiv = qualityDropdown.querySelector(\"#videoExportQualityTitleDiv\"); \n\n        if (qualityOptions[qualitySetting]) {\n            chosenQuality = qualitySetting; \n            titleDiv.textContent = chosenQuality; \n        } else {\n            chosenQuality = defaultQuality; \n            titleDiv.textContent = chosenQuality;\n            console.error(qualitySetting + \" is not a valid video quality setting! Defaulting to High Quality.\"); \n        }\n    }\n\n    self.syncWithEditorState = function () {\n\n    }\n    \n    self.setProgressBarPercent = function (percent) {\n        percent = percent*100\n\n        if (typeof percent != \"number\") {\n            console.error(\"Error: Input percentage is not a number.\"); \n            return; \n        }\n\n        if(percent >= 100) {\n            progressBar.style.width = \"100%\";\n        } else if (percent <= 0) {\n            progressBar.style.width = \"0%\";\n        } else {\n            progressBar.style.width = percent + \"%\";\n        }\n    }\n\n    self.setSparkText = function (newSparkText) {\n        self.setProgressBarPercent(0)\n        sparkText.innerHTML = newSparkText; \n    }\n    \n    self.open = function () {\n        self.setSparkText('Ready to export video.');\n        self.setProgressBarPercent(0);\n        videoExportWindow.style.display = \"block\"; \n    }\n    \n    self.close = function () {\n        videoExportWindow.style.display = \"none\";\n    }\n    \n    self.exportVideo = function () {\n        if(!videoExporter) {\n            videoExporter = new VideoExporter();\n            videoExporter.setProgressBarFn(self.setProgressBarPercent)\n            videoExporter.init();\n        }\n\n        wickEditor.canvas.getCanvasRenderer().getProjectFrames(function (frames) {\n            renderVideoFromFrames(frames, function (videoBuffer) {\n                generateAudioTrack(function (audioBuffer) {\n                    if(!audioBuffer) {\n                        downloadVideo(videoBuffer);\n                    } else {\n                        mergeAudioTrackWithVideo(videoBuffer, audioBuffer, function (finalVideoBuffer) {\n                            downloadVideo(finalVideoBuffer);\n                        });\n                    }\n                });\n            });\n        });\n\n    }\n\n    function renderVideoFromFrames (frames, callback) {\n        self.setSparkText('Converting frames to video...')\n\n        videoExporter.renderVideoFromFrames({\n            quality: qualityOptions[chosenQuality],\n            frames: frames,\n            framerate: wickEditor.project.framerate,\n            completedCallback: function (videoArrayBuffer) {\n                var videoBuffer = new Uint8Array(videoArrayBuffer);\n                callback(videoBuffer);\n            }\n        })\n    }\n\n    function generateAudioTrack (callback) {\n        self.setSparkText('Generating audio track...')\n\n        var soundFrames = wickEditor.project.rootObject.getAllFramesWithSound();\n        if(soundFrames.length === 0) {\n            console.log('Video has no sound. Skipping audio export.')\n            callback(null);\n            return;\n        }\n\n        soundFrames.forEach(function (soundFrame) {\n            var library = wickEditor.project.library;\n            var asset = library.getAsset(soundFrame.audioAssetUUID);\n            var src = asset.getData();\n            videoExporter.addAudioTrack(\n                convertDataURIToBinary(src),\n                0,\n                soundFrame.length / wickEditor.project.framerate,\n                1 + (soundFrame.playheadPosition / wickEditor.project.framerate * 1000),\n            )\n        })\n\n        videoExporter.mergeAudioTracks({\n            callback: function (soundTrackArrayBuffer) {\n                var soundBuffer = new Uint8Array(soundTrackArrayBuffer);\n                callback(soundBuffer);\n            }\n        })\n    }\n\n    function mergeAudioTrackWithVideo (videoBuffer, audioBuffer, callback) {\n        self.setSparkText('Merging audio and video...')\n\n        videoExporter.combineAudioAndVideo({\n            videoBuffer: videoBuffer,\n            soundBuffer: audioBuffer,\n            framerate: wickEditor.project.framerate,\n            filename: 'test.mp4',\n            percentCallback: console.log,\n            completedCallback: callback,\n        })\n    }\n\n    function downloadVideo (videoBuffer) {\n        self.setSparkText('Finished exporting!')\n        self.setProgressBarPercent(1);\n        var blob = new Blob([videoBuffer], {type: \"application/octet-stream\"});\n        var fileName = wickEditor.project.name + '.mp4';\n        saveAs(blob, fileName);\n    }\n}\n"
  },
  {
    "path": "src/editor/tools/Tools.Dropper.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n    \nif(!window.Tools) Tools = {};\n\nTools.Dropper = function (wickEditor) {\n\n    var that = this;\n\n    var PREVIEW_IMG = 'resources/colorpreviewcursoricon.png';\n\n    this.paperTool = new paper.Tool();\n\n    this.getCursorImage = function () {\n        return 'url(\"resources/dropper.png\") 2 14,default';\n    }\n\n    this.getToolbarIcon = function () {\n        return \"resources/tools/Dropper.svg\";\n    }\n\n    this.getTooltipName = function () {\n        return \"Eyedropper (D)\";\n    }\n\n    this.onSelected = function () {\n        wickEditor.inspector.clearSpecialMode();\n    }\n\n    this.onDeselected = function () {\n       wickEditor.cursorIcon.hide();\n    }\n\n    this.setup = function () {\n        \n    }\n\n    this.paperTool = new paper.Tool();\n\n    this.paperTool.onMouseMove = function(event) {\n        var colorResult = wickEditor.canvas.getInteractiveCanvas().getColorAtPoint(event.point)\n        if(colorResult) {\n            wickEditor.cursorIcon.setImage(PREVIEW_IMG, colorResult.color);\n        } else {\n            wickEditor.cursorIcon.hide();\n        }\n    }\n\n    this.paperTool.onMouseDown = function(event) {\n        var colorResult = wickEditor.canvas.getInteractiveCanvas().getColorAtPoint(event.point)\n        if(colorResult) {\n            if(!wickEditor.colorPicker.isOpen()) wickEditor.settings.setValue('fillColor', colorResult.color);\n            wickEditor.colorPicker.setColor(colorResult.color)\n            wickEditor.syncInterfaces();\n        }\n    }\n\n}"
  },
  {
    "path": "src/editor/tools/Tools.Ellipse.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nif(!window.Tools) Tools = {};\n\nTools.Ellipse = function (wickEditor) {\n\n    var that = this;\n    \n    var drawingEllipse;\n    var topLeft;\n    var bottomRight;\n\n    var tempGroup;\n\n    this.getCursorImage = function () {\n        return \"crosshair\"\n    };\n\n    this.getToolbarIcon = function () {\n        return \"resources/tools/Circle.svg\";\n    }\n\n    this.getTooltipName = function () {\n        return \"Ellipse (S)\";\n    }\n\n    this.onSelected = function () {\n        wickEditor.inspector.openToolSettings('ellipse');\n        wickEditor.project.clearSelection();\n        wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n    }\n\n    this.onDeselected = function () {\n        if(tempGroup) tempGroup.remove();\n    }\n\n    this.setup = function () {\n        \n    }\n\n    this.paperTool = new paper.Tool();\n\n    this.paperTool.onMouseDown = function (event) {\n        tempGroup = new paper.Group();\n        topLeft = event.point;\n        bottomRight = null;\n    }\n\n    this.paperTool.onMouseDrag = function (event) {\n        bottomRight = event.point;\n\n        tempGroup.remove();\n\n        var newPath = new paper.Path.Ellipse({\n            point: [topLeft.x, topLeft.y],\n            size: [bottomRight.x-topLeft.x, bottomRight.y-topLeft.y],\n        });\n        newPath.fillColor = wickEditor.settings.fillColor;\n        newPath.strokeColor = wickEditor.settings.strokeColor;\n        newPath.strokeWidth = wickEditor.settings.strokeWidth;\n        newPath.strokeJoin = wickEditor.settings.strokeJoin;\n        newPath.strokeCap = wickEditor.settings.strokeCap;\n        drawingEllipse = newPath;\n\n        tempGroup = new paper.Group();\n        tempGroup.addChild(newPath);\n    }\n\n    this.paperTool.onMouseUp = function (event) {\n\n        if(!bottomRight)\n            return;\n\n        var svgString = tempGroup.exportSVG({asString:true});\n        tempGroup.remove();\n        var pathWickObject = WickObject.createPathObject(svgString);\n        pathWickObject.x = (bottomRight.x+topLeft.x)/2;\n        pathWickObject.y = (bottomRight.y+topLeft.y)/2;\n        pathWickObject.width = tempGroup.bounds._width;\n        pathWickObject.height = tempGroup.bounds._height;\n        pathWickObject.svgX = tempGroup.bounds._x;\n        pathWickObject.svgY = tempGroup.bounds._y;\n\n        //wickEditor.canvas.getInteractiveCanvas().pathRoutines.refreshPathData(pathWickObject);\n\n        wickEditor.actionHandler.doAction('addObjects', {\n            wickObjects: [pathWickObject],\n            dontSelectObjects: true,\n        });\n    }\n\n}"
  },
  {
    "path": "src/editor/tools/Tools.Eraser.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n    \nif(!window.Tools) Tools = {};\n\nTools.Eraser = function (wickEditor) {\n\n    var that = this;\n\n    this.getCursorImage = function () {\n        var canvas = document.createElement(\"canvas\");\n        canvas.width = 128;\n        canvas.height = 128;\n        var context = canvas.getContext('2d');\n        var centerX = canvas.width / 2;\n        var centerY = canvas.height / 2;\n        var radius = wickEditor.settings.brushThickness/2;\n\n        context.beginPath();\n        context.arc(centerX, centerY, radius+1, 0, 2 * Math.PI, false);\n        context.fillStyle = \"#000000\"\n        context.fill();\n\n        context.beginPath();\n        context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);\n        context.fillStyle = \"#FFFFFF\";\n        context.fill();\n\n        return 'url(' + canvas.toDataURL() + ') 64 64,default';\n    }\n\n    this.getToolbarIcon = function () {\n        return \"resources/tools/Erase.svg\";\n    }\n\n    this.getTooltipName = function () {\n        return \"Eraser (E)\";\n    }\n\n    this.setup = function () {\n\n    }\n\n    this.onSelected = function () {\n        wickEditor.inspector.openToolSettings('eraser');\n        wickEditor.project.clearSelection();\n        wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n    }\n\n    this.onDeselected = function () {\n        if(path) path.remove();\n    }\n\n    this.paperTool = new paper.Tool();\n    var path;\n    var totalDelta;\n    var lastEvent;\n\n    this.paperTool.onMouseDown = function (event) {\n        if (!path) {\n            path = new paper.Path({\n                strokeColor: 'white',\n                strokeCap: 'round',\n                strokeWidth: wickEditor.settings.brushThickness/wickEditor.canvas.getZoom(),\n            });\n        }\n\n        path.add(event.point);\n    }\n\n    this.paperTool.onMouseDrag = function (event) {\n\n        if(!totalDelta) {\n            totalDelta = event.delta;\n        } else {\n            totalDelta.x += event.delta.x;\n            totalDelta.y += event.delta.y;\n        }\n\n        if (totalDelta.length > 2/wickEditor.canvas.getZoom()) {\n\n            totalDelta.x = 0;\n            totalDelta.y = 0;\n\n            path.add(event.point)\n            path.smooth();\n            lastEvent = event;\n\n        }\n    }\n\n    this.paperTool.onMouseUp = function (event) {\n        if(!path) return;\n\n        path.add(event.point)\n        path.simplify(5);\n\n        path.remove();\n\n        path.strokeCap = 'round';\n        path.strokeJoin = 'round';\n\n        var offset = path.strokeWidth/2;\n        var outerPath = OffsetUtils.offsetPath(path, offset, true);\n        var innerPath = OffsetUtils.offsetPath(path, -offset, true);\n        path = OffsetUtils.joinOffsets(outerPath.clone(), innerPath.clone(), path, offset);\n        path = path.unite();\n        path.fillColor = wickEditor.settings.fillColor;\n\n        var eraseObjects = wickEditor.project.getCurrentFrame().wickObjects\n        eraseObjects = eraseObjects.filter(function (wickObject) {\n            return wickObject.paper;\n        });\n\n        var modifiedStates = [];\n        eraseObjects.forEach(function (wickObject) {\n            var parentAbsPos;\n            if(wickObject.parentObject)\n                parentAbsPos = wickObject.parentObject.getAbsolutePosition();\n            else \n                parentAbsPos = {x:0,y:0};\n\n            if(!wickObject.paper.closed) {\n                \n            } else {\n                wickObject.paper = wickObject.paper.subtract(path);\n            }\n\n            modifiedStates.push({\n                x: wickObject.paper.position.x - parentAbsPos.x,\n                y: wickObject.paper.position.y - parentAbsPos.y,\n                svgX: wickObject.paper.bounds._x,\n                svgY: wickObject.paper.bounds._y,\n                width: wickObject.paper.bounds._width,\n                height: wickObject.paper.bounds._height,\n                pathData: wickObject.paper.exportSVG({asString:true}),\n            });\n        });\n\n        wickEditor.actionHandler.doAction('modifyObjects', {\n            objs: eraseObjects,\n            modifiedStates: modifiedStates,\n        });\n\n        path = null;\n    }\n}\n"
  },
  {
    "path": "src/editor/tools/Tools.FillBucket.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nif(!window.Tools) Tools = {};\n\n// IMPROVEMENTS\n// Extend paths by CLONE_WIDTH_SHRINK\n// Use paper.js bounds to ignore paths that definitely won't be part of the fill process\n\nTools.FillBucket = function (wickEditor) {\n\n    var RES = 1.75;\n    var FILL_TOLERANCE = 35;\n    var N_RASTER_CLONE = 1;\n    var CLONE_WIDTH_SHRINK = 1.0;\n    var SHRINK_AMT = 0.85;\n    var FILLBUCKETMOUSE_DELAY = 50; // milliseconds\n    \n    var PREVIEW_IMAGE = false;\n    var LOG_PERFORMANCE = false;\n\n    var that = this;\n\n    this.getCursorImage = function () {\n        return 'url(\"resources/fillbucket-cursor.png\") 64 64,default';\n    };\n\n    this.getToolbarIcon = function () {\n        return \"resources/tools/Bucket.svg\";\n    }\n\n    this.getTooltipName = function () {\n        return \"Fill Bucket (G)\";\n    }\n\n    this.setup = function () {\n\n    }\n\n    this.onSelected = function () {\n        wickEditor.inspector.openToolSettings('fillbucket');\n        wickEditor.project.clearSelection();\n        wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n    }\n\n    this.paperTool = new paper.Tool();\n\n    this.paperTool.onMouseMove = function(event) {\n        \n    }\n\n    this.paperTool.onMouseDown = function (event) {\n        var hitResult = wickEditor.canvas.getInteractiveCanvas().getItemAtPoint(event.point, {\n            fill: true,\n            stroke: true,\n            curves: true,\n        });\n        if(hitResult) {\n            if(hitResult.type === 'fill') {\n                changeFillColorOfItem(hitResult.item);\n            } else if (hitResult.type === 'stroke') {\n                changeStrokeColorOfItem(hitResult.item);\n            }\n        } else {\n            setTimeout(function () {\n                wickEditor.canvas.getCanvasContainer().style.cursor = 'wait';\n            }, 0); \n\n            setTimeout(function () {\n                fillHole(event, function () {\n                    wickEditor.canvas.getCanvasContainer().style.cursor = that.getCursorImage();\n                });\n            }, FILLBUCKETMOUSE_DELAY);\n        }\n    }\n\n    function changeFillColorOfItem (item) {\n        wickEditor.guiActionHandler.doAction(\"changePathProperties\", {\n            fillColor: wickEditor.settings.fillColor,\n            objs: [item.wick],\n        });\n    }\n\n    function changeStrokeColorOfItem (item) {\n        wickEditor.guiActionHandler.doAction(\"changePathProperties\", {\n            strokeColor: wickEditor.settings.fillColor,\n            objs: [item.wick],\n        });\n    }\n\n    // This is zach's secret vector fill bucket technique\n    // Will document how it works later but trust me it's great\n\n    function fillHole (event, callback) {\n        var superGroup = new paper.Group({insert:false});\n        wickEditor.project.getCurrentFrame().wickObjects.forEach(function (wo) {\n            if(!wo.paper) return;\n            if(wo.paper._class !== 'Path' && wo.paper._class !== 'CompoundPath') return;\n            for(var i = 0; i < N_RASTER_CLONE; i++) {\n                var clone = wo.paper.clone({insert:false});\n                clone.strokeWidth *= CLONE_WIDTH_SHRINK;\n                superGroup.addChild(clone);\n            }\n        });\n        if(superGroup.children.length > 0) {\n            startTiming()\n            var raster = superGroup.rasterize(paper.view.resolution*RES/window.devicePixelRatio, {insert:false});\n            var rasterPosition = raster.bounds.topLeft;\n            var x = (event.point.x - rasterPosition.x) * RES;\n            var y = (event.point.y - rasterPosition.y) * RES;\n            if(x<0 || y<0) {\n                callback();\n                return;\n            } \n            if(LOG_PERFORMANCE) stopTiming('rasterize')\n            generateFloodFillImage(raster, x, y, function (floodFillImage) {\n                if(LOG_PERFORMANCE) stopTiming('generateFloodFillImage')\n                if(PREVIEW_IMAGE) previewImage(floodFillImage)\n                imageToPath(floodFillImage, function (path) {\n                    if(LOG_PERFORMANCE) stopTiming('imageToPath')\n                    addFilledHoleToProject(path, rasterPosition.x, rasterPosition.y);\n                });\n            });\n        } else {\n            console.log('No paths to find holes of!');\n        }\n    }\n\n    function generateFloodFillImage (raster, x, y, callback) {\n        x = Math.round(x);\n        y = Math.round(y);\n\n        var rasterCanvas = raster.canvas;\n        var rasterCtx = rasterCanvas.getContext('2d');\n        var rasterImageData = rasterCtx.getImageData(0, 0, raster.width, raster.height);\n\n        var floodFillCanvas = document.createElement('canvas');\n        floodFillCanvas.width = rasterCanvas.width;\n        floodFillCanvas.height = rasterCanvas.height;\n        var floodFillCtx = floodFillCanvas.getContext('2d');\n        floodFillCtx.putImageData(rasterImageData, 0, 0);\n        floodFillCtx.fillStyle = \"rgba(123,124,125,1)\";\n        floodFillCtx.fillFlood(x, y, FILL_TOLERANCE);\n        var floodFillImageData = floodFillCtx.getImageData(0,0,floodFillCanvas.width,floodFillCanvas.height);\n        var floodFillImageDataRaw = floodFillImageData.data;\n        for(var i = 0; i < floodFillImageDataRaw.length; i += 4) {\n          if(floodFillImageDataRaw[i] === 123 && floodFillImageDataRaw[i+1] === 124 && floodFillImageDataRaw[i+2] === 125) {\n            floodFillImageDataRaw[i] = 0;\n            floodFillImageDataRaw[i+1] = 0;\n            floodFillImageDataRaw[i+2] = 0;\n            floodFillImageDataRaw[i+3] = 255;\n          } else if(floodFillImageDataRaw[i+3] !== 0) {\n            floodFillImageDataRaw[i] = 255;\n            floodFillImageDataRaw[i+1] = 0;\n            floodFillImageDataRaw[i+2] = 0;\n            floodFillImageDataRaw[i+3] = 255;\n          } else {\n            floodFillImageDataRaw[i] = 1;\n            floodFillImageDataRaw[i+1] = 0;\n            floodFillImageDataRaw[i+2] = 0;\n            floodFillImageDataRaw[i+3] = 0;\n          }\n        }\n\n        var w = floodFillCanvas.width;\n        var h = floodFillCanvas.height;\n        var r = 4;\n        for(var this_x = 0; this_x < w; this_x++) {\n            for(var this_y = 0; this_y < h; this_y++) {\n                var thisPix = getPixelAt(this_x, this_y, w, h, floodFillImageDataRaw);\n                if(thisPix && thisPix.r === 255) {\n                    for(var offset_x = -r; offset_x <= r; offset_x++) {\n                        for(var offset_y = -r; offset_y <= r; offset_y++) {\n                            var other_x = this_x+offset_x;\n                            var other_y = this_y+offset_y;\n                            var otherPix = getPixelAt(other_x, other_y, w, h, floodFillImageDataRaw);\n                            if(otherPix && otherPix.r === 0) {\n                                setPixelAt(this_x, this_y, w, h, floodFillImageDataRaw, {\n                                    r: 1,\n                                    g: 255,\n                                    b: 0,\n                                    a: 255,\n                                });\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        for(var i = 0; i < floodFillImageDataRaw.length; i += 4) {\n          if(floodFillImageDataRaw[i] === 255) {\n            floodFillImageDataRaw[i] = 0;\n            floodFillImageDataRaw[i+1] = 0;\n            floodFillImageDataRaw[i+2] = 0;\n            floodFillImageDataRaw[i+3] = 0;\n          }\n        }\n        floodFillCtx.putImageData(floodFillImageData, 0, 0);\n\n        var floodFillImage = new Image();\n        floodFillImage.onload = function () {\n            callback(floodFillImage);\n        }\n        floodFillImage.src = floodFillCanvas.toDataURL();\n    }\n\n    function imageToPath (image, callback) {\n        potraceImage(image, function (svgString) {\n            var xmlString = svgString\n              , parser = new DOMParser()\n              , doc = parser.parseFromString(xmlString, \"text/xml\");\n            callback(paper.project.importSVG(doc, {insert:true}));\n        }, wickEditor.settings.fillColor);\n    }\n\n    function addFilledHoleToProject (path, x, y) {\n        path.scale(1/RES, new paper.Point(0,0))\n        expandHole(path, SHRINK_AMT);\n        var pathWickObject = WickObject.createPathObject(path.exportSVG({asString:true}));\n        pathWickObject.width = path.bounds.width;\n        pathWickObject.height = path.bounds.height;\n        pathWickObject.x = path.position.x+x// - wickEditor.project.width/2;\n        pathWickObject.y = path.position.y+y// - wickEditor.project.height/2;\n        pathWickObject.svgX = path.bounds._x;\n        pathWickObject.svgY = path.bounds._y;\n        wickEditor.actionHandler.doAction('addObjects', {\n            wickObjects: [pathWickObject],\n            dontSelectObjects: true,\n            sendToBack: true,\n        });\n    }\n\n    function expandHole (path, HOLE_EXPAND_AMT) {\n        if(path instanceof paper.Group) {\n            path = path.children[0];\n        }\n\n        var children;\n        if(path instanceof paper.Path) {\n            children = [path];\n        } else if(path instanceof paper.CompoundPath) {\n            children = path.children;\n        }\n\n        children.forEach(function (hole) {\n            var normals = [];\n            hole.closePath();\n            hole.segments.forEach(function (segment) {\n                //var n = segment.path.getNormalAt(segment.path.getOffsetOf(segment.point))\n                //normals.push(n);\n                var a = segment.previous.point;\n                var b = segment.point;\n                var c = segment.next.point;\n\n                var ab = {x: b.x-a.x, y: b.y-a.y};\n                var cb = {x: b.x-c.x, y: b.y-c.y};\n\n                var d = {x: ab.x-cb.x, y: ab.y-cb.y};\n                d.h = Math.sqrt((d.x*d.x)+(d.y*d.y));\n                d.x /= d.h;\n                d.y /= d.h;\n\n                d = rotate_point(d.x, d.y, 0, 0, 90);\n\n                normals.push({x:d.x,y:d.y});\n            });\n\n            for (var i = 0; i < hole.segments.length; i++) {\n                var segment = hole.segments[i];\n                var normal = normals[i];\n                segment.point.x += normal.x*-HOLE_EXPAND_AMT;\n                segment.point.y += normal.y*-HOLE_EXPAND_AMT;\n            }\n\n            for (var i = 0; i < hole.segments.length; i++) {\n                var segment = hole.segments[i];\n                \n            }\n        });\n    }\n\n}\n"
  },
  {
    "path": "src/editor/tools/Tools.Line.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nif(!window.Tools) Tools = {};\n\nTools.Line = function (wickEditor) {\n\n    var that = this;\n\n    var drawingLine;\n    var tempGroup;\n\n    this.getCursorImage = function () {\n        return \"crosshair\"\n    };\n\n    this.getToolbarIcon = function () {\n        return \"resources/tools/Line.svg\";\n    }\n\n    this.getTooltipName = function () {\n        return \"Line (L)\";\n    }\n\n    this.setup = function () {\n\n    }\n\n    this.onSelected = function () {\n        wickEditor.inspector.openToolSettings('line');\n        wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n        wickEditor.project.clearSelection();\n    }\n\n    this.onDeselected = function () {\n        if(tempGroup) tempGroup.remove();\n    }\n\n    this.paperTool = new paper.Tool();\n\n    this.paperTool.onMouseDown = function (event) {\n        var newPath = new paper.Path({insert:false});\n        newPath.strokeColor = wickEditor.settings.strokeColor;\n        newPath.strokeWidth = wickEditor.settings.strokeWidth;\n        newPath.strokeJoin = wickEditor.settings.strokeJoin;\n        newPath.strokeCap = wickEditor.settings.strokeCap;\n        newPath.add(event.point);\n        newPath.add(event.point);\n\n        tempGroup = new paper.Group();\n        tempGroup.addChild(newPath);\n\n        drawingLine = newPath;\n    }\n\n    this.paperTool.onMouseDrag = function (event) {\n        drawingLine.segments[1].point = event.point;\n    }\n\n    this.paperTool.onMouseUp = function (event) {\n        tempGroup.remove();\n\n        var group = tempGroup.clone({insert:false});\n\n        var svgString = group.exportSVG({asString:true});\n        var pathWickObject = WickObject.createPathObject(svgString);\n        pathWickObject.x = (drawingLine.segments[0].point.x + drawingLine.segments[1].point.x)/2;\n        pathWickObject.y = (drawingLine.segments[0].point.y + drawingLine.segments[1].point.y)/2;\n        pathWickObject.width = drawingLine.bounds._width;\n        pathWickObject.height = drawingLine.bounds._height;\n        pathWickObject.svgX = drawingLine.bounds._x;\n        pathWickObject.svgY = drawingLine.bounds._y;\n\n        wickEditor.actionHandler.doAction('addObjects', {\n            wickObjects: [pathWickObject],\n            dontSelectObjects: true,\n        });\n    }\n\n}"
  },
  {
    "path": "src/editor/tools/Tools.Paintbrush.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nif(!window.Tools) Tools = {};\n\nTools.Paintbrush = function (wickEditor) {\n\n    var self = this;\n\n    var croquis;\n    var croquisDOMElement;\n\n    var brush;\n\n    this.getCursorImage = function () {\n        return 'crosshair'\n    };\n\n    this.getToolbarIcon = function () {\n        return \"resources/tools/Paintbrush.svg\";\n    }\n\n    this.getTooltipName = function () {\n        return \"Brush (B)\";\n    }\n\n    this.setup = function () {\n        croquis = new Croquis();\n        croquis.setCanvasSize(window.innerWidth, window.innerHeight);\n        croquis.addLayer();\n        croquis.fillLayer('rgba(0,0,0,0)');\n        croquis.addLayer();\n        croquis.selectLayer(1);\n\n        brush = new Croquis.Brush();\n\n        croquis.setTool(brush);\n\n        croquisDOMElement = croquis.getDOMElement();\n        croquisDOMElement.style.display = 'none'\n        croquisDOMElement.style.pointerEvents = 'none';\n        document.getElementById('editorCanvasContainer').appendChild(croquisDOMElement);\n    }\n\n    this.onSelected = function () {\n        wickEditor.inspector.openToolSettings('paintbrush');\n        wickEditor.project.clearSelection();\n        wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n        croquisDOMElement.style.display = 'block'\n    }\n\n    this.onDeselected = function () {\n        croquisDOMElement.style.display = 'none'\n    }\n\n    this.paperTool = new paper.Tool();\n\n    this.paperTool.onMouseDown = function (event) {\n        brush.setSize(wickEditor.settings.brushThickness);\n        brush.setColor(wickEditor.settings.fillColor);\n        brush.setSpacing(0.2);\n        croquis.setToolStabilizeLevel(10);\n        croquis.setToolStabilizeWeight(wickEditor.settings.brushSmoothing / 100);\n\n        e = event.event\n        var pointerPosition = getRelativePosition(e.clientX, e.clientY);\n        var penPressure = wickEditor.inputHandler.getPenPressure();\n        croquis.down(pointerPosition.x, pointerPosition.y, penPressure);\n    }\n\n    this.paperTool.onMouseDrag = function (event) {\n        e = event.event\n        var pointerPosition = getRelativePosition(e.clientX, e.clientY);\n        var penPressure = wickEditor.inputHandler.getPenPressure();\n        croquis.move(pointerPosition.x, pointerPosition.y, penPressure);\n    }\n\n    this.paperTool.onMouseUp = function (event) {\n        e = event.event\n        var pointerPosition = getRelativePosition(e.clientX, e.clientY);\n        var penPressure = wickEditor.inputHandler.getPenPressure();\n        croquis.up(pointerPosition.x, pointerPosition.y, penPressure);\n        \n        setTimeout(function () {\n            var i = new Image();\n            i.onload = function () {\n                //previewImage(i)\n                potraceImage(i, function (svgString) {\n                    var xmlString = svgString\n                      , parser = new DOMParser()\n                      , doc = parser.parseFromString(xmlString, \"text/xml\");\n                    var tempPaperForPosition = paper.project.importSVG(doc, {insert:false});\n\n                    var pathWickObject = WickObject.createPathObject(svgString);\n                    pathWickObject.width = tempPaperForPosition.bounds.width;\n                    pathWickObject.height = tempPaperForPosition.bounds.height;\n\n                    pathWickObject.x = tempPaperForPosition.position.x - wickEditor.canvas.getPan().x;\n                    pathWickObject.y = tempPaperForPosition.position.y - wickEditor.canvas.getPan().y;\n\n                    //tempPaperForPosition.scale(1/smoothing);\n                    tempPaperForPosition.fillColor = wickEditor.settings.fillColor;\n                    pathWickObject.pathData = tempPaperForPosition.exportSVG({asString:true});\n\n                    wickEditor.actionHandler.doAction('addObjects', {\n                        wickObjects: [pathWickObject],\n                        dontSelectObjects: true,\n                    });\n\n                    croquis.clearLayer();\n                });\n            }\n            i.src = document.getElementsByClassName('croquis-layer-canvas')[1].toDataURL();\n        }, 20);\n    }\n\n    function getRelativePosition(absoluteX, absoluteY) {\n        var rect = croquisDOMElement.getBoundingClientRect();\n        return {x: absoluteX - rect.left, y: absoluteY - rect.top};\n    }\n}\n"
  },
  {
    "path": "src/editor/tools/Tools.Pan.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n    \nif(!window.Tools) Tools = {};\n\nTools.Pan = function (wickEditor) {\n\n    var that = this;\n\n    this.getCursorImage = function () {\n        return \"move\";\n    }\n\n    this.getToolbarIcon = function () {\n        return \"resources/tools/Pan.svg\";\n    }\n\n    this.getTooltipName = function () {\n        return \"Pan (Space)\";\n    }\n\n    this.paperTool = new paper.Tool();\n    \n    this.onSelected = function () {\n        wickEditor.inspector.clearSpecialMode();\n    }\n\n    this.setup = function () {\n        \n    }\n\n    this.paperTool.onMouseDrag = function(event) {\n        wickEditor.canvas.panByAmount(event.event.movementX, event.event.movementY);\n    }\n\n}"
  },
  {
    "path": "src/editor/tools/Tools.Pen.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nif(!window.Tools) Tools = {};\n\nTools.Pen = function (wickEditor) {\n\n    var that = this;\n\n    var drawingPathUUID;\n\n    this.getCursorImage = function () {\n        return \"crosshair\"\n    };\n\n    this.getToolbarIcon = function () {\n        return \"resources/tools/Path.svg\";\n    }\n\n    this.getTooltipName = function () {\n        return \"Pen (O)\";\n    }\n\n    this.setup = function () {\n\n    }\n\n    this.onSelected = function () {\n        wickEditor.inspector.openToolSettings('pen');\n        wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n    }\n\n    this.onDeselected = function () {\n        drawingPathUUID = null\n        drawingPath = null\n        currentSegment = null\n        if(previewStroke) previewStroke.remove();\n    }\n\n    this.paperTool = new paper.Tool();\n    \n    var hitOptions = {\n        tolerance: 3,\n        allowGroups: true,\n        segments: true,\n        fill: false,\n        curves: false,\n        handles: true,\n        stroke: false,\n    }\n\n    this.paperTool.onMouseMove = function (event) {\n        /*wickEditor.tools.vectorcursor.paperTool.onMouseMove(event)\n\n        wickEditor.project.getSelectedObjects().forEach(function (wo) {\n            wo.paper.selected = true;\n        })*/\n\n        updateDrawingPath();\n\n        hitResult = wickEditor.canvas.getInteractiveCanvas().getItemAtPoint(event.point, hitOptions);\n\n        if(previewStroke) previewStroke.remove();\n        if(drawingPath) {\n            if(hitResult && hitResult.type.startsWith('handle') && hitResult.item === drawingPath) {\n\n            } else if (hitResult && hitResult.item !== drawingPath && (hitResult.segment === hitResult.item.lastSegment || hitResult.segment === hitResult.item.firstSegment)) {\n\n            } else {\n                previewStroke = new paper.Path({insert:false});\n                previewStroke.strokeColor = GUI_DOTS_STROKECOLOR;\n                previewStroke.strokeWidth = 1;\n                previewStroke.add(currentSegment.clone())\n                previewStroke.add(event.point)\n                previewStroke.segments[0].handleIn.x *= -1\n                previewStroke.segments[0].handleIn.y *= -1\n                previewStroke.segments[0].handleOut.x *= -1\n                previewStroke.segments[0].handleOut.y *= -1\n                previewStroke.selected = false;\n                paper._guiLayer.addChild(previewStroke)\n            }\n        }\n\n        if(!hitResult) {\n            wickEditor.cursorIcon.hide()\n        } else if(hitResult.type === 'segment' && hitResult.segment) {\n            if(hitResult.segment === drawingPath.firstSegment ||\n               hitResult.segment === drawingPath.lastSegment) {\n                wickEditor.cursorIcon.setImage('resources/cursor-segment.png')\n            }\n        } else if((hitResult.type === 'handle-in' ||\n                  hitResult.type === 'handle-out') &&\n                 hitResult.item === drawingPath) {\n            wickEditor.cursorIcon.setImage('resources/cursor-segment.png')\n        } else {\n            wickEditor.cursorIcon.hide()\n        }\n    }\n\n    var drawingPath;\n    var currentSegment;\n    var currentSegmentIndex;\n    var previewStroke;\n\n    this.paperTool.onMouseDown = function (event) {\n        if(previewStroke) previewStroke.remove();\n        /*drawingPath = null;\n        paper.project.selectedItems.forEach(function (item) {\n            if(item instanceof paper.Group) return;\n            if(item.closed) return;\n            drawingPath = item;\n        })*/\n\n        hitResult = wickEditor.canvas.getInteractiveCanvas().getItemAtPoint(event.point, hitOptions);\n\n        if(hitResult && hitResult.type === 'segment' && hitResult.item.wick.uuid !== drawingPathUUID) {\n            if (hitResult.segment === hitResult.item.firstSegment) {\n                drawingPathUUID = hitResult.item.wick.uuid;\n                currentSegmentIndex = hitResult.segment.index;\n                updateDrawingPath();\n                return;\n            }\n            if (hitResult.segment === hitResult.item.lastSegment) {\n                drawingPathUUID = hitResult.item.wick.uuid;\n                currentSegmentIndex = hitResult.segment.index;\n                updateDrawingPath();\n                return;\n            }\n        }\n\n        if(drawingPath) {\n\n            if(hitResult && (hitResult.type === 'handle-in' || hitResult.type === 'handle-out')) {\n\n            } else {\n\n                if(currentSegment === drawingPath.firstSegment) {\n                    drawingPath.firstSegment.handleIn.x = -drawingPath.firstSegment.handleOut.x\n                    drawingPath.firstSegment.handleIn.y = -drawingPath.firstSegment.handleOut.y\n                } else if(currentSegment === drawingPath.lastSegment) {\n                    drawingPath.lastSegment.handleOut.x = -drawingPath.lastSegment.handleIn.x\n                    drawingPath.lastSegment.handleOut.y = -drawingPath.lastSegment.handleIn.y\n                }\n\n                if(hitResult && \n                    ((hitResult.segment === drawingPath.firstSegment && currentSegment === drawingPath.lastSegment) || \n                     (hitResult.segment === drawingPath.lastSegment && currentSegment === drawingPath.firstSegment))\n                ) {\n                    drawingPath.closePath();\n                    drawingPath.fillColor = wickEditor.settings.fillColor;\n                    if(currentSegment === drawingPath.firstSegment) {\n                        currentSegmentIndex = drawingPath.lastSegment.index\n                    } else if(currentSegment === drawingPath.lastSegment) {\n                        currentSegmentIndex = drawingPath.firstSegment.index\n                    }\n                } else {\n                    if(currentSegment === drawingPath.firstSegment) {\n                        currentSegmentIndex = drawingPath.insert(0, event.point).index;\n                    } else if(currentSegment === drawingPath.lastSegment) {\n                        currentSegmentIndex = drawingPath.add(event.point).index;\n                    }\n                } \n            }\n            \n        } else {\n            //if(!hitResult) {\n                var newPath = new paper.Path({insert:false});\n                newPath.strokeColor = wickEditor.settings.strokeColor;\n                newPath.strokeWidth = wickEditor.settings.strokeWidth;\n                newPath.strokeJoin = wickEditor.settings.strokeJoin;\n                newPath.strokeCap = wickEditor.settings.strokeCap;\n                newPath.add(event.point);\n\n                var group = new paper.Group({insert:false});\n                group.addChild(newPath);\n\n                var svgString = group.exportSVG({asString:true});\n                var pathWickObject = WickObject.createPathObject(svgString);\n                pathWickObject.x = event.point.x;\n                pathWickObject.y = event.point.y;\n                pathWickObject.width = 1;\n                pathWickObject.height = 1;\n\n                wickEditor.actionHandler.doAction('addObjects', {\n                    wickObjects: [pathWickObject]\n                });\n                drawingPathUUID = pathWickObject.uuid;\n                currentSegmentIndex = 0;\n            //} else {\n                //wickEditor.tools.vectorcursor.paperTool.onMouseDown(event)\n            //}\n        }\n\n        updateDrawingPath()\n\n    }\n\n    this.paperTool.onMouseDrag = function(event) {\n        if(hitResult && hitResult.item === drawingPath && (hitResult.type === 'handle-in' || hitResult.type === 'handle-out')) {\n            if(hitResult.type === 'handle-in') {\n                hitResult.segment.handleIn.x += event.delta.x;\n                hitResult.segment.handleIn.y += event.delta.y;\n                hitResult.segment.handleOut.x -= event.delta.x;\n                hitResult.segment.handleOut.y -= event.delta.y;\n            } else if (hitResult.type === 'handle-out') {\n                hitResult.segment.handleIn.x -= event.delta.x;\n                hitResult.segment.handleIn.y -= event.delta.y;\n                hitResult.segment.handleOut.x += event.delta.x;\n                hitResult.segment.handleOut.y += event.delta.y;\n            }\n        } else if(currentSegment) {\n            if(currentSegment === drawingPath.lastSegment) {\n                currentSegment.handleIn.x -= event.delta.x;\n                currentSegment.handleIn.y -= event.delta.y;\n                currentSegment.handleOut.x += event.delta.x;\n                currentSegment.handleOut.y += event.delta.y;\n            } else {\n                currentSegment.handleIn.x += event.delta.x;\n                currentSegment.handleIn.y += event.delta.y;\n                currentSegment.handleOut.x -= event.delta.x;\n                currentSegment.handleOut.y -= event.delta.y;\n            }\n        } else {\n            //wickEditor.tools.vectorcursor.paperTool.onMouseDrag(event)\n        }\n        updateDrawingPath()\n    }\n\n    this.paperTool.onMouseUp = function (event) {\n        if(currentSegment) {\n            var wickObject = drawingPath.wick;\n\n            var parentAbsPos;\n            if(wickObject.parentObject)\n                parentAbsPos = wickObject.parentObject.getAbsolutePosition();\n            else \n                parentAbsPos = {x:0,y:0};\n\n            wickEditor.actionHandler.doAction('modifyObjects', {\n                objs: [wickObject],\n                modifiedStates: [{\n                    x: wickObject.paper.position.x - parentAbsPos.x,\n                    y: wickObject.paper.position.y - parentAbsPos.y,\n                    svgX: wickObject.paper.bounds._x,\n                    svgY: wickObject.paper.bounds._y,\n                    width: wickObject.paper.bounds._width,\n                    height: wickObject.paper.bounds._height,\n                    pathData: wickObject.paper.exportSVG({asString:true}),\n                }],\n            });\n\n            if(drawingPath.closed) {\n                currentSegment = null;\n                currentSegmentIndex = null;\n                drawingPath = null;\n                drawingPathUUID = null;\n                wickEditor.project.clearSelection();\n                wickEditor.syncInterfaces();\n            }\n        } else {\n            //wickEditor.tools.vectorcursor.paperTool.onMouseUp(event)\n        }\n        updateDrawingPath()\n    }\n\n    function updateDrawingPath () {\n        paper.project.activeLayer.children.forEach(function (item) {\n            if(item && item.wick && item.wick.uuid === drawingPathUUID) {\n                item.fullySelected = true;\n                drawingPath = item;\n                currentSegment = drawingPath.segments[currentSegmentIndex]\n            }\n        })\n    }\n\n}"
  },
  {
    "path": "src/editor/tools/Tools.Pencil.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nif(!window.Tools) Tools = {};\n\nTools.Pencil = function (wickEditor) {\n\n    var that = this;\n\n    this.getCursorImage = function () {\n        return 'url(resources/cursors/pencil.png) 0 16,default';\n    };\n\n    this.getToolbarIcon = function () {\n        return \"resources/tools/Pencil.svg\";\n    }\n\n    this.getTooltipName = function () {\n        return \"Pencil (V)\";\n    }\n\n    this.setup = function () {\n\n    }\n\n    this.onSelected = function () {\n        wickEditor.inspector.openToolSettings('pencil');\n        wickEditor.project.clearSelection();\n        wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n    }\n\n    this.onDeselected = function () {\n        if(path) path.remove();\n    }\n\n    this.paperTool = new paper.Tool();\n    var path;\n    var totalDelta;\n    var lastEvent;\n\n    this.paperTool.onMouseDown = function (event) {\n        if(wickEditor.settings.strokeWidth === 0)\n            wickEditor.settings.setValue('strokeWidth', 1);\n\n        if (!path) {\n            path = new paper.Path({\n                //fillColor: wickEditor.settings.fillColor,\n                strokeColor: wickEditor.settings.strokeColor,\n                strokeCap: 'round',\n                strokeWidth: wickEditor.settings.strokeWidth,\n            });\n            //path.add(event.lastPoint);\n        }\n\n        path.add(event.point);\n    }\n\n    this.paperTool.onMouseDrag = function (event) {\n\n        if(!totalDelta) {\n            totalDelta = event.delta;\n        } else {\n            totalDelta.x += event.delta.x;\n            totalDelta.y += event.delta.y;\n        }\n\n        if (totalDelta.length > (2+wickEditor.settings.pencilSmoothing)/wickEditor.canvas.getZoom()) {\n\n            totalDelta.x = 0;\n            totalDelta.y = 0;\n\n            path.add(event.point)\n            path.smooth();\n            lastEvent = event;\n\n            //path.simplify(1);\n\n        }\n    }\n\n    this.paperTool.onMouseUp = function (event) {\n        if (path) {\n\n            path.add(event.point)\n            \n            if(path.segments.length > 2) {\n                path.smooth();\n\n                /*if(wickEditor.settings.pencilSmoothing > 0) {\n                    var t = wickEditor.settings.strokeWidth;\n                    var s = wickEditor.settings.pencilSmoothing/100*10;\n                    var z = wickEditor.canvas.getZoom();\n                    path.simplify(t / z * s);\n                }*/\n\n                path.join(path, 5/wickEditor.canvas.getZoom())\n            }\n\n            path.remove();\n\n            path.strokeCap = 'round'\n            path.strokeJoin = 'round'\n\n            var group = new paper.Group({insert:false});\n            group.addChild(path);\n\n            var svgString = group.exportSVG({asString:true});\n            var pathWickObject = WickObject.createPathObject(svgString);\n            pathWickObject.x = group.position.x;\n            pathWickObject.y = group.position.y;\n            pathWickObject.width = group.bounds._width;\n            pathWickObject.height = group.bounds._height;\n            pathWickObject.svgX = group.bounds._x;\n            pathWickObject.svgY = group.bounds._y;\n\n            //wickEditor.canvas.getInteractiveCanvas().pathRoutines.refreshPathData(pathWickObject);\n\n            wickEditor.actionHandler.doAction('addObjects', {\n                wickObjects: [pathWickObject],\n                dontSelectObjects: true,\n            });\n\n            path = null;\n        }\n    }\n\n}"
  },
  {
    "path": "src/editor/tools/Tools.Rectangle.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nif(!window.Tools) Tools = {};\n\nTools.Rectangle = function (wickEditor) {\n\n    var that = this;\n    \n    var tempGroup;\n\n    var topLeft;\n    var bottomRight;\n\n    this.getCursorImage = function () {\n        return \"crosshair\"\n    };\n\n    this.getToolbarIcon = function () {\n        return \"resources/tools/Square.svg\";\n    }\n\n    this.getTooltipName = function () {\n        return \"Rectangle (R)\";\n    }\n\n    this.setup = function () {\n\n    }\n\n    this.onSelected = function () {\n        wickEditor.inspector.openToolSettings('rectangle');\n        wickEditor.project.clearSelection();\n        wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n    }\n\n    this.onDeselected = function () {\n        if(tempGroup) tempGroup.remove();\n    }\n\n    this.paperTool = new paper.Tool();\n\n    this.paperTool.onMouseDown = function (event) {\n        tempGroup = new paper.Group();\n        topLeft = event.point;\n        bottomRight = null;\n    }\n\n    this.paperTool.onMouseDrag = function (event) {\n        bottomRight = event.point;\n\n        tempGroup.remove();\n\n        var rectangle = new paper.Rectangle(\n            new paper.Point(topLeft.x, topLeft.y), \n            new paper.Point(bottomRight.x, bottomRight.y));\n\n        var roundedRect = new paper.Path.RoundRectangle(rectangle, wickEditor.settings.rectangleCornerRadius);\n        roundedRect.fillColor = wickEditor.settings.fillColor;\n        roundedRect.strokeColor = wickEditor.settings.strokeColor;\n        roundedRect.strokeWidth = wickEditor.settings.strokeWidth;\n        roundedRect.strokeJoin = wickEditor.settings.strokeJoin;\n        roundedRect.strokeCap = wickEditor.settings.strokeCap;\n\n        tempGroup = new paper.Group();\n        tempGroup.addChild(roundedRect);\n    }\n\n    this.paperTool.onMouseUp = function (event) {\n        if(!bottomRight)\n            return;\n\n        var svgString = tempGroup.exportSVG({asString:true});\n        tempGroup.remove();\n        var pathWickObject = WickObject.createPathObject(svgString);\n        pathWickObject.x = topLeft.x+(bottomRight.x-topLeft.x)/2;\n        pathWickObject.y = topLeft.y+(bottomRight.y-topLeft.y)/2;\n        pathWickObject.width = tempGroup.bounds._width;\n        pathWickObject.height = tempGroup.bounds._height;\n        pathWickObject.svgX = tempGroup.bounds._x;\n        pathWickObject.svgY = tempGroup.bounds._y;\n\n        //wickEditor.canvas.getInteractiveCanvas().pathRoutines.refreshPathData(pathWickObject);\n\n        wickEditor.actionHandler.doAction('addObjects', {\n            wickObjects: [pathWickObject],\n            dontSelectObjects: true,\n        });\n    }\n\n}"
  },
  {
    "path": "src/editor/tools/Tools.SelectionCursor.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nif(!window.Tools) Tools = {};\n\nvar GUI_DOTS_SIZE = 5;\nvar GUI_DOTS_FILLCOLOR = 'rgba(255,255,255,0.3)';\nvar GUI_DOTS_STROKECOLOR = 'rgba(100,150,255,1.0)'\nvar HIDDEN_ROTATE_HANDLE_COLOR = 'rgba(0,0,0,0.0001)'\nvar ROTATE_HANDLE_LENGTH = 20;\n\nTools.SelectionCursor = function (wickEditor) {\n\n    var self = this;\n\n    var makingSelectionSquare = false;\n    var selectionSquare = null;\n    var selectionSquareTopLeft;\n    var selectionSquareBottomRight;\n\n    var selectionRect;\n    var selectionBoundsRect;\n    var scaleBR;\n    var scaleTR;\n    var scaleTL;\n    var scaleBL;\n    var scaleT;\n    var scaleB;\n    var scaleL;\n    var scaleR;\n    var rotateTL;\n    var rotateTR;\n    var rotateBL;\n    var rotateBR;\n    var individualObjectBoxes;\n\n    var hitResult;\n    var addedPoint;\n\n    var lastEvent;\n    var transformMode;\n\n    var pathHoverGhost;\n\n    this.getCursorImage = function () {\n        return \"auto\"\n    };\n\n    this.getToolbarIcon = function () {\n        return \"resources/tools/Cursor.svg\";\n    }\n\n    this.getTooltipName = function () {\n        return \"Selection Cursor (C)\";\n    }\n\n    this.setup = function () {\n        \n    }\n\n    this.onSelected = function () {\n        wickEditor.inspector.clearSpecialMode();\n        wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n    }\n\n    this.paperTool = new paper.Tool();\n\n    var hitOptions = {\n        allowGroups: true,\n        segments: false,\n        fill: true,\n        curves: true,\n        handles: false,\n        stroke: true,\n    }\n\n    this.paperTool.onMouseMove = function(event) {\n        //updateSelection()\n\n        hitResult = wickEditor.canvas.getInteractiveCanvas().getItemAtPoint(event.point, hitOptions);\n\n        if(hitResult && hitResult.item._cursor)\n            wickEditor.canvas.getCanvasContainer().style.cursor = hitResult.item._cursor;\n        else if (hitResult && !hitResult.item._wickInteraction)\n            wickEditor.canvas.getCanvasContainer().style.cursor = 'move';\n        else\n            wickEditor.canvas.updateCursor();\n\n        if(pathHoverGhost) pathHoverGhost.remove();\n        pathHoverGhost = null;\n        if(hitResult && !hitResult.item._wickInteraction) {\n            if(hitResult.item.wick && !wickEditor.project.isObjectSelected(hitResult.item.wick)) {\n                if(hitResult.item.wick.isSymbol || hitResult.item.wick.isImage) {\n                    pathHoverGhost = new paper.Path.Rectangle(hitResult.item.bounds);\n                } else {\n                    pathHoverGhost = hitResult.item.clone({insert:false});\n                }\n                paper._guiLayer.addChild(pathHoverGhost)\n                pathHoverGhost._wickInteraction = 'pathHoverGhost';\n                pathHoverGhost.fillColor = 'rgba(0,0,0,0)';\n                pathHoverGhost.strokeColor = GUI_DOTS_STROKECOLOR;\n                pathHoverGhost.strokeWidth = 1.5/wickEditor.canvas.getZoom();\n            }\n        }\n    }\n\n    this.paperTool.onMouseDown = function(event) {\n        if(pathHoverGhost) pathHoverGhost.remove();\n\n        if(lastEvent \n        && event.timeStamp-lastEvent.timeStamp<300 \n        && event.point.x===lastEvent.point.x\n        && event.point.y===lastEvent.point.y) {\n            self.paperTool.onDoubleClick(event);\n            return;\n        }\n        lastEvent = event;\n        \n        if(hitResult && hitResult.item && hitResult.item._wickInteraction) {\n            transformMode = hitResult.item._wickInteraction\n            return;\n        }\n\n        if(hitResult && !hitResult.item._wickInteraction) {\n\n            var wickObj = hitResult.item.wick || hitResult.item.parent.wick;\n            if(wickObj) {\n                if(wickEditor.project.isObjectSelected(wickObj)) {\n                    if(event.modifiers.shift) {\n                        wickEditor.project.deselectObject(wickObj);\n                    }\n                } else {\n                    if(!event.modifiers.shift) {\n                        wickEditor.project.clearSelection();\n                    }\n                    wickEditor.project.selectObject(wickObj);\n                }\n\n                var currObj = wickEditor.project.getCurrentObject();\n                currObj.currentLayer = currObj.layers.indexOf(wickObj.parentFrame.parentLayer);\n                wickEditor.syncInterfaces();\n            }\n\n        } else {\n            if(!event.modifiers.shift && !wickEditor.colorPicker.isOpen()) {\n                wickEditor.project.clearSelection();\n            }\n            wickEditor.syncInterfaces();\n\n            makingSelectionSquare = true;\n            selectionSquareTopLeft = event.point;\n            selectionSquareBottomRight = event.point\n        }\n\n        //updateSelection()\n\n    }\n\n    this.paperTool.onDoubleClick = function (event) {\n        if(hitResult) {\n            var selected = wickEditor.project.getSelectedObjectsByType(WickObject)[0];\n            if(selected)  {\n                if(selected.isSymbol) {\n                    wickEditor.guiActionHandler.doAction('editObject');\n                } else if (selected.isText) {\n                    wickEditor.guiActionHandler.doAction('useTools.text')\n                }\n            }\n        } else {\n            if(wickEditor.project.getCurrentObject().isRoot) return;\n            wickEditor.guiActionHandler.doAction('finishEditingObject');\n        }\n        hitResult = null;\n    }\n\n    this.paperTool.onMouseDrag = function(event) {\n        if(transformMode && transformMode.startsWith('scale')) {\n            var keepAspectRatio = event.modifiers.shift;\n            var rect = selectionBoundsRect\n\n            wickEditor.project.getSelectedObjectsByType(WickObject).forEach(function (o) {\n                var resizeRatio;\n                var referencePos = {x:0,y:0};\n                if(transformMode === 'scaleBR') { referencePos = rect.topLeft;      resizeRatio = event.point.subtract(rect.topLeft); }\n                if(transformMode === 'scaleTL') { referencePos = rect.bottomRight;  resizeRatio = rect.bottomRight.subtract(event.point); }\n                if(transformMode === 'scaleBL') { referencePos = rect.topRight;     resizeRatio = { x: rect.topRight.x - event.point.x, y: event.point.y - rect.topRight.y }; }\n                if(transformMode === 'scaleTR') { referencePos = rect.bottomLeft;   resizeRatio = { x: event.point.x - rect.bottomLeft.x, y: rect.bottomLeft.y - event.point.y }; }\n                if(transformMode === 'scaleT')  { referencePos = rect.bottomCenter; resizeRatio = { x: rect.width, y: rect.bottomCenter.y - event.point.y }; keepAspectRatio = false; }\n                if(transformMode === 'scaleB')  { referencePos = rect.topCenter;    resizeRatio = { x: rect.width, y: event.point.y - rect.topCenter.y }; keepAspectRatio = false; }\n                if(transformMode === 'scaleR')  { referencePos = rect.leftCenter;   resizeRatio = { x: event.point.x - rect.leftCenter.x, y: rect.height }; keepAspectRatio = false; }\n                if(transformMode === 'scaleL')  { referencePos = rect.rightCenter;  resizeRatio = { x: rect.rightCenter.x - event.point.x, y: rect.height }; keepAspectRatio = false; }\n\n                if(resizeRatio.x < 1 || resizeRatio.y < 1) return;\n                resizeRatio.x /= rect.width;\n                resizeRatio.y /= rect.height;\n                if (keepAspectRatio) {\n                    resizeRatio.x = resizeRatio.y = Math.max(resizeRatio.x, resizeRatio.y);\n                }\n                o.paper.scale(resizeRatio.x, resizeRatio.y, referencePos);\n                updateSelection()\n            });\n            return;\n        }\n        if(transformMode === 'rotate') {\n            var rect = selectionBoundsRect\n            var pivot = rect.center;\n            var oldAngle = event.lastPoint.subtract(pivot).angle;\n            var newAngle = event.point.subtract(pivot).angle;\n            var rotationAmount = newAngle-oldAngle;\n            wickEditor.project.getSelectedObjectsByType(WickObject).forEach(function (o) {\n                o.paper.rotate(rotationAmount, pivot);\n                //updateSelection()\n            });\n            selectionRect.rotate(rotationAmount, pivot);\n            //rotate.rotate(rotationAmount, pivot);\n            scaleBR.rotate(rotationAmount, pivot);\n            scaleBL.rotate(rotationAmount, pivot);\n            scaleTR.rotate(rotationAmount, pivot);\n            scaleTL.rotate(rotationAmount, pivot);\n            scaleT.rotate(rotationAmount, pivot);\n            scaleB.rotate(rotationAmount, pivot);\n            scaleL.rotate(rotationAmount, pivot);\n            scaleR.rotate(rotationAmount, pivot);\n            return;\n        }\n\n        if(makingSelectionSquare) {\n            selectionSquareBottomRight = event.point;\n\n            if(selectionSquare) {\n                selectionSquare.remove();\n            }\n\n            selectionSquare = new paper.Path.Rectangle(\n                    new paper.Point(selectionSquareTopLeft.x, selectionSquareTopLeft.y), \n                    new paper.Point(selectionSquareBottomRight.x, selectionSquareBottomRight.y));\n            selectionSquare.strokeColor = 'rgba(100,100,255,0.7)';\n            selectionSquare.strokeWidth = 1/wickEditor.canvas.getZoom();\n            selectionSquare.fillColor = 'rgba(100,100,255,0.15)';\n        } else {\n            if(hitResult && hitResult.item) {\n                wickEditor.project.getSelectedObjectsByType(WickObject).forEach(function (o) {\n                    o.paper.position = new paper.Point(\n                        o.paper.position.x + event.delta.x,\n                        o.paper.position.y + event.delta.y\n                    );\n                });\n                updateSelection()\n            }\n        }\n\n    }\n\n    this.paperTool.onMouseUp = function (event) {\n\n        transformMode = null;\n\n        if(makingSelectionSquare) {\n            if(!selectionSquare) {\n                selectionSquare = null;\n                makingSelectionSquare = false;\n                return;\n            }\n\n            if(!event.modifiers.shift) {\n                wickEditor.project.clearSelection()\n            }\n            wickEditor.project.getCurrentObject().getAllActiveChildObjects().forEach(function (wickObject) {\n                if(!wickObject.paper) return;\n                if(wickObject.parentFrame.parentLayer.locked || wickObject.parentFrame.parentLayer.hidden) return;\n                if(selectionSquare.bounds.intersects(wickObject.paper.bounds)) {\n                    if(selectionSquare.bounds.contains(wickObject.paper.bounds)\n                    || (selectionSquare.intersects(wickObject.paper)) && !event.modifiers.alt) {\n                        wickEditor.project.selectObject(wickObject)\n                    }\n                }\n            });\n            wickEditor.syncInterfaces()\n\n            if(selectionSquare) {\n                selectionSquare.remove();\n            }\n            selectionSquare = null;\n            makingSelectionSquare = false;\n            return;\n        }\n\n        if(!hitResult) return;\n        if(!hitResult.item) return;\n\n        var objs = wickEditor.project.getSelectedObjectsByType(WickObject);\n        var modifiedStates = [];\n        objs.forEach(function (wickObject) {\n            var parentAbsPos;\n            if(wickObject.parentObject)\n                parentAbsPos = wickObject.parentObject.getAbsolutePosition();\n            else \n                parentAbsPos = {x:0,y:0};\n\n            if(wickObject.isSymbol) {\n                modifiedStates.push({\n                    rotation: wickObject.paper.rotation,\n                    x: wickObject.paper.position.x - parentAbsPos.x,\n                    y: wickObject.paper.position.y - parentAbsPos.y,\n                    scaleX: wickObject.paper.scaling.x,\n                    scaleY: wickObject.paper.scaling.y,\n                });\n            } else if (wickObject.isPath) {\n                wickObject.paper.applyMatrix = true;\n\n                wickObject.rotation = 0;\n                wickObject.scaleX = 1;\n                wickObject.scaleY = 1;\n                wickObject.flipX = false;\n                wickObject.flipY = false;\n\n                modifiedStates.push({\n                    x : wickObject.paper.position.x - parentAbsPos.x,\n                    y : wickObject.paper.position.y - parentAbsPos.y,\n                    svgX : wickObject.paper.bounds._x,\n                    svgY : wickObject.paper.bounds._y,\n                    width : wickObject.paper.bounds._width,\n                    height : wickObject.paper.bounds._height,\n                    pathData: wickObject.paper.exportSVG({asString:true}),\n                });\n            } else if (wickObject.isImage) {\n                modifiedStates.push({\n                    x : wickObject.paper.position.x - parentAbsPos.x,\n                    y : wickObject.paper.position.y - parentAbsPos.y,\n                    scaleX : wickObject.paper.scaling.x,\n                    scaleY : wickObject.paper.scaling.y,\n                    rotation : wickObject.paper.rotation,\n                })\n            } else if (wickObject.isText) {\n                modifiedStates.push({\n                    x : wickObject.paper.position.x - parentAbsPos.x,\n                    y : wickObject.paper.position.y - parentAbsPos.y,\n                    rotation : wickObject.paper.rotation,\n                });\n            }\n        });\n        wickEditor.actionHandler.doAction('modifyObjects', {\n            objs: objs,\n            modifiedStates: modifiedStates\n        });\n    }\n\n    self.forceUpdateSelection = function () {\n        updateSelection();\n    }\n\n    function updateSelection () {\n        paper.settings.handleSize = 10;\n        paper.project.activeLayer.children.forEach(function (child) {\n            if(!child.wick) return;\n            if(wickEditor.project.isObjectSelected(child.wick)) {\n                if(!selectionBoundsRect) {\n                    selectionBoundsRect = child.bounds.clone()\n                } else {\n                    selectionBoundsRect = selectionBoundsRect.unite(child.bounds);\n                }\n            }\n        });\n\n        selectionBoundsRect = null;\n\n        paper.project.activeLayer.children.forEach(function (child) {\n            if(!child.wick) return;\n            if(wickEditor.project.isObjectSelected(child.wick)) {\n                if(!selectionBoundsRect) {\n                    selectionBoundsRect = child.bounds.clone()\n                } else {\n                    selectionBoundsRect = selectionBoundsRect.unite(child.bounds);\n                }\n            }\n        });\n\n        if(selectionRect) selectionRect.remove();\n        if(scaleBR) scaleBR.remove();\n        if(scaleBL) scaleBL.remove();\n        if(scaleTL) scaleTL.remove();\n        if(scaleTR) scaleTR.remove();\n        if(scaleT) scaleT.remove();\n        if(scaleB) scaleB.remove();\n        if(scaleL) scaleL.remove();\n        if(scaleR) scaleR.remove();\n        if(rotateTL) rotateTL.remove();\n        if(rotateTR) rotateTR.remove();\n        if(rotateBL) rotateBL.remove();\n        if(rotateBR) rotateBR.remove();\n        if(individualObjectBoxes) {\n            individualObjectBoxes.forEach(function (o) {\n                o.remove();\n            })\n        }\n\n        if(selectionBoundsRect) {\n            //selectionBoundsRect = selectionBoundsRect.expand(10);\n            var strokeWidth = 1/wickEditor.canvas.getZoom();\n\n            selectionRect = new paper.Path.Rectangle(selectionBoundsRect);\n            selectionRect.strokeColor = GUI_DOTS_STROKECOLOR;\n            selectionRect.strokeWidth = strokeWidth;\n            selectionRect._wickInteraction = 'selectionRect';\n            selectionRect.locked = true;\n\n            var dotSize = GUI_DOTS_SIZE/wickEditor.canvas.getZoom();\n\n            individualObjectBoxes = [];\n            var selectedObjs = wickEditor.project.getSelectedObjectsByType(WickObject)\n            if(selectedObjs.length > 1) {\n                selectedObjs.forEach(function (o) {\n                    var oRect = new paper.Rectangle(o.paper.bounds);\n                    var oPaperRect = new paper.Path.Rectangle(oRect);\n                    oPaperRect.strokeWidth = strokeWidth;\n                    oPaperRect.strokeColor = GUI_DOTS_STROKECOLOR;\n                    oPaperRect._wickInteraction = 'individualObjectBox';\n                    individualObjectBoxes.push(oPaperRect);\n                });\n            }\n\n            var rotateHandleLength = ROTATE_HANDLE_LENGTH/wickEditor.canvas.getZoom()\n\n            rotateTL = new paper.Path.Ellipse({\n                center: selectionBoundsRect.topLeft,\n                radius: rotateHandleLength\n            });\n            rotateTL.fillColor = HIDDEN_ROTATE_HANDLE_COLOR;\n            rotateTL._wickInteraction = 'rotate';\n            rotateTL._cursor = 'url(\"resources/cursor-rotate.png\") 32 32,default';\n\n            rotateTR = new paper.Path.Ellipse({\n                center: selectionBoundsRect.topRight,\n                radius: rotateHandleLength\n            });\n            rotateTR.fillColor = HIDDEN_ROTATE_HANDLE_COLOR;\n            rotateTR._wickInteraction = 'rotate';\n            rotateTR._cursor = 'url(\"resources/cursor-rotate.png\") 32 32,default';\n\n            rotateBL = new paper.Path.Ellipse({\n                center: selectionBoundsRect.bottomLeft,\n                radius: rotateHandleLength\n            });\n            rotateBL.fillColor = HIDDEN_ROTATE_HANDLE_COLOR;\n            rotateBL._wickInteraction = 'rotate';\n            rotateBL._cursor = 'url(\"resources/cursor-rotate.png\") 32 32,default';\n\n            rotateBR = new paper.Path.Ellipse({\n                center: selectionBoundsRect.bottomRight,\n                radius: rotateHandleLength\n            });\n            rotateBR.fillColor = HIDDEN_ROTATE_HANDLE_COLOR;\n            rotateBR._wickInteraction = 'rotate';\n            rotateBR._cursor = 'url(\"resources/cursor-rotate.png\") 32 32,default';\n\n            scaleBR = new paper.Path.Circle(selectionBoundsRect.bottomRight, dotSize);\n            scaleBR.fillColor = GUI_DOTS_FILLCOLOR;\n            scaleBR.strokeColor = GUI_DOTS_STROKECOLOR;\n            scaleBR.strokeWidth = strokeWidth;\n            scaleBR._wickInteraction = 'scaleBR';\n            scaleBR._cursor = 'nwse-resize';\n\n            scaleBL = new paper.Path.Circle(selectionBoundsRect.bottomLeft, dotSize);\n            scaleBL.fillColor = GUI_DOTS_FILLCOLOR;\n            scaleBL.strokeColor = GUI_DOTS_STROKECOLOR;\n            scaleBL.strokeWidth = strokeWidth;\n            scaleBL._wickInteraction = 'scaleBL';\n            scaleBL._cursor = 'nesw-resize';\n\n            scaleTL = new paper.Path.Circle(selectionBoundsRect.topLeft, dotSize);\n            scaleTL.fillColor = GUI_DOTS_FILLCOLOR;\n            scaleTL.strokeColor = GUI_DOTS_STROKECOLOR;\n            scaleTL.strokeWidth = strokeWidth;\n            scaleTL._wickInteraction = 'scaleTL';\n            scaleTL._cursor = 'nwse-resize';\n\n            scaleTR = new paper.Path.Circle(selectionBoundsRect.topRight, dotSize);\n            scaleTR.fillColor = GUI_DOTS_FILLCOLOR;\n            scaleTR.strokeColor = GUI_DOTS_STROKECOLOR;\n            scaleTR.strokeWidth = strokeWidth;\n            scaleTR._wickInteraction = 'scaleTR';\n            scaleTR._cursor = 'nesw-resize';\n\n            scaleT = new paper.Path.Circle(selectionBoundsRect.topCenter, dotSize);\n            scaleT.fillColor = GUI_DOTS_FILLCOLOR;\n            scaleT.strokeColor = GUI_DOTS_STROKECOLOR;\n            scaleT.strokeWidth = strokeWidth;\n            scaleT._wickInteraction = 'scaleT';\n            scaleT._cursor = 'ns-resize';\n\n            scaleB = new paper.Path.Circle(selectionBoundsRect.bottomCenter, dotSize);\n            scaleB.fillColor = GUI_DOTS_FILLCOLOR;\n            scaleB.strokeColor = GUI_DOTS_STROKECOLOR;\n            scaleB.strokeWidth = strokeWidth;\n            scaleB._wickInteraction = 'scaleB';\n            scaleB._cursor = 'ns-resize';\n\n            scaleL = new paper.Path.Circle(selectionBoundsRect.leftCenter, dotSize);\n            scaleL.fillColor = GUI_DOTS_FILLCOLOR;\n            scaleL.strokeColor = GUI_DOTS_STROKECOLOR;\n            scaleL.strokeWidth = strokeWidth;\n            scaleL._wickInteraction = 'scaleL';\n            scaleL._cursor = 'ew-resize';\n\n            scaleR = new paper.Path.Circle(selectionBoundsRect.rightCenter, dotSize);\n            scaleR.fillColor = GUI_DOTS_FILLCOLOR;\n            scaleR.strokeColor = GUI_DOTS_STROKECOLOR;\n            scaleR.strokeWidth = strokeWidth;\n            scaleR._wickInteraction = 'scaleR';\n            scaleR._cursor = 'ew-resize';\n        }\n    }\n\n}"
  },
  {
    "path": "src/editor/tools/Tools.Text.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nif(!window.Tools) Tools = {};\n\nTools.Text = function (wickEditor) {\n\n    var self = this;\n\n    this.getCursorImage = function () {\n        return \"default\";\n    }\n\n    this.getToolbarIcon = function () {\n        return \"resources/tools/Text.svg\";\n    }\n\n    this.getTooltipName = function () {\n        return \"Text (T)\";\n    }\n\n    this.setup = function () {\n        \n    }\n\n    this.onSelected = function () {\n        wickEditor.project.clearSelection();\n        wickEditor.inspector.clearSpecialMode();\n        wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n    }\n\n    this.onDeselected = function () {\n        \n    }\n\n    this.paperTool = new paper.Tool();\n\n    this.paperTool.onMouseMove = function(event) {\n        if(event.item) {\n            if(event.item.wick && event.item.wick.isText) {\n                wickEditor.canvas.getCanvasContainer().style.cursor = 'text';\n            }\n        } else {\n            wickEditor.canvas.getCanvasContainer().style.cursor = 'crosshair';\n        }\n    }\n\n    this.paperTool.onMouseDown = function (event) {\n        if(event.item && event.item.wick && event.item.wick.isText) {\n            wickEditor.project.clearSelection();\n            wickEditor.project.selectObject(event.item.wick)\n            wickEditor.syncInterfaces();\n        } else {\n            if(!wickEditor.project.clearSelection()) {\n                var m = wickEditor.inputHandler.mouse;\n                var ms = wickEditor.canvas.screenToCanvasSpace(m.x,m.y)\n                addText(ms.x, ms.y);\n            } else {\n                wickEditor.syncInterfaces();\n            }\n\n        }\n    }\n\n    function addText (x,y) {                                                     \n    \tvar newWickObject = WickObject.createTextObject('Text');\n\n        if(x && y) {\n            newWickObject.x = x;\n            newWickObject.y = y;\n        } else {\n            newWickObject.x = wickEditor.project.width/2;\n            newWickObject.y = wickEditor.project.height/2;\n        }\n\n        wickEditor.actionHandler.doAction('addObjects', {wickObjects:[newWickObject]});\n    }\n}\n"
  },
  {
    "path": "src/editor/tools/Tools.VectorCursor.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nif(!window.Tools) Tools = {};\n\nTools.VectorCursor = function (wickEditor) {\n\n    var self = this;\n\n    this.getCursorImage = function () {\n        return \"auto\"\n    };\n\n    this.getToolbarIcon = function () {\n        return \"resources/tools/PathCursor.svg\";\n    }\n\n    this.getTooltipName = function () {\n        return \"Path Cursor (P)\";\n    }\n\n    this.setup = function () {\n\n    }\n\n    this.onSelected = function () {\n        wickEditor.inspector.clearSpecialMode();\n        wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n    }\n\n    this.paperTool = new paper.Tool();\n\n    var makingSelectionSquare = false;\n    var selectionSquare = null;\n    var selectionSquareTopLeft;\n    var selectionSquareBottomRight;\n\n    var hitResult;\n    var addedPoint;\n\n    var lastEvent;\n\n    var baseTol = 3;\n    var hitOptions = {\n        allowGroups: false,\n        segments: true,\n        fill: true,\n        curves: true,\n        handles: true,\n        stroke: true,\n        tolerance: 5,\n    }\n\n    var hitResult;\n    var pathHoverGhost;\n\n    this.paperTool.onMouseMove = function(event) {\n        //hitOptions.tolerance = baseTol / wickEditor.canvas.getZoom();\n        hitResult = wickEditor.canvas.getInteractiveCanvas().getItemAtPoint(event.point, hitOptions);\n\n        if(pathHoverGhost) pathHoverGhost.remove();\n        pathHoverGhost = null;\n        if(hitResult && !hitResult.item._wickInteraction) {\n            var wickObj = hitResult.item.wick || hitResult.item.parent.wick;\n            if(!wickEditor.project.isObjectSelected(wickObj)) {\n                if(wickObj.isSymbol || wickObj.isImage) {\n                    pathHoverGhost = new paper.Path.Rectangle(hitResult.item.bounds);\n                } else {\n                    pathHoverGhost = hitResult.item.clone({insert:false});\n                }\n                paper._guiLayer.addChild(pathHoverGhost)\n                pathHoverGhost._wickInteraction = 'pathHoverGhost';\n                pathHoverGhost.fillColor = 'rgba(0,0,0,0)';\n                pathHoverGhost.strokeColor = GUI_DOTS_STROKECOLOR;\n                pathHoverGhost.strokeWidth = 1.5/wickEditor.canvas.getZoom();\n            }\n            if(hitResult.type === 'curve' || hitResult.type === 'stroke') {\n                wickEditor.cursorIcon.setImage('resources/cursor-curve.png')\n            } else if(hitResult.type === 'fill') {\n                wickEditor.cursorIcon.setImage('resources/cursor-fill.png')\n            } else if(hitResult.type === 'segment' ||\n                      hitResult.type === 'handle-in' ||\n                      hitResult.type === 'handle-out') {\n                wickEditor.cursorIcon.setImage('resources/cursor-segment.png')\n            } else {\n                wickEditor.cursorIcon.hide()\n            }\n        } else {\n            wickEditor.cursorIcon.hide()\n        }\n\n        /*self.setImage('resources/cursor-curve.png')\n            } else if(hitResult.type === 'fill') {\n                self.setImage('resources/cursor-fill.png')\n            } else if(hitResult.type === 'segment' ||\n                      hitResult.type === 'handle-in' ||\n                      hitResult.type === 'handle-out') {\n                self.setImage('resources/cursor-segment.png')*/\n\n        /*if(hitResult && hitResult.item && hitResult.item.wick && wickEditor.project.isObjectSelected(hitResult.item.wick)) {\n            wickEditor.cursorIcon.setImageForPaperEvent(event)\n        } else {\n            wickEditor.cursorIcon.hide();\n\n            if(hitResult && hitResult.item._cursor)\n                wickEditor.canvas.getCanvasContainer().style.cursor = hitResult.item._cursor;\n            else if (hitResult && !hitResult.item._wickInteraction)\n                wickEditor.canvas.getCanvasContainer().style.cursor = 'move';\n            else\n                wickEditor.canvas.updateCursor();\n        }*/\n    }\n\n    this.paperTool.onMouseDown = function(event) {\n\n        if(pathHoverGhost) pathHoverGhost.remove();\n\n        if(lastEvent \n        && event.timeStamp-lastEvent.timeStamp<300\n        && event.point.x===lastEvent.point.x\n        && event.point.y===lastEvent.point.y) {\n            self.paperTool.onDoubleClick(event);\n            return;\n        }\n        lastEvent = event;\n        \n        if(hitResult) {\n            if(hitResult.item.selected) {\n                if(hitResult.type === 'fill') {\n                    \n                }\n\n                if (hitResult.type == 'segment') {\n                    if(event.modifiers.alt || \n                        event.modifiers.command ||\n                        event.modifiers.control ||\n                        event.modifiers.option ||\n                        event.modifiers.shift) {\n                        hitResult.segment.remove();\n                        modifySelectedPath();\n                    }\n                }\n\n                if (hitResult.type == 'stroke' || hitResult.type == 'curve') {\n                    var location = hitResult.location;\n                    var path = hitResult.item;\n\n                    addedPoint = path.insert(location.index + 1, event.point);\n\n                    if(!event.modifiers.shift) {\n                        addedPoint.smooth()\n\n                        var handleInMag = Math.sqrt(\n                            addedPoint.handleIn.x*addedPoint.handleIn.x+\n                            addedPoint.handleIn.y+addedPoint.handleIn.y)\n                        var handleOutMag = Math.sqrt(\n                            addedPoint.handleOut.x*addedPoint.handleOut.x+\n                            addedPoint.handleOut.y+addedPoint.handleOut.y)\n\n                        if(handleInMag > handleOutMag) {\n                            avgMag = handleOutMag;\n                            addedPoint.handleIn.x = -addedPoint.handleOut.x*1.5;\n                            addedPoint.handleIn.y = -addedPoint.handleOut.y*1.5;\n                            addedPoint.handleOut.x *= 1.5;\n                            addedPoint.handleOut.y *= 1.5;\n                        } else {\n                            avgMag = handleInMag;\n                            addedPoint.handleOut.x = -addedPoint.handleIn.x*1.5;\n                            addedPoint.handleOut.y = -addedPoint.handleIn.y*1.5;\n                            addedPoint.handleIn.x *= 1.5;\n                            addedPoint.handleIn.y *= 1.5;\n                        }\n                    }\n                } else {\n                    addedPoint = null;\n                }\n            }\n\n            var wickObj = hitResult.item.wick || hitResult.item.parent.wick;\n            if(wickObj) {\n                if(wickEditor.project.isObjectSelected(wickObj)) {\n                    if(event.modifiers.shift && !hitResult.type.startsWith('handle')) {\n                        wickEditor.project.deselectObject(wickObj);\n                        wickEditor.syncInterfaces();\n                    }\n                } else {\n                    if(!event.modifiers.shift) {\n                        wickEditor.project.clearSelection();\n                    }\n                    wickEditor.project.selectObject(wickObj);\n                    var currObj = wickEditor.project.getCurrentObject();\n                    currObj.currentLayer = currObj.layers.indexOf(wickObj.parentFrame.parentLayer);\n                    wickEditor.syncInterfaces();\n                }\n            }\n\n        } else {\n            if(!event.modifiers.shift && !wickEditor.colorPicker.isOpen()) {\n                wickEditor.project.clearSelection();\n            }\n            wickEditor.syncInterfaces();\n\n            makingSelectionSquare = true;\n            selectionSquareTopLeft = event.point;\n            selectionSquareBottomRight = event.point\n        }\n\n    }\n\n    this.paperTool.onDoubleClick = function (event) {\n        //hitOptions.tolerance = baseTol / wickEditor.canvas.getZoom();\n        hitResult = wickEditor.canvas.getInteractiveCanvas().getItemAtPoint(event.point, hitOptions);\n\n        if (hitResult && hitResult.type === 'segment') {\n            var hix = hitResult.segment.handleIn.x;\n            var hiy = hitResult.segment.handleIn.y;\n            var hox = hitResult.segment.handleOut.x;\n            var hoy = hitResult.segment.handleOut.y;\n            if(hix === 0 && hiy === 0 && hix === 0 && hiy === 0) {\n                hitResult.segment.smooth();\n            } else {\n                hitResult.segment.handleIn.x = 0;\n                hitResult.segment.handleIn.y = 0;\n                hitResult.segment.handleOut.x = 0;\n                hitResult.segment.handleOut.y = 0;\n            }\n            modifySelectedPath();\n            resetSelection(event)\n        }\n    }\n\n    this.paperTool.onMouseDrag = function (event) {\n\n        if(makingSelectionSquare) {\n            selectionSquareBottomRight = event.point;\n\n            if(selectionSquare) {\n                selectionSquare.remove();\n            }\n\n            selectionSquare = new paper.Path.Rectangle(\n                    new paper.Point(selectionSquareTopLeft.x, selectionSquareTopLeft.y), \n                    new paper.Point(selectionSquareBottomRight.x, selectionSquareBottomRight.y));\n            selectionSquare.strokeColor = 'rgba(100,100,255,0.7)';\n            selectionSquare.strokeWidth = 1/wickEditor.canvas.getZoom();\n            selectionSquare.fillColor = 'rgba(100,100,255,0.15)';\n        } else {\n            \n        }\n\n        if(!hitResult) return;\n\n        if(hitResult.type === 'fill') {\n            paper.project.activeLayer.children.forEach(function (child) {\n                if(child.selected) {\n                    child.position.x += event.delta.x;\n                    child.position.y += event.delta.y;\n                }\n            });\n        } \n\n        if (hitResult.type === 'segment') {\n\n            hitResult.segment.point = new paper.Point(\n                hitResult.segment.point.x + event.delta.x, \n                hitResult.segment.point.y + event.delta.y\n            );\n\n        }\n\n        if( hitResult.type.startsWith('handle')) {\n            var otherHandle;\n            var handle;\n            if(hitResult.type === 'handle-in') {\n                handle = hitResult.segment.handleIn;\n                otherHandle = hitResult.segment.handleOut;\n            } else if (hitResult.type === 'handle-out') {\n                handle = hitResult.segment.handleOut;\n                otherHandle = hitResult.segment.handleIn;\n            }\n\n            handle.x += event.delta.x;\n            handle.y += event.delta.y;\n            if(!event.modifiers.shift) {\n                otherHandle.x -= event.delta.x;\n                otherHandle.y -= event.delta.y;\n            }\n        }\n\n        if(addedPoint) {\n            addedPoint.point = new paper.Point(\n                addedPoint.point.x + event.delta.x, \n                addedPoint.point.y + event.delta.y\n            );\n            addedPoint.smooth()\n        }\n\n        /*if(!hitResult) return;\n\n        if(hitResult.type === 'fill') {\n\n            hitResult.item.position = new paper.Point(\n                hitResult.item.position.x + event.delta.x,\n                hitResult.item.position.y + event.delta.y\n            );\n\n        }*/\n\n        /*if(!hitResult) return;\n\n        function handlesAreOpposite() {\n            var a = hitResult.segment.handleIn;\n            var b = hitResult.segment.handleOut;\n            var dx = Math.abs(a.x - -b.x);\n            var dy = Math.abs(a.y - -b.y);\n            var tol = 1;\n            return dx < tol && dy < tol;\n        }\n\n        if(hitResult.type === 'fill') {\n\n            hitResult.item.position = new paper.Point(\n                hitResult.item.position.x + event.delta.x,\n                hitResult.item.position.y + event.delta.y\n            );\n\n        } else if (hitResult.type === 'segment') {\n            hitResult.segment.point = new paper.Point(\n                hitResult.segment.point.x + event.delta.x, \n                hitResult.segment.point.y + event.delta.y\n            );\n\n        } else if (hitResult.type.startsWith('handle')) {\n\n            var otherHandle;\n            var handle;\n            var opposite = handlesAreOpposite();\n            if(hitResult.type === 'handle-in') {\n                handle = hitResult.segment.handleIn;\n                otherHandle = hitResult.segment.handleOut;\n            } else if (hitResult.type === 'handle-out') {\n                handle = hitResult.segment.handleOut;\n                otherHandle = hitResult.segment.handleIn;\n            }\n\n            handle.x += event.delta.x;\n            handle.y += event.delta.y;\n            if(!event.modifiers.shift && opposite) {\n                otherHandle.x -= event.delta.x;\n                otherHandle.y -= event.delta.y;\n            }\n        }\n\n        if(addedPoint) {\n            addedPoint.point = new paper.Point(\n                addedPoint.point.x + event.delta.x, \n                addedPoint.point.y + event.delta.y\n            );\n        }*/\n\n    }\n\n    this.paperTool.onMouseUp = function (event) {\n\n        if(makingSelectionSquare) {\n            if(!selectionSquare) {\n                selectionSquare = null;\n                makingSelectionSquare = false;\n                return;\n            }\n\n            if(!event.modifiers.shift) {\n                wickEditor.project.clearSelection()\n            }\n            wickEditor.project.getCurrentObject().getAllActiveChildObjects().forEach(function (wickObject) {\n                if(!wickObject.paper) return;\n                if(wickObject.parentFrame.parentLayer.locked || wickObject.parentFrame.parentLayer.hidden) return;\n                if(selectionSquare.bounds.intersects(wickObject.paper.bounds)) {\n                    if(selectionSquare.bounds.contains(wickObject.paper.bounds)\n                    || (selectionSquare.intersects(wickObject.paper)) && !event.modifiers.alt) {\n                        wickEditor.project.selectObject(wickObject)\n                    }\n                }\n            });\n            wickEditor.syncInterfaces()\n\n            if(selectionSquare) {\n                selectionSquare.remove();\n            }\n            selectionSquare = null;\n            makingSelectionSquare = false;\n        } else {\n            if(hitResult && hitResult.item && !(event.delta.x === 0 && event.delta.y === 0)) {\n                modifySelectedPath();\n            }\n        }\n\n        resetSelection(event);\n\n        //hitOptions.tolerance = baseTol / wickEditor.canvas.getZoom();\n        hitResult = wickEditor.canvas.getInteractiveCanvas().getItemAtPoint(event.point, hitOptions);\n\n    }\n\n    function resetSelection (event) {\n        //hitResult = wickEditor.canvas.getInteractiveCanvas().getItemAtPoint(event.point);\n\n        /*if(hitResult && hitResult.item && !hitResult.item._wickInteraction) {\n            paper.project.activeLayer.selected = false;\n            paper.project.deselectAll();\n            hitResult.item.selected = true;\n            hitResult.item.fullySelected = true;\n        }*/\n\n        //wickEditor.cursorIcon.setImageForPaperEvent(event)\n\n        paper.project.activeLayer.selected = false;\n        paper.project.deselectAll();\n        paper.project.activeLayer.children.forEach(function (child) {\n            if(!child.wick) return;\n            if(wickEditor.project.isObjectSelected(child.wick)) {\n                if(child.wick.isSymbol) {\n\n                } else {\n                    //child.selected = true;\n                    child.fullySelected = true;\n                }\n            }\n        });\n    }\n\n    self.forceUpdateSelection = function () {\n        resetSelection();\n    }\n\n    function modifySelectedPath () {\n\n        var objs = wickEditor.project.getSelectedObjects();\n        var modifiedStates = [];\n        objs.forEach(function (wickObject) {\n            var parentAbsPos;\n            if(wickObject.parentObject)\n                parentAbsPos = wickObject.parentObject.getAbsolutePosition();\n            else \n                parentAbsPos = {x:0,y:0};\n\n            if(wickObject.isSymbol) {\n                modifiedStates.push({\n                    rotation: wickObject.paper.rotation,\n                    x: wickObject.paper.position.x - parentAbsPos.x,\n                    y: wickObject.paper.position.y - parentAbsPos.y,\n                    scaleX: wickObject.paper.scaling.x,\n                    scaleY: wickObject.paper.scaling.y,\n                });\n            } else if (wickObject.isPath) {\n                wickObject.paper.applyMatrix = true;\n\n                wickObject.rotation = 0;\n                wickObject.scaleX = 1;\n                wickObject.scaleY = 1;\n                wickObject.flipX = false;\n                wickObject.flipY = false;\n\n                modifiedStates.push({\n                    x : wickObject.paper.position.x - parentAbsPos.x,\n                    y : wickObject.paper.position.y - parentAbsPos.y,\n                    svgX : wickObject.paper.bounds._x,\n                    svgY : wickObject.paper.bounds._y,\n                    width : wickObject.paper.bounds._width,\n                    height : wickObject.paper.bounds._height,\n                    pathData: wickObject.paper.exportSVG({asString:true}),\n                });\n            } else if (wickObject.isImage) {\n                modifiedStates.push({\n                    x : wickObject.paper.position.x - parentAbsPos.x,\n                    y : wickObject.paper.position.y - parentAbsPos.y,\n                    scaleX : wickObject.paper.scaling.x,\n                    scaleY : wickObject.paper.scaling.y,\n                    rotation : wickObject.paper.rotation,\n                })\n            } else if (wickObject.isText) {\n                modifiedStates.push({\n                    x : wickObject.paper.position.x - parentAbsPos.x,\n                    y : wickObject.paper.position.y - parentAbsPos.y,\n                    rotation : wickObject.paper.rotation,\n                });\n            }\n        });\n        wickEditor.actionHandler.doAction('modifyObjects', {\n            objs: objs,\n            modifiedStates: modifiedStates\n        });\n    }\n\n}"
  },
  {
    "path": "src/editor/tools/Tools.Zoom.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nif(!window.Tools) Tools = {};\n\nTools.Zoom = function (wickEditor) {\n\n    var self = this;\n\n    var zoomboxRect;\n    var zoomboxStartPoint;\n    var zoomboxEndPoint;\n\n    var CLICK_ZOOM_AMT = 0.15;\n    var SCROLL_ZOOM_AMT = 0.1;\n\n    this.paperTool = new paper.Tool();\n\n    this.getCursorImage = function () {\n        return \"zoom-in\";\n    }\n\n    this.getToolbarIcon = function () {\n        return \"resources/tools/Zoom.svg\";\n    }\n\n    this.getTooltipName = function () {\n        return \"Zoom (Z/Command+Scroll)\";\n    }\n\n    this.onSelected = function () {\n        wickEditor.inspector.clearSpecialMode();\n    }\n    \n    this.setup = function () {\n        var sq = document.getElementById(\"editorCanvasContainer\");\n        if (sq.addEventListener) {\n            sq.addEventListener(\"mousewheel\", MouseWheelHandler, false);\n            sq.addEventListener(\"DOMMouseScroll\", MouseWheelHandler, false);\n        } else {\n            sq.attachEvent(\"onmousewheel\", MouseWheelHandler);\n        }\n    }\n\n    this.paperTool.onMouseDown = function(event) {\n        zoomboxStartPoint = {\n            x:wickEditor.inputHandler.mouse.x,\n            y:wickEditor.inputHandler.mouse.y\n        }\n    }\n\n    this.paperTool.onMouseDrag = function(event) {\n        zoomboxEndPoint = {\n            x:wickEditor.inputHandler.mouse.x,\n            y:wickEditor.inputHandler.mouse.y\n        }\n\n        if(zoomboxRect) zoomboxRect.remove();\n        zoomboxRect = new paper.Path.Rectangle(event.point, event.downPoint);\n        zoomboxRect.strokeColor = 'red';\n        zoomboxRect.strokeWidth = 1/wickEditor.canvas.getZoom();\n        zoomboxRect.strokeColor = 'black';\n        zoomboxRect.fillColor = 'rgba(255,255,255,0.1)';\n    }\n\n    this.paperTool.onMouseUp = function(event) {\n\n        if(zoomboxStartPoint && zoomboxEndPoint) {\n            var startX = zoomboxStartPoint.x;\n            var startY = zoomboxStartPoint.y;\n            var endX = zoomboxEndPoint.x;\n            var endY = zoomboxEndPoint.y;\n            diffX = Math.abs(endX-startX);\n            diffY = Math.abs(endY-startY);\n            var wZoom = window.innerWidth/diffX*0.8;\n            var hZoom = window.innerHeight/diffY*0.8;\n            wickEditor.canvas.zoomToPoint(Math.min(wZoom, hZoom), (startX+endX)/2, (startY+endY)/2);\n        } else {\n            var mouse = wickEditor.inputHandler.mouse;\n            if(event.modifiers.alt ||\n               event.modifiers.command ||\n               event.modifiers.meta || \n               event.modifiers.option) {\n                wickEditor.canvas.zoomToPoint(1-CLICK_ZOOM_AMT, mouse.x, mouse.y);\n            } else {\n                wickEditor.canvas.zoomToPoint(1+CLICK_ZOOM_AMT, mouse.x, mouse.y);\n            }\n        }\n\n        zoomboxStartPoint = null;\n        zoomboxEndPoint = null;\n        paperStart =null;\n        paperEnd = null;\n        if(zoomboxRect) zoomboxRect.remove();\n    }\n\n// Scroll-to-zoom\n\n    function MouseWheelHandler(e) {\n        if(wickEditor.currentTool !== wickEditor.tools.zoom) {\n            if(wickEditor.project.getSelectedObjects().length > 0) {\n                //wickEditor.project.clearSelection();\n                //wickEditor.syncInterfaces();\n                \n                /*if(wickEditor.currentTool.forceUpdateSelection)\n                    wickEditor.currentTool.forceUpdateSelection();*/\n            }\n        }\n\n        e.preventDefault()\n        if(e.ctrlKey || e.metaKey) {\n            var e = window.event || e;\n            var delta = (e.wheelDelta || -e.detail)*0.01\n            var mouse = wickEditor.inputHandler.mouse;\n            wickEditor.canvas.zoomToPoint(1.0 + delta*SCROLL_ZOOM_AMT, mouse.x, mouse.y);\n        }\n\n        return false;\n    }\n\n}"
  },
  {
    "path": "src/player/WickPlayer.HowlerAudioPlayer.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar WickHowlerAudioPlayer = function () {\n\n    var self = this;\n\n    var howlSoundInstances = {};\n    var frameSoundsMappings = {};\n    var frameWaveforms = {};\n    var framesActiveSoundID = {};\n\n    var muted = false;\n\n    var projectFramerateForSeekAmt;\n\n    self.reloadSoundsInProject = function (project) {\n        projectFramerateForSeekAmt = project.framerate;\n\n        initHowlerInstancesForAllAssets(project);\n        initSoundsOnFrames(project);\n    }\n\n    self.playSoundFromLibrary = function (asset) {\n        if(!muted) {\n            var howlerSound = howlSoundInstances[asset.uuid];\n            var howlerID = howlerSound.play();\n        }\n    }\n\n    self.playSoundOnFrame = function (frame) {\n        if(!muted) {\n            if(framesActiveSoundID[frame.uuid]) {\n                framesActiveSoundID[frame.uuid] = null;\n                self.stopSoundOnFrame(frame);\n            }\n\n            var howlerSound = frameSoundsMappings[frame.uuid];\n            var howlerID = howlerSound.play();\n\n            var seekAmtFrames = frame.parentObject.playheadPosition - frame.playheadPosition;\n            var seekAmtSeconds = seekAmtFrames / projectFramerateForSeekAmt;\n            howlerSound.volume(frame.volume);\n            howlerSound.seek(seekAmtSeconds, howlerID);\n            framesActiveSoundID[frame.uuid] = howlerID;\n        }\n    }\n\n    self.stopSoundOnFrame = function (frame) {\n        if(!muted) {\n            var howlerSound = frameSoundsMappings[frame.uuid];\n            var howlerID = framesActiveSoundID[frame.uuid];\n            howlerSound.stop(howlerID);\n            framesActiveSoundID[frame.uuid] = null;\n        }\n    }\n\n    this.stopAllSounds = function () {\n        for(uuid in howlSoundInstances) {\n            howlSoundInstances[uuid].stop();\n        }\n        for(uuid in frameSoundsMappings) {\n            frameSoundsMappings[uuid].stop();\n        }\n    }\n\n    this.cleanup = function () {\n        // todo\n    }\n\n    this.clearCacheForFrame = function (frame) {\n        frameSoundsMappings[frame.uuid] = null;\n        frameWaveforms[frame.uuid] = null;\n    }\n\n    this.getWaveformOfFrame = function (frame) {\n        if(frameWaveforms[frame.uuid]) {\n            return {\n                src: frameWaveforms[frame.uuid],\n                length: frameSoundsMappings[frame.uuid].duration()\n            }\n        }\n    }\n\n    this.getDurationOfSound = function (assetUUID) {\n        return howlSoundInstances[assetUUID].duration();\n    }\n\n    this.generateAudioTrack = function (frames) {\n        var frame = frames[0];\n        var howlerSound = frameSoundsMappings[frame.uuid];\n\n        console.log(howlerSound)\n\n        var data = atob(howlerSound._src.split(',')[1]);\n        var dataView = new Uint8Array(data.length);\n        for (var i=0; i<data.length; ++i) {\n            dataView[i] = data.charCodeAt(i);\n        }\n\n        Howler.ctx.decodeAudioData(dataView.buffer, function(buffer) {\n            console.log(buffer)\n        })\n    }\n\n    /* Wick player API functions */\n\n    window.playSound = function (assetFilename) {\n        var asset = (wickPlayer || wickEditor).project.library.getAssetByName(assetFilename);\n        if(asset) {\n            self.playSoundFromLibrary(asset);\n        }\n    }\n\n    window.stopAllSounds = function () {\n        self.stopAllSounds();\n    }\n\n    window.mute = function () {\n        self.stopAllSounds();\n        muted = true;\n    }\n\n    window.unmute = function () {\n        muted = false;\n    }\n\n    /* Util */\n\n    function initHowlerInstancesForAllAssets (project) {\n\n        project.library.getAllAssets('audio').forEach(function (asset) {\n            if(howlSoundInstances[asset.uuid]) return;\n\n            var audioData = asset.getData();\n\n            howlSoundInstances[asset.uuid] = new Howl({\n                src: [audioData],\n                loop: false,\n                volume: 1.0\n            });\n        });\n\n    }\n\n    function initSoundsOnFrames (project) {\n\n        project.getAllFrames().filter(function (frame) {\n            return frame.hasSound() && !frameSoundsMappings[frame.uuid];\n        }).forEach(function (frame) {\n            var howlerSound = howlSoundInstances[frame.audioAssetUUID];\n            frameSoundsMappings[frame.uuid] = howlerSound;\n            framesActiveSoundID[frame.uuid] = null;\n\n            if(window.WickEditor) {\n                generateWaveformForFrame(frame);\n            }\n        });\n\n    }\n\n    function generateWaveformForFrame (frame) {\n\n        var asset = window.wickEditor.project.library.getAsset(frame.audioAssetUUID);\n        var src = asset.getData();\n        var scwf = new SCWF();\n        scwf.generate(src, {\n            onComplete: function(png, pixels) {\n                frameWaveforms[frame.uuid] = png;\n                window.wickEditor.syncInterfaces();\n            }\n        });\n        \n    }\n}\n"
  },
  {
    "path": "src/player/WickPlayer.InputHandler.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n    \nWickPlayerInputHandler = function (canvasContainer, wickProject) {\n\n    var self = this;\n\n    var mouse;\n    var mouseDiff;\n    var lastMouse;\n    var newMouse;\n    var keys;\n    var keysJustPressed; \n    var keysJustReleased;\n\n    var _cachedKeysDown;\n    var _cachedKeysJustPressed;\n    var _cachedKeysJustReleased;\n\n    var project;\n\n    var canvas = canvasContainer.children[0];\n\n    self.setup = function () {\n        mouse = null;\n        keys = [];\n        keysJustPressed = [];\n        keysJustReleased = [];\n\n        if(bowser.mobile || bowser.tablet) {\n            // Touch event (one touch = like a mouse click)\n            document.body.addEventListener(\"touchstart\", onTouchStart, false);\n            document.body.addEventListener(\"touchmove\", onTouchMove, false);\n\n            // Squash gesture events\n            document.body.addEventListener('gesturestart',  function(e) { e.preventDefault(); });\n            document.body.addEventListener('gesturechange', function(e) { e.preventDefault(); });\n            document.body.addEventListener('gestureend',    function(e) { e.preventDefault(); });\n        } else {\n            document.body.addEventListener('mousemove', onMouseMove, false);\n            document.body.addEventListener(\"mousedown\", onMouseDown, false);\n            document.body.addEventListener(\"mouseup\",   onMouseUp,   false);\n\n            document.body.addEventListener(\"keydown\", onKeyDown);\n            document.body.addEventListener(\"keyup\", onKeyUp);\n        }\n    }\n\n    self.update = function () {\n        keysJustPressed = [];\n        keysJustReleased = [];\n\n        _cachedKeysDown = null;\n        _cachedKeysJustPressed = null;\n        _cachedKeysJustReleased = null;\n\n        lastMouse = mouse;\n        if(newMouse) mouse = newMouse;\n\n        if(mouse && lastMouse) {\n            mouseDiff = {\n                x: mouse.x - lastMouse.x,\n                y: mouse.y - lastMouse.y\n            }\n        }\n        if(mouse && lastMouse) {\n            lastMouse.x = mouse.x;\n            lastMouse.y = mouse.y;\n        }\n    }\n\n    self.cleanup = function () {\n        document.body.removeEventListener(\"mousedown\", onMouseDown);\n        document.body.removeEventListener(\"mousemove\", onMouseMove);\n        document.body.removeEventListener(\"mouseup\", onMouseUp);\n\n        document.body.removeEventListener(\"touchstart\", onTouchStart);\n        document.body.removeEventListener(\"touchmove\", onTouchMove);\n\n        document.body.removeEventListener(\"keydown\", onKeyDown);\n        document.body.removeEventListener(\"keyup\", onKeyUp);\n    }\n    \n    self.getMouse = function () {\n        return mouse || {x:0,y:0};\n    }\n\n    self.getMouseDiff = function () {\n        return mouseDiff || {x:0,y:0};\n    }\n\n    self.getKeys = function () {\n        return keys || [];\n    }\n\n    self.getKeysJustPressed = function () {\n        return keysJustPressed || [];\n    }\n\n    self.getKeysJustReleased = function () {\n        return keysJustReleased || [];\n    }\n\n    self.keyIsDown = function (keyString) {\n        return self.getKeys()[keyCharToCode[keyString.toUpperCase()]];\n    }\n\n    self.keyJustPressed = function (keyString) {\n        return self.getKeysJustPressed()[keyCharToCode[keyString.toUpperCase()]];\n    }\n\n    self.getAllKeysDown = function () {\n        if(_cachedKeysDown) return _cachedKeysDown;\n\n        _cachedKeysDown = [];\n\n        var _keys = self.getKeys();\n        for(var i = 0; i < _keys.length; i++) {\n            if(_keys[i]) {\n                var c = codeToKeyChar[i];\n                _cachedKeysDown.push(c);\n            }\n        }\n\n        return _cachedKeysDown;\n    }\n\n    self.getAllKeysJustPressed = function () {\n        if(_cachedKeysJustPressed) return _cachedKeysJustPressed;\n\n        _cachedKeysJustPressed = [];\n\n        var _keys = self.getKeysJustPressed();\n        for(var i = 0; i < _keys.length; i++) {\n            if(_keys[i]) {\n                var c = codeToKeyChar[i];\n                _cachedKeysJustPressed.push(c);\n            }\n        }\n\n        return _cachedKeysJustPressed;\n    }\n\n    self.getAllKeysJustReleased = function () {\n        if(_cachedKeysJustReleased) return _cachedKeysJustReleased;\n\n        _cachedKeysJustReleased = [];\n\n        var _keys = self.getKeysJustReleased();\n        for(var i = 0; i < _keys.length; i++) {\n            if(_keys[i]) {\n                var c = codeToKeyChar[i];\n                _cachedKeysJustReleased.push(c);\n            }\n        }\n\n        return _cachedKeysJustReleased;\n    }\n\n    self.hideCursor = function () {\n        canvasContainer.className = 'hideCursor'\n    }\n\n    self.showCursor = function () {\n        canvasContainer.className = ''\n    }\n\n\n    var onMouseMove = function (evt) {\n\n        setMousePos(calcMousePos(canvasContainer, evt));\n\n        canvasContainer.style.cursor = \"default\";\n\n        // Check if we're hovered over a clickable object...\n        var hoveredOverObj = null;\n        wickProject.rootObject.getAllActiveChildObjectsRecursive(true).forEachBackwards(function(child) {\n            if(!child.isSymbol) return;\n\n            if(!(hoveredOverObj && hoveredOverObj.isButton) && child.isPointInside(self.getMouse())) {\n                if(!child.hoveredOver) {\n                    child._wasHoveredOver = true;\n                }\n                if(child.isButton) canvasContainer.style.cursor = child.cursor || \"pointer\";\n                child.hoveredOver = true;\n                hoveredOverObj = child;\n            } else {\n                if(child.hoveredOver) {\n                    child._mouseJustLeft = true;\n                }\n                child.hoveredOver = false;\n            }\n        });\n\n    }\n\n    var onMouseDown = function (evt) {\n\n        canvasContainer.focus();\n\n        // Hack to avoid \"'requestFullscreen' can only be initiated by a user gesture.\" error\n        if(wickPlayer.fullscreenRequested) {\n            wickPlayer.enterFullscreen();\n            wickPlayer.fullscreenRequested = false;\n        }\n\n        var currFrame = wickProject.getCurrentFrame();\n        if(currFrame) {\n            currFrame._wasClicked = true;\n            currFrame._beingClicked = true;\n        }\n        \n        var clickedObj;\n        wickProject.rootObject.getAllActiveChildObjectsRecursive(true).forEachBackwards(function(child) {\n            var hasMousePressedScript = child.mousePressed && child.mousePressed.toString() !== 'function mousePressed(){return;}'\n            if(!clickedObj && hasMousePressedScript && child.isPointInside(self.getMouse())) {\n                child._wasClicked = true;\n                child._beingClicked = true;\n                clickedObj = child;\n            }\n        });\n\n    }\n\n    var onMouseUp = function (evt) {\n        var currFrame = wickProject.getCurrentFrame();\n        if(currFrame) {\n            currFrame._beingClicked = false;\n            currFrame._wasClickedOff = true;\n        }\n\n        wickProject.rootObject.getAllActiveChildObjectsRecursive(true).forEachBackwards(function(child) {\n            child._beingClicked = false;\n\n            if(child.isPointInside(self.getMouse())) {\n                child._wasClickedOff = true;\n            }\n        });\n    }\n\n    var onKeyDown = function (event) {\n        event.preventDefault();\n\n        // Quit builtin editor\n        if(window.wickEditor && event.keyCode === 27) {\n            window.wickEditor.guiActionHandler.doAction('stopRunningProject')\n        }\n\n        // Check for new keyDown...\n        if (!keys[event.keyCode]) {\n            keysJustPressed[event.keyCode] = true; \n        }\n\n        keys[event.keyCode] = true;\n    }\n\n    var onKeyUp = function (event) {\n        event.preventDefault();\n\n        keysJustReleased[event.keyCode] = true;\n        \n        keys[event.keyCode] = false;\n    }\n\n    var onTouchStart = function (evt) {\n\n        document.getElementById('rendererCanvas').focus();\n\n        evt.preventDefault();\n\n        // on iOS, WebAudio context only gets 'unmuted' after first user interaction\n        if(!audioContext) {\n            wickPlayer.audioPlayer.setup(wickProject);\n        }\n\n        var touchPos = getTouchPos(canvasContainer, evt);\n        setMousePos(touchPos);\n\n        wickProject.rootObject.getAllActiveChildObjects().forEach(function(child) {\n            if(child.isPointInside(touchPos)) {\n                child._wasClicked = true;\n            }\n        });\n        \n\n    }\n\n    var onTouchMove = function (evt) {\n\n        evt.preventDefault();\n        \n        var touchPos = getTouchPos(canvasContainer, evt);\n        setMousePos(touchPos);\n\n    }\n\n    var calcMousePos = function (canvas, evt) {\n        var canvasBoundingClientRect = canvas.getBoundingClientRect();\n\n        var mouseX = evt.clientX;\n        var mouseY = evt.clientY;\n\n        return {\n            x: mouseX,\n            y: mouseY\n        };\n    }\n\n    var getTouchPos = function (canvas, evt) {\n        var canvasBoundingClientRect = canvas.getBoundingClientRect();\n\n        var touch = evt.targetTouches[0];\n\n        var touchX = touch.pageX;\n        var touchY = touch.pageY;\n\n        return {\n            x: touchX,\n            y: touchY\n        };\n    }\n\n    var setMousePos = function (newPos) {\n        var windowScale = getWindowScale();\n        newMouse = {\n            x: newPos.x * windowScale.x,\n            y: newPos.y * windowScale.y\n        }\n    }\n\n    var getWindowScale = function () {\n        // Fit to screen disabled for now.\n        return {\n            x:1,\n            y:1\n        }\n        /*return {\n            x: wickProject.width / window.innerWidth,\n            y: wickProject.height / window.innerHeight\n        }*/\n    }\n\n}"
  },
  {
    "path": "src/player/WickPlayer.PixiRenderer.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar WickPixiRenderer = function (canvasContainer) {\n\n    var self = this;\n\n    var SVG_SCALE = 1.4;\n\n    var renderer = PIXI.autoDetectRenderer(100, 100, {\n        backgroundColor : \"#FFFFFF\", \n        resolution: window.devicePixelRatio,\n        preserveDrawingBuffer: true,\n        antialias: true,\n        transparent: true,\n    });\n    renderer.clearBeforeRender = true;\n    renderer.roundPixels = false;\n    renderer.view.setAttribute('tabindex', 0);\n\n    canvasContainer.appendChild(renderer.view);\n    renderer.view.focus();\n\n    var currentProjectUUID = null;\n    var container = new PIXI.Container();\n    var pixiSprites = {};\n    var pixiTextures = {};\n\n    var wickProject;\n\n    var graphics = new PIXI.Graphics();\n    \n    container.addChild(graphics);\n\n    _cached_w = 0;\n    _cached_h = 0;\n\n    self.preloadAllAssets = function (project, callback) {\n        currentProjectUUID = project.uuid;\n\n        wickProject = project;\n\n        var assetsToLoad = [];\n        project.getAllObjects().forEach(function (o) {\n            if((o.isPath && o.pathData) || o.isImage || o.isText) {\n                assetsToLoad.push(o);\n            }\n        });\n\n        var loadedAssetCount = 0;\n        assetsToLoad.forEach(function (o) {\n            function checkIfDone () {\n                if(loadedAssetCount === assetsToLoad.length) {\n                    callback();\n                }\n            }\n\n            if (!pixiSprites[o.uuid]) {\n                createPixiSprite(o, function () {\n                    loadedAssetCount++;\n                    checkIfDone()\n                });\n            } else if(o._renderDirty) {\n                regenPixiPath(o, pixiSprites[o.uuid], function () {\n                    loadedAssetCount++;\n                    checkIfDone()\n                });\n                o._renderDirty = false;\n            } else if(pixiTextures[o.uuid]) {\n                loadedAssetCount++;\n                checkIfDone()\n            } else {\n                loadedAssetCount++;\n                checkIfDone();\n            }\n        });\n    }\n\n    self.renderWickObjects = function (project, wickObjects, renderExtraSpace, fitToScreen) {\n        window._lastRender = {\n            project: project,\n            wickObjects: wickObjects, \n            renderExtraSpace: renderExtraSpace\n        }\n        if(!renderExtraSpace) renderExtraSpace = 1;\n\n        if(renderExtraSpace === 1) {\n            graphics.clear();\n            graphics.beginFill(parseInt(project.backgroundColor.replace(\"#\",\"0x\")));\n            graphics.moveTo(0, 0);\n            graphics.lineTo(project.width, 0);\n            graphics.lineTo(project.width, project.height);\n            graphics.lineTo(0, project.height);\n            graphics.endFill();\n        }\n\n        wickProject = project;\n\n        if(currentProjectUUID !== project.uuid) {\n            currentProjectUUID = project.uuid;\n            loadAllAssets(project);\n        }\n\n        if(fitToScreen) {\n            var w = project.width;\n            var h = project.height;\n            canvasContainer.style.width  = w + 'px';\n            canvasContainer.style.height = h + 'px';\n            if(_cached_w !== w || _cached_h !== h) {\n                renderer.resize(w, h);\n                _cached_w = w;\n                _cached_h = h;\n                renderer.view.style.width  = w + \"px\";\n                renderer.view.style.height = h + \"px\";\n                container.scale.x = 1//w / project.width;\n                container.scale.y = 1//h / project.height;\n            }\n        } else {\n            container.position.x = 0;\n            container.position.y = 0;\n            renderer.resize(project.width*renderExtraSpace, project.height*renderExtraSpace);\n            renderer.view.style.width  = project.width*renderExtraSpace  + \"px\";\n            renderer.view.style.height = project.height*renderExtraSpace + \"px\";\n            if(renderer.width !== project.width || renderer.height !== project.height) {\n                renderer.resize(project.width*renderExtraSpace, project.height*renderExtraSpace);\n                renderer.view.style.width  = project.width*renderExtraSpace  + \"px\";\n                renderer.view.style.height = project.height*renderExtraSpace + \"px\";\n\n                if(renderExtraSpace !== 1) {\n                    container.position.x = project.width/renderExtraSpace;\n                    container.position.y = project.height/renderExtraSpace;\n                }\n            }\n        }\n\n        for (uuid in pixiSprites) {\n            pixiSprites[uuid].visible = false;\n        }\n\n        wickObjects.forEach(function (wickObject) {\n            renderWickObject(wickObject);\n        });\n        renderer.render(container);\n    }\n\n    self.reorderAllObjects = function (project) {\n        var objectsToReorder = container.removeChildren(0, container.children.length);\n        var allWickObjects = project.getAllObjects();\n\n        container.addChild(graphics);\n        allWickObjects.forEach(function (wickObject) {\n            objectsToReorder.forEach(function (pixiObject) {\n                if(pixiSprites[wickObject.uuid] === pixiObject) {\n                    container.addChild(pixiObject);\n                }\n            });\n        });\n    }\n\n    self.cleanupObjectTextures = function (wickObj) {\n        var sprite = pixiSprites[wickObj.uuid];\n        if(sprite)\n            sprite.parent.removeChild(sprite);\n    }\n\n    function renderWickObject (wickObject) {\n        var sprite = pixiSprites[wickObject.uuid];\n        if(!sprite && !wickObject.isSymbol) {\n            createPixiSprite(wickObject);\n        }\n        if(sprite && wickObject._renderDirty && wickObject.isPath) {\n            regenPixiPath(wickObject, sprite);\n            wickObject._renderDirty = false;\n        }\n        if(sprite && wickObject._renderDirty && wickObject.isText) {\n            sprite = regenPixiText(wickObject, sprite);\n            wickObject._renderDirty = false;\n        }\n        if(sprite) {\n            sprite.visible = !wickObject.parentFrame.parentLayer.hidden;\n            sprite.anchor = new PIXI.Point(0.5, 0.5);\n            var textureScale = (wickObject.pathData || wickObject.isText ? SVG_SCALE : 1);\n\n            var absTransforms = wickObject.getAbsoluteTransformations();\n            var textOffset = wickObject.isText ? \n                rotate_point(sprite.textboxOffset, 0, 0, 0, absTransforms.rotation) :\n                {x:0,y:0};\n            sprite.position.x = absTransforms.position.x - textOffset.x;\n            sprite.position.y = absTransforms.position.y - textOffset.y;\n            sprite.rotation = absTransforms.rotation/360*2*3.14159;\n            sprite.scale.x = absTransforms.scale.x/textureScale;\n            sprite.scale.y = absTransforms.scale.y/textureScale;\n            sprite.alpha = absTransforms.opacity;\n            sprite.scale.x *= (absTransforms.flip.x ? -1 : 1);\n            sprite.scale.y *= (absTransforms.flip.y ? -1 : 1);\n        }\n\n        wickObject.getAllActiveChildObjects().forEach(function (child) {\n            renderWickObject(child);\n        });\n    }\n\n    function loadAllAssets (project) {\n        project.getAllObjects().forEach(function (wickObject) {\n            createPixiSprite(wickObject);\n        });\n    }\n\n    function createPixiSprite (wickObject, callback) {\n        if(wickObject.sourceUUID) {\n            var pixiTexture = pixiTextures[wickObject.sourceUUID];\n            if(pixiTexture) {\n                var pixiSprite = new PIXI.Sprite(pixiTexture);\n                wickObject.alphaMask = wickProject.getObjectByUUID(wickObject.sourceUUID).alphaMask\n                var sourceIndex = container.children.indexOf(pixiSprites[wickObject.sourceUUID])\n                container.addChildAt(pixiSprite, sourceIndex);\n                pixiSprites[wickObject.uuid] = pixiSprite;\n                pixiSprite.visible = false;\n                return;\n            }\n        }\n\n        var type;\n\n        if (wickObject.asset && wickObject.asset.type === 'image') {\n            type = 'image';\n        } else if (wickObject.isPath && wickObject.pathData) {\n            type = 'svg';\n        } else if (wickObject.isText) {\n            type = 'text';\n        }\n\n        if(type) {\n            var newPixiSprite = WickToPixiSprite[type](wickObject, callback);\n            container.addChild(newPixiSprite);\n            pixiSprites[wickObject.uuid] = newPixiSprite;\n\n            var textureSrc = newPixiSprite.texture.baseTexture.imageUrl;\n            if(textureSrc && !wickProject.disableAlphaMaskGeneration)\n                wickObject.generateAlphaMask(textureSrc);\n        }\n    }\n\n    function regenPixiPath (wickObject, pixiSprite, callback) {\n        var base64svg = getBase64SVG(wickObject);\n        var texture = PIXI.Texture.fromImage(base64svg, undefined, undefined, SVG_SCALE);\n        pixiSprite.setTexture(texture);\n        texture.baseTexture.on('loaded', function(){\n            if(callback) callback();\n        });\n    }\n\n    function regenPixiText (wickObject, pixiSprite) {\n        container.removeChild(pixiSprite);\n        var newPixiText = WickToPixiSprite['text'](wickObject);\n        container.addChild(newPixiText);\n        pixiSprites[wickObject.uuid] = newPixiText;\n        return newPixiText;\n    }\n\n    var WickToPixiSprite = {\n        'image': function (wickObject, callback) {\n            var pixiTexture = PIXI.Texture.fromImage(wickObject.asset.getData());\n            var pixiSprite = new PIXI.Sprite(pixiTexture);\n            pixiSprite.texture.baseTexture.on('loaded', function(){\n                if(window._lastRender) {\n                    self.renderWickObjects(\n                        window._lastRender.project, \n                        window._lastRender.wickObjects, \n                        window._lastRender.renderExtraSpace);\n                }\n                if(callback) callback();\n            });\n            pixiTextures[wickObject.uuid] = pixiTexture;\n            return pixiSprite;\n        },\n        'svg': function (wickObject, callback) {\n            var base64svg = getBase64SVG(wickObject);\n            var pixiTexture = PIXI.Texture.fromImage(base64svg, undefined, undefined, SVG_SCALE);\n            var newSprite = new PIXI.Sprite(pixiTexture);\n            newSprite.texture.baseTexture.on('loaded', function(){\n                if(window._lastRender) {\n                    self.renderWickObjects(\n                        window._lastRender.project, \n                        window._lastRender.wickObjects, \n                        window._lastRender.renderExtraSpace);\n                }\n                if(callback) callback();\n            });\n            pixiTextures[wickObject.uuid] = pixiTexture;\n            return newSprite;\n        },\n        'text': function (wickObject, callback) {\n            var textData = wickObject.textData;\n            var style = {\n                font : textData.fontWeight + \" \" + textData.fontStyle + \" \" + (textData.fontSize*SVG_SCALE) + \"px \" + textData.fontFamily,\n                fill : textData.fill,\n                wordWrap : false,\n                wordWrapWidth : wickObject.width*SVG_SCALE,\n                align: textData.textAlign,\n            };\n            var pixiText = new PIXI.Text(textData.text, style);\n            var textWidth = pixiText.width/SVG_SCALE;\n            var textboxWidth = wickObject.width;\n            if(textData.textAlign === 'left') {\n                pixiText.textboxOffset = (textboxWidth-textWidth)/2;\n            } else if (textData.textAlign === 'center') {\n                pixiText.textboxOffset = 0;\n            } else if (textData.textAlign === 'right') {\n                pixiText.textboxOffset = -(textboxWidth-textWidth)/2;\n            }\n            if(callback) callback();\n            return pixiText;\n        }\n    }\n\n    function getBase64SVG (wickObject) {\n        var parser = new DOMParser();\n        var x = (wickObject.svgX || 0);\n        var y = (wickObject.svgY || 0);\n        if(!wickObject.svgStrokeWidth) wickObject.svgStrokeWidth = 0;\n        x -= wickObject.svgStrokeWidth/2;\n        y -= wickObject.svgStrokeWidth/2;\n        var w = (wickObject.width  + wickObject.svgStrokeWidth*1);\n        var h = (wickObject.height + wickObject.svgStrokeWidth*1);\n        var svgDoc = parser.parseFromString('<svg id=\"svg\" viewBox=\"'+x+' '+y+' '+w+' '+h+'\" version=\"1.1\" width=\"'+w+'\" height=\"'+h+'\" xmlns=\"http://www.w3.org/2000/svg\">'+wickObject.pathData+'</svg>', \"image/svg+xml\");\n        var s = new XMLSerializer().serializeToString(svgDoc);\n        var base64svg = 'data:image/svg+xml;base64,' + window.btoa(s);\n        return base64svg;\n    }\n\n};\n\n"
  },
  {
    "path": "src/player/WickPlayer.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n    \nvar WickPlayer = function () {\n\n    var self = this;\n\n    self.running = false;\n\n    var initialStateProject;\n    var stats;\n\n    self.runProject = function (projectJSON) {\n\n        if(localStorage.enableStats) {\n            stats = new Stats();\n            stats.showPanel(1);\n            document.body.appendChild(stats.dom);\n        }\n\n        try {\n            if(window.parent && window.parent.wickEditor) window.wickEditor = window.parent.wickEditor;\n        } catch (e) {\n            console.log(e)\n        }\n\n        self.running = true;\n\n        self.canvasContainer = document.getElementById('playerCanvasContainer');\n\n        resetElapsedTime();\n\n        // Load the project!\n        self.project = WickProject.fromJSON(projectJSON);\n        initialStateProject = WickProject.fromJSON(projectJSON);\n\n        self.canvasContainer.style.width = self.project.width+'px';\n        self.canvasContainer.style.height = self.project.height+'px';\n        self.canvasContainer.style.backgroundColor = self.project.backgroundColor;\n\n        self.project.rootObject.generateObjectNameReferences(self.project.rootObject);\n        initialStateProject.rootObject.generateObjectNameReferences(initialStateProject.rootObject);\n\n        self.project.prepareForPlayer();\n        initialStateProject.prepareForPlayer();\n\n        // Make the camera\n        window.camera = new WickCamera(self.project);\n\n        // Setup renderer/input/audio player\n        self.renderer = new WickPixiRenderer(self.canvasContainer);\n        self.inputHandler = new WickPlayerInputHandler(self.canvasContainer, self.project);\n        self.audioPlayer = new WickHowlerAudioPlayer(self.project);\n        self.audioPlayer.reloadSoundsInProject(self.project);\n\n        self.inputHandler.setup();\n\n        self.project.loadFonts(function () {\n            self.renderer.preloadAllAssets(self.project, function () {\n                startUpdate();\n            });\n        });\n    }\n\n    window.runProject = function (projectJSON) {\n        self.runProject(projectJSON)\n    }\n\n    self.stopRunningProject = function () {\n\n        self.running = false;\n\n        update();\n        clearTimeout(loopTimeout);\n\n        self.project = null;\n\n        self.inputHandler.cleanup();\n        self.audioPlayer.cleanup();\n    }\n\n    function startUpdate(fps) {\n        then = Date.now();\n        startTime = then;\n        update(false);\n    }\n\n    var loopTimeout;\n    var update = function (firstTick) {\n\n        if(!self.running) return;\n\n        if(stats) stats.begin();\n\n        requestAnimationFrame(function() { update(false); });\n\n        now = Date.now();\n        elapsed = now - then;\n\n        var fpsInterval = 1000/self.project.framerate;\n        if (self.project.framerate === 60 || elapsed > fpsInterval) {\n            then = now - (elapsed % fpsInterval);\n            \n            deleteObjects = [];\n            if(!firstTick) {\n                self.project.rootObject.generateObjectNameReferences()\n                self.project.tick();\n            }\n            deleteObjects.forEach(function (d) {\n                self.renderer.cleanupObjectTextures(d);\n                d.remove();\n                if(d.objectClonedFrom) {\n                    var removeIndex = d.objectClonedFrom.clones.indexOf(d);\n                    if(removeIndex !== -1) {\n                        d.objectClonedFrom.clones.splice(removeIndex, 1);\n                    }\n                }\n            });\n            var activeObjs = self.project.rootObject.getAllActiveChildObjects();\n            self.renderer.renderWickObjects(self.project, activeObjs, null, true);\n            \n            checkForSounds();\n\n            self.inputHandler.update();\n        }\n\n        if(stats) stats.end();\n\n    }\n\n    function checkForSounds () {\n        self.project.getAllFrames().forEach(function (frame) {\n            if(frame._wantsToPlaySound) {\n                self.audioPlayer.playSoundOnFrame(frame);\n                frame._wantsToPlaySound = false;\n            }\n            if(frame._wantsToStopSound) {\n                self.audioPlayer.stopSoundOnFrame(frame);\n                frame._wantsToStopSound = false;\n            }\n        });\n    }\n\n    self.cloneObject = function (wickObj, args) {\n        var clone = wickObj.copy();\n        clone.name = undefined;\n        clone.isClone = true;\n        for(key in args) {\n            clone[key] = args[key];\n        }\n        clone.asset = wickObj.asset;\n\n        wickObj.clones.push(clone);\n\n        clone.objectClonedFrom = wickObj;\n\n        clone.prepareForPlayer()\n\n        clone.parentObject = wickObj.parentObject;\n        clone.parentFrame = wickObj.parentFrame;\n        clone.parentObject.getCurrentLayer().getCurrentFrame().wickObjects.push(clone);\n        clone.generateParentObjectReferences();\n\n        return clone;\n    }\n\n    self.deleteObject = function (wickObj) {\n        deleteObjects.push(wickObj);\n        \n    }\n\n    self.resetStateOfObject = function (wickObject) {\n\n        // Clones go away because they have no original state! :O\n        if(wickObject.isClone) {\n            self.deleteObject(wickObject)\n            return;\n        }\n\n        var initialStateObject = initialStateProject.getObjectByUUID(wickObject.uuid);\n        if(!initialStateObject) return;\n\n        // TOXXXIC\n        //console.log(\"-------------\");\n        var blacklist = ['_hitBox', 'asset', 'alphaMask', 'pixiSprite', 'pixiContainer', 'pixiText', 'audioData', 'wickScripts', 'parentObject', 'layers', '_active', '_wasActiveLastTick', '_scopeWrapper', 'parentFrame', 'bbox', 'tweens'];\n        for (var name in wickObject) {\n            if (name !== 'undefined' && wickObject.hasOwnProperty(name) && blacklist.indexOf(name) === -1) {\n                if(initialStateObject[name] !== wickObject[name]) {\n                    wickObject[name] = initialStateObject[name];\n                }\n            }\n        }\n        \n        wickObject.hoveredOver = false;\n        wickObject.playheadPosition = 0;\n        wickObject._playing = true;\n\n        // Don't forget to reset the childrens states\n        if(wickObject.isSymbol) {\n            wickObject.getAllChildObjects().forEach(function (child) {\n                if(child.isSymbol)\n                    wickPlayer.resetStateOfObject(child);\n            });\n        }\n\n    }\n\n}\n\n// this is temporary, need a better system for this...\nfunction runProject (json) {\n    window.wickPlayer = new WickPlayer(); \n    window.wickPlayer.runProject(json);\n}\n\nfunction tryToLoadProjectFromWindowHash () {\n    if(window.location.hash) {\n        var projectPath = window.location.hash.slice(1); // remove first char (the hash)\n\n        var xhr = new XMLHttpRequest();\n        xhr.open('GET', projectPath, true);\n        xhr.responseType = 'arraybuffer';\n\n        xhr.onload = function(e) {\n          if (this.status == 200) {\n            var byteArray = new Uint8Array(this.response);\n            var wickProjectJSON = LZString.decompressFromUint8Array(byteArray);\n            runProject(wickProjectJSON);\n          }\n        };\n\n        xhr.send();\n    }\n}\nif(!window.WickEditor) tryToLoadProjectFromWindowHash();\n"
  },
  {
    "path": "src/player/emptyplayer.htm",
    "content": "<!-- \n    You've peeked inside the source code for a Wick project... you are clever!\n\n    This file was generated by the WickProject exporter. \n    (see src/editor/WickProject.Exporter.js) at https://github.com/zrispo/wick/ \n\n    Send any questions to https://twitter.com/zrispo !!!\n -->\n\n<head>\n    <style>\n        /* remove the top and left whitespace */\n    \t* { margin:0; padding:0; }\n\n        /* just to be sure these are full screen */\n    \thtml, body { width:100%; height:100%; background-color: #FFFFFF; }\n\n        /* To remove the scrollbars */\n    \tcanvas { display:block; }\n\n        canvas:focus {\n            outline: none;\n            outline-style: none;\n        }\n\n        /* Cross browser cursor hide class */\n        .hideCursor {\n            cursor: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjbQg61aAAAADUlEQVQYV2P4//8/IwAI/QL/+TZZdwAAAABJRU5ErkJggg=='),\n            none !important;\n        }\n    </style>\n</head>\n\n<script>wickEditor = null;</script>\n\n<body>\n\t<div id=\"playerCanvasContainer\" readonly=\"readonly\"></div>\n</body>\n\n"
  },
  {
    "path": "src/project/WickAsset.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar WickAsset = function (data, type, filename, compress) {\n\n    this.data = data;\n    this.type = type;\n    this.filename = filename;\n    this.compressed = compress;\n\n    if(compress) {\n        console.log(\"big file size: \" + this.data.length);\n        this.data = LZString.compressToBase64(this.data);\n        console.log(\"compressed file size: \" + this.data.length);\n        console.log(\"Look how much space we saved wow!\");\n    }\n\n}\n\nWickAsset.prototype.getData = function () {\n    if(this.compressed) {\n        return LZString.decompressFromBase64(this.data);\n    } else {\n        return this.data;\n    }\n}\n\nWickAsset.prototype.getType = function () {\n    return this.type;\n}\n\nWickAsset.prototype.getFilename = function () {\n    return this.filename;\n}\n"
  },
  {
    "path": "src/project/WickCamera.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar WickCamera = function (project) {\n\n    var self = this;\n\n    var x = project.width/2;\n    var y = project.height/2;\n\n    var followingObject = null;\n    var followingSmoothness = 1;\n\n    this.followObject = function (object, smoothness) {\n    \tfollowingObject = object;\n    \tfollowingSmoothness = smoothness || 1;\n    }\n\n    this.getPosition = function () {\n    \treturn {\n    \t\tx: x, \n    \t\ty: y\n    \t};\n    }\n\n    this.setPosition = function (_x,_y) {\n    \tx = _x;\n    \ty = _y;\n    }\n\n    this.update = function () {\n    \tif(followingObject) {\n    \t\tvar dx = followingObject.x - x;\n    \t\tvar dy = followingObject.y - y;\n    \t\tself.setPosition(\n    \t\t\tx + dx*followingSmoothness, \n    \t\t\ty + dy*followingSmoothness\n    \t\t);\n    \t}\n    }\n\n};\n\n"
  },
  {
    "path": "src/project/WickDocs.js",
    "content": "window.wickDocs = \n    [{\n      \"name\": \"Timeline\",\n      \"properties\": [\n        {\n          \"name\": \"play()\",\n          \"description\": \"Plays the timeline. \",\n          \"example\": \"play();\",\n          \"snippet\": \"play()\",\n          \"return\": null,\n          \"args\": []\n        },\n        {\n          \"name\": \"stop()\",\n          \"description\": \"Stops the timeline.\",\n          \"example\": \"stop();\",\n          \"snippet\": \"stop()\",\n          \"return\": null,\n          \"args\": []\n        },\n        {\n          \"name\": \"gotoAndStop(frame)\",\n          \"description\": \"Moves the timeline to a frame number or name and stops that timeline.\",\n          \"example\": \"gotoAndStop(2);\\ngotoAndStop('menu');\",\n          \"snippet\": \"gotoAndStop(1)\",\n          \"args\": [\n            {\n              \"name\": \"frame\",\n              \"type\": \"Number\",\n              \"description\": \"frame number or name to jump to\"\n            }\n          ]\n        },\n        {\n          \"name\": \"gotoAndPlay(frame)\",\n          \"description\": \"Moves the timeline to a frame number or name and stops that timeline.\",\n          \"example\": \"gotoAndPlay(2);\\ngotoAndPlay('menu');\",\n          \"snippet\": \"gotoAndPlay(1)\",\n          \"args\": [\n            {\n              \"name\": \"frame\",\n              \"type\": \"Number\",\n              \"description\": \"frame number or name to jump to\"\n            }\n          ]\n        },\n        {\n          \"name\": \"gotoNextFrame()\",\n          \"description\": \"Moves the timeline forward one frame.\",\n          \"example\": \"gotoNextFrame();\",\n          \"snippet\": \"gotoNextFrame()\",\n          \"args\": []\n        },\n        {\n          \"name\": \"gotoPrevFrame()\",\n          \"description\": \"Moves the timeline backwards one frame.\",\n          \"example\": \"gotoPrevFrame();\",\n          \"snippet\": \"gotoPrevFrame()\",\n          \"args\": []\n        }\n      ]\n    },\n    {\n      \"name\": \"Events\",\n      \"properties\": [\n        {\n          \"name\": \"load\",\n          \"description\": \"Gets called as soon as the object appears on screen.\",\n          \"example\": \"// Define some variables and set them on load\\nvar points;\\nvar dead;\\n\\nfunction load() {\\n    points = 0;\\n    dead = false;\\n}\",\n          \"snippet\": \"function load() {\\n    // Do something here!\\n}\\n\",\n          \"return\": null,\n          \"args\": []\n        },\n        {\n          \"name\": \"update\",\n          \"description\": \"Gets called every tick.\",\n          \"example\": \"// This will move the object slowly to the left\\nfunction update() {\\n    this.x --;\\n}\",\n          \"snippet\": \"function update() {\\n    // Do something here!\\n}\\n\",\n          \"return\": null,\n          \"args\": []\n        },\n        {\n          \"name\": \"mousePressed\",\n          \"description\": \"Gets called once when the object is pressed\",\n          \"example\": \"// Delete this object when it's pressed.\\nfunction mousePressed() {\\n    this.delete();\\n}\",\n          \"snippet\": \"function mousePressed() {\\n    // Do something here!\\n}\\n\",\n          \"return\": null,\n          \"args\": []\n        },\n        {\n          \"name\": \"mouseDown\",\n          \"description\": \"Gets called every tick if the mouse is down and hovered over the object.\",\n          \"example\": \"\\nfunction mouseDown() {\\n    this.x = mouseX;\\n    this.y = mouseY\\n}\",\n          \"snippet\": \"function mouseDown() {\\n    // Do something here!\\n}\\n\",\n          \"return\": null,\n          \"args\": []\n        },\n        {\n          \"name\": \"mouseReleased\",\n          \"description\": \"Gets called once when the mouse is released over the object.\",\n          \"example\": \"// Delete this object when it's clicked.\\nfunction mouseReleased() {\\n    this.delete();\\n}\",\n          \"snippet\": \"function mouseReleased() {\\n    // Do something here!\\n}\\n\",\n          \"return\": null,\n          \"args\": []\n        },\n        {\n          \"name\": \"mouseHover\",\n          \"description\": \"Gets called every update when the mouse hovers over the object.\",\n          \"example\": \"// Move this object when the mouse hovers over it\\nfunction mouseHover() {\\n    this.x ++;\\n}\",\n          \"snippet\": \"function mouseHover() {\\n    // Do something here!\\n}\\n\",\n          \"return\": null,\n          \"args\": []\n        },\n        {\n          \"name\": \"mouseEnter\",\n          \"description\": \"Gets called once when the mouse enters the object\",\n          \"example\": \"// Delete the object if the mouse touches it.\\nfunction mouseEnter() {\\n    this.delete();\\n}\",\n          \"snippet\": \"function mouseEnter() {\\n    // Do something here!\\n}\\n\",\n          \"return\": null,\n          \"args\": []\n        },\n        {\n          \"name\": \"mouseLeave\",\n          \"description\": \"Gets called once when the mouse leaves the object\",\n          \"example\": \"// Delete the object if the mouse ever leaves.\\nfunction mouseLeave() {\\n    this.delete();\\n}\",\n          \"snippet\": \"function mouseLeave() {\\n    // Do something here!\\n}\\n\",\n          \"return\": null,\n          \"args\": []\n        },\n        {\n          \"name\": \"keyPressed\",\n          \"description\": \"Gets called once when a key is first pressed.\",\n          \"example\": \"function keyPressed(key) {\\n    if (key == 'UP') {\\n        this.x += 20; //Move 20 pixels to the right\\n    }\\n}\",\n          \"snippet\": \"function keyPressed(key) {\\n    // Do something here!\\n}\\n\",\n          \"return\": null,\n          \"args\": []\n        },\n        {\n          \"name\": \"keyReleased\",\n          \"description\": \"Gets called once when a key is released.\",\n          \"example\": \"function keyReleased(key) {\\n    if (key == 'z') {\\n        //user is no longer pressing z\\n    }\\n}\",\n          \"snippet\": \"function keyReleased(key) {\\n    // Do something here!\\n}\\n\",\n          \"return\": null,\n          \"args\": []\n        },\n        {\n          \"name\": \"keyDown\",\n          \"description\": \"Gets called once every update while a key is down.\",\n          \"example\": \"function keyDown(key) {\\n    if (key == 'UP') {\\n        this.x += 20; //Move 20 pixels to the right\\n    }\\n}\",\n          \"snippet\": \"function keyDown(key) {\\n    // Do something here!\\n}\\n\",\n          \"return\": null,\n          \"args\": []\n        }\n      ]\n    },\n    {\n      \"name\": \"Object\",\n      \"properties\": [\n        {\n          \"name\": \"x\",\n          \"type\": \"Number\",\n          \"description\": \"Refers to the x-location (left-to-right) of the object.\",\n          \"example\": \"this.x += 1; // Moves the object to the right by 1 pixel\",\n          \"snippet\": \"this.x\",\n          \"args\": [],\n          \"return\": null\n        },\n        {\n          \"name\": \"y\",\n          \"type\": \"Number\",\n          \"description\": \"Refers to the y-location (top-to-bottom) of the object. Y values increase as you go down on the canvas.\",\n          \"example\": \"this.y += 1; // Moves the object down by one pixel\",\n          \"snippet\": \"this.y\",\n          \"args\": [],\n          \"return\": null\n        },\n        {\n          \"name\": \"scaleX\",\n          \"type\": \"Number\",\n          \"description\": \"Scales the width of the object. By default scaleX is set to 1.\",\n          \"example\": \"this.scaleX = 2; // Doubles the width of this object.\",\n          \"snippet\": \"this.scaleX\",\n          \"args\": [],\n          \"return\": null\n        },\n        {\n          \"name\": \"scaleY\",\n          \"type\": \"Number\",\n          \"description\": \"Scales the height of the object. By default scaleY is set to 1.\",\n          \"example\": \"this.scaleY = 2; // Doubles the height of this object.\",\n          \"snippet\": \"this.scaleY\",\n          \"args\": [],\n          \"return\": null\n        },\n        {\n          \"name\": \"rotation\",\n          \"type\": \"Number\",\n          \"description\": \"Controls the angle of rotation on the object in degrees.\",\n          \"example\": \"this.rotation += 10; // Rotate this object 10 degrees to the right\",\n          \"snippet\": \"this.rotation\",\n          \"args\": [],\n          \"return\": null\n        },\n        {\n          \"name\": \"flipX\",\n          \"type\": \"Boolean\",\n          \"description\": \"A boolean which determines whether or not to flip the object horizontally. By default flipX is set to false.\",\n          \"example\": \"this.flipX = true; // Flip this object horizontally.\",\n          \"snippet\": \"this.flipX\",\n          \"args\": [],\n          \"return\": null\n        },\n        {\n          \"name\": \"flipY\",\n          \"type\": \"Boolean\",\n          \"description\": \"A boolean which determines whether or not to flip the object vertically. By default flipY is set to false.\",\n          \"example\": \"this.flipY = true; // Flip this object vertically.\",\n          \"snippet\": \"this.flipY\",\n          \"args\": [],\n          \"return\": null\n        },\n        {\n          \"name\": \"opacity\",\n          \"type\": \"Number\",\n          \"description\": \"A value between 0 and 1 which determines how transparent an object is. 1 is completely opaque while 0 is completely transparent. By default opacity is set to 1.\",\n          \"example\": \"this.opacity = 0.8; // Make this object slightly transparent.\",\n          \"snippet\": \"this.opacity\",\n          \"args\": [],\n          \"return\": null\n        },\n        {\n          \"name\": \"name\",\n          \"type\": \"Number\",\n          \"description\": \"The name of the object, can be set in the inspector.\",\n          \"example\": \"console.log('My name is ' + this.name)\",\n          \"snippet\": \"this.name\",\n          \"args\": [],\n          \"return\": null\n        },\n        {\n          \"name\": \"clone()\",\n          \"description\": \"Makes a clone of the WickObject.\",\n          \"example\": \"// Creates a clone of the current wick object and stores it in the variable myClone\\nvar myClone = this.clone();\",\n          \"snippet\": \"var clone = this.clone()\",\n          \"args\": [],\n          \"return\": {\n            \"type\": \"WickObject\",\n            \"description\": \"A clone of the object that called clone().\"\n          }\n        },\n        {\n          \"name\": \"clones\",\n          \"description\": \"An array of all of the clones of the WickObject.\",\n          \"example\": \"// This will delete all of the clones of this Wick Object.\\nfor (var i = 0; i < this.clones.length; i++) {\\n    this.clones[i].delete();\\n}\",\n          \"snippet\": \"for (var i = 0; i < this.clones.length; i++) {\\n    \\n}\",\n          \"args\": [],\n          \"return\": null,\n        },\n        {\n          \"name\": \"delete()\",\n          \"description\": \"Deletes the object completely.\",\n          \"example\": \"this.delete(); // Removes the object from the scene.\",\n          \"snippet\": \"this.delete()\",\n          \"args\": [],\n          \"return\": null\n        },\n        {\n          \"name\": \"hitTest(otherObject)\",\n          \"description\": \"Checks for a collision with another object.\",\n          \"example\": \"// If this object collides with objectTwo delete this object\\nif (this.hitTest(objectTwo)) {\\n    this.delete(); \\n} \",\n          \"snippet\": \"if(this.hitTest(other_object_name)) {\\n    // Do something here!\\n}\",\n          \"args\": [\n            {\n              \"name\": \"otherObject\",\n              \"type\": \"WickObject\",\n              \"description\": \"Wick Object to check for collision with.\"\n            }\n          ],\n          \"return\": {\n            \"type\": \"Boolean\",\n            \"description\": \"True if the objects collide, false otherwise.\"\n          }\n        },\n        /*{\n          \"name\": \"getHitInfo(otherObject)\",\n          \"description\": \"Returns information about a collision between two objects if they are touching.\",\n          \"example\": \"// If there's a collision, move this object so that the objects are no longer touching.\\nvar hitInfo = this.getHitInfo(other_object_name);\\nif (hitInfo.hit) {\\n      this.x -= hitInfo.overlapX\\n      this.y -= hitInfo.overlapY\\n}\",\n          \"snippet\": \"var hitInfo = this.getHitInfo(other_object_name)\",\n          \"args\": [\n            {\n              \"name\": \"otherObject\",\n              \"type\": \"WickObject\",\n              \"description\": \"Wick Object to check for collision with.\"\n            }\n          ],\n          \"return\": {\n            \"type\": \"HitInfo\",\n            \"description\": \"An object holdng the information about the collision.\"\n          }\n        },*/\n        /*{\n          \"name\": \"pointTo(x,y)\",\n          \"description\": \"Rotates this object so that it is facing in the direction of the given point (x,y)\",\n          \"example\": \"// Make this object point towards the mouse\\nthis.pointTo(mouseX, mouseY)\",\n          \"snippet\": \"this.pointTo(x,y)\",\n          \"args\": [\n            {\n              \"name\": \"x\",\n              \"type\": \"Number\",\n              \"description\": \"The x-coordinate of the point to rotate towards.\"\n            },\n            {\n              \"name\": \"y\",\n              \"type\": \"Number\",\n              \"description\": \"The y-coordinate of the point to rotate towards.\"\n            }\n          ],\n          \"return\": null\n        },*/\n        {\n          \"name\": \"play()\",\n          \"description\": \"Plays this objects timeline (only usable for Clips). \",\n          \"example\": \"this.play();\",\n          \"snippet\": \"this.play()\",\n          \"return\": null,\n          \"args\": []\n        },\n        {\n          \"name\": \"stop()\",\n          \"description\": \"Stops this objects timeline (only usable for Clips).\",\n          \"example\": \"this.stop();\",\n          \"snippet\": \"this.stop()\",\n          \"return\": null,\n          \"args\": []\n        },\n        {\n          \"name\": \"gotoAndStop(frame)\",\n          \"description\": \"Moves this objects timeline to a frame number or name and stops that timeline (only usable for Clips).\",\n          \"example\": \"this.gotoAndStop(2);\\nthis.gotoAndStop('menu');\",\n          \"snippet\": \"this.gotoAndStop(1)\",\n          \"args\": [\n            {\n              \"name\": \"frame\",\n              \"type\": \"Number\",\n              \"description\": \"frame number or name to jump to\"\n            }\n          ]\n        },\n        {\n          \"name\": \"gotoAndPlay(frame)\",\n          \"description\": \"Moves the object's timeline to a frame number or name and stops the object's timeline (only usable for Clips).\",\n          \"example\": \"this.gotoAndPlay(2);\\nthis.gotoAndPlay('menu');\",\n          \"snippet\": \"this.gotoAndPlay(1)\",\n          \"args\": [\n            {\n              \"name\": \"frame\",\n              \"type\": \"Number\",\n              \"description\": \"frame number or name to jump to\"\n            }\n          ]\n        },\n        {\n          \"name\": \"currentFrameNumber\",\n          \"description\": \"The position of the playhead of the object (only works on Clips).\",\n          \"example\": \"if(this.currentFrameNumber === 10) {\\n    alert('On frame 10!')\\n}\",\n          \"snippet\": \"this.currentFrameNumber\",\n          \"args\": [],\n          \"return\": null\n        },\n        {\n          \"name\": \"currentFrameName\",\n          \"description\": \"The name of the current frame of the object (only works on Clips).\",\n          \"example\": \"if(this.currentFrameName === 'walking') {\\n    alert('On walking frame!')\\n}\",\n          \"snippet\": \"this.currentFrameName\",\n          \"args\": [],\n          \"return\": null\n        },\n        { \"name\": \"setText(text)\",\n          \"description\": \"Changes the text of a text object.\",\n          \"example\": \"//Update with mouse position\\nfunction update () {\\n this.setText('mouseX:' + mouseX);\\n}\",\n          \"snippet\": \"this.setText('update text here')\",\n          \"args\": [\n            {\n              \"name\": \"text\",\n              \"type\": \"String\",\n              \"description\": \"The string to update the textbox with.\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"name\": \"Project\",\n      \"properties\": [\n        {\n          \"name\": \"project.getObject(name)\",\n          \"description\": \"Returns the object with the requested name.\",\n          \"example\": \"// Returns the object named 'The Bee'\\nproject.getObject('The Bee')\",\n          \"snippet\": \"project.getObject(object_name)\",\n          \"args\": [],\n          \"return\": {\n            \"type\": \"WickObject\",\n            \"description\": \"The object with the requested name.\"\n          }\n        },\n        {\n          \"name\": \"project.width\",\n          \"description\": \"The width of the project\",\n          \"example\": \"project.width\",\n          \"snippet\": \"project.width\",\n          \"args\": [],\n          \"return\": null\n        },\n        {\n          \"name\": \"project.height\",\n          \"description\": \"The height of the project\",\n          \"example\": \"project.height\",\n          \"snippet\": \"project.height\",\n          \"args\": [],\n          \"return\": null\n        }\n      ]\n    },\n    {\n      \"name\": \"Sounds\",\n      \"properties\": [\n        {\n          \"name\": \"playSound(filename)\",\n          \"description\": \"Plays the sound in the asset library with the specified filename.\",\n          \"example\": \"playSound('something.mp3');\",\n          \"snippet\": \"playSound('something.mp3');\",\n          \"args\": [\n            {\n              \"name\": \"filename\",\n              \"type\": \"String\",\n              \"description\": \"The filename of the sound to play.\"\n            }\n          ],\n          \"return\": null\n        },\n        {\n          \"name\": \"stopAllSounds()\",\n          \"description\": \"Stops any sounds currently being played.\",\n          \"example\": \"stopAllSounds();\",\n          \"snippet\": \"stopAllSounds()\",\n          \"args\": [],\n          \"return\": null\n        },\n        {\n          \"name\": \"mute()\",\n          \"description\": \"Mutes the entire project (no sounds will play).\",\n          \"example\": \"mute();\",\n          \"snippet\": \"mute()\",\n          \"args\": [],\n          \"return\": null\n        },\n        {\n          \"name\": \"unmute()\",\n          \"description\": \"Unmutes the enite project (sounds will play again).\",\n          \"example\": \"unmute();\",\n          \"snippet\": \"unmute()\",\n          \"args\": [],\n          \"return\": null\n        }\n      ]\n    },\n    {\n      \"name\": \"Input\",\n      \"properties\": [\n        {\n          \"name\": \"mouseX\",\n          \"description\": \"The x-location of the mouse on the project canvas. The origin (0,0) is the upper-left corner of the canvas.\",\n          \"example\": \"// Sets the object's x-position to the mouse's x-position.\\nthis.x = mouseX\",\n          \"snippet\": \"mouseX\",\n          \"args\": [],\n          \"return\": null\n        },\n        {\n          \"name\": \"mouseY\",\n          \"description\": \"The y-location of the mouse on the project canvas. The origin (0,0) is the upper-left corner of the canvas.\",\n          \"example\": \"// Sets the object's y-position to the mouse's y-position.\\nthis.y = mouseY\",\n          \"snippet\": \"mouseY\",\n          \"args\": [],\n          \"return\": null\n        },\n        {\n          \"name\": \"mouseMoveX\",\n          \"description\": \"The amount the mouse moved on the x-axis during the last tick.\",\n          \"example\": \"// Make a clone that follows you around!\\n// Add this to a picture or circle! \\nvar clone = this.clone();\\nfunction update () {\\n    this.x = mouseX;\\n    this.y = mouseY;\\n    clone.x = this.x - mouseMoveX;\\n    clone.y = this.y - mouseMoveY;\\n}\",\n          \"snippet\": \"mouseMoveX\",\n          \"args\": [],\n          \"return\": null\n        },\n        {\n          \"name\": \"mouseMoveY\",\n          \"description\": \"The amount the mouse moved on the y-axis during the last tick.\",\n          \"example\": \"// Make a clone that follows you around!\\n// Add this to a picture or circle! \\nvar clone = this.clone();\\nfunction update () {\\n    this.x = mouseX;\\n    this.y = mouseY;\\n    clone.x = this.x - mouseMoveX;\\n    clone.y = this.y - mouseMoveY;\\n}\",\n          \"snippet\": \"mouseMoveY\",\n          \"args\": [],\n          \"return\": null\n        },\n        {\n          \"name\": \"keyIsDown(key)\",\n          \"description\": \"Returns true if 'key' is currently down and false otherwise. Casing does not matter i.e. keyIsDown('a') is equivalent to keyIsDown('A').\",\n          \"example\": \"// If SPACE is pressed, move this object right by 10 pixels\\nif (keyIsDown('SPACE')) { \\n    this.x += 10;\\n}\",\n          \"snippet\": \"if(keyIsDown(key)) {\\n    // Do something here!\\n}\\n\",\n          \"args\": [\n            {\n              \"name\": \"key\",\n              \"type\": \"String\",\n              \"description\": \"Any character such as 'A' or special characters including 'SPACE', 'UP', 'DOWN', 'LEFT', 'RIGHT', 'BACKSPACE', 'TAB', 'ENTER', 'SHIFT', 'CTRL', 'COMMAND', 'ALT', 'WINDOWS', 'F1', 'NUM 0', 'NUM LOCK'\"\n            }\n          ],\n          \"return\": {\n            \"type\": \"Boolean\",\n            \"description\": \"true if key is down, false otherwise.\"\n          }\n        },\n        {\n          \"name\": \"keyJustPressed(key)\",\n          \"description\": \"Returns true if 'key' was just pressed and false otherwise. Casing does not matter i.e. keyJustPressed('a') is equivalent to keyJustPressed('A').\",\n          \"example\": \"// If SPACE is pressed, move this object right by 10 pixels\\nif (keyJustPressed('SPACE')) { \\n    this.x += 10;\\n}\",\n          \"snippet\": \"if(keyJustPressed(key)) {\\n    // Do something here!\\n}\\n\",\n          \"args\": [\n            {\n              \"name\": \"key\",\n              \"type\": \"String\",\n              \"description\": \"Any character such as 'A' or special characters including 'SPACE', 'UP', 'DOWN', 'LEFT', 'RIGHT', 'BACKSPACE', 'TAB', 'ENTER', 'SHIFT', 'CTRL', 'COMMAND', 'ALT', 'WINDOWS', 'F1', 'NUM 0', 'NUM LOCK'\"\n            }\n          ],\n          \"return\": {\n            \"type\": \"Boolean\",\n            \"description\": \"true if key was just pressed, false otherwise.\"\n          }\n        },\n        {\n          \"name\": \"hideCursor()\",\n          \"description\": \"Makes the cursor invisible.\",\n          \"example\": \"hideCursor();\",\n          \"snippet\": \"hideCursor()\",\n          \"args\": [],\n          \"return\": null\n        },\n        {\n          \"name\": \"showCursor()\",\n          \"description\": \"Makes the cursor visible.\",\n          \"example\": \"showCursor();\",\n          \"snippet\": \"showCursor()\",\n          \"args\": [],\n          \"return\": null\n        }\n      ]\n    },\n    /*{\n      \"name\": \"Camera\",\n      \"properties\": [\n        {\n          \"name\": \"camera.setPosition(x,y)\",\n          \"description\": \"Moves the camera to the given x-y coordinates.\",\n          \"example\": \"camera.setPosition(0,0)\",\n          \"snippet\": \"camera.setPosition(0,0)\",\n          \"return\": null,\n          \"args\": [{\n              \"name\": \"x\",\n              \"type\": \"Number\",\n              \"description\": \"The x coordinate to move the camera to.\"\n            }, {\n              \"name\": \"y\",\n              \"type\": \"Number\",\n              \"description\": \"The y coordinate to move the camera to.\"\n            }]\n        },\n        {\n          \"name\": \"camera.followObject(wickObject, smoothness)\",\n          \"description\": \"Makes the camera follow the wickObject that is passed in.\",\n          \"example\": \"// Follow this object nice and smoothly.\\ncamera.followObject(wickObject, 0.1)\",\n          \"snippet\": \"camera.followObject(wickObject, 0.1)\",\n          \"return\": null,\n          \"args\": [{\n              \"name\": \"wickObject\",\n              \"type\": \"WickObject\",\n              \"description\": \"The WickObject to follow.\"\n            }, {\n              \"name\": \"smoothness\",\n              \"type\": \"Number\",\n              \"description\": \"How smoothly the camera should follow the object. The less this value is, the longer it will take the camera to catch up with the object.\"\n            }]\n        }\n      ]\n    },*/\n    /*{\n      \"name\": \"Scope\",\n      \"properties\": [\n        {\n          \"name\": \"this\",\n          \"description\": \"When used inside of a script, ‘this’ refers to the symbol the script belongs to.\",\n          \"example\": \"// Move the symbol which ran this script to the right by one pixel\\nthis.x += 1;\",\n          \"snippet\": \"this\",\n          \"args\": [],\n          \"return\": null\n        },\n        {\n          \"name\": \"root\",\n          \"description\": \"Refers to the 'root' object. The root object contains all other objects. The root object has no parent and holds the 'root' timeline which controls the main information being shown. The keyword root can be used in any script.\",\n          \"example\": \"// Moves the playhead on the root timeline to frame 2 and stops the root timeline\\nroot.gotoAndStop(2);\",\n          \"snippet\": \"root\",\n          \"args\": [],\n          \"return\": null\n        },\n        {\n          \"name\": \"parentObject\",\n          \"description\": \"Refers to the parent of the object. 'parent' can be used to access the parent object's timeline, or other objects contained within the parent.\",\n          \"example\": \"// Moves the playhead on the parent obect's timeline to frame 2 and plays that timeline\\nparent.gotoAndPlay(2);\",\n          \"snippet\": \"parentObject\",\n          \"args\": [],\n          \"return\": null\n        }\n      ]\n    },*/\n    {\n      \"name\": \"Utilities\",\n      \"properties\": [\n        {\n          \"name\": \"saveData(key,data)\",\n          \"description\": \"Saves data that persists between sessions.\",\n          \"example\": \"// Save what frame the project was at.\\nsaveData('frame', root.currentFrameNumber);\",\n          \"snippet\": \"saveData('name', data)\",\n          \"return\": null,\n          \"args\": [\n            {\n              \"name\": \"key\",\n              \"type\": \"String\",\n              \"description\": \"The name that can be used to load the data later.\"\n            }, {\n              \"name\": \"data\",\n              \"type\": \"Number, String, or Object\",\n              \"description\": \"The data to save\"\n            }\n          ]\n        }, {\n          \"name\": \"loadData(key)\",\n          \"description\": \"Loads data that was saved from a previous session.\",\n          \"example\": \"// Go to the frame where the project was last time it was run.\\nvar frameNumber = loadData('frame');\\ngotoAndStop(frameNumber);\",\n          \"snippet\": \"var data = loadData('name')\",\n          \"return\": null,\n          \"args\": [\n            {\n              \"name\": \"key\",\n              \"type\": \"String\",\n              \"description\": \"The name of the data you wish to load.\"\n            }\n          ]\n        },\n        {\n          \"name\": \"randomBool()\",\n          \"description\": \"Generates a random boolean (true or false).\",\n          \"example\": \"// Use randomBool to simulate a coin flip.\\nvar coinFlip = randomBool();\\nif(coinFlip == true) {\\n    alert('You&#8217;re lucky!!');\\n}\",\n          \"snippet\": \"var randombool = randomBool()\",\n          \"return\": {\n            \"type\": \"Boolean\",\n            \"description\": \"A random boolean. Will be true 50% of the time, and false 50% of the time.\"\n          },\n          \"args\": []\n        }, {\n          \"name\": \"randomInt(min,max)\",\n          \"description\": \"Generates a random whole number between min and max.\",\n          \"example\": \"// Use randomInt to move to a random frame from 1-10.\\nvar randomFrame = randomInt(1,10);\\ngotoAndStop(randomFrame);\",\n          \"snippet\": \"var randomint = randomInt(min, max)\",\n          \"return\": {\n            \"type\": \"Number\",\n            \"description\": \"A random integer (whole number).\"\n          },\n          \"args\": [\n            {\n              \"name\": \"min\",\n              \"type\": \"Number\",\n              \"description\": \"The generated number will be greater than or equal to min\"\n            }, {\n              \"name\": \"max\",\n              \"type\": \"Number\",\n              \"description\": \"The generated number will be less than or equal to max\"\n            }\n           ]\n        }, {\n          \"name\": \"randomFloat(min,max)\",\n          \"description\": \"Generates a random float between min and max.\",\n          \"example\": \"// Use randomFloat to choose how transparent an object appears.\\nthis.opacity = randomFloat(0,1);\",\n          \"snippet\": \"var randomfloat = randomFloat(min, max)\",\n          \"return\": {\n            \"type\": \"Number\",\n            \"description\": \"A random float (rational number).\"\n          },\n          \"args\": [\n            {\n              \"name\": \"min\",\n              \"type\": \"Number\",\n              \"description\": \"The generated number will be greater than or equal to min\"\n            }, {\n              \"name\": \"max\",\n              \"type\": \"Number\",\n              \"description\": \"The generated number will be less than or equal to max\"\n            }\n          ]\n        }\n      ]\n    },\n  ];\n  \n\n"
  },
  {
    "path": "src/project/WickFrame.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar WickFrame = function () {\n    // Identifier so we can do e.g. movePlayheadTo(\"menu\") \n    this.name = \"New Frame\";\n\n    // Store all objects in frame. \n    this.wickObjects = [];\n\n    this.tweens = [];\n\n    // All path data of the frame (Stored as SVG)\n    this.pathData = null;\n\n    // Where this frame exists on the timeline\n    this.playheadPosition = null;\n\n    // Frame length for long frames\n    this.length = 1;\n\n    // Should the frame reset on being entered?\n    this.alwaysSaveState = false;\n\n    // Generate unique id\n    this.uuid = random.uuid4();\n\n    // The layer that this frame belongs to\n    this.parentLayer = null;\n\n    // Set script to default\n    this.wickScript = \"\";\n\n    this.audioAssetUUID = null;\n};\n    \nWickFrame.prototype.tick = function () {\n    var self = this;\n    \n    // Inactive -> Inactive\n    // Do nothing, frame is still inactive\n    if (!this._wasActiveLastTick && !this._active) {\n\n    }\n    // Inactive -> Active\n    // Frame just became active! It's fresh!\n    else if (!this._wasActiveLastTick && this._active) {\n        if(this.hasScript()) {\n            (wickPlayer || wickEditor).project.initScript(this);\n            \n            (wickPlayer || wickEditor).project.runScript(this, 'load');\n            (wickPlayer || wickEditor).project.runScript(this, 'update');\n        }\n\n        if(this.hasSound()) {\n            this._wantsToPlaySound = true;\n        }\n    }\n    // Active -> Active\n    // Frame is still active!\n    else if (this._wasActiveLastTick && this._active) {\n        if(this.hasScript()) {\n            (wickPlayer || wickEditor).project.runScript(this, 'update');\n        }\n    }    \n    // Active -> Inactive\n    // Frame just stopped being active. Clean up!\n    else if (this._wasActiveLastTick && !this._active) {\n        if(this.hasSound()) {\n            this._wantsToStopSound = true;\n        }\n    }\n\n    if(this.hasScript()) {\n        if(this._wasClicked) {\n            (wickPlayer || wickEditor).project.runScript(this, 'mousePressed');\n            this._wasClicked = false;\n        }\n\n        if(this._beingClicked) {\n            (wickPlayer || wickEditor).project.runScript(this, 'mouseDown');\n        }\n\n        if(this._wasHoveredOver) {\n            (wickPlayer || wickEditor).project.runScript(this, 'mouseHover');\n            this._wasHoveredOver = false;\n        }\n\n        if(this._mouseJustLeft) {\n            (wickPlayer || wickEditor).project.runScript(this, 'mouseLeave');\n            this._mouseJustLeft = false;\n        }\n\n        if(this._wasClickedOff) {\n            (wickPlayer || wickEditor).project.runScript(this, 'mouseReleased');\n            this._wasClickedOff = false;\n        }\n\n        wickPlayer.inputHandler.getAllKeysJustReleased().forEach(function (key) {\n            (wickPlayer || wickEditor).project.runScript(self, 'keyReleased', key);\n        });\n\n        wickPlayer.inputHandler.getAllKeysJustPressed().forEach(function (key) {\n            (wickPlayer || wickEditor).project.runScript(self, 'keyPressed', key);\n        });\n\n        wickPlayer.inputHandler.getAllKeysDown().forEach(function (key) {\n            (wickPlayer || wickEditor).project.runScript(self, 'keyDown', key);\n        });\n    }\n\n    this.wickObjects.forEach(function (wickObject) {\n        wickObject.tick();\n    });\n}\n\nWickFrame.prototype.isActive = function () {\n    var parent = this.parentLayer.parentWickObject;\n\n    //if(parent.isRoot) console.log(parent.playheadPosition)\n\n    /*console.log(\"---\")\n    console.log(\"ph \"+(parent.playheadPosition))\n    console.log(\"s  \"+(this.playheadPosition))\n    console.log(\"e  \"+(this.playheadPosition+this.length))\n    console.log(\"---\")*/\n\n    return parent.playheadPosition >= this.playheadPosition\n        && parent.playheadPosition < this.playheadPosition+this.length\n        && parent.isActive();\n}\n\nWickFrame.prototype.hasScript = function () {\n    return this.wickScript !== \"\";\n}\n\n// Extend our frame to encompass more frames. \nWickFrame.prototype.extend = function(length) {\n    this.length += length; \n}\n\n// Reduce the number of frames this WickFrame Occupies. \nWickFrame.prototype.shrink = function(length) {\n    // Never \"shrink\" by a negative amount. \n    if (length <= 0) {\n        return;\n    }\n\n    originalLength = this.length; \n    this.length -= length; \n\n    // determine and return the actual change in frames. \n    if (this.length <= 0) {\n        this.length = 1;\n        return originalLength - 1;\n    } else {\n        return length; \n    }\n}\n\nWickFrame.prototype.copy = function () {\n\n    var copiedFrame = new WickFrame();\n\n    copiedFrame.name = this.name;\n    copiedFrame.playheadPosition = this.playheadPosition;\n    copiedFrame.length = this.length;\n    copiedFrame.wickScript = this.wickScript;\n    copiedFrame.uuid = random.uuid4();\n    copiedFrame.sourceUUID = this.uuid;\n\n    this.wickObjects.forEach(function (wickObject) {\n        copiedFrame.wickObjects.push(wickObject.copy());\n    })\n\n    this.tweens.forEach(function (tween) {\n        copiedFrame.tweens.push(tween.copy());\n    })\n\n    return copiedFrame;\n\n}\n\nWickFrame.prototype.remove = function () {\n    this.parentLayer.removeFrame(this);\n}\n\nWickFrame.prototype.getFramesDistance = function (frame) {\n    var A = this;\n    var B = frame;\n\n    if(A._beingMoved || B._beingMoved) return false;\n\n    var AStart = A.playheadPosition;\n    var AEnd = A.playheadPosition + A.length;\n\n    var BStart = B.playheadPosition;\n    var BEnd = B.playheadPosition + B.length;\n\n    var distA = BStart-AEnd;\n    var distB = BEnd-AStart;\n\n    return {\n        distA: distA,\n        distB: distB\n    };\n}\n\nWickFrame.prototype.touchesFrame = function (frame) {\n    var framesDist = this.getFramesDistance(frame);\n    return framesDist.distA < 0 && framesDist.distB > 0;\n}\n\nWickFrame.prototype.encodeStrings = function () {\n\n    if(this.wickScripts) {\n        for (var key in this.wickScripts) {\n            this.wickScripts[key] = WickProject.Compressor.encodeString(this.wickScripts[key]);\n        }\n    }\n    if(this.wickScript) {\n        this.wickScript = WickProject.Compressor.encodeString(this.wickScript);\n    }\n\n    if(this.pathData) this.pathData = WickProject.Compressor.encodeString(this.pathData);\n\n}\n\nWickFrame.prototype.decodeStrings = function () {\n\n    if(this.wickScripts) {\n        for (var key in this.wickScripts) {\n            this.wickScripts[key] = WickProject.Compressor.decodeString(this.wickScripts[key]);\n        }\n    }\n    if(this.wickScript) {\n        this.wickScript = WickProject.Compressor.decodeString(this.wickScript);\n    }\n\n    if(this.pathData) this.pathData = WickProject.Compressor.decodeString(this.pathData);\n\n}\n\nWickFrame.prototype.getFrameEnd = function () {\n    return this.playheadPosition + this.length; \n}\n\nWickFrame.prototype.getObjectByUUID = function () {\n\n    var foundWickObject;\n\n    this.wickObjects.forEach(function (wickObject) {\n        if(wickObject.uuid === uuid) {\n            foundWickObject = wickObject;\n        }\n    });\n\n    return foundWickObject;\n\n}\n\nWickFrame.prototype.getAsJSON = function () {\n    this.wickObjects.forEach(function (wickObject) {\n        wickObject.encodeStrings();\n    });\n\n    var frameJSON = JSON.stringify(this, WickProject.Exporter.JSONReplacerObject);\n\n    this.wickObjects.forEach(function (wickObject) {\n        wickObject.decodeStrings();\n    });\n\n    return frameJSON;\n}\n\nWickFrame.fromJSON = function (frameJSON) {\n    var frame = JSON.parse(frameJSON);\n    frame.__proto__ = WickFrame.prototype;\n    if(frame.tweens) {\n        frame.tweens.forEach(function (tween) {\n            tween.__proto__ = WickTween.prototype;\n        });\n    }\n    frame.uuid = random.uuid4();\n    frame.wickObjects.forEach(function (wickObject) {\n        WickObject.addPrototypes(wickObject);\n        wickObject.generateParentObjectReferences();\n        wickObject.decodeStrings();\n        wickObject.uuid = random.uuid4();\n    })\n    return frame;\n}\n\nWickFrame.fromJSONArray = function (jsonArrayObject) {\n    var frames = [];\n\n    var framesJSONArray = jsonArrayObject.wickObjectArray;\n    framesJSONArray.forEach(function (frameJSON) {\n        var newframe = WickFrame.fromJSON(frameJSON)\n        frames.push(newframe)\n    });\n\n    return frames;\n}\n\nWickFrame.prototype.getNextOpenPlayheadPosition = function () {\n    return this.parentLayer.getNextOpenPlayheadPosition(this.playheadPosition);\n}\n\nWickFrame.prototype.addTween = function (newTween) {\n    var self = this;\n\n    var replacedTween = false;\n    self.tweens.forEach(function (tween) {\n        if (tween.playheadPosition === newTween.playheadPosition) {\n            self.tweens[self.tweens.indexOf(tween)] = newTween;\n            replacedTween = true;\n        }\n    });\n\n    if(!replacedTween)\n        self.tweens.push(newTween);\n}\n\nWickFrame.prototype.removeTween = function (tweenToDelete) {\n    var self = this;\n\n    var deleteTweenIndex = null;\n    self.tweens.forEach(function (tween) {\n        if(deleteTweenIndex) return;\n        if (tweenToDelete === tween) {\n            deleteTweenIndex = self.tweens.indexOf(tween);\n        }\n    });\n\n    if(deleteTweenIndex !== null) {\n        self.tweens.splice(deleteTweenIndex, 1);\n    }\n}\n\nWickFrame.prototype.getCurrentTween = function () {\n    return this.getTweenAtFrame(this.parentObject.playheadPosition-this.playheadPosition)\n}\n\nWickFrame.prototype.getTweenAtPlayheadPosition = function (playheadPosition) {\n    var foundTween;\n    this.tweens.forEach(function (tween) {\n        if(foundTween) return;\n        if(tween.playheadPosition === playheadPosition) foundTween = tween;\n    })\n    return foundTween;\n}\n\nWickFrame.prototype.hasTweenAtFrame = function () {\n    var playheadPosition = this.parentObject.playheadPosition-this.playheadPosition;\n\n    var foundTween = false\n    this.tweens.forEach(function (tween) {\n        if(foundTween) return;\n        if(tween.playheadPosition === playheadPosition) foundTween = true;\n    })\n    return foundTween;\n}\n\nWickFrame.prototype.getTweenAtFrame = function (playheadPosition) {\n    var playheadPosition = this.parentObject.playheadPosition-this.playheadPosition;\n    \n    var foundTween;\n    this.tweens.forEach(function (tween) {\n        if(foundTween) return;\n        if(tween.playheadPosition === playheadPosition) foundTween = tween;\n    })\n    return foundTween;\n}\n\nWickFrame.prototype.getFromTween = function () {\n    var foundTween = null;\n\n    var relativePlayheadPosition = this.parentObject.playheadPosition-this.playheadPosition;\n\n    var seekPlayheadPosition = relativePlayheadPosition;\n    while (!foundTween && seekPlayheadPosition >= 0) {\n        this.tweens.forEach(function (tween) {\n            if(tween.playheadPosition === seekPlayheadPosition) {\n                foundTween = tween;\n            }\n        });\n        seekPlayheadPosition--;\n    }\n\n    return foundTween;\n}\n\nWickFrame.prototype.getToTween = function () {\n    var foundTween = null;\n\n    var relativePlayheadPosition = this.parentObject.playheadPosition-this.playheadPosition;\n\n    var seekPlayheadPosition = relativePlayheadPosition;\n    var parentFrameLength = this.length;\n    while (!foundTween && seekPlayheadPosition < parentFrameLength) {\n        this.tweens.forEach(function (tween) {\n            if(tween.playheadPosition === seekPlayheadPosition) {\n                foundTween = tween;\n            }\n        });\n        seekPlayheadPosition++;\n    }\n\n    return foundTween;\n}\n\nWickFrame.prototype.applyTween = function () {\n\n    var self = this;\n\n    var tweenToApply;\n\n    if(self.tweens.length === 1) {\n        tweenToApply = self.tweens[0];\n    } else if (self.tweens.length > 1) {\n        var tweenFrom = self.getFromTween();\n        var tweenTo = self.getToTween();\n\n        if (tweenFrom && tweenTo) {\n            var A = tweenFrom.playheadPosition;\n            var B = tweenTo.playheadPosition;\n            var L = B-A;\n            var P = (this.parentObject.playheadPosition-this.playheadPosition)-A;\n            var T = P/L;\n            if(B-A === 0) T = 1;\n            \n            tweenToApply = WickTween.interpolateTweens(tweenFrom, tweenTo, T);\n        }\n        if (!tweenFrom && tweenTo) {\n            tweenToApply = tweenTo;\n        }\n        if (!tweenTo && tweenFrom) {\n            tweenToApply = tweenFrom;\n        }\n    }\n\n    if(!tweenToApply) return;\n    self.wickObjects.forEach(function (wickObject) {\n        tweenToApply.applyTweenToWickObject(wickObject);\n    });\n\n}\n\nWickFrame.prototype.hasSound = function () {\n    return this.audioAssetUUID;\n}\n"
  },
  {
    "path": "src/project/WickLayer.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar WickLayer = function () {\n    this.frames = [new WickFrame()];\n    this.frames[0].playheadPosition = 0;\n\n    this.identifier = \"Layer 1\"\n    this.locked = false;\n    this.hidden = false;\n\n    this.parentWickObject = null; // The WickObject that this layer belongs to\n};\n\nWickLayer.prototype.getTotalLength = function () {\n    var length = 0;\n\n    this.frames.forEach(function (frame) {\n        var frameEnd = frame.playheadPosition + frame.length;\n        if(frameEnd > length) length = frameEnd;\n    });\n\n    return length;\n}\n\nWickLayer.prototype.getFrameAtPlayheadPosition = function (playheadPosition) {\n    var foundFrame = null;\n\n    this.frames.forEach(function (frame) {\n        if(foundFrame) return;\n        if(playheadPosition >= frame.playheadPosition && playheadPosition < frame.playheadPosition+frame.length) {\n            foundFrame = frame;\n        }\n    });\n\n    return foundFrame;\n}\n\nWickLayer.prototype.getCurrentFrame = function () {\n    return this.getFrameAtPlayheadPosition(this.parentWickObject.playheadPosition);\n}\n\n\nWickLayer.prototype.addFrame = function(newFrame) {\n    this.frames.push(newFrame);\n}\n\nWickLayer.prototype.removeFrame = function(frame) {\n    var i = this.frames.indexOf(frame);\n    this.frames.splice(i, 1);\n}\n\nWickLayer.prototype.copy = function () {\n\n    var copiedLayer = new WickLayer();\n    copiedLayer.frames = [];\n\n    this.frames.forEach(function (frame) {\n        copiedLayer.frames.push(frame.copy());\n    })\n\n    return copiedLayer;\n\n}\n\nWickLayer.prototype.getFrameByIdentifier = function (id) {\n\n    var foundFrame = null;\n\n    this.frames.forEach(function (frame) {\n        if(frame.identifier === id) {\n            foundFrame = frame;\n        }\n    });\n\n    return foundFrame;\n\n}\n\nWickLayer.prototype.getRelativePlayheadPosition = function (wickObj, args) {\n\n    var playheadRelativePosition = this.playheadPosition - wickObj.parentFrame.playheadPosition;\n\n    if(args && args.normalized) playheadRelativePosition /= wickObj.parentFrame.length-1;\n\n    return playheadRelativePosition;\n\n}\n\nWickLayer.prototype.getFramesAtPlayheadPosition = function(pos, args) {\n    var frames = [];\n\n    var counter = 0;\n    for(var f = 0; f < this.frames.length; f++) {\n        var frame = this.frames[f];\n        for(var i = 0; i < frame.length; i++) {\n            if(counter == pos) {\n                frames.push(frame);\n            }\n            counter++;\n        }\n    }\n\n    return frames;\n}\n\nWickLayer.prototype.getNextOpenPlayheadPosition = function (startPosition) {\n    var targetPosition = startPosition;\n\n    while(this.getFrameAtPlayheadPosition(targetPosition)) {\n        targetPosition ++;\n    }\n\n    return targetPosition;\n}\n\nWickLayer.prototype.getLastFrame = function (playheadPosition) {\n    var lastFrame = null;\n\n    if(!playheadPosition) playheadPosition = 0;\n\n    // Look backwards\n    this.frames.forEach(function (frame) {\n        if(!lastFrame) lastFrame = frame;\n        if(frame.playheadPosition > lastFrame.playheadPosition && frame.playheadPosition < playheadPosition) {\n            lastFrame = frame;\n        }\n    });\n\n    if(lastFrame.playheadPosition > playheadPosition) return null;\n\n    return lastFrame;\n}\n\nWickLayer.prototype.containsWickObject = function (o) {\n    \n}\n"
  },
  {
    "path": "src/project/WickObject.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar WickObject = function () {\n\n    this.uuid = random.uuid4();\n    this.name = undefined;\n    this.x = 0;\n    this.y = 0;\n    this.width = undefined;\n    this.height = undefined;\n    this.scaleX = 1;\n    this.scaleY = 1;\n    this.rotation = 0;\n    this.flipX = false;\n    this.flipY = false;\n    this.opacity = 1;\n    this.wickScript = \"\";\n    this.assetUUID = null;\n    this.loop = false;\n    this.isText = false;\n    this.isImage = false;\n    this.isSymbol = false;\n    this.isButton = false;\n    this.isGroup = false;\n    this.playheadPosition = null;\n    this.currentLayer = null;\n    this.layers = undefined;\n\n    this._renderDirty = false;  // Tell the renderer if this object has changed. \n\n};\n\nWickObject.fromJSON = function (jsonString) {\n    // Parse JSON\n    var newWickObject = JSON.parse(jsonString);\n\n    // Put prototypes back on object ('class methods'), they don't get JSONified on project export.\n    WickObject.addPrototypes(newWickObject);\n\n    // Decode scripts back to human-readble and eval()-able format\n    newWickObject.decodeStrings();\n\n    return newWickObject;\n}\n\nWickObject.fromJSONArray = function (jsonArrayObject) {\n    var newWickObjects = [];\n\n    var wickObjectJSONArray = jsonArrayObject.wickObjectArray;\n    for (var i = 0; i < wickObjectJSONArray.length; i++) {\n        \n        var newWickObject = WickObject.fromJSON(wickObjectJSONArray[i]);\n        \n        if(wickObjectJSONArray.length > 1) {\n            newWickObject.x += jsonArrayObject.groupPosition.x;\n            newWickObject.y += jsonArrayObject.groupPosition.y;\n        }\n\n        newWickObjects.push(newWickObject);\n    }\n\n    return newWickObjects;\n}\n\nWickObject.createPathObject = function (svg) {\n    var obj = new WickObject();\n    obj.isPath = true;\n    obj.pathData = svg;\n\n    return obj;\n}\n\nWickObject.createTextObject = function (text) {\n    var obj = new WickObject();\n\n    obj.isText = true;\n    obj.width = 400;\n    obj.textData = {\n        fontFamily: 'Arial',\n        fontSize: 40,\n        fontStyle: 'normal',\n        fontWeight: 'normal',\n        lineHeight: 1.0,\n        fill: '#000000',\n        textAlign: 'left',\n        text: text\n    };\n\n    return obj;\n}\n\nWickObject.createNewSymbol = function (name) {\n\n    var symbol = new WickObject();\n\n    symbol.isSymbol = true;\n    symbol.playheadPosition = 0;\n    symbol.currentLayer = 0;\n    symbol.layers = [new WickLayer()];\n    symbol.name = name;\n\n    return symbol;\n\n}\n\n// Create a new symbol and add every object in wickObjects as children\nWickObject.createSymbolFromWickObjects = function (wickObjects) {\n\n    var symbol = WickObject.createNewSymbol();\n\n    // Calculate center of all WickObjects\n    var topLeft = {x:Number.MAX_SAFE_INTEGER, y:Number.MAX_SAFE_INTEGER};\n    var bottomRight = {x:-Number.MAX_SAFE_INTEGER,y:-Number.MAX_SAFE_INTEGER};\n    wickObjects.forEach(function (wickObj) {\n        topLeft.x = Math.min(topLeft.x, wickObj.x - wickObj.width /2);\n        topLeft.y = Math.min(topLeft.y, wickObj.y - wickObj.height/2);\n        bottomRight.x = Math.max(bottomRight.x, wickObj.x + wickObj.width /2);\n        bottomRight.y = Math.max(bottomRight.y, wickObj.y + wickObj.height/2);\n    });\n\n    var center = {\n        x: topLeft.x + (bottomRight.x - topLeft.x)/2,\n        y: topLeft.y + (bottomRight.y - topLeft.y)/2\n    }\n    symbol.x = center.x;\n    symbol.y = center.y;\n\n    var firstFrame = symbol.layers[0].frames[0];\n    for(var i = 0; i < wickObjects.length; i++) {\n        firstFrame.wickObjects[i] = wickObjects[i];\n\n        firstFrame.wickObjects[i].x = wickObjects[i].x - symbol.x;\n        firstFrame.wickObjects[i].y = wickObjects[i].y - symbol.y;\n    }\n\n    symbol.width  = firstFrame.wickObjects[0].width;\n    symbol.height = firstFrame.wickObjects[0].height;\n\n    return symbol;\n\n}\n\nWickObject.prototype.copy = function () {\n\n    var copiedObject = new WickObject();\n\n    copiedObject.name = this.name;\n    copiedObject.x = this.x;\n    copiedObject.y = this.y;\n    copiedObject.width = this.width;\n    copiedObject.height = this.height;\n    copiedObject.scaleX = this.scaleX;\n    copiedObject.scaleY = this.scaleY;\n    copiedObject.rotation = this.rotation;\n    copiedObject.flipX = this.flipX;\n    copiedObject.flipY = this.flipY;\n    copiedObject.opacity = this.opacity;\n    copiedObject.uuid = random.uuid4();\n    copiedObject.sourceUUID = this.uuid;\n    copiedObject.assetUUID = this.assetUUID;\n    copiedObject.svgX = this.svgX;\n    copiedObject.svgY = this.svgY;\n    copiedObject.pathData = this.pathData;\n    copiedObject.isImage = this.isImage;\n    copiedObject.isPath = this.isPath;\n    copiedObject.isText = this.isText;\n    copiedObject.isButton = this.isButton;\n    copiedObject.isGroup = this.isGroup;\n    copiedObject.cachedAbsolutePosition = this.getAbsolutePosition();\n    copiedObject.svgStrokeWidth = this.svgStrokeWidth;\n\n    if(this.isText)\n        copiedObject.textData = JSON.parse(JSON.stringify(this.textData));\n\n    copiedObject.wickScript = this.wickScript\n\n    if(this.isSymbol) {\n        copiedObject.isSymbol = true;\n\n        copiedObject.playheadPosition = 0;\n        copiedObject.currentLayer = 0;\n\n        copiedObject.layers = [];\n        this.layers.forEach(function (layer) {\n            copiedObject.layers.push(layer.copy());\n        });\n    } else {\n        copiedObject.isSymbol = false;\n    }\n\n    return copiedObject;\n\n}\n\nWickObject.prototype.getAsJSON = function () {\n    var oldX = this.x;\n    var oldY = this.y;\n\n    var absPos = this.getAbsolutePosition();\n    this.x = absPos.x;\n    this.y = absPos.y;\n\n    // Encode scripts to avoid JSON format problems\n    this.encodeStrings();\n\n    var JSONWickObject = JSON.stringify(this, WickProject.Exporter.JSONReplacerObject);\n\n    // Put prototypes back on object ('class methods'), they don't get JSONified on project export.\n    WickObject.addPrototypes(this);\n\n    // Decode scripts back to human-readble and eval()-able format\n    this.decodeStrings();\n\n    this.x = oldX;\n    this.y = oldY;\n\n    return JSONWickObject;\n}\n\nWickObject.prototype.downloadAsFile = function () {\n\n    var filename = this.name || \"wickobject\";\n\n    if(this.isSymbol) {\n        var blob = new Blob([this.getAsJSON()], {type: \"text/plain;charset=utf-8\"});\n        saveAs(blob, filename+\".json\");\n        return;\n    }\n\n    var asset = wickEditor.project.library.getAsset(this.assetUUID);\n\n    if(asset.type === 'image') {\n        var ext = asset.getData().split(\"/\")[1].split(';')[0];\n        saveAs(dataURItoBlob(asset.getData()), filename+\".\"+ext);\n        return;\n    }\n\n    console.error(\"export not supported for this type of wickobject yet\");\n\n}\n\nWickObject.addPrototypes = function (obj) {\n\n    // Put the prototype back on this object\n    obj.__proto__ = WickObject.prototype;\n\n    if(obj.isSymbol) {\n        obj.layers.forEach(function (layer) {\n            layer.__proto__ = WickLayer.prototype;\n            layer.frames.forEach(function(frame) {\n                frame.__proto__ = WickFrame.prototype;\n\n                if(frame.tweens) {\n                    frame.tweens.forEach(function (tween) {\n                        tween.__proto__ = WickTween.prototype;\n                    });\n                }\n            });\n        });\n\n        obj.getAllChildObjects().forEach(function(currObj) {\n            WickObject.addPrototypes(currObj);\n        });\n    }\n}\n\n/* Encodes scripts and strings to avoid JSON format problems */\nWickObject.prototype.encodeStrings = function () {\n\n    if(this.wickScript) {\n        this.wickScript = WickProject.Compressor.encodeString(this.wickScript);\n    }\n\n    if(this.textData) {\n        this.textData.text = WickProject.Compressor.encodeString(this.textData.text);\n    }\n\n    if(this.pathData) {\n        this.pathData = WickProject.Compressor.encodeString(this.pathData);\n    }\n\n    if(this.isSymbol) {\n        this.getAllFrames().forEach(function (frame) {\n            frame.encodeStrings();\n        });\n\n        this.getAllChildObjects().forEach(function(child) {\n            child.encodeStrings();\n        });\n    }\n\n}\n\n/* Decodes scripts and strings back to human-readble and eval()-able format */\nWickObject.prototype.decodeStrings = function () {\n    \n    if(this.wickScript) {\n        this.wickScript = WickProject.Compressor.decodeString(this.wickScript);\n    }\n\n    if(this.textData) {\n        this.textData.text = WickProject.Compressor.decodeString(this.textData.text);\n    }\n\n    if(this.pathData) {\n        this.pathData = WickProject.Compressor.decodeString(this.pathData);\n    }\n\n    if(this.isSymbol) {\n        this.getAllFrames().forEach(function (frame) {\n            frame.decodeStrings();\n        });\n\n        this.getAllChildObjects().forEach(function(child) {\n            child.decodeStrings();\n        });\n    }\n\n}\n\nWickObject.prototype.generateParentObjectReferences = function() {\n\n    var self = this;\n\n    if(!self.isSymbol) return;\n\n    self.layers.forEach(function (layer) {\n        layer.parentWickObject = self;\n\n        layer.frames.forEach(function (frame) {\n            frame.parentLayer = layer;\n            frame.parentObject = self;\n\n            frame.wickObjects.forEach(function (wickObject) {\n                wickObject.parentObject = self;\n                wickObject.parentFrame = frame;\n\n                wickObject.generateParentObjectReferences();\n            });\n        });\n    });\n\n}\n\nWickObject.prototype.generateObjectNameReferences = function () {\n\n    var that = this;\n\n    this.getAllChildObjects().forEach(function(child) {\n        that[child.name] = child;\n\n        if(child.isSymbol) {\n            child.generateObjectNameReferences();\n        }\n    });\n    this.getAllActiveChildObjects().forEach(function(child) {\n        that[child.name] = child;\n    });\n\n}\n\nWickObject.prototype.getCurrentLayer = function() {\n    return this.layers[this.currentLayer];\n}\n\nWickObject.prototype.addLayer = function (layer) {\n    var currentLayerNum = 0;\n\n    this.layers.forEach(function (layer) {\n        var splitName = layer.identifier.split(\"Layer \")\n        if(splitName && splitName.length > 1) {\n            layerNum = parseInt(splitName[1]);\n            if(layerNum > currentLayerNum) {\n                currentLayerNum = layerNum;\n            }\n        }\n    });\n\n    layer.identifier = \"Layer \" + (currentLayerNum+1);\n\n    this.layers.push(layer);\n}\n\nWickObject.prototype.removeLayer = function (layer) {\n    var that = this;\n    this.layers.forEach(function (currLayer) {\n        if(layer === currLayer) {\n            that.layers.splice(that.layers.indexOf(layer), 1);\n        }\n    });\n}\n\nWickObject.prototype.getTotalTimelineLength = function () {\n    var longestLayerLength = 0;\n\n    this.layers.forEach(function (layer) {\n        var layerLength = layer.getTotalLength();\n        if(layerLength > longestLayerLength) {\n            longestLayerLength = layerLength;\n        }\n    });\n\n    return longestLayerLength;\n\n}\n\nWickObject.prototype.updateFrameTween = function (relativePlayheadPosition) {\n    var frame = this.parentFrame;\n    var tween = frame.getTweenAtFrame(relativePlayheadPosition);\n\n    if(tween) {\n        tween.updateFromWickObjectState(this);\n    }\n}\n\nWickObject.prototype.getActiveFrames = function () {\n    if(!this.isSymbol) {\n        return [];\n    }\n    \n    var activeFrames = [];\n\n    this.layers.forEach(function (layer) {\n        var frame = layer.getCurrentFrame();\n        if(frame)\n            activeFrames.push(frame);\n    });\n\n    return activeFrames;\n}\n\n/* Return all child objects of a parent object */\nWickObject.prototype.getAllChildObjects = function () {\n\n    if (!this.isSymbol) {\n        return [];\n    }\n\n    var children = [];\n    for(var l = this.layers.length-1; l >= 0; l--) {\n        var layer = this.layers[l];\n        for(var f = 0; f < layer.frames.length; f++) {\n            var frame = layer.frames[f];\n            for(var o = 0; o < frame.wickObjects.length; o++) {\n                children.push(frame.wickObjects[o]);\n            }\n        }\n    }\n    return children;\n}\n\n/* Return all child objects in the parent objects current frame. */\nWickObject.prototype.getAllActiveChildObjects = function () {\n\n    if (!this.isSymbol) {\n        return [];\n    }\n\n    var children = [];\n    for (var l = this.layers.length-1; l >= 0; l--) {\n        var layer = this.layers[l];\n        var frame = layer.getFrameAtPlayheadPosition(this.playheadPosition);\n        if(frame) {\n            frame.wickObjects.forEach(function (obj) {\n                children.push(obj);\n            });\n        }\n    }\n    return children;\n}\n\n/* Return all child objects of a parent object (and their children) */\nWickObject.prototype.getAllChildObjectsRecursive = function () {\n\n    if (!this.isSymbol) {\n        return [this];\n    }\n\n    var children = [this];\n    this.layers.forEachBackwards(function (layer) {\n        layer.frames.forEach(function (frame) {\n            frame.wickObjects.forEach(function (wickObject) {\n                children = children.concat(wickObject.getAllChildObjectsRecursive());\n            });\n        });\n    });\n    return children;\n}\n\n/* Return all active child objects of a parent object (and their children) */\nWickObject.prototype.getAllActiveChildObjectsRecursive = function (includeParents) {\n\n    if (!this.isSymbol) {\n        return [];\n    }\n\n    var children = [];\n    for (var l = this.layers.length-1; l >= 0; l--) {\n        var frame = this.layers[l].getFrameAtPlayheadPosition(this.playheadPosition);\n        if(frame) {\n            for(var o = 0; o < frame.wickObjects.length; o++) {\n                var obj = frame.wickObjects[o];\n                if(includeParents || !obj.isSymbol) children.push(obj);\n                children = children.concat(obj.getAllActiveChildObjectsRecursive(includeParents));\n            }\n        }\n    }\n    return children;\n\n}\n\n/* Return all child objects in the parent objects current layer. */\nWickObject.prototype.getAllActiveLayerChildObjects = function () {\n\n    if (!this.isSymbol) {\n        return [];\n    }\n\n    var children = [];\n    var layer = this.getCurrentLayer();\n    var frame = layer.getFrameAtPlayheadPosition(this.playheadPosition);\n    if(frame) {\n        frame.wickObjects.forEach(function (obj) {\n            children.push(obj);\n        });\n    }\n    return children;\n}\n\n// Use this to get objects on other layers\nWickObject.prototype.getAllInactiveSiblings = function () {\n\n    if(!this.parentObject) {\n        return [];\n    }\n\n    var that = this;\n    var siblings = [];\n    this.parentObject.getAllActiveChildObjects().forEach(function (child) {\n        if(child !== that) {\n            siblings.push(child);\n        }\n    });\n    siblings = siblings.concat(this.parentObject.getAllInactiveSiblings());\n\n    return siblings;\n\n}\n\n// Use this for onion skinning\nWickObject.prototype.getNearbyObjects = function (numFramesBack, numFramesForward) {\n\n    // Get nearby frames\n\n    var nearbyFrames = [];\n\n    var startPlayheadPosition = Math.max(0, this.playheadPosition - numFramesBack);\n    var endPlayheadPosition = this.playheadPosition + numFramesForward;\n    var tempPlayheadPosition = startPlayheadPosition;\n\n    while(tempPlayheadPosition <= endPlayheadPosition) {\n        var frame = this.getCurrentLayer().getFrameAtPlayheadPosition(tempPlayheadPosition);\n\n        if(frame && tempPlayheadPosition !== this.playheadPosition && nearbyFrames.indexOf(frame) == -1) {\n            nearbyFrames.push(frame);\n        }\n        \n        tempPlayheadPosition ++;\n    }\n\n    // Get objects in nearby frames\n\n    var nearbyObjects = [];\n\n    nearbyFrames.forEach(function(frame) {\n        nearbyObjects = nearbyObjects.concat(frame.wickObjects);\n    });\n\n    return nearbyObjects;\n\n}\n\n//\nWickObject.prototype.getObjectsOnFirstFrame = function () {\n\n    var objectsOnFirstFrame = [];\n\n    this.layers.forEach(function (layer) {\n        layer.frames[0].wickObjects.forEach(function (wickObj) {\n            objectsOnFirstFrame.push(wickObj);\n        });\n    });\n\n    return objectsOnFirstFrame;\n\n}\n\nWickObject.prototype.getParents = function () {\n    if(!this.isSymbol) {\n        return [];\n    } else if(this.isRoot) {\n        return [this];\n    } else {\n        return this.parentObject.getParents().concat([this]);\n    }\n}\n\n/* Excludes children of children */\nWickObject.prototype.getTotalNumChildren = function () {\n    var count = 0;\n    for(var l = 0; l < this.layers.length; l++) {\n        for(var f = 0; f < this.layers[l].frames.length; f++) {\n            for(var o = 0; o < this.layers[l].frames[f].wickObjects.length; o++) {\n                count++;\n            }\n        }\n    }\n    return count;\n}\n\nWickObject.prototype.getAllFrames = function () {\n\n    if(!this.isSymbol) return [];\n\n    var allFrames = [];\n\n    this.layers.forEach(function (layer) {\n        layer.frames.forEach(function (frame) {\n            allFrames.push(frame);\n        });\n    });\n\n    return allFrames;\n}\n\nWickObject.prototype.getAllFramesWithSound = function () {\n    return this.getAllFrames().filter(function (frame) {\n        return frame.hasSound();\n    });\n}\n\nWickObject.prototype.getFrameWithChild = function (child) {\n\n    var foundFrame = null;\n\n    this.layers.forEach(function (layer) {\n        layer.frames.forEach(function (frame) {\n            frame.wickObjects.forEach(function (wickObject) {\n                if(wickObject.uuid === child.uuid) {\n                    foundFrame = frame;\n                }\n            });\n        });\n    });\n\n    return foundFrame;\n}\n\nWickObject.prototype.getLayerWithChild = function (child) {\n\n    var foundLayer = null;\n\n    this.layers.forEach(function (layer) {\n        layer.frames.forEach(function (frame) {\n            if(frame.wickObjects.indexOf(child) !== -1) {\n                foundLayer = layer;\n            }\n        });\n    });\n\n    return foundLayer;\n}\n\nWickObject.prototype.remove = function () {\n    this.parentObject.removeChild(this);\n}\n\nWickObject.prototype.removeChild = function (childToRemove) {\n\n    if(!this.isSymbol) {\n        return;\n    }\n\n    var that = this;\n    this.getAllChildObjects().forEach(function(child) {\n        if(child == childToRemove) {\n            var index = child.parentFrame.wickObjects.indexOf(child);\n            child.parentFrame.wickObjects.splice(index, 1);\n        }\n    });\n}\n\nWickObject.prototype.getZIndex = function () {\n    return this.parentFrame.wickObjects.indexOf(this);\n}\n\n/* Get the absolute position of this object (the position not relative to the parents) */\nWickObject.prototype.getAbsolutePosition = function () {\n    if(this.isRoot) {\n        return {\n            x: this.x,\n            y: this.y\n        };\n    } else if (!this.parentObject) {\n        return this.cachedAbsolutePosition;\n    } else {\n        var parent = this.parentObject;\n        var parentPosition = parent.getAbsolutePosition();\n        return {\n            x: this.x + parentPosition.x,\n            y: this.y + parentPosition.y\n        };\n    }\n}\n\n/* Get the absolute position of this object taking into account the scale of the parent */\nWickObject.prototype.getAbsolutePositionTransformed = function () {\n    if(this.isRoot) {\n        return {\n            x: this.x,\n            y: this.y\n        };\n    } else {\n        var parent = this.parentObject;\n        var parentPosition = parent.getAbsolutePositionTransformed();\n        var parentScale = parent.getAbsoluteScale()\n        var parentFlip = parent.getAbsoluteFlip();\n        var rotatedPosition = {x:this.x*parentScale.x, y:this.y*parentScale.y};\n        if(parentFlip.x) rotatedPosition.x *= -1;\n        if(parentFlip.y) rotatedPosition.y *= -1;\n        rotatedPosition = rotate_point(rotatedPosition.x, rotatedPosition.y, 0, 0, parent.getAbsoluteRotation());\n        return {\n            x: rotatedPosition.x + parentPosition.x,\n            y: rotatedPosition.y + parentPosition.y\n        };\n    }\n}\n\nWickObject.prototype.getAbsoluteScale = function () {\n    if(this.isRoot) {\n        return {\n            x: this.scaleX,\n            y: this.scaleY\n        };\n    } else {\n        var parentScale = this.parentObject.getAbsoluteScale();\n        return {\n            x: this.scaleX * parentScale.x,\n            y: this.scaleY * parentScale.y\n        };\n    }\n}\n\nWickObject.prototype.getAbsoluteRotation = function () {\n    if(this.isRoot) {\n        return this.rotation;\n    } else {\n        var parentRotation = this.parentObject.getAbsoluteRotation();\n        return this.rotation + parentRotation;\n    }\n}\n\nWickObject.prototype.getAbsoluteOpacity = function () {\n    if(this.isRoot) {\n        return this.opacity;\n    } else {\n        var parentOpacity = this.parentObject.getAbsoluteOpacity();\n        return this.opacity * parentOpacity;\n    }\n}\n\nWickObject.prototype.getAbsoluteFlip = function () {\n    if(this.isRoot) {\n        return {\n            x: this.flipX,\n            y: this.flipY\n        };\n    } else {\n        var parentFlip = this.parentObject.getAbsoluteFlip();\n        return {\n            x: this.flipX !== parentFlip.x,\n            y: this.flipY !== parentFlip.y\n        };\n    }\n}\n\nWickObject.prototype.getAbsoluteTransformations = function () {\n    return {\n        position: this.getAbsolutePositionTransformed(),\n        scale: this.getAbsoluteScale(),\n        rotation: this.getAbsoluteRotation(),\n        opacity: this.getAbsoluteOpacity(),\n        flip: this.getAbsoluteFlip(),\n    }\n}\n\nWickObject.prototype.isOnActiveLayer = function (activeLayer) {\n\n    return this.parentFrame.parentLayer === activeLayer;\n\n}\n\nWickObject.prototype.play = function () {\n\n    this._playing = true;\n}\n\nWickObject.prototype.stop = function () {\n\n    this._playing = false;\n}\n\nWickObject.prototype.getFrameById = function (identifier) {\n    var foundFrame = null;\n\n    this.getAllFrames().forEach(function (frame) {\n        if(frame.name === identifier) {\n            foundFrame = frame;\n        }\n    });\n\n    return foundFrame;\n}\n\nWickObject.prototype.getFrameByPlayheadPosition = function (php) {\n    var foundFrame = null;\n\n    this.getAllFrames().forEach(function (frame) {\n        if(frame.playheadPosition === php) {\n            foundFrame = frame;\n        }\n    });\n\n    return foundFrame;\n}\n\n\nWickObject.prototype.gotoAndStop = function (frame) {\n    this.movePlayheadTo(frame);\n    this.stop();\n}\n\nWickObject.prototype.gotoAndPlay = function (frame) {\n    this.movePlayheadTo(frame);\n    this.play();\n}\n\nWickObject.prototype.movePlayheadTo = function (frame) {\n\n    var oldFrame = this.getCurrentLayer().getCurrentFrame();\n\n    // Frames are zero-indexed internally but start at one in the editor GUI, so you gotta subtract 1.\n    if (typeof frame === 'number') {\n        var actualFrame = frame-1;\n\n        var endOfFrames = this.getFramesEnd(); \n        // Only navigate to an integer frame if it is nonnegative and a valid frame\n        if(actualFrame < endOfFrames) {\n            this._newPlayheadPosition = actualFrame;\n        } else {\n            throw (new Error(\"Failed to navigate to frame \\'\" + actualFrame + \"\\': is not a valid frame.\"));\n        }\n\n    } else if (typeof frame === 'string') {\n\n        var foundFrame = this.getFrameById(frame)\n\n        if (foundFrame) {\n            if(this.playheadPosition < foundFrame.playheadPosition || this.playheadPosition >= foundFrame.playheadPosition+foundFrame.length-1) {\n                this._newPlayheadPosition = foundFrame.playheadPosition;\n            }\n        } else {\n            throw (new Error(\"Failed to navigate to frame. \\'\" + frame + \"\\' is not a valid frame.\"));\n        }\n\n    }\n\n}\n\nWickObject.prototype.gotoNextFrame = function () {\n\n    var nextFramePos = this.playheadPosition+1;\n    var totalLength = this.getTotalTimelineLength();\n    if(nextFramePos >= totalLength) {\n        nextFramePos = 0;\n    }\n\n    this._newPlayheadPosition = nextFramePos;\n\n}\n\nWickObject.prototype.gotoPrevFrame = function () {\n\n    var nextFramePos = this.playheadPosition-1;\n    if(nextFramePos < 0) {\n        nextFramePos = this.layers[this.currentLayer].getTotalLength()-1;\n    }\n\n    this._newPlayheadPosition = nextFramePos;\n\n}\n\nWickObject.prototype.getFramesEnd = function() {\n    endFrame = 0; \n\n    this.layers.forEach(function (layer) {\n        layer.frames.forEach( function (frame) {\n            endFrame = Math.max (frame.getFrameEnd(), endFrame); \n        })\n    });\n\n    return endFrame;\n\n}\n\nWickObject.prototype.hitTest = function (otherObj) {\n    this.regenBounds();\n    otherObj.regenBounds();\n\n    return intersectRect(this.bounds, otherObj.bounds);\n}\n\nWickObject.prototype.regenBounds = function () {\n    var self = this;\n    if(this.isSymbol) {\n        this.bounds = {\n            left: Infinity,\n            right: -Infinity,\n            top: Infinity,\n            bottom: -Infinity,\n        }\n        this.getAllActiveChildObjects().forEach(function (child) {\n            child.regenBounds();\n            self.bounds.left = Math.min(child.bounds.left, self.bounds.left)\n            self.bounds.right = Math.max(child.bounds.right, self.bounds.right)\n            self.bounds.top = Math.min(child.bounds.top, self.bounds.top)\n            self.bounds.bottom = Math.max(child.bounds.bottom, self.bounds.bottom)\n        });\n    } else {\n        var absPos = this.getAbsolutePosition();\n        this.bounds = {\n            left: absPos.x - this.width/2,\n            right: absPos.x + this.width/2,\n            top: absPos.y - this.height/2,\n            bottom: absPos.y + this.height/2,\n        };\n    }\n}\n\nWickObject.prototype.isPointInside = function(point) {\n\n    var objects = this.getAllActiveChildObjectsRecursive(false);\n    if(!this.isSymbol) {\n        objects.push(this);\n    }\n\n    var hit = false;\n\n    objects.forEach(function(object) {\n        if(hit) return;\n\n        var transformedPosition = object.getAbsolutePositionTransformed();\n        var transformedPoint = {x:point.x, y:point.y};\n        var transformedScale = object.getAbsoluteScale();\n        var transformedWidth = (object.width+object.svgStrokeWidth)*transformedScale.x;\n        var transformedHeight = (object.height+object.svgStrokeWidth)*transformedScale.y;\n\n        transformedPoint = rotate_point(\n            transformedPoint.x, \n            transformedPoint.y, \n            transformedPosition.x, \n            transformedPosition.y,\n            -object.getAbsoluteRotation()\n        );\n\n        // Bounding box check\n        if ( transformedPoint.x >= transformedPosition.x - transformedWidth /2 &&\n             transformedPoint.y >= transformedPosition.y - transformedHeight/2 &&\n             transformedPoint.x <= transformedPosition.x + transformedWidth /2 &&\n             transformedPoint.y <= transformedPosition.y + transformedHeight/2 ) {\n\n            if(!object.alphaMask) {\n                hit = true;\n                return;\n            }\n\n            var relativePoint = {\n                x: transformedPoint.x - transformedPosition.x + transformedWidth /2,\n                y: transformedPoint.y - transformedPosition.y + transformedHeight/2\n            }\n\n            // Alpha mask check\n            var objectAlphaMaskIndex =\n                (Math.floor(relativePoint.x/transformedScale.x)%Math.floor(object.width+object.svgStrokeWidth)) +\n                (Math.floor(relativePoint.y/transformedScale.y)*Math.floor(object.width+object.svgStrokeWidth));\n            if(!object.alphaMask[(objectAlphaMaskIndex)] && \n               objectAlphaMaskIndex < object.alphaMask.length &&\n               objectAlphaMaskIndex >= 0) {\n                hit = true;\n                return;\n            }\n        }\n    });\n\n    return hit;\n}\n\nWickObject.prototype.clone = function (args) {\n    return wickPlayer.cloneObject(this, args);\n};\n\nWickObject.prototype.delete = function () {\n    return wickPlayer.deleteObject(this);\n};\n\nWickObject.prototype.setCursor = function (cursor) {\n    this.cursor = cursor;\n}\n\nWickObject.prototype.isHoveredOver = function () {\n    return this.hoveredOver;\n}\n\nWickObject.prototype.prepareForPlayer = function () {\n    // Set all playhead vars\n    if(this.isSymbol) {\n        // Set this object to it's first frame\n        this.playheadPosition = 0;\n\n        this.clones = [];\n\n        // Start the object playing\n        this._playing = true;\n        this._active = false;\n        this._wasActiveLastTick = false;\n\n        this.layers.forEach(function (layer) {\n            layer.hidden = false;\n        })\n\n        this.getAllFrames().forEach(function (frame) {\n            //frame.prepareForPlayer();\n        });\n        this.getAllChildObjects().forEach(function (o) {\n            o.prepareForPlayer();\n        })\n    }\n\n    // Reset the mouse hovered over state flag\n    this.hoveredOver = false;\n}\n\nWickObject.prototype.regenerateAssetLinkedSymbols = function () {\n    if(this.assetUUID && this.isSymbol && this !== wickEditor.project.getCurrentObject()) {\n        var asset = wickEditor.project.library.getAsset(this.assetUUID)\n        var source = WickObject.fromJSON(asset.data);\n        for(key in source) {\n            if(key !== 'x' && \n               key !== 'y' && \n               key !== 'scaleX' && \n               key !== 'scaleY' && \n               key !== 'flipX' && \n               key !== 'flipY' && \n               key !== 'rotation' &&\n               key !== 'opacity' &&\n               key !== 'name' &&\n               key !== 'uuid' && \n               key !== 'assetUUID') {\n                this[key] = source[key];\n            }\n        }\n        var self = this;\n        this.getAllChildObjectsRecursive().forEach(function (child) {\n            if(self !== child) child.uuid = random.uuid4();\n            (child.layers||[]).forEach(function (layer) {\n                layer.frames.forEach(function (frame) {\n                    frame.uuid = random.uuid4();\n                })\n            });\n        });\n        this.getAllFrames().forEach(function (frame) {\n            frame.uuid = random.uuid4();\n        });\n    }\n\n    this.getAllChildObjects().forEach(function (o) {\n        o.regenerateAssetLinkedSymbols();\n    })\n}\n\n/* Generate alpha mask for per-pixel hit detection */\nWickObject.prototype.generateAlphaMask = function (imageData) {\n\n    var that = this;\n\n    var alphaMaskSrc = imageData || that.asset.getData();\n    if(!alphaMaskSrc) return;\n\n    //window.open(alphaMaskSrc)\n\n    ImageToCanvas(alphaMaskSrc, function (canvas,ctx) {\n        //if(window.wickPlayer) window.open(canvas.toDataURL())\n        var w = canvas.width;\n        var h = canvas.height;\n        var rgba = ctx.getImageData(0,0,w,h).data;\n        that.alphaMask = [];\n        for (var y = 0; y < h; y ++) {\n            for (var x = 0; x < w; x ++) {\n                var alphaMaskIndex = x+y*w;\n                that.alphaMask[alphaMaskIndex] = rgba[alphaMaskIndex*4+3] <= 10;\n            }\n        }\n    }, {width:Math.floor(that.width+that.svgStrokeWidth), height:Math.floor(that.height+that.svgStrokeWidth)} );\n\n}\n\nWickObject.prototype.getCurrentFrames = function () {\n    var currentFrames = [];\n\n    this.layers.forEach(function (layer) {\n        var frame = layer.getCurrentFrame();\n        if(frame) currentFrames.push(frame)\n    });\n\n    return currentFrames;\n}\n\nWickObject.prototype.tick = function () {\n    var self = this;\n\n    if(this.isSymbol) {\n        this.layers.forEach(function (layer) {\n            layer.frames.forEach(function (frame) {\n                frame.tick();\n            });\n        });\n    }\n\n    if(this.isButton) {\n        this.stop();\n        if(this._beingClicked) {\n            if(this.getFrameByPlayheadPosition(2))\n                this.movePlayheadTo(3);\n        } else if (this.hoveredOver) {\n            if(this.getFrameByPlayheadPosition(1))\n                this.movePlayheadTo(2);\n        } else {\n            if(this.getFrameByPlayheadPosition(0))\n                this.movePlayheadTo(1);\n        }\n    }\n\n    if(this.isSymbol) {\n        if(true) {\n            if(this._wasClicked) {\n                (wickPlayer || wickEditor).project.runScript(this, 'mousePressed');\n                this._wasClicked = false;\n            }\n\n            if(this._beingClicked) {\n                (wickPlayer || wickEditor).project.runScript(this, 'mouseDown');\n                this._wasClicked = false;\n            }\n\n            if(this._wasClickedOff) {\n                (wickPlayer || wickEditor).project.runScript(this, 'mouseReleased');\n                this._wasClickedOff = false;\n            }\n\n            if(this.isHoveredOver()) {\n                (wickPlayer || wickEditor).project.runScript(this, 'mouseHover');\n            }\n\n            if(this._wasHoveredOver) {\n                (wickPlayer || wickEditor).project.runScript(this, 'mouseEnter');\n                this._wasHoveredOver = false;\n            }\n\n            if(this._mouseJustLeft) {\n                (wickPlayer || wickEditor).project.runScript(this, 'mouseLeave');\n                this._mouseJustLeft = false;\n            }\n\n            wickPlayer.inputHandler.getAllKeysJustReleased().forEach(function (key) {\n                (wickPlayer || wickEditor).project.runScript(self, 'keyReleased', key);\n            });\n\n            wickPlayer.inputHandler.getAllKeysJustPressed().forEach(function (key) {\n                (wickPlayer || wickEditor).project.runScript(self, 'keyPressed', key);\n            });\n\n            wickPlayer.inputHandler.getAllKeysDown().forEach(function (key) {\n                (wickPlayer || wickEditor).project.runScript(self, 'keyDown', key);\n            });\n\n            // Inactive -> Inactive\n            if (!this._wasActiveLastTick && !this._active) {\n                \n            }\n            // Inactive -> Active\n            else if (!this._wasActiveLastTick && this._active) {\n                (wickPlayer || wickEditor).project.initScript(this);\n\n                (wickPlayer || wickEditor).project.runScript(this, 'load');\n                (wickPlayer || wickEditor).project.runScript(this, 'update');\n\n                // Force playhead update on first tick to fix:\n                // https://github.com/zrispo/wick-editor/issues/810\n                if(this._newPlayheadPosition) {\n                    this.playheadPosition = this._newPlayheadPosition;\n                    this._newPlayheadPosition = undefined;\n                }\n            }\n            // Active -> Active\n            else if (this._wasActiveLastTick && this._active) {\n                (wickPlayer || wickEditor).project.runScript(this, 'update');\n            }\n            // Active -> Inactive\n            else if (this._wasActiveLastTick && !this._active) {\n                if(!this.parentFrame.alwaysSaveState) {\n                    wickPlayer.resetStateOfObject(this);\n                }\n            }\n        }\n\n        if(this.isSymbol) {\n            if(this._active) {\n                this.advanceTimeline();\n            }\n        \n            this.currentFrameNumber = this.playheadPosition+1;\n            var self = this;\n            this.getActiveFrames().forEach(function (frame) {\n                self.currentFrameName = frame.name;\n            });\n        }\n    }\n\n}\n\nWickObject.prototype.advanceTimeline = function () {\n    if(this._playing && this.isSymbol && this._newPlayheadPosition === undefined) {\n        this._newPlayheadPosition = this.playheadPosition+1;\n        if(this._newPlayheadPosition >= this.getTotalTimelineLength()) {\n            this._newPlayheadPosition = 0;\n        }\n    }\n}\n\nWickObject.prototype.isActive = function () {\n    if(this.isRoot) return true;\n\n    return this.parentFrame._active;\n}\n\nWickObject.prototype.setText = function (text) {\n    this.textData.text = String(text); // Convert to a string, just in case.\n    this._renderDirty = true;  \n}\n\nWickObject.prototype.pointTo = function ( x2, y2 ) {\n    var dx = this.x - x2,\n        dy = this.y - y2;\n    \n    this.rotation = Math.atan2(dy,dx) * 180 / Math.PI - 90;\n};\n\nWickObject.prototype.moveUp = function ( d ) {\n    this.y -= d === undefined ? 1 : d;\n}\n\nWickObject.prototype.moveDown = function ( d ) {\n    this.y += d === undefined ? 1 : d;\n}\n\nWickObject.prototype.moveLeft = function ( d ) {\n    this.x -= d === undefined ? 1 : d;\n}\n\nWickObject.prototype.moveRight = function ( d ) {\n    this.x += d === undefined ? 1 : d;\n}\n\nWickObject.prototype.getSourceInside = function () {\n    if(this.isRoot) {\n        return null;\n    } else if(this.assetUUID && this.isSymbol) {\n        return this;\n    } else {\n        return this.parentObject.getSourceInside();\n    }\n}\n"
  },
  {
    "path": "src/project/WickProject.AssetLibrary.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n    \nvar AssetLibrary = function () {\n\n    this.assets = {};\n\n};\n\nAssetLibrary.prototype.addAsset = function (asset) {\n\n    if(asset.uuid) {\n        this.assets[asset.uuid] = asset;\n    } else {\n        var uuid = random.uuid4();\n        this.assets[uuid] = asset;\n        asset.uuid = uuid;\n\n        return uuid;\n    }\n}\n\nAssetLibrary.prototype.deleteAsset = function (uuid) {\n\n    this.assets[uuid] = null;\n    delete this.assets[uuid];\n\n}\n\nAssetLibrary.prototype.getAsset = function (uuid) {\n\n    return this.assets[uuid];\n\n}\n\nAssetLibrary.prototype.getAllAssets = function (type) {\n\n    var allAssets = [];\n\n    for (assetUUID in this.assets) {\n        var asset = this.assets[assetUUID];\n        if(!type || asset.type === type) {\n            allAssets.push(asset);\n        }\n    }\n\n    return allAssets;\n\n}\n\nAssetLibrary.prototype.getAssetByName = function (filename) {\n\n    var foundAsset = null;\n    this.getAllAssets().forEach(function (asset) {\n        if (asset.filename === filename)\n            foundAsset = asset;\n    });\n    return foundAsset\n\n}\n\n/* For backwards compatibility... */\nAssetLibrary.prototype.regenAssetUUIDs = function () {\n\n    for (assetUUID in this.assets) {\n        var asset = this.assets[assetUUID];\n        asset.uuid = assetUUID;\n    }\n\n}\n\nAssetLibrary.prototype.printInfo = function () {\n\n    var totalSize = 0;\n    for (assetUUID in this.assets) {\n        var asset = this.assets[assetUUID];\n        totalSize += asset.data.length;\n\n        console.log(\"Filename: \"+asset.filename);\n        console.log(\"Type: \"+asset.type);\n        console.log(\"Size: \"+asset.data.length);\n        console.log(\"---\")\n    }\n    console.log(\"Total library size: \" + totalSize)\n\n}\n\nAssetLibrary.prototype.encodeStrings = function () {\n    this.getAllAssets().forEach(function (asset) {\n        asset.filename = WickProject.Compressor.encodeString(asset.filename);\n        asset.data = WickProject.Compressor.encodeString(asset.data);\n    });\n}\n\nAssetLibrary.prototype.decodeStrings = function () {\n    this.getAllAssets().forEach(function (asset) {\n        asset.filename = WickProject.Compressor.decodeString(asset.filename);\n        asset.data = WickProject.Compressor.decodeString(asset.data);\n    });\n}\n\nAssetLibrary.addPrototypes = function (library) {\n\n    for (assetUUID in library.assets) {\n        library.assets[assetUUID].__proto__ = WickAsset.prototype;\n    }\n\n}\n"
  },
  {
    "path": "src/project/WickProject.Compressor.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nWickProject.Compressor = (function () {\n\n    var projectCompressor = { };\n\n    var printFilesize = false;\n\n    var compressionRoutines = {\n        'LZSTRING-BASE64': {\n            compress:LZString.compressToBase64, \n            decompress:LZString.decompressFromBase64\n        },\n        'LZSTRING-UTF16': {\n            compress:LZString.compressToUTF16, \n            decompress:LZString.decompressFromUTF16\n        }\n    }\n\n    projectCompressor.compressProject = function (projectJSON, compressionRoutineName) {\n        if(printFilesize) console.log(\"Compressing project of size \" + projectJSON.length);\n\n        var compressionRoutine = compressionRoutines[compressionRoutineName];\n        var compressedProjectJSON = compressionRoutineName+compressionRoutine.compress(projectJSON)\n\n        if(printFilesize) console.log(\"Done! Result size \" + compressedProjectJSON.length);\n        return compressedProjectJSON;\n    }\n\n    projectCompressor.decompressProject = function (compressedProjectJSON) {\n        if(printFilesize) console.log(\"Decompressing project...\")\n\n        var projectJSON = compressedProjectJSON;\n\n        for (var compressionRoutineName in compressionRoutines) {\n            if(compressedProjectJSON.startsWith(compressionRoutineName)) {\n                console.log(\"Project compressed with \" + compressionRoutineName)\n                var compressionRoutine = compressionRoutines[compressionRoutineName];\n                var rawCompressedProjectJSON = compressedProjectJSON.substring(compressionRoutineName.length, compressedProjectJSON.length);\n                projectJSON = compressionRoutine.decompress(rawCompressedProjectJSON);\n            }\n        }\n\n        if(printFilesize) console.log(\"Done!\");\n        return projectJSON;\n    }\n    \n    projectCompressor.encodeString = function (str) {\n        var newStr = str;\n        newStr = encodeURI(str);\n        newStr = newStr.replace(/'/g, \"%27\");\n        return newStr;\n    }\n\n    projectCompressor.decodeString = function (str) {\n        var newStr = str;\n        newStr = newStr.replace(/%27/g, \"'\");\n        newStr = decodeURI(str);\n        return newStr;\n    }\n\n    return projectCompressor;\n\n})();"
  },
  {
    "path": "src/project/WickProject.Exporter.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n    \nWickProject.Exporter = (function () {\n\n    var projectExporter = { };\n\n    projectExporter.generatePlayer = function () {\n\n        if(window.cachedPlayer) return window.cachedPlayer;\n        \n        var fileOut = \"\";\n\n        // Add the player webpage (need to download the empty player)\n        var emptyPlayerPath = \"src/player/emptyplayer.htm\";\n        fileOut += FileDownloader.downloadFile(emptyPlayerPath) + \"\\n\";\n\n        // All libs needed by the player. \n        var requiredLibFiles = [\n            \"lib/pixi.4.5.6.min.js\",\n            \"lib/webfont.js\",\n            //\"https://cdnjs.cloudflare.com/ajax/libs/stats.js/r16/Stats.min.js\",\n            \"lib/lz-string.min.js\",\n            \"lib/polyfills.js\",\n            \"lib/keyCharToCode.js\",\n            \"lib/fpscounter.js\",\n            \"lib/base64-arraybuffer.js\",\n            \"lib/canvasutils.js\",\n            \"lib/random.js\",\n            \"lib/SAT.js\",\n            \"lib/jquery.min.js\",\n            \"lib/Tween.js\",\n            \"lib/lerp.js\",\n            \"lib/bowser.js\",\n            \"lib/howler.min.js\",\n            \"lib/URLParameterUtils.js\",\n            \"lib/stats.min.js\",\n            \"lib/localstoragewrapper.js\",\n            \"src/project/WickTween.js\",\n            \"src/project/WickFrame.js\",\n            \"src/project/WickLayer.js\",\n            \"src/project/WickObject.js\",\n            \"src/project/WickAsset.js\",\n            \"src/project/WickProject.js\",\n            \"src/project/WickCamera.js\",\n            \"src/project/WickProject.AssetLibrary.js\",\n            \"src/project/WickProject.Compressor.js\",\n            \"src/player/WickPlayer.PixiRenderer.js\",\n            \"src/player/WickPlayer.HowlerAudioPlayer.js\",\n            \"src/player/WickPlayer.InputHandler.js\",\n            \"src/player/WickPlayer.js\",\n        ];\n\n        var totalSize = 0;\n        requiredLibFiles.forEach(function (filename) {\n            var script = FileDownloader.downloadFile(filename);\n            //console.log(script.length + \" used for \" + filename);\n\n            //var scriptCompressed = LZString.compressToBase64(script)\n            //console.log(scriptCompressed.length + \" compressed: \" + filename);\n\n            totalSize += script.length;\n            fileOut += \"<script>\" + script + \"</script>\\n\";\n        });\n        //console.log(totalSize + \" total\");\n\n        window.cachedPlayer = fileOut;\n        return fileOut;\n\n    }\n\n    projectExporter.exportPlayer = function () {\n        var emptyplayerString = projectExporter.generatePlayer();\n        var blob = new Blob([emptyplayerString], {type: \"text/plain;charset=utf-8\"});\n        saveAs(blob, \"player.html\")\n    }\n\n    projectExporter.bundleProjectToHTML = function (wickProject, callback) {\n\n        var fileOut = projectExporter.generatePlayer();\n\n        // Bundle the JSON project\n        wickProject.getAsJSON(function (JSONProject) {\n\n            wickProject.library.getAllAssets('script').forEach(function (asset) {\n                fileOut += '<script>' + asset.getData() + '</script>';\n            });\n\n            fileOut += \"<script>var wickPlayer = new WickPlayer(); wickPlayer.runProject('\" + JSONProject + \"', document.getElementById('playerCanvasContainer'));</script>\" + \"\\n\";\n            callback(fileOut);\n        });\n\n    }\n\n    projectExporter.exportProject = function (wickProject, args) {\n\n        if(args && args.wick) {\n            wickProject.getAsJSON(function(JSONProject) {\n                var byteArray = LZString.compressToUint8Array(JSONProject);\n                \n                var blob1 = new Blob([byteArray], {type: \"application/octet-stream\"});\n\n                saveAs(blob1, wickProject.name+'-'+timeStamp()+\".wick\");\n            });\n            return;\n        }\n\n        if(args && args.json) {\n            wickProject.getAsJSON(function(JSONProject) {\n                var blob = new Blob([JSONProject], {type: \"text/plain;charset=utf-8\"});\n                saveAs(blob, wickProject.name+'-'+timeStamp()+'.json');\n            }, '\\t');\n            return;\n        }\n\n        projectExporter.bundleProjectToHTML(wickProject, function(fileOut) {\n            var filename = wickProject.name || \"project\";\n            if(args && args.zipped) {\n                var zip = new JSZip();\n                zip.file(\"index.html\", fileOut);\n                zip.generateAsync({type:\"blob\"}).then(function(content) {\n                    saveAs(content, filename+'-'+timeStamp()+\".zip\");\n                });\n            } else {\n                if(args && args.asNewWindow) {\n                    var x=window.open('','','width='+wickProject.width+', height='+wickProject.height);\n                    x.document.open().write(fileOut);\n                } else {\n                    var blob = new Blob([fileOut], {type: \"text/plain;charset=utf-8\"});\n                    saveAs(blob, filename+'-'+timeStamp()+\".html\");\n                }\n            }\n        });\n\n    }\n\n    projectExporter.autosaveProject = function (wickProject, args) {\n        wickProject.getAsJSON(function (projectJSON) {\n            console.log(\"Project size: \" + projectJSON.length)\n            idbKeyval.set('AutosavedWickProject', projectJSON)\n              .then(() => {\n                wickEditor.alertbox.showProjectSavedMessage();\n                wickProject.unsaved = false;\n                wickEditor.syncInterfaces();\n              })\n              .catch(err => console.log('idbKeyval failed to save. ', err));\n        });\n    }\n\n    projectExporter.getAutosavedProject = function (callback) {\n        idbKeyval.get('AutosavedWickProject').then(val => {\n            if(!val) {\n                callback(new WickProject());\n            } else {\n                if(localStorage.alwaysLoadAutosavedProject === 'true' || window.confirm(\"There is an autosaved project. Would you like to recover it?\")) {\n                    var project = WickProject.fromJSON(val);\n                    callback(project);\n                    return;\n                } else {\n                    callback(new WickProject());\n                    return;\n                }\n            }\n        });\n    }\n\n    var dontJSONVars = [\n        \"thumbnail\",\n        \"clones\",\n        \"currentObject\",\n        \"parentObject\",\n        \"causedAnException\",\n        \"parentFrame\",\n        \"alphaMask\",\n        \"cachedImageData\",\n        \"parentWickObject\",\n        \"parentLayer\",\n        \"asset\",\n        \"paper\",\n        \"unsaved\",\n        \"_renderDirty\",\n        \"_selection\",\n        \"smallFramesMode\",\n        \"_soundDataForPreview\",\n        \"_wasClicked\",\n        \"_wasClickedOff\",\n        \"_wasHoveredOver\",\n        \"_beingClicked\",\n        \"_pixiTextureCached\",\n        \"_hitBox\",\n        \"sourceUUID\",\n        \"_renderAsBGObject\",\n        \"howl\",\n        \"tweenClipboardData\",\n    ];\n\n    projectExporter.JSONReplacer = function(key, value) {\n        if (dontJSONVars.indexOf(key) !== -1) {\n            return undefined;\n        } else {\n            return value;\n        }\n    }\n\n    projectExporter.JSONReplacerObject = function (key, value) {\n        if (key === \"uuid\" || dontJSONVars.indexOf(key) !== -1) {\n            return undefined;\n        } else {\n            return value;\n        }\n    }\n\n    return projectExporter;\n\n})();\n"
  },
  {
    "path": "src/project/WickProject.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar WickProject = function () {\n\n    // Create the root object. The editor is always editing the root\n    // object or its sub-objects and cannot ever leave the root object.\n    this.createNewRootObject();\n\n    // Only used by the editor. Keeps track of current object editor is editing.\n    this.currentObject = this.rootObject;\n    this.rootObject.currentFrame = 0;\n\n    this.library = new AssetLibrary();\n\n    this.name = \"New Project\";\n\n    this.onionSkinning = false;\n    this.smallFramesMode = false;\n    \n    this.width = 720;\n    this.height = 480;\n\n    this.backgroundColor = \"#FFFFFF\";\n    this.transparent = false;\n\n    this.pixelPerfectRendering = false;\n\n    this.framerate = 12;\n\n    this.uuid = random.uuid4();\n\n    this._selection = [];\n\n    if(window.wickVersion) this.wickVersion = window.wickVersion;\n\n};\n\nWickProject.prototype.createNewRootObject = function () {\n    var rootObject = new WickObject();\n    rootObject.isSymbol = true;\n    rootObject.isRoot = true;\n    rootObject.playheadPosition = 0;\n    rootObject.currentLayer = 0;\n    var firstLayer = new WickLayer();\n    firstLayer.identifier = \"Layer 1\";\n    rootObject.layers = [firstLayer];\n    rootObject.x = 0;\n    rootObject.y = 0;\n    rootObject.opacity = 1.0;\n    this.rootObject = rootObject;\n    this.rootObject.generateParentObjectReferences();\n}\n\nWickProject.fromFile = function (file, callback) {\n\n    var reader = new FileReader();\n    reader.onload = function(e) {\n        if (file.type === \"text/html\") {\n            callback(WickProject.fromWebpage(e.target.result));\n        } else if (file.type === \"application/json\") {\n            callback(WickProject.fromJSON(e.target.result));\n        }\n    };\n    reader.readAsText(file);\n\n}\n\nWickProject.fromZIP = function (file, callback) {\n      JSZip.loadAsync(file).then(function (zip) {\n          return zip.file(\"index.html\").async(\"text\");\n        }).then(function (txt) {\n          callback(WickProject.fromWebpage(txt));\n        });\n}\n\nWickProject.fromWebpage = function (webpageString) {\n\n    var extractedProjectJSON;\n\n    var webpageStringLines = webpageString.split('\\n');\n    webpageStringLines.forEach(function (line) {\n        if(line.startsWith(\"<script>var wickPlayer = new WickPlayer(); wickPlayer.runProject(\")) {\n            extractedProjectJSON = line.split(\"'\")[1];\n        }\n    });\n\n    if(!extractedProjectJSON) {\n        // Oh no, something went wrong\n        console.error(\"Bundled JSON project not found in specified HTML file (webpageString). The HTML supplied might not be a Wick project, or zach might have changed the way projects are bundled. See WickProject.Exporter.js!\");\n        return null;\n    } else {\n        // Found a bundled project's JSON, let's load it!\n        return WickProject.fromJSON(extractedProjectJSON);\n    }\n}\n\nWickProject.fromJSON = function (rawJSONProject, uncompressed) {\n\n    var JSONString = uncompressed ? rawJSONProject : WickProject.Compressor.decompressProject(rawJSONProject);\n\n    // Replace current project with project in JSON\n    var projectFromJSON = JSON.parse(JSONString);\n\n    // Put prototypes back on object ('class methods'), they don't get JSONified on project export.\n    projectFromJSON.__proto__ = WickProject.prototype;\n    WickObject.addPrototypes(projectFromJSON.rootObject);\n\n    WickProject.fixForBackwardsCompatibility(projectFromJSON);\n    projectFromJSON.library.__proto__ = AssetLibrary.prototype;\n    AssetLibrary.addPrototypes(projectFromJSON.library);\n\n    // Decode scripts back to human-readble and eval()-able format\n    projectFromJSON.rootObject.decodeStrings();\n    projectFromJSON.library.decodeStrings();\n\n    // Add references to wickobject's parents (optimization)\n    projectFromJSON.rootObject.generateParentObjectReferences();\n    projectFromJSON.regenAssetReferences();\n\n    // Start at the first from of the root object\n    projectFromJSON.currentObject = projectFromJSON.rootObject;\n    projectFromJSON.rootObject.playheadPosition = 0;\n    projectFromJSON.currentObject.currentLayer = 0;\n\n    projectFromJSON.currentObject = projectFromJSON.rootObject;\n\n    return projectFromJSON;\n}\n\n// Backwards compatibility for old Wick projects\nWickProject.fixForBackwardsCompatibility = function (project) {\n\n    var allObjectsInProject = project.rootObject.getAllChildObjectsRecursive();\n    allObjectsInProject.push(project.rootObject);\n    allObjectsInProject.forEach(function (wickObj) {\n        // Tweens belong to frames now\n        if(wickObj.tweens) wickObj.tweens = null;\n\n        if(!wickObj.isSymbol) return\n        wickObj.layers.forEach(function (layer) {\n            if(!layer.locked) layer.locked = false;\n            if(!layer.hidden) layer.hidden = false;\n            layer.frames.forEach(function (frame) {\n                if(!frame.tweens) frame.tweens = [];\n                // Make sure tweens have rotations now\n                frame.tweens.forEach(function (tween) {\n                    if(!tween.rotations) tween.rotations = 0;\n                });\n            });\n        });\n    });\n\n    // Selection is handled in the project now\n    if(!project._selection){\n        project._selection = [];\n    }\n\n    // Data for sounds and images is stored in the asset library now\n    if(!project.library) {\n        project.library = new AssetLibrary();\n\n        allObjectsInProject.forEach(function (wickObject) {\n            if(wickObject.imageData) {\n                var asset = new WickAsset(wickObject.imageData, 'image', 'untitled');\n                wickObject.assetUUID = project.library.addAsset(asset);\n                wickObject.isImage = true;\n                wickObject.imageData = null;\n                wickObject.name = 'untitled';\n            } else if(wickObject.audioData) {\n                var asset = new WickAsset(wickObject.imageData, 'audio', 'untitled');\n                var assetUUID = project.library.addAsset(asset);\n            }\n        })\n    }\n\n    project.library.__proto__ = AssetLibrary.prototype;\n    project.library.regenAssetUUIDs();\n\n}\n\nWickProject.prototype.getAsJSON = function (callback, format) {\n\n    var self = this;\n\n    // Encode scripts/text to avoid JSON format problems\n    self.rootObject.encodeStrings();\n    self.library.encodeStrings();\n\n    // Add some browser/OS/wick editor version info for debugging other ppl's projects\n    self.metaInfo = getBrowserAndOSInfo();\n    self.metaInfo.wickVersion = wickEditor.version;\n    self.metaInfo.dateSaved = new Date().toGMTString();\n\n    var JSONProject = JSON.stringify(self, WickProject.Exporter.JSONReplacer, format);\n    \n    // Decode scripts back to human-readble and eval()-able format\n    self.rootObject.decodeStrings();\n    self.library.decodeStrings();\n\n    callback(JSONProject);\n\n}\n\nWickProject.prototype.getCopyData = function () {\n    var objectJSONs = [];\n    var objects = this.getSelectedObjects();\n    objects.forEach(function(obj) {\n        if(obj instanceof WickObject)\n            obj._tempZIndex = wickEditor.project.getCurrentFrame().wickObjects.indexOf(obj);\n    })\n    objects.sort(function (a,b) {\n        return a._tempZIndex - b._tempZIndex;\n    });\n    for(var i = 0; i < objects.length; i++) {\n        objectJSONs.push(objects[i].getAsJSON());\n    }\n    var clipboardObject = {\n        groupPosition: {x : 0,\n                        y : 0},\n        wickObjectArray: objectJSONs\n    }\n    return JSON.stringify(clipboardObject);\n}\n\nWickProject.prototype.getCurrentObject = function () {\n    return this.currentObject;\n}\n\nWickProject.prototype.getCurrentLayer = function () {\n    return this.getCurrentObject().getCurrentLayer();\n}\n\nWickProject.prototype.getCurrentFrame = function () {\n    return this.getCurrentObject().getCurrentLayer().getCurrentFrame();\n}\n\nWickProject.prototype.getCurrentFrames = function () {\n    return this.getCurrentObject().getCurrentFrames();\n}\n\nWickProject.prototype.getAllObjects = function () {\n    var allObjectsInProject = this.rootObject.getAllChildObjectsRecursive();\n    return allObjectsInProject;\n}\n\nWickProject.prototype.getAllFrames = function () {\n    var frames = [];\n\n    var allObjectsInProject = this.getAllObjects();\n    allObjectsInProject.forEach(function (obj) {\n        frames = frames.concat(obj.getAllFrames());\n    });\n\n    return frames;\n}\n\nWickProject.prototype.getObjectByUUID = function (uuid) {\n    var allObjectsInProject = this.rootObject.getAllChildObjectsRecursive();\n    allObjectsInProject.push(this.rootObject);\n\n    var foundObj = null;\n    allObjectsInProject.forEach(function (object) {\n        if(foundObj) return;\n        if(object.uuid === uuid) {\n            foundObj = object;\n        }\n    });\n\n    return foundObj;\n}\n\nWickProject.prototype.getObject = function (name) {\n    return this.getObjectByName(name);\n}\n\nWickProject.prototype.getObjectByName = function (name) {\n    var allObjectsInProject = this.rootObject.getAllChildObjectsRecursive();\n    allObjectsInProject.push(this.rootObject);\n\n    var foundObj = null;\n    allObjectsInProject.forEach(function (object) {\n        if(foundObj) return;\n        if(object.name === name) {\n            foundObj = object;\n        }\n    });\n\n    return foundObj;\n}\n\nWickProject.prototype.getFrameByUUID = function (uuid) {\n    var allObjectsInProject = this.rootObject.getAllChildObjectsRecursive();\n    allObjectsInProject.push(this.rootObject);\n\n    var foundFrame = null;\n    allObjectsInProject.forEach(function (object) {\n        if(!object.isSymbol) return;\n        object.layers.forEach(function (layer) {\n            layer.frames.forEach(function (frame) {\n                if(frame.uuid === uuid) {\n                    foundFrame = frame;\n                }   \n            });\n        })\n    });\n\n    return foundFrame;\n}\n\nWickProject.prototype.addObject = function (wickObject, zIndex, ignoreSymbolOffset, frame) {\n\n    var frame = frame || this.getCurrentFrame();\n\n    if(!ignoreSymbolOffset) {\n        var insideSymbolOffset = this.currentObject.getAbsolutePosition();\n        wickObject.x -= insideSymbolOffset.x;\n        wickObject.y -= insideSymbolOffset.y;\n    }\n\n    if(!wickObject.uuid) wickObject.uuid = random.uuid4();\n    \n    if(zIndex === undefined || zIndex === null) {\n        frame.wickObjects.push(wickObject);\n    } else {\n        frame.wickObjects.splice(zIndex, 0, wickObject);\n    }\n\n    this.rootObject.generateParentObjectReferences();\n\n}\n\nWickProject.prototype.getNextAvailableName = function (baseName) {\n\n    var nextName = baseName;\n    var number = 0;\n\n    this.getAllObjects().forEach(function (object) {\n        if(!object.name) return;\n        var nameSuffix = object.name.split(baseName)[1]\n\n        if(nameSuffix === \"\") {\n            if(number === 0)\n                number = 1;\n        } else {\n            var prefixNumber = parseInt(nameSuffix);\n            if(!isNaN(prefixNumber) && prefixNumber > number) \n                number = prefixNumber;\n        }\n    });\n\n    if(number === 0) {\n        return baseName;\n    } else {\n        return baseName + \" \" + (number+1);\n    }\n\n}\n\nWickProject.prototype.jumpToObject = function (obj) {\n\n    var that = this;\n\n    this.rootObject.getAllChildObjectsRecursive().forEach(function (child) {\n        if(child.uuid === obj.uuid) {\n            that.currentObject = child.parentObject;\n        }\n    });\n\n    var currentObject = this.currentObject;\n    var frameWithChild = currentObject.getFrameWithChild(obj);\n    var playheadPositionWithChild = frameWithChild.playheadPosition\n    currentObject.playheadPosition = playheadPositionWithChild;\n\n}\n\nWickProject.prototype.jumpToFrame = function (frame) {\n\n    var that = this;\n\n    var allObjectsInProject = this.rootObject.getAllChildObjectsRecursive();\n    allObjectsInProject.push(this.rootObject);\n    allObjectsInProject.forEach(function (child) {\n        if(!child.isSymbol) return;\n        child.layers.forEach(function (layer) {\n            layer.frames.forEach(function (currframe) {\n                if(frame === currframe) {\n                    that.currentObject = child;\n                }\n            })\n        })\n    });\n\n    var currentObject = this.currentObject;\n    var frameWithChild = frame;\n    var playheadPositionWithChild = frameWithChild.playheadPosition\n    currentObject.playheadPosition = playheadPositionWithChild;\n}\n\nWickProject.prototype.hasSyntaxErrors = function () {\n\n    var projectHasSyntaxErrors = false;\n\n    this.rootObject.getAllChildObjectsRecursive().forEach(function (child) {\n        child.getAllFrames().forEach(function (frame) {\n            if(frame.scriptError && frame.scriptError.type === 'syntax') {\n                projectHasSyntaxErrors = true;\n            }\n        });\n\n        if(child.scriptError && child.scriptError.type === 'syntax') {\n            projectHasSyntaxErrors = true;\n        }\n    });\n\n    return projectHasSyntaxErrors;\n\n}\n\nWickProject.prototype.handleWickError = function (e, objectCausedError) {\n\n    objectCausedError = window.errorCausingObject\n    if(objectCausedError.objectClonedFrom) {\n        objectCausedError = objectCausedError.objectClonedFrom\n    }\n\n    if (window.wickEditor) {\n        //if(!wickEditor.builtinplayer.running) return;\n\n        console.log(\"Exception thrown while running script of WickObject: \" + this.name);\n        console.log(e);\n        var lineNumber = null;\n        if(e.stack) {\n            e.stack.split('\\n').forEach(function (line) {\n                if(lineNumber) return;\n                if(!line.includes(\"<anonymous>:\")) return;\n\n                lineNumber = parseInt(line.split(\"<anonymous>:\")[1].split(\":\")[0]);\n            });\n        }\n        if(lineNumber) lineNumber -= 12;\n\n        //console.log(e.stack.split(\"\\n\")[1].split('<anonymous>:')[1].split(\":\")[0]);\n        //console.log(e.stack.split(\"\\n\"))\n        //if(wickEditor.builtinplayer.running) wickEditor.builtinplayer.stopRunningProject()\n        \n        wickEditor.builtinplayer.stopRunningProject()\n\n        wickEditor.scriptingide.displayError(objectCausedError, {\n            message: e,\n            line: lineNumber,\n            type: 'runtime'\n        });\n\n        objectCausedError.scriptError = {\n            message: e,\n            line: lineNumber,\n            type: 'runtime'\n        }\n\n    } else {\n        alert(\"An exception was thrown while running a WickObject script. See console!\");\n        console.log(e);\n    }\n}\n\nWickProject.prototype.isObjectSelected = function (obj) {\n    var selected = false;\n\n    this._selection.forEach(function (uuid) {\n        if(obj.uuid === uuid) selected = true;\n    });\n\n    return selected;\n}\n\nWickProject.prototype.isTypeSelected = function (type) {\n    var self = this;\n    var selected = false;\n\n    this._selection.forEach(function (uuid) {\n        var obj = self.getObjectByUUID(uuid) \n               || self.getFrameByUUID(uuid);\n        if(obj instanceof type) selected = true;\n    });\n\n    return selected;\n}\n\nWickProject.prototype.getSelectedObject = function () {\n    var selectedObjects = this.getSelectedObjects();\n    if(selectedObjects.length !== 1) {\n        return null;\n    } else {\n        return selectedObjects[0];\n    }\n}\n\nWickProject.prototype.getSelectedObjectByType = function (type) {\n    var selectedObjects = this.getSelectedObjects();\n    returnObject = null;\n    \n    selectedObjects.forEach(function (obj) {\n        if(obj instanceof type) {\n            returnObject = obj;\n        }\n    })\n\n    return returnObject;\n}\n\nWickProject.prototype.getSelectedObjectsByType = function (type) {\n    var selectedObjects = this.getSelectedObjects();\n    \n    selectedObjects = selectedObjects.filter(function (obj) {\n        return (obj instanceof type);\n    })\n\n    return selectedObjects;\n}\n\nWickProject.prototype.getSelectedObjects = function () {\n    var self = this;\n\n    var objs = [];\n    this._selection.forEach(function (uuid) {\n        var obj = self.getObjectByUUID(uuid) \n               || self.getFrameByUUID(uuid);\n               //|| self.getTweenByUUID(uuid);\n        if(obj) objs.push(obj);\n    });\n\n    return objs;\n}\n\nWickProject.prototype.getSelectedWickObjects = function () {\n    var self = this;\n\n    var objs = [];\n    this._selection.forEach(function (uuid) {\n        var obj = self.getObjectByUUID(uuid);\n        if(obj) objs.push(obj);\n    });\n\n    return objs;\n}\n\nWickProject.prototype.getSelectedObjectsUUIDs = function () {\n    var self = this;\n\n    var objs = [];\n    this._selection.forEach(function (uuid) {\n        var obj = self.getObjectByUUID(uuid) \n               || self.getFrameByUUID(uuid);\n        if(obj) objs.push(obj.uuid);\n    });\n\n    return objs;\n}\n\nWickProject.prototype.getNumSelectedObjects = function (obj) {\n    return this.getSelectedObjects().length;\n}\n\nWickProject.prototype.selectObject = function (obj) {\n    wickEditor.inspector.clearSpecialMode();\n    if(this._selection.indexOf(obj.uuid) === -1)\n        this._selection.push(obj.uuid);\n}\n\nWickProject.prototype.selectObjectByUUID = function (uuid) {\n    wickEditor.inspector.clearSpecialMode();\n    if(this._selection.indexOf(uuid) === -1)\n        this._selection.push(uuid);\n}\n\nWickProject.prototype.clearSelection = function () {\n    var thingsWereCleared = false;\n    if(this._selection.length > 0)  thingsWereCleared = true;\n    this._selection = [];\n    return thingsWereCleared;\n}\n\nWickProject.prototype.deselectObject = function (obj) {\n    wickEditor.inspector.clearSpecialMode();\n    for ( var i = 0; i < this._selection.length; i++ ) {\n        var uuid = this._selection[i];\n        if(obj.uuid === uuid) {\n            this._selection[i] = null;\n        }\n    }\n}\n\nWickProject.prototype.deselectObjectType = function (type) {\n    var deselectionHappened = false;\n    \n    for ( var i = 0; i < this._selection.length; i++ ) {\n        var uuid = this._selection[i];\n        var obj = this.getObjectByUUID(uuid) \n               || this.getFrameByUUID(uuid);\n        if(obj instanceof type) {\n            this._selection[i] = null;\n            deselectionHappened = true;\n        }\n    }\n\n    this._selection = this._selection.filter(function (obj) {\n        return obj !== null;\n    });\n\n    return deselectionHappened;\n}\n\nWickProject.prototype.loadBuiltinFunctions = function (contextObject) {\n\n    if(contextObject.wickScript === '') return;\n\n    var objectScope = null;\n    if(contextObject instanceof WickObject) {\n        objectScope = contextObject.parentObject;\n    } else if (contextObject instanceof WickFrame) {\n        objectScope = contextObject.parentLayer.parentWickObject;\n    }\n\n    window.project = wickPlayer.project || wickEditor.project;\n    window.parentObject = contextObject.parentObject;\n    window.root = project.rootObject;\n\n    window.play           = function ()      { objectScope.play(); }\n    window.stop           = function ()      { objectScope.stop(); }\n    window.movePlayheadTo = function (frame) { objectScope.movePlayheadTo(frame); }\n    window.gotoAndStop    = function (frame) { objectScope.gotoAndStop(frame); }\n    window.gotoAndPlay    = function (frame) { objectScope.gotoAndPlay(frame); }\n    window.gotoNextFrame  = function ()      { objectScope.gotoNextFrame(); }\n    window.gotoPrevFrame  = function ()      { objectScope.gotoPrevFrame(); }\n\n    window.keyIsDown      = function (keyString) { return wickPlayer.inputHandler.keyIsDown(keyString); };\n    window.keyJustPressed = function (keyString) { return wickPlayer.inputHandler.keyJustPressed(keyString); }\n    window.mouseX = wickPlayer.inputHandler.getMouse().x;\n    window.mouseY = wickPlayer.inputHandler.getMouse().y;\n    window.mouseMoveX = wickPlayer.inputHandler.getMouseDiff().x;\n    window.mouseMoveY = wickPlayer.inputHandler.getMouseDiff().y;\n    window.hideCursor = function () { wickPlayer.inputHandler.hideCursor(); };\n    window.showCursor = function () { wickPlayer.inputHandler.showCursor(); };\n\n    // WickObjects in same frame (scope) are accessable without using root./parent.\n    if(objectScope) {\n        objectScope.getAllChildObjects().forEach(function(child) {\n            if(child.name) window[child.name] = child;\n        });\n    }\n    if(objectScope) {\n        objectScope.getAllActiveChildObjects().forEach(function(child) {\n            if(child.name) window[child.name] = child;\n        });\n    }\n\n}\n\nvar WickObjectBuiltins = [\n    'load',\n    'update',\n    'mousePressed',\n    'mouseDown',\n    'mouseReleased',\n    'mouseHover',\n    'mouseEnter',\n    \"mouseLeave\",\n    \"keyPressed\",\n    \"keyDown\",\n    \"keyReleased\",\n];\n\nWickProject.prototype.loadScriptOfObject = function (obj) {\n\n    if(obj.wickScript === '') return;\n\n    if(!window.cachedWickScripts) window.cachedWickScripts = {};\n\n    var dummyInitScript = \"\";\n    var dummyLoaderScript = \"\";\n    WickObjectBuiltins.forEach(function (builtinName) {\n        dummyInitScript += 'function ' + builtinName + ' (){return;};\\n';\n        dummyLoaderScript += '\\nthis.'+builtinName+\"=\"+builtinName+\";\";\n    });\n\n    var scriptEventsReplaced = obj.wickScript;\n    var onEventFinderRegex = /^ *on *\\( *[a-zA-Z]+ *\\)/gm\n    var m;\n    do {\n        m = onEventFinderRegex.exec(scriptEventsReplaced, 'g');\n        if (m) {\n            eventName = m[0].split('(')[1].split(')')[0]\n            scriptEventsReplaced = scriptEventsReplaced.replace(m[0], 'function ' + eventName + '()')\n        }\n    } while (m);\n\n    var evalScriptTag = \n        '<script>\\nwindow.cachedWickScripts[\"'+obj.uuid+'\"] = function () {\\n' + \n        dummyInitScript + \n        scriptEventsReplaced + \n        dummyLoaderScript + \n        '\\n}\\n<'+'/'+'script>';\n    $('head').append(evalScriptTag);\n}\n\nWickProject.prototype.initScript = function (obj) {\n    window.errorCausingObject = obj;\n\n    if(!window.cachedWickScripts) window.cachedWickScripts = {};\n    \n    if(!obj.cachedWickScript) {\n        if(obj.sourceUUID) {\n            obj.cachedWickScript = window.cachedWickScripts[obj.sourceUUID];\n        } else {\n            obj.cachedWickScript = window.cachedWickScripts[obj.uuid];\n        }\n    }\n\n    if(obj.cachedWickScript) {\n        this.loadBuiltinFunctions(obj);\n        try {\n            obj.cachedWickScript();\n            //obj.cachedWickScript.call(obj instanceof WickObject ? obj : obj.parentObject);\n        } catch (e) {\n            this.handleWickError(e,obj);\n        }\n    }\n}\n\nWickProject.prototype.runScript = function (obj, fnName, arg1, arg2, arg3) {\n\n    window.errorCausingObject = obj;\n\n    try {\n        if(obj[fnName]) {\n            this.loadBuiltinFunctions(obj);\n            obj[fnName](arg1, arg2, arg3);\n        }\n    } catch (e) {\n        this.handleWickError(e,obj);\n    }\n\n}\n\nWickProject.prototype.regenAssetReferences = function () {\n\n    var self = this;\n\n    self.getAllObjects().forEach(function (obj) {\n        obj.asset = self.library.getAsset(obj.assetUUID);\n    });\n\n}\n\nWickProject.prototype.loadFonts = function (callback) {\n    var self = this;\n    var fontsInProject = [];\n    self.getAllObjects().forEach(function (o) {\n        if(o.isText && o.textData.fontFamily !== 'Arial' && fontsInProject.indexOf(o.textData.fontFamily))\n            fontsInProject.push(o.textData.fontFamily);\n    });\n    if(fontsInProject.length === 0 && callback) {\n        callback()\n    } else {\n        loadGoogleFonts(fontsInProject, function () {\n            if(window.wickEditor) {\n                wickEditor.canvas.getInteractiveCanvas().needsUpdate = true;\n                wickEditor.syncInterfaces();\n            }\n            if(callback) {\n                callback();\n            }\n        });\n    }   \n}\n\nWickProject.prototype.prepareForPlayer = function () {\n    var self = this;\n\n    self.regenAssetReferences();\n\n    self.rootObject.prepareForPlayer();\n    if(window.WickEditor) self.loadFonts();\n\n    self.getAllObjects().forEach(function (obj) {\n        self.loadScriptOfObject(obj);\n    });\n    self.getAllFrames().forEach(function (obj) {\n        self.loadScriptOfObject(obj);\n    });\n}\n\nWickProject.prototype.tick = function () {\n    var allObjectsInProject = this.rootObject.getAllChildObjectsRecursive();\n\n    // Make sure all playhead positions are up to date \n    // (this is deferred to outside the main tick code so timeline changes happen all at once right here)\n    allObjectsInProject.forEach(function (obj) {\n        if(obj._newPlayheadPosition !== undefined)\n            obj.playheadPosition = obj._newPlayheadPosition;\n    });\n\n    allObjectsInProject.forEach(function (obj) {\n        obj._newPlayheadPosition = undefined;\n    });\n    allObjectsInProject.forEach(function (obj) {\n        obj.getAllFrames().forEach(function (frame) {\n            frame._wasActiveLastTick = frame._active;\n            frame._active = frame.isActive();\n        });\n    });\n    allObjectsInProject.forEach(function (obj) {\n        obj._wasActiveLastTick = obj._active;\n        obj._active = obj.isActive();\n    });\n    \n    this.rootObject.tick();\n    this.updateCamera();\n    this.applyTweens();\n}\n\nWickProject.prototype.applyTweens = function () {\n    this.getAllFrames().forEach(function (frame) {\n        frame.applyTween();\n    });\n}\n\nWickProject.prototype.updateCamera = function () {\n    var camera = window.camera;\n    if(!camera) return;\n\n    camera.update();\n\n    var camPos = camera.getPosition();\n    this.rootObject.x = -camPos.x+this.width/2;\n    this.rootObject.y = -camPos.y+this.height/2;\n}\n"
  },
  {
    "path": "src/project/WickTween.js",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\nvar tweenValueNames = [\"x\",\"y\",\"scaleX\",\"scaleY\",\"rotation\",\"opacity\"];\n\nvar WickTween = function() {\n    this.x = 0;\n    this.y = 0; \n    this.z = 0; \n    this.scaleX = 1;\n    this.scaleY = 1;\n    this.rotation = 0;\n    this.opacity = 1;\n\n    this.playheadPosition = 0;\n    this.rotations = 0;\n\n    this.uuid = random.uuid4();\n\n    this.tweenType = 'Linear';\n    this.tweenDir = 'None';\n}\n\nWickTween.fromWickObjectState = function (wickObject) {\n\tvar tween = new WickTween();\n\n\ttweenValueNames.forEach(function (name) {\n\t\ttween[name] = wickObject[name];\n\t});\n\n\treturn tween;\n}\n\nWickTween.prototype.copy = function () {\n    var copy = new WickTween();\n\n    copy.x = this.x;\n    copy.y = this.y; \n    copy.z = this.z; \n    copy.scaleX = this.scaleX;\n    copy.scaleY = this.scaleY;\n    copy.rotation = this.rotation;\n    copy.opacity = this.opacity;\n\n    copy.playheadPosition = this.playheadPosition;\n    copy.rotations = this.rotations;\n\n    copy.tweenType = this.tweenType;\n    copy.tweenDir = this.tweenDir;\n\n    return copy;\n}\n\nWickTween.prototype.updateFromWickObjectState = function (wickObject) {\n    var self = this;\n    \n    tweenValueNames.forEach(function (name) {\n        self[name] = wickObject[name];\n    });\n}\n\nWickTween.prototype.applyTweenToWickObject = function(wickObject) {\n\tvar that = this;\n\n\ttweenValueNames.forEach(function (name) {\n\t\twickObject[name] = that[name];\n\t});\n};\n\nWickTween.interpolateTweens = function (tweenA, tweenB, t) {\n\tvar interpTween = new WickTween();\n\n\tvar tweenFunc = (tweenA.tweenType === \"Linear\") ? (TWEEN.Easing.Linear.None) : (TWEEN.Easing[tweenA.tweenType][tweenA.tweenDir]);\n\ttweenValueNames.forEach(function (name) {\n\t\tvar tt = tweenFunc(t);\n        var valA = tweenA[name];\n        var valB = tweenB[name];\n        if(name === 'rotation') {\n            while(valA < -180) valA += 360;\n            while(valB < -180) valB += 360;\n            while(valA > 180) valA -= 360;\n            while(valB > 180) valB -= 360;\n            valB += tweenA.rotations * 360;\n        }\n\t\tinterpTween[name] = lerp(valA, valB, tt);\n\t});\n\n\treturn interpTween;\n}\n"
  },
  {
    "path": "styles/Open_Sans/LICENSE.txt",
    "content": "\r\n                                 Apache License\r\n                           Version 2.0, January 2004\r\n                        http://www.apache.org/licenses/\r\n\r\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\r\n\r\n   1. Definitions.\r\n\r\n      \"License\" shall mean the terms and conditions for use, reproduction,\r\n      and distribution as defined by Sections 1 through 9 of this document.\r\n\r\n      \"Licensor\" shall mean the copyright owner or entity authorized by\r\n      the copyright owner that is granting the License.\r\n\r\n      \"Legal Entity\" shall mean the union of the acting entity and all\r\n      other entities that control, are controlled by, or are under common\r\n      control with that entity. For the purposes of this definition,\r\n      \"control\" means (i) the power, direct or indirect, to cause the\r\n      direction or management of such entity, whether by contract or\r\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\r\n      outstanding shares, or (iii) beneficial ownership of such entity.\r\n\r\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\r\n      exercising permissions granted by this License.\r\n\r\n      \"Source\" form shall mean the preferred form for making modifications,\r\n      including but not limited to software source code, documentation\r\n      source, and configuration files.\r\n\r\n      \"Object\" form shall mean any form resulting from mechanical\r\n      transformation or translation of a Source form, including but\r\n      not limited to compiled object code, generated documentation,\r\n      and conversions to other media types.\r\n\r\n      \"Work\" shall mean the work of authorship, whether in Source or\r\n      Object form, made available under the License, as indicated by a\r\n      copyright notice that is included in or attached to the work\r\n      (an example is provided in the Appendix below).\r\n\r\n      \"Derivative Works\" shall mean any work, whether in Source or Object\r\n      form, that is based on (or derived from) the Work and for which the\r\n      editorial revisions, annotations, elaborations, or other modifications\r\n      represent, as a whole, an original work of authorship. For the purposes\r\n      of this License, Derivative Works shall not include works that remain\r\n      separable from, or merely link (or bind by name) to the interfaces of,\r\n      the Work and Derivative Works thereof.\r\n\r\n      \"Contribution\" shall mean any work of authorship, including\r\n      the original version of the Work and any modifications or additions\r\n      to that Work or Derivative Works thereof, that is intentionally\r\n      submitted to Licensor for inclusion in the Work by the copyright owner\r\n      or by an individual or Legal Entity authorized to submit on behalf of\r\n      the copyright owner. For the purposes of this definition, \"submitted\"\r\n      means any form of electronic, verbal, or written communication sent\r\n      to the Licensor or its representatives, including but not limited to\r\n      communication on electronic mailing lists, source code control systems,\r\n      and issue tracking systems that are managed by, or on behalf of, the\r\n      Licensor for the purpose of discussing and improving the Work, but\r\n      excluding communication that is conspicuously marked or otherwise\r\n      designated in writing by the copyright owner as \"Not a Contribution.\"\r\n\r\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\r\n      on behalf of whom a Contribution has been received by Licensor and\r\n      subsequently incorporated within the Work.\r\n\r\n   2. Grant of Copyright License. Subject to the terms and conditions of\r\n      this License, each Contributor hereby grants to You a perpetual,\r\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r\n      copyright license to reproduce, prepare Derivative Works of,\r\n      publicly display, publicly perform, sublicense, and distribute the\r\n      Work and such Derivative Works in Source or Object form.\r\n\r\n   3. Grant of Patent License. Subject to the terms and conditions of\r\n      this License, each Contributor hereby grants to You a perpetual,\r\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r\n      (except as stated in this section) patent license to make, have made,\r\n      use, offer to sell, sell, import, and otherwise transfer the Work,\r\n      where such license applies only to those patent claims licensable\r\n      by such Contributor that are necessarily infringed by their\r\n      Contribution(s) alone or by combination of their Contribution(s)\r\n      with the Work to which such Contribution(s) was submitted. If You\r\n      institute patent litigation against any entity (including a\r\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\r\n      or a Contribution incorporated within the Work constitutes direct\r\n      or contributory patent infringement, then any patent licenses\r\n      granted to You under this License for that Work shall terminate\r\n      as of the date such litigation is filed.\r\n\r\n   4. Redistribution. You may reproduce and distribute copies of the\r\n      Work or Derivative Works thereof in any medium, with or without\r\n      modifications, and in Source or Object form, provided that You\r\n      meet the following conditions:\r\n\r\n      (a) You must give any other recipients of the Work or\r\n          Derivative Works a copy of this License; and\r\n\r\n      (b) You must cause any modified files to carry prominent notices\r\n          stating that You changed the files; and\r\n\r\n      (c) You must retain, in the Source form of any Derivative Works\r\n          that You distribute, all copyright, patent, trademark, and\r\n          attribution notices from the Source form of the Work,\r\n          excluding those notices that do not pertain to any part of\r\n          the Derivative Works; and\r\n\r\n      (d) If the Work includes a \"NOTICE\" text file as part of its\r\n          distribution, then any Derivative Works that You distribute must\r\n          include a readable copy of the attribution notices contained\r\n          within such NOTICE file, excluding those notices that do not\r\n          pertain to any part of the Derivative Works, in at least one\r\n          of the following places: within a NOTICE text file distributed\r\n          as part of the Derivative Works; within the Source form or\r\n          documentation, if provided along with the Derivative Works; or,\r\n          within a display generated by the Derivative Works, if and\r\n          wherever such third-party notices normally appear. The contents\r\n          of the NOTICE file are for informational purposes only and\r\n          do not modify the License. You may add Your own attribution\r\n          notices within Derivative Works that You distribute, alongside\r\n          or as an addendum to the NOTICE text from the Work, provided\r\n          that such additional attribution notices cannot be construed\r\n          as modifying the License.\r\n\r\n      You may add Your own copyright statement to Your modifications and\r\n      may provide additional or different license terms and conditions\r\n      for use, reproduction, or distribution of Your modifications, or\r\n      for any such Derivative Works as a whole, provided Your use,\r\n      reproduction, and distribution of the Work otherwise complies with\r\n      the conditions stated in this License.\r\n\r\n   5. Submission of Contributions. Unless You explicitly state otherwise,\r\n      any Contribution intentionally submitted for inclusion in the Work\r\n      by You to the Licensor shall be under the terms and conditions of\r\n      this License, without any additional terms or conditions.\r\n      Notwithstanding the above, nothing herein shall supersede or modify\r\n      the terms of any separate license agreement you may have executed\r\n      with Licensor regarding such Contributions.\r\n\r\n   6. Trademarks. This License does not grant permission to use the trade\r\n      names, trademarks, service marks, or product names of the Licensor,\r\n      except as required for reasonable and customary use in describing the\r\n      origin of the Work and reproducing the content of the NOTICE file.\r\n\r\n   7. Disclaimer of Warranty. Unless required by applicable law or\r\n      agreed to in writing, Licensor provides the Work (and each\r\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\r\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\r\n      implied, including, without limitation, any warranties or conditions\r\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\r\n      PARTICULAR PURPOSE. You are solely responsible for determining the\r\n      appropriateness of using or redistributing the Work and assume any\r\n      risks associated with Your exercise of permissions under this License.\r\n\r\n   8. Limitation of Liability. In no event and under no legal theory,\r\n      whether in tort (including negligence), contract, or otherwise,\r\n      unless required by applicable law (such as deliberate and grossly\r\n      negligent acts) or agreed to in writing, shall any Contributor be\r\n      liable to You for damages, including any direct, indirect, special,\r\n      incidental, or consequential damages of any character arising as a\r\n      result of this License or out of the use or inability to use the\r\n      Work (including but not limited to damages for loss of goodwill,\r\n      work stoppage, computer failure or malfunction, or any and all\r\n      other commercial damages or losses), even if such Contributor\r\n      has been advised of the possibility of such damages.\r\n\r\n   9. Accepting Warranty or Additional Liability. While redistributing\r\n      the Work or Derivative Works thereof, You may choose to offer,\r\n      and charge a fee for, acceptance of support, warranty, indemnity,\r\n      or other liability obligations and/or rights consistent with this\r\n      License. However, in accepting such obligations, You may act only\r\n      on Your own behalf and on Your sole responsibility, not on behalf\r\n      of any other Contributor, and only if You agree to indemnify,\r\n      defend, and hold each Contributor harmless for any liability\r\n      incurred by, or claims asserted against, such Contributor by reason\r\n      of your accepting any such warranty or additional liability.\r\n\r\n   END OF TERMS AND CONDITIONS\r\n\r\n   APPENDIX: How to apply the Apache License to your work.\r\n\r\n      To apply the Apache License to your work, attach the following\r\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\r\n      replaced with your own identifying information. (Don't include\r\n      the brackets!)  The text should be enclosed in the appropriate\r\n      comment syntax for the file format. We also recommend that a\r\n      file or class name and description of purpose be included on the\r\n      same \"printed page\" as the copyright notice for easier\r\n      identification within third-party archives.\r\n\r\n   Copyright [yyyy] [name of copyright owner]\r\n\r\n   Licensed under the Apache License, Version 2.0 (the \"License\");\r\n   you may not use this file except in compliance with the License.\r\n   You may obtain a copy of the License at\r\n\r\n       http://www.apache.org/licenses/LICENSE-2.0\r\n\r\n   Unless required by applicable law or agreed to in writing, software\r\n   distributed under the License is distributed on an \"AS IS\" BASIS,\r\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n   See the License for the specific language governing permissions and\r\n   limitations under the License.\r\n"
  },
  {
    "path": "styles/colorpicker.css",
    "content": "#colorPickerGUI {\n\twidth: 335px;\n\theight: 250px;\n\tposition: absolute;\n\tleft: 0px;\n\ttop: 0px;\n\tborder: 1px solid white;\n\tz-index: 9;\n\tborder-radius: 4px;\n\tbackground-color: #444;\n}\n\n.color-picker-close-button {\n\twidth: 25px;\n\theight: 25px;\n\tfloat: right;\n\tcursor: pointer;\n\tbackground-image: url(\"../resources/check-sign.svg\");\n    background-repeat: no-repeat;\n    background-position: center;\n    text-overflow: clip;\n    overflow: hidden;\n    background-size: 18px 18px;\n    opacity: 1.0;\n    margin-top: 6px;\n\tmargin-right: 6px;\n}\n.color-picker-close-button:hover {\n\topacity: 0.6;\n}\n\n.color-picker-dropper-button {\n\twidth: 25px;\n\theight: 25px;\n\tfloat: right;\n\tcursor: pointer;\n\tbackground-image: url(\"../resources/tools/Dropper.svg\");\n    background-repeat: no-repeat;\n    background-position: center;\n    text-overflow: clip;\n    overflow: hidden;\n    background-size: 25px 25px;\n    opacity: 1.0;\n    margin-top: 3px;\n\tmargin-right: 3px;\n\tposition: absolute;\n\tleft: 122px;\n\ttop: 203px;\n\tz-index: 99999999999;\n}\n.color-picker-dropper-button:hover {\n\topacity: 0.6;\n}\n\n.sp-container {\n\tborder: none !important;\n\tbackground-color: rgba(0,0,0,0) !important;\n}\n\n.sp-palette-container {\n\tborder: none !important;\n}\n\n.sp-picker-container {\n\tborder: none !important;\n}"
  },
  {
    "path": "styles/editor.css",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick.\n\n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n\n* { margin:0; padding:0; } /* to remove the top and left whitespace */\n\n@font-face {\n    font-family:\"Open Sans\";\n    src: url(\"Open_Sans/OpenSans-Regular.ttf\");\n}\n\n.noselect {\n    -webkit-touch-callout: none; /* iOS Safari */\n    -webkit-user-select: none;   /* Chrome/Safari/Opera */\n    -khtml-user-select: none;    /* Konqueror */\n    -moz-user-select: none;      /* Firefox */\n    -ms-user-select: none;       /* Internet Explorer/Edge */\n    user-select: none;           /* Non-prefixed version, currently\n                                  not supported by any browser */\n}\n\n.hideCursor {\n    cursor: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjbQg61aAAAADUlEQVQYV2P4//8/IwAI/QL/+TZZdwAAAABJRU5ErkJggg=='),\n    none !important;\n}\n\nhtml, body { width:100%; height:100%; overflow: hidden; } /* just to be sure these are full screen*/\n\nbody {\n    background-color: #B7B7B7;\n}\n\ncanvas { display:block; } /* To remove the scrollbars */\n\nhr {\n    border: 0;\n    height: 1px;\n    background: #FFF;\n    /*background-image: linear-gradient(to right, #ccc, #999, #ccc);*/\n    margin: 2px;\n}\n\n#editor {\n    display: block;\n    width: 100%;\n    height: 100%;\n}\n\ncanvas:focus {\n    outline: none;\n    outline-style: none;\n}\n\ninput {\n    font-size: 16px;\n    color: #666;\n    border: none;\n}\nselect {\n    font-size: 16px;\n    color: #666;\n    width: 80px;\n}\n\n.GUIBox {\n    position: absolute;\n    font-size: 16px;\n    font-family: \"Anonymous Pro\", \"Helvetica\", \"Arial\", sans-serif;\n    color: #666;\n    background-color: #585757;\n\n/*    border: 1px solid #878787;*/\n\n}\n\n#dropFileMessage {\n    z-index: 999999;\n    display: none;\n    position: absolute;\n    width: 100%;\n    height: 100%;\n    top: 0px;\n    left: 0px;\n    background-color: rgba(255,255,255,0.7);\n    font-size: 32px;\n}\n#dropFileMessageImage {\n    width: 100%;\n    height: 100%;\n    background-image: url(\"../resources/dropfile.png\");\n    background-repeat: no-repeat;\n    background-position: center;\n    background-size: 600px 400px;\n}\n\n#menuBarGUI {\n    display: flex;\n    top: 0px;\n    left: 0px;\n    height: 28px;\n    width: calc(100% - 2px);\n    /*background-color: #31E19C;*/\n    background-color: black;\n    border: 1px solid #585757;\n/*\n    border-top-color: black;\n    border-left-color: black;\n    border-right-color: black;\n*/\n}\n.menubarTab {\n    float:left;\n    margin-top: 3px;\n    margin-left: 10px;\n    margin-right: 10px;\n    cursor: pointer;\n    color: white;\n    padding: 3px;\n\n    -webkit-transition: background-color 100ms linear;\n    -ms-transition: background-color 100ms linear;\n    transition: background-color 100ms linear;\n}\n.menubarTab:hover {\n    cursor: pointer;\n    background-color: #6EF8B0;\n    border-radius: 3px;\n    color: black;\n}\n\n.menubarMenu {\n    top: 30px;\n    left: 0px;\n    line-height: 30px;\n    padding: 5px;\n    min-width: 70px;\n    border-top:none;\n    text-align: left;\n    text-indent: 5px;\n    z-index: 10;\n    box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n    border-radius: 3px;\n    /*background-color: black;*/\n}\n\n.menubarButton {\n    cursor: pointer;\n    color: #FFFFFF;\n\n    -webkit-transition: background-color 100ms linear;\n    -ms-transition: background-color 100ms linear;\n    transition: background-color 100ms linear;\n}\n.menubarButton:hover {\n    cursor: pointer;\n    background-color: #31E19C;\n    border-radius: 3px;\n}\n\n.tab-container{\n    flex: 0 0 auto;\n}\n\n.menuBarProjectControls{\n    display: flex;\n    flex-grow: 1;\n    max-width: calc(100% - 383px);\n}\n\n.menuBarProjectTitle {\n    color: white;\n    cursor: pointer;\n    flex-grow: 1;\n    flex-shrink: 1;\n    overflow: hidden;\n    opacity: 1.0;\n    padding: 6px 0;\n    text-overflow: ellipsis;\n    text-align: right;\n    white-space: nowrap;\n}\n.menuBarProjectTitle:hover {\n    opacity: 0.8;\n}\n\n.unsavedText {\n    color: red;\n}\n.menuBarProjectSettingsButton {\n    flex-shrink: 0;\n    flex-grow: 0;\n    width: 28px;\n    height: 28px;\n    background-image: url(\"../resources/settings.png\");\n    background-repeat: no-repeat;\n    background-position: center;\n    text-overflow: clip;\n    overflow: hidden;\n    background-size: 16px 16px;\n    opacity: 1.0;\n    cursor: pointer;\n}\n.menuBarProjectSettingsButton:hover {\n    opacity: 0.5;\n}\n\n.scriptButton {\n    background: #58F9BA;\n    color: #0b2018;\n    box-shadow: 0 0 2px 0 rgba(0,0,0,0.12), 0 2px 2px 0 rgba(0,0,0,0.24);\n    border-radius: 8px;\n    float: center;\n    width: 180px;\n    text-align: center;\n    font-weight: bold;\n    margin:0 auto;\n    margin-top:5px;\n    padding: 7px;\n}\n\n.scriptButton:hover {\n    cursor: pointer;\n    background: #009688;\n}\n\n.scriptbutton:active {\n    cursor: pointer;\n    background-color: #009688;\n}\n\n.scriptbutton:selected {\n    cursor: pointer;\n    background-color: #009688;\n}\n\n.fontSelector {\n    width:148px;\n}\n\n.jscolor {\n    border-radius: 8px;\n}\n\n.jscolorInline {\n    padding-left: 10px;\n}\n\n#statusBarGUI {\n    top: 1px;\n    right: 1px;\n    text-align: right;\n    display: block;\n    border: none;\n    text-align: right;\n    padding-right: 5px;\n    font-size: 16px;\n    margin-top: 3px;\n    color: #888;\n}\n\n#splashScreenGUI {\n    width: 500px;\n    top: 0px;\n    left: 0px;\n    text-align: center;\n    display: block;\n}\n\n#settingsGUI {\n    width: 170px;\n    top: 0px;\n    left: 0px;\n    text-align: center;\n    display: block;\n}\n\n.rangeslider_handle {\n\n    background-color: aliceblue;\n\n\n}\n\n\n#objectType {\n    margin: 15px;\n}\n#closeSplashScreenButton {\n    right: 5px;\n    top: 5px;\n    position: absolute;\n}\n\n#builtinPlayer {\n    display: none;\n    background-color: rgba(0,0,0,0.7);\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    z-index: 999; /* HA! HA ! i lOVE CSS*/\n    width: 100%;\n    height: 100%;\n}\n#rendererCanvas {\n    /*-webkit-box-shadow: 3px 3px 12px 0px rgba(0,0,0,0.73);\n    -moz-box-shadow: 3px 3px 12px 0px rgba(0,0,0,0.73);\n    box-shadow: 3px 3px 12px 0px rgba(0,0,0,0.73);*/\n}\n#builtinPlayerGUI {\n    top: 0px;\n    left: 0px;\n    text-align: center;\n}\n#closeBuiltinPlayerButton {\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    width: 16px;\n    height: 16px;\n    background-color: none;\n    cursor: pointer;\n\n    background-image: url(\"../resources/close.png\");\n    background-repeat: no-repeat;\n    background-position: center;\n    text-overflow: clip;\n    overflow: hidden;\n    background-size: 16px 16px;\n\n    opacity: 1.0;\n}\n#closeBuiltinPlayerButton:hover {\n    opacity: 0.5;\n}\n\n#builtinPlayerProjectInfo {\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    width: 0px;\n    height: 0px;\n    color: #888;\n    font-weight: bold;\n    text-align: left;\n    font-size: 18px;\n}\n\n#lineColor {\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n    border: 0px solid #666;\n\n    margin-top: 8px;\n    margin-bottom: 8px;\n\n    font-size: 8px;\n    width: 27px;\n    height: 27px;\n}\n\n#objectTypeName {\n    color: #FAFAFA\n}\n\n#rightClickMenu {\n    position: fixed;\n    top: 0px;\n    left: 0px;\n    background-color: #2b2b2b;\n    display: none;\n    z-index: 11110;\n    border-radius: 3px;\n    padding: 3px;\n    box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n}\n.rightClickMenuButton {\n    padding: 2px;\n    background-color: transparent;\n    color: white;\n    cursor: pointer;\n    border-radius: 5px;\n}\n.rightClickMenuButton:hover {\n    background-color: #31E19C;\n    color: black;\n}\n.rightClickMenuButtonIcon {\n    background-repeat: no-repeat;\n    background-position: center;\n    text-overflow: clip;\n    background-size: 10px 10px;\n    width: 13px;\n    height: 13px;\n    float: left;\n    margin-right: 3px;\n\n}\n\n#popupGUI {\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    background-color: #EEEEEE;\n    display: none;\n}\n\n.button {\n    padding: 4px;\n}\n.button:hover {\n    cursor: pointer;\n    background-color: #a5a5a5;\n/*    border-radius: 2px;*/\n}\n.button:active {\n    cursor: pointer;\n    background-color: #A0A0A0;\n}\n.button:selected {\n    cursor: pointer;\n    background-color: #A1A1A1;\n}\n.activeScriptButton {\n    background-color: #FFFFFF;\n}\n\n.buttonInRow {\n    float: left;\n}\n\n.fabricButton {\n    position: fixed;\n    display: block;\n    width: 21px;\n    height: 21px;\n\n    top: 0px;\n    left: 0px;\n    text-align: center;\n    display: block;\n\n    background-color: #EEEEEE;\n\n    margin: 5px;\n\n    border: 1px solid #bbb;\n/*  border-radius: 2px;*/\n\n    /*box-shadow: 2px 2px 2px #AAA;*/\n}\n\n.elemInRow {\n    float: left;\n}\n\n#timelineGUI {\n    top: 45px;\n    left:46px; /*0px;*/\n    /*padding: 10px;*/\n    width: calc(100% - 266px);\n    background-color: #E6E6E6;\n    overflow: hidden;\n}\n\n#layersGUI {\n    top: 30px;\n    left: 35px;\n    width: 33px;\n    height: /*84px;*/ 10px;\n    background-color: #E6E6E6;\n}\n\n#timelineScrollbar {\n    overflow-x:scroll;\n}\n\n#timelineScrollbarFiller {\n    width:3000px;\n    height:1px;\n}\n\n#gifImportDummyElem {\n    display: none;\n    visibility: hidden;\n}\n\n.paperCanvas {\n    position: absolute;\n    bottom: 6px;\n    right: 6px;\n}\n\n\n.hidden {\n    position: absolute;\n    bottom: 0;\n    left: 0;\n    width: 10px;\n    height: 10px;\n    display: block;\n    font-size: 1;\n    z-index: -1;\n    color: transparent;\n    background: transparent;\n    overflow: hidden;\n    border: none;\n    padding: 0;\n    resize: none;\n    outline: none;\n    -webkit-user-select: text;\n    user-select: text;\n    /* Because for user-select:none, Safari won't allow input */\n}\n\n.thumbnailPreview {\n    position: absolute;\n    left: 130px;\n    top: 130px;\n    width: 100px;\n    height: 100px;\n    background-color: blue;\n}\n\n#tooltipGUI {\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    background-color: #FFFFFF;\n    display: none;\n    z-index: 1000;\n    border: none;\n    padding-left:5px;\n    padding-right: 5px;\n    max-width: 300px;\n    box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n    padding: 2px;\n    opacity: 0.0;\n    pointer-events: none;\n    border-radius: 2px;\n\n    transition: opacity 0.15s ease-in-out;\n    -moz-transition: opacity 0.15s ease-in-out;\n    -webkit-transition: opacity 0.15s ease-in-out;\n}\n\n#alert-box {\n    position: absolute;\n    right: 15px;\n    top: 15px;\n    width: 300px;\n    height: 50px;\n    z-index: 999999;\n    background-color: #777;\n    box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n    background-color: #585757;\n\n    border-radius: 5px;\n\n    transition: opacity .25s ease-in-out;\n    -moz-transition: opacity .25s ease-in-out;\n    -webkit-transition: opacity .25s ease-in-out;\n\n    opacity: 0.0;\n\n    cursor: pointer;\n}\n#alert-box:hover {\n    background-color: #31E19C;\n}\n\n\n.alert-box-icon {\n    background-image: url(\"../resources/check-sign.svg\");\n    background-repeat: no-repeat;\n    background-position: center;\n    text-overflow: clip;\n    background-size: 30px 30px;\n\n    color: white;\n\n    float: left;\n    width: 50px;\n    height: 50px;\n}\n.alert-box-text {\n    float: right;\n\n    color: white;\n    font-size: 24px;\n\n    text-align: center;\n    margin-top: 10px;\n\n    width: 250px;\n    height: 50px;\n}\n\n#previewRenderContainer {\n    position: absolute;\n    left: 0px;\n    top: 0px;\n    background-color: rgba(0,0,0,0);\n    width: 100%;\n    height: 100%;\n    overflow: hidden;\n    display: none;\n    pointer-events: none;\n}\n\n#builtinPlayerViewer {\n    position: absolute;\n    left: 0px;\n    top: 0px;\n    border: none;\n    -webkit-box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n    -moz-box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n    box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n}\n\n#cursorIcon {\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    display: none;\n    width: 15px;\n    height: 15px;\n\n    pointer-events: none;\n    background-color: transparent;\n\n    background-repeat: no-repeat;\n    background-position: center;\n    background-size: 15px 15px;\n}\n\n.alpha-warning {\n    position: absolute;\n    right: 15px;\n    top: 15px;\n    width: 300px;\n    height: 115px;\n    background-color: #e05a12;\n    box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n    z-index: 999999999;\n    font-size: 18px;\n    border-radius: 3px;\n\n    font-weight: normal;\n    font-family: \"Anonymous Pro\", \"Helvetica\", \"Arial\", sans-serif;\n    color: #FFFFFF;\n}\n\n.alpha-warning-text {\n    text-align: center;\n    width: 90%;\n    height: 90%;\n    margin: 10px;\n}\n\n.alpha-warning-hr {\n    width: 60%;\n    margin-left: 20%;\n}\n\n.alpha-warning-closebutton {\n    position: absolute;\n    top: 3px;\n    right: 3px;\n    width: 20px;\n    height: 20px;\n    font-weight: normal;\n    font-family: \"Arial\", sans-serif;\n    text-align: center;\n    font-size: 20px;\n    cursor: pointer;\n    opacity: 1.0;\n\n    background-image: url(\"../resources/close.svg\");\n    background-repeat: no-repeat;\n    background-position: center;\n    text-overflow: clip;\n    background-size: 15px 15px;\n}\n.alpha-warning-closebutton:hover {\n    opacity: 0.6;\n}\n\n.forums-link {\n    font-weight: bold;\n    text-decoration: underline;\n    color: white;\n}\n\n#editorSettingsGUI {\n    border-radius: 3px;\n    left: 50%;\n    top: 50%;\n    width: 500px;\n    height: 80%;\n    position: absolute;\n    z-index: 10;\n    box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n    transform: translateX(-50%) translateY(-50%);\n    display: none;\n}\n\n.editorSettingsGUITitle {\n    color: white;\n    width: 100%;\n    height: 25px;\n    text-align: center;\n    margin-top: 10px;\n    font-weight: bold;\n    font-size: 14px;\n}\n\n.editorSettingsGUICloseButton {\n    position: absolute;\n    right: 6px;\n    top: 6px;\n    width: 12px;\n    height: 12px;\n    border-radius: 3px;\n    background-color: transparent;\n    cursor: pointer;\n\n    background-image: url(\"../resources/close.png\");\n    background-repeat: no-repeat;\n    background-position: center;\n    background-size: 12px 12px;\n}\n.editorSettingsGUICloseButton:hover {\n    background-color: rgba(255,255,255,0.5);\n}\n.editorSettingsGUIHotkeys {\n    width: 100%;\n    height: 90%;\n    overflow-y: scroll;\n    font-size: 14px;\n}\n\n.editorCreditsContent {\n    color: white;\n    width: 100%;\n    height: 100%;\n}\n\n#editorCreditsGUI {\n    border-radius: 3px;\n    left: 50%;\n    top: 50%;\n    width: 500px;\n    height: 400px;\n    position: absolute;\n    z-index: 10;\n    box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n    transform: translateX(-50%) translateY(-50%);\n    display: none;\n}\n\n.GUIBoxCloseButton {\n    position: absolute;\n    right: 6px;\n    top: 6px;\n    width: 12px;\n    height: 12px;\n    border-radius: 3px;\n    background-color: transparent;\n    cursor: pointer;\n\n    background-image: url(\"../resources/close.png\");\n    background-repeat: no-repeat;\n    background-position: center;\n    background-size: 12px 12px;\n}\n\n.GUIBoxCloseButton:hover {\n    background-color: rgba(255,255,255,0.5);\n}\n\n.GUIBoxTitle {\n    color: white;\n    width: 100%;\n    height: 25px;\n    text-align: center;\n    margin-top: 10px;\n    font-weight: bold;\n    font-size: 14px;\n}\n\n.editorCreditsCloseButton {\n    position: absolute;\n    right: 6px;\n    top: 6px;\n    width: 12px;\n    height: 12px;\n    border-radius: 3px;\n    background-color: transparent;\n    cursor: pointer;\n\n    background-image: url(\"../resources/close.png\");\n    background-repeat: no-repeat;\n    background-position: center;\n    background-size: 12px 12px;\n}\n\n.editorCreditsCloseButton:hover {\n    background-color: rgba(255,255,255,0.5);\n}\n\n.hotkey {\n    margin-left: 5%;\n    width: 90%;\n    height: 17px;\n    color: white;\n}\n.hotkey-title {\n    width: 47%;\n    height: 100%;\n    float:left;\n    text-align: left;\n    font-weight: bold;\n}\n.hotkey-description {\n    width: 47%;\n    height: 100%;\n    float:right;\n    text-align: left;\n    font-weight: normal;\n}\nhr.hotkeyhr {\n    margin: 2px;\n    margin-bottom: 4px;\n    background-color: rgba(255,255,255,0.5)\n}\n\n#wick-editor-version {\n    position: absolute;\n    width: 220px;\n    height: 15px;\n    font-size: 13px;\n    bottom: 0px;\n    margin-bottom: 3px;\n    right: 0px;\n    color: white;\n    font-family: \"Anonymous Pro\", \"Helvetica\", \"Arial\", sans-serif;\n    text-align: center;\n    cursor: pointer;\n}\n#wick-editor-version:hover {\n    color: gray;\n}\n\n#treeFilterInput {\n    color: #4E4D4D;\n    width: 100%;\n    padding-left: 2px;\n    background: #A2A2A2 url(../resources/icon_search.png) no-repeat scroll 3px 3px;\n    background-size: 12px 12px;\n    padding-left:20px;\n    text-overflow: ellipsis;\n    display: block;\n    border-radius: 2px 2px 0px 0px;\n\n}\n"
  },
  {
    "path": "styles/inspector.css",
    "content": "#inspectorGUI {\n    right: 0px;\n    top: 0px;\n    margin-top: 30px;\n    height: calc(100% - 25px);\n    width: 210px;\n    display: inline;\n    overflow: hidden;\n    border-right: 0px;\n    border-bottom: 0px;\n    font-family: \"Open Sans\";\n    padding: 5px;\n}\n\n#inspector-title {\n\tcolor: #BBB;\n\ttext-align: center;\n\tbackground-color: #666;\n\twidth: 100%;\n\tborder-radius: 3px;\n}\n\n.inspector-selection-icon {\n\twidth: 50px;\n\theight: 50px;\n\n\tbackground-repeat: no-repeat;\n    background-position: center;\n    text-overflow: clip;\n    overflow: hidden;\n    background-size: 60% 60%;\n    float: left;\n}\n\n.inspector-title-bar {\n\theight: 50px;\n\twidth: 100%;\n}\n\n.inspector-selection-title {\n\tcolor: white;\n\tfont-size: 20px;\n\twidth: calc(100% - 55px);\n\theight: 45px;\n\tfloat: right;\n\tmargin-top: 12px;\n\tmargin-left: 5px;\n}\n\n.inspector-allitems-container {\n\twidth: 100%;\n\theight: 59%;\n\toverflow-y: auto;\n}\n\n.inspector-properties-container {\n\twidth: 100%;\n\theight:auto;\n\tpadding-top: 5px;\n\tpadding-bottom: 10px;\n    display: flex;\n    flex-wrap: wrap;\n    justify-content: center;\n}\n\n.inspector-buttons-container {\n\twidth: calc(100% - 20px);\n\tpadding-left: 10px;\n\theight:auto;\n\tpadding-bottom: 15px;\n\n\tdisplay: -webkit-flex;\n    display: flex;\n    flex-wrap: wrap;\n    justify-content: center;\n}\n\n.inspector-icon {\n\twidth: 16px;\n\theight: 16px;\n}\n\n/***************************************************************/\n\n.inspector-property {\n\theight: 28px;\n\twidth: 95%;\n\toverflow: hidden;\n}\n\n.inspector-input-title {\n\tcolor: white;\n\n\twidth: calc(28% - 15px);\n\tpadding-right: 10px;\n\theight: 20px;\n\n\tfont-size: 11.5px;\n\tpadding-top: 4px;\n\n\tfloat: left;\n\n\ttext-align: right;\n}\n.inspector-input-title-small {\n\twidth: 10%;\n\ttext-align: center;\n\tpadding-left: 5px;\n\tpadding-right: 5px;\n}\n\n.inspector-input-string {\n\tborder-radius: 4px;\n\n\twidth: 65%;\n\theight: 22px;\n\n\tfloat: left;\n\tmargin-bottom: 4px;\n\n\ttext-align: center;\n\n\tfont-size: 14px;\n}\n.inspector-input-string-small {\n\twidth: 25%;\n}\n.inspector-input-string-tiny {\n\twidth: 15%;\n}\n\n.inspector-input-slider {\n\twidth: 45%;\n\t-webkit-appearance: none;\n    height: 22px;\n    background: #d3d3d3;\n    outline: none;\n    opacity: 0.7;\n    -webkit-transition: .2s;\n    transition: opacity .2s;\n    margin-left: 10px;\n    border-radius: 3px;\n}\n.inspector-input-slider:hover {\n\topacity: 1.0;\n}\n.inspector-input-slider::-webkit-slider-thumb {\n    -webkit-appearance: none;\n    appearance: none;\n    width: 15px;\n    height: 22px;\n    background: #fff;\n    cursor: pointer;\n    border-radius: 2px;\n}\n.inspector-input-slider::-moz-range-thumb {\n    width: 22px;\n    height: 22px;\n    background: #fff;\n    cursor: pointer;\n    border-radius: 2px;\n}\n\n.inspector-input-checkbox {\n\twidth: 50%;\n\theight: 16px;\n\n\tfloat: left;\n\tmargin-top: 4px;\n\tmargin-bottom: 4px;\n}\n\n.inspector-input-togglebutton {\n\twidth: 21.4px;\n\theight: 22px;\n\tborder-radius: 2px;\n\tcursor: pointer;\n\n\tfloat: left;\n\tmargin-top: 0px;\n\tmargin-bottom: 4px;\n\tmargin-right: 3px;\n\n\tborder: 1px solid #FFF;\n\tbackground-color: rgba(0,0,0,0);\n\topacity: 1.0;\n\n\tbackground-repeat: no-repeat;\n    background-position: center;\n    text-overflow: clip;\n    overflow: hidden;\n    background-size: 70% 70%;\n    float: center;\n}\n.inspector-input-togglebutton:hover {\n\tbackground-color: #444;\n}\n.inspector-input-togglebutton:active {\n\t\n}\n.inspector-input-togglebutton-activated {\n\tbackground-color: #CCC;\n}\n.inspector-input-togglebutton:hover {\n\tbackground-color: #AAA;\n}\n\n.inspector-input-select {\n\twidth: 65%;\n\theight: 22px;\n\n\tfloat: left;\n\tmargin-bottom: 4px;\n}\n\n.inspector-color-picker {\n\twidth: 65%;\n\theight: 22px;\n\n\tfloat: left;\n\tmargin-bottom: 0px;\n\t/*margin-left: 16px;\n\tmargin-right: 16px;*/\n\n\toverflow: hidden;\n\n\tborder: 1px solid white;\n\tborder-radius: 3px;\n\n\tcursor: pointer;\n\topacity: 1.0;\n}\n.inspector-color-picker:hover {\n\topacity: 0.8;\n}\n\n.inspector-color-picker-small {\n\twidth: 24%;\n}\n\n.inspector-button {\n\twidth: 30px;\n\theight: 30px;\n\n\tmargin: 6px;\n\n\tborder-radius: 4px;\n\n    background-repeat: no-repeat;\n    background-position: center;\n    text-overflow: clip;\n    overflow: hidden;\n    background-size: 60% 60%;\n\n    box-shadow: 2px 2px 2px rgba(0,0,0,0.5);\n\n    cursor: pointer;\n\n    opacity: 1.0;\n\n    -webkit-transition: opacity 100ms linear;\n    -ms-transition: opacity 100ms linear;\n    transition: opacity 100ms linear;\n}\n\n.inspector-button-common {\n\tbackground-color: #4ECDC4;\n}\n\n.inspector-button-multiple {\n\tbackground-color: #556270;\n}\n\n.inspector-button-symbol {\n\tbackground-color: #FF6B6B;\n}\n\n.inspector-button-all-paths {\n\tbackground-color: #FF6B6B;\n}\n\n.inspector-button-frames {\n\tbackground-color: #C44D58;\n}\n\n.inspector-button-playranges {\n\tbackground-color: #C44D58;\n}\n\n.inspector-button-tweens {\n\tbackground-color: #556270;\n}\n\n.inspector-divider {\n\twidth: 100%;\n\theight: 0px;\n\tclear: left;\n}\n\n/***************************************************************/\n\n.inspector-button:hover {\n\topacity: 1.0;\n}\n\n.inspector-button:hover {\n\topacity: 0.7;\n}\n\n.inspector-button:active {\n\topacity: 0.3;\n}\n"
  },
  {
    "path": "styles/library.css",
    "content": "#treeContainer {\n\tposition: absolute;\n    top: 70%;\n    bottom: 40px;\n\tleft: 10px;\n    right: 10px;\n    /*height: 100%;*/\n\twidth: calc(100% - 20px);\n\toverflow: hidden;\n  \tborder-radius: 3px;\n}\n\n#asset-library-title {\n\tcolor: white;\n\tmargin-bottom: 3px;\n}\n\n#tree {\n  \tborder-radius: 0px 0px 2px 2px;\n\tposition: absolute;\n\twidth: 100%;\n\tborder: none;\n\tbackground-color: white;\n\theight: calc(100% - 60px);\n\toverflow-y: auto;\n\tbackground-color: #CFCFCF;\n    box-sizing:border-box;\n}\n\n#draggedAsset {\n\tposition: absolute;\n    top: 0px;\n    left: 0px;\n    display: none;\n    pointer-events: none;\n    width: 100px;\n    height: 100px;\n    opacity: 0.6;\n    transform: translateX(-50%) translateY(-50%);\n    background-size: 100px 100px;\n}\n\n#fancytree-container {\n\tborder-radius: 2px;\n\tbackground-color: rgba(0,0,0,0);\n}\n\n#treeFilterInput {\n    color: #4E4D4D;\n    width: 100%;\n    background: #A2A2A2 url(../resources/icon_search.png) no-repeat scroll 3px 3px;\n    background-size: 12px 12px;\n    padding-left:20px;\n    text-overflow: ellipsis; \n    display: block;\n    border-radius: 2px 2px 0px 0px;\n    box-sizing:border-box;\n\n}\n\n#treeOptionsContainer {\n    position: absolute;\n    height: 20px;\n    background-color: #CFCFCF;\n    width: 100%;\n    bottom: 0px;\n    border-top: #A2A2A2 1px solid;\n    border-radius: 0px 0px 2px 2px;\n}\n\n.assetLibraryButton {\n    padding-right:2px;\n    text-align: right; \n}\n\n.fancytree-expander {\n    width: 1px !important; \n    height: 1px !important; \n}\n\nspan.fancytree-title {\n    border-radius: 3px !important; \n    color: #585757     !important;\n}\n\n.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-active span.fancytree-title,\n.fancytree-plain.fancytree-container.fancytree-treefocus span.fancytree-selected span.fancytree-title {\n    background-color: #CFCFCF !important;\n    border-color: #585757     !important;\n    color:#585757             !important;\n}\n\nspan.fancytree-title:hover {\n    background-color: #585757 !important; \n    border-color: #585757     !important;\n    color: #CFCFCF            !important;\n}\n\nspan.fancytree-title:active {\n    background-color: #585757 !important; \n    border-color: #585757     !important;\n    color: #CFCFCF            !important;\n}\n\n.assetLibraryButton {\n    height: 20px; \n    width: 20px;\n    float: right; \n    background: #CFCFCF no-repeat 1px 0px;\n    background-size: 20px 20px;\n    border-radius: 2px;\n}\n\n.assetLibraryButton:hover {\n    background: #A2A2A2 no-repeat 1px 0px;\n    background-size: 20px 20px;\n    cursor: pointer;\n}\n\n.assetLibraryButton:active {\n    background: #CFCFCF no-repeat 1px 0px;\n    background-size: 20px 20px;\n    cursor: pointer;\n}\n\n#deleteAssetButton {\n    background-image: url(../resources/delete_layer.png);\n}\n\n#renameAssetButton {\n    background-image: url(../resources/rename.png);\n}\n"
  },
  {
    "path": "styles/progressBar.css",
    "content": "/*\n\t CSS-Tricks Example\n\t by Chris Coyier\n\t http://css-tricks.com\n*/\n\n.meter { \n    height: 20px;  /* Can be anything */\n    position: relative;\n    background: #555;\n    -moz-border-radius: 10px;\n    -webkit-border-radius: 10px;\n    border-radius: 10px;\n    padding: 10px;\n    -webkit-box-shadow: inset 0 -1px 1px rgba(255,255,255,0.3);\n    -moz-box-shadow   : inset 0 -1px 1px rgba(255,255,255,0.3);\n    box-shadow        : inset 0 -1px 1px rgba(255,255,255,0.3);\n}\n\n.meter > span {\n    display: block;\n    height: 100%;\n       -webkit-border-top-right-radius: 6px;\n    -webkit-border-bottom-right-radius: 6px;\n           -moz-border-radius-topright: 6px;\n        -moz-border-radius-bottomright: 6px;\n               border-top-right-radius: 6px;\n            border-bottom-right-radius: 6px;\n        -webkit-border-top-left-radius: 6px;\n     -webkit-border-bottom-left-radius: 6px;\n            -moz-border-radius-topleft: 6px;\n         -moz-border-radius-bottomleft: 6px;\n                border-top-left-radius: 6px;\n             border-bottom-left-radius: 6px;\n    background-color: rgb(43,194,83);\n    background-image: -webkit-gradient(\n      linear,\n      left bottom,\n      left top,\n      color-stop(0, rgb(43,194,83)),\n      color-stop(1, rgb(84,240,84))\n     );\n    background-image: -moz-linear-gradient(\n      center bottom,\n      rgb(43,194,83) 37%,\n      rgb(84,240,84) 69%\n     );\n    -webkit-box-shadow: \n      inset 0 2px 9px  rgba(255,255,255,0.3),\n      inset 0 -2px 6px rgba(0,0,0,0.4);\n    -moz-box-shadow: \n      inset 0 2px 9px  rgba(255,255,255,0.3),\n      inset 0 -2px 6px rgba(0,0,0,0.4);\n    box-shadow: \n      inset 0 2px 9px  rgba(255,255,255,0.3),\n      inset 0 -2px 6px rgba(0,0,0,0.4);\n    position: relative;\n    overflow: hidden;\n}\n.meter > span:after, .animate > span > span {\n    content: \"\";\n    position: absolute;\n    top: 0; left: 0; bottom: 0; right: 0;\n    background-image: \n       -webkit-gradient(linear, 0 0, 100% 100%, \n          color-stop(.25, rgba(255, 255, 255, .2)), \n          color-stop(.25, transparent), color-stop(.5, transparent), \n          color-stop(.5, rgba(255, 255, 255, .2)), \n          color-stop(.75, rgba(255, 255, 255, .2)), \n          color-stop(.75, transparent), to(transparent)\n       );\n    background-image: \n        -moz-linear-gradient(\n          -45deg, \n          rgba(255, 255, 255, .2) 25%, \n          transparent 25%, \n          transparent 50%, \n          rgba(255, 255, 255, .2) 50%, \n          rgba(255, 255, 255, .2) 75%, \n          transparent 75%, \n          transparent\n       );\n    z-index: 1;\n    -webkit-background-size: 50px 50px;\n    -moz-background-size: 50px 50px;\n    -webkit-animation: move 2s linear infinite;\n       -webkit-border-top-right-radius: 8px;\n    -webkit-border-bottom-right-radius: 8px;\n           -moz-border-radius-topright: 8px;\n        -moz-border-radius-bottomright: 8px;\n               border-top-right-radius: 8px;\n            border-bottom-right-radius: 8px;\n        -webkit-border-top-left-radius: 20px;\n     -webkit-border-bottom-left-radius: 20px;\n            -moz-border-radius-topleft: 20px;\n         -moz-border-radius-bottomleft: 20px;\n                border-top-left-radius: 20px;\n             border-bottom-left-radius: 20px;\n    overflow: hidden;\n}\n\n.animate > span:after {\n    display: none;\n}\n\n@-webkit-keyframes move {\n    0% {\n       background-position: 0 0;\n    }\n    100% {\n       background-position: 50px 50px;\n    }\n}\n\n.wickGreen > span {\n    background-color: #01C094;\n    background-image: -moz-linear-gradient(top, #01C094, #29F1A3);\n    background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #01C094),color-stop(1, #29F1A3));\n    background-image: -webkit-linear-gradient(#01C094, #29F1A3);\n}"
  },
  {
    "path": "styles/scriptingide.css",
    "content": "#scriptingGUI {\n    bottom: 0px;\n    left: 46px;\n    text-align: center;\n    width: calc(100% - 266px);\n    height: 300px;\n    z-index: 4;\n    /* transition: height 0.2s ease; */\n    border-radius: 9px 9px 0px 0px;\n}\n\n#errorMessage {\n    margin-left: 3px;\n    margin-top: 3px;\n    color: red;\n    display:hidden;\n    position: absolute;\n    font-weight: bold;\n}\n\n#scriptObjectDiv {\n    width: 100%;\n    height: 100%;\n}\n\n#scriptEditor {\n    text-align: left;\n    width: calc(100% - 152px);\n    height: calc(100% - 36px);\n    left: 149px;\n    top: 24px;\n    font-size: 14px;\n    border-style: solid;\n    border-width: 1px;\n    border-color: #AAA;\n}\n\n#scriptEditorSidebar {\n    position: absolute;\n    width: calc(149px);\n    height: calc(100% - 36px);\n    left: 2px;\n    top: 24px;\n    background-color: #333;\n\n    border-style: solid;\n    border-width: 1px;\n    border-color: #AAA;\n\n    overflow-x: hidden;\n    overflow-y: auto;\n}\n\n#noSelectionDiv {\n    color: #DDD;\n    height: calc(100% - 36px);\n    background-color: #444;\n    border-style: solid;\n    border-width: 1px;\n    border-color: #666;\n    margin-left: 2px;\n    margin-right: 2px;\n    margin-top: 24px;\n    overflow: hidden;\n}\n#noSelectionText {\n    position: relative;\n    height: 100%;\n    width: 100%;\n    top: calc(50% - 8px);\n}\n\n#scriptEditorObjectName {\n    position: absolute;\n    width: 100%;\n    height: 30px;\n    top: 0px;\n    left: 0px;\n    color: white;\n    overflow: hidden;\n}\n\n#scriptEditorObjectThumbnail {\n    position: absolute;\n    width: 100px;\n    height: 100px;\n    top: 30px;\n    left: 0px;\n}\n\n#scriptingIDEHeader {\n    left: 0px;\n    top: 0px;\n    width: calc(100% - 7px);\n    height: 23px;\n    position: absolute;\n    color: white;\n    padding-top: 6px;\n    padding-left: 7px;\n    text-align: left;\n\n    font-size: 14px;\n\n    background-color: none;\n    /*cursor: pointer;*/\n\n    box-shadow: none;\n\n    -webkit-transition: background-color 500ms linear;\n    -ms-transition: background-color 500ms linear;\n    transition: background-color 500ms linear;\n\n    border-radius: 7px;\n}\n/*#scriptingIDEHeader:hover {\n    box-shadow: inset 0 0 1px #fff;\n}*/\n\n#closeScriptingGUIButton {\n    right: 5px;\n    top: 1px;\n    position: absolute;\n    background-image: url('../resources/close-tab.svg');\n    width: 14px;\n    height: 14px;\n    background-size: 13px 13px;\n    background-repeat: no-repeat;\n    background-position: center;\n    border-radius: 2px;\n}\n\n#openScriptingGUIButton {\n    right: 5px;\n    top: 1px;\n    position: absolute;\n    background-image: url('../resources/open-tab.svg');\n    width: 14px;\n    height: 14px;\n    background-size: 13px 13px;\n    background-repeat: no-repeat;\n    background-position: center;\n    border-radius: 2px;\n}\n\n#beautifyButton {\n    right: 51px;\n    top: 1px;\n    position: absolute;\n    background-image: url('../resources/beautify.png');\n    width: 14px;\n    height: 14px;\n    background-size: 13px 13px;\n    background-repeat: no-repeat;\n    background-position: center;\n    border-radius: 2px;\n}\n\n#expandScriptingGUIButton {\n    right: 28px;\n    top: 1px;\n    position: absolute;\n    background-image: url('../resources/fullscreen.png');\n    width: 14px;\n    height: 14px;\n    background-size: 13px 13px;\n    background-repeat: no-repeat;\n    background-position: center;\n    border-radius: 2px;\n}\n\n#minimizeScriptingGUIButton {\n    right: 28px;\n    top: 1px;\n    position: absolute;\n    background-image: url('../resources/unfullscreen.png');\n    width: 14px;\n    height: 14px;\n    background-size: 13px 13px;\n    background-repeat: no-repeat;\n    background-position: center;\n    border-radius: 2px;\n}\n\n#resizeScriptingGUIBar {\n    position: absolute;\n    background-color: rgba(0,0,0,0);\n    cursor: ns-resize;\n    height: 24px;\n    width: 100%;\n    left: 0px;\n    top: 0px;\n}\n\n/* reference section */\n\n#scriptEditorReference {\n    margin-left: 0px;\n    margin-top: 5px;\n    margin-bottom: 15px;\n}\n\n.sidebarGroup {\n    text-align: left;\n    overflow: hidden;\n    height: 16px;\n    cursor: pointer;\n}\n\n.sidebarTitle {\n    font-weight: bold;\n    margin-left: 6px;\n    border-radius: 3px;\n    color: #BBB;\n    padding-left: 3px;\n\n    width: 90%;\n\n    -webkit-transition: background-color 50ms linear;\n    -ms-transition: background-color 50ms linear;\n    transition: background-color 50ms linear;\n    -webkit-transition: color 50ms linear;\n    -ms-transition: color 50ms linear;\n    transition: color 50ms linear;\n}\n.sidebarTitle:hover {\n    background-color: #31E19C;\n    color: black;\n}\n\n.sidebarGroupElement {\n    cursor: pointer;\n    margin-left: 18px;\n    border-radius: 3px;\n    color: #BBB;\n    padding-left: 3px;\n}\n.sidebarGroupElement:hover {\n    background-color: #31E19C;\n    color: black;\n\n    -webkit-transition: background-color 50ms linear;\n    -ms-transition: background-color 50ms linear;\n    transition: background-color 50ms linear;\n    -webkit-transition: color 50ms linear;\n    -ms-transition: color 50ms linear;\n    transition: color 50ms linear;\n}"
  },
  {
    "path": "styles/textBox.css",
    "content": ".canvasTextEdit {\n\tposition: absolute;\n\tbackground-color: 'white';\n\tborder: rgb(100, 100, 100);\n\tborder-style: dotted;\n\tborder-width: 1px;\n\tresize: none;\n\toverflow: hidden;\n\tpadding: 0px; \n}"
  },
  {
    "path": "styles/timeline.css",
    "content": "/* Wick - (c) 2017 Zach Rispoli, Luca Damasco, and Josh Rispoli */\n\n/*  This file is part of Wick. \n    \n    Wick is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    Wick is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with Wick.  If not, see <http://www.gnu.org/licenses/>. */\n    \nbody {\n    --common-padding: 2px;\n    \n    --max-timeline-height: 160px; \n\n    --layers-width: 135px;\n    --layer-height: 30px;\n\n\n    --frame-width: 20px;\n    --frame-handle-width: 8px;\n\n    --frame-padding-width: 4px;\n    --frame-padding-height: 4px;\n\n    --frames-strip-padding-vertical: 3px;\n\n    --shadow: 3px 3px 3px rgba(0, 0, 0, 0.1);\n    --border: inset 0px 0px 1px #555;\n    \n    --timeline-left-padding: 5px; \n    --timeline-top-padding: 6px; \n    --timeline-bottom-padding: 5px; \n\n    --frames-cell-first-padding: 5px;\n\n    --scrollbar-thickness: 14px;\n\n\n    --number-line-height: 16px;\n    \n}\n\n.timeline {\n    background-color: #585757;\n\n    margin: 0px;\n    padding: 0px;\n    \n    width: 100%;\n    height: 100px;  \n\n    overflow: hidden;\n}\n\n.playhead {\n    width: 26px;\n    height: 100%;\n\n    position: absolute;\n    top: -5px;\n\n    pointer-events: none;\n    cursor: pointer;\n}\n.playhead-body {\n    width: 100%;\n    height: 100%;\n    background-image: url('../resources/playhead.png');\n    position: absolute;\n    top: 0px;\n    left: 0px;\n}\n.playhead-nub {\n    width: 100%;\n    height: 20px;\n    background-color: rgba(0,0,0,0);\n    position: absolute;\n    top: 0px;\n    left: 0px;\n}\n\n.playhead-ghost {\n    opacity: 0.4;\n}\n\n.layers-container {\n    background-color: #414141;\n/*    border-right-color: #878787;*/\n    width: var(--layers-width);\n    height: 1000%;\n    left: 0px;\n    top: 0px;\n\n    position: absolute;\n    overflow: hidden;\n\n    box-shadow: var(--border);\n}\n\n.layer-tools-button {\n    position: absolute;\n    \n    top: 0px;\n    left: 0px;\n    width: var(--scrollbar-thickness);\n    height: var(--scrollbar-thickness);\n\n    background-color: #F0EFEF;\n    \n    border-radius: 2px;\n    margin-left: 5px;\n\n    cursor: pointer;\n\n    background-repeat: no-repeat;\n    background-position: 50% 50%;\n    background-size: 12px 12px;\n    background-size: 12px 12px;\n}\n\n.add-layer-button {\n    position: absolute;\n    top: 5px;\n    left: 5px;\n    background-image: url(\"../resources/plusButton.svg\");\n}\n.add-layer-button:hover {\n    background-color: #31E19C;\n}\n\n.delete-layer-button {\n    position: absolute;\n    top: 5px;\n    left: 25px;\n    background-image: url(\"../resources/minusButton.svg\");\n    \n}\n.delete-layer-button:hover {\n    /*width: 100px;*/\n    background-color: #31E19C;\n}\n\n.onion-skin-button {\n    position: absolute;\n    top: 5px;\n    left: 110px;\n    border-radius: 7px;\n    background-image: url(\"../resources/onion.png\");\n    \n}\n.onion-skin-button:hover {\n    background-color: #31E19C;\n}\n\n.small-frames-button {\n    position: absolute;\n    top: 5px;\n    left: 85px;\n    background-image: url('../resources/zoomin.png');\n}\n.small-frames-button:hover {\n    background-color: #31E19C;\n}\n\n.play-preview-button {\n    position: absolute;\n    top: calc(100% - 15px);\n    left: 5px;\n    background-image: url('../resources/play.png');\n    border-radius: 7px;\n    background-size: 8px 8px;\n}\n.play-preview-button:hover {\n    background-color: #31E19C;\n}\n\n.pause-preview-button {\n    position: absolute;\n    top: calc(100% - 15px);\n    left: 25px;\n    background-image: url('../resources/pause.png');\n    background-size: 8px 8px;\n}\n.pause-preview-button:hover {\n    background-color: #31E19C;\n}\n\n.step-backward-preview-button {\n    position: absolute;\n    top: calc(100% - 15px);\n    left: 65px;\n    background-image: url('../resources/step-backward.png');\n}\n.step-backward-preview-button:hover {\n    background-color: #31E19C;\n}\n\n.step-forward-preview-button {\n    position: absolute;\n    top: calc(100% - 15px);\n    left: 85px;\n    background-image: url('../resources/step-forward.png');\n}\n.step-forward-preview-button:hover {\n    background-color: #31E19C;\n}\n\n.layer {\n    background-color: #4a6588;\n    /*background-image: url('../resources/layer-handle.svg');\n    background-size: 15px 17px;\n    background-repeat: no-repeat;\n    background-position: left;*/\n    \n    \n    width:  calc(100% - 10px);\n    height: calc(var(--layer-height) - 5px);\n    \n    margin: calc(var(--common-padding) / 2);\n    margin-top: 9px;\n    margin-left: 5px;\n    margin-bottom: 5px;\n    border-radius: 1px;\n    text-align: center;\n    line-height: calc(var(--layer-height) - 5px);\n    color: white;\n\n    position: absolute;\n\n    box-shadow: var(--border);\n\n    font-size: 12px;\n    font-family: \"Anonymous Pro\";\n    font-style: Bold; \n}\n\n.soundLayer {\n    background-color: #47ad8a;\n}\n\n.layer-name {\n    cursor: text;\n    width: 100px;\n    height: 25px;\n    margin-left: 60px;\n    text-align: left;\n}\n\n.layer-rename-textfield {\n    display: none;\n    width: 60px;\n    height: 15px;\n    z-index: 999;\n    position: absolute;\n    top: 5px;\n    left: 60px;\n    font-size: 12px;\n    font-family: \"Anonymous Pro\";\n    font-style: Bold; \n}\n\n.layer-gnurl {\n    width: 14px;\n    height: 21px;\n    left: 2px;\n    top: 2px;\n    position: absolute;\n    cursor: move;\n    background-image: url('../resources/layer-gnurl.svg');\n    background-size: 100% 100%;\n    background-repeat: no-repeat;\n    background-position: left;\n    opacity: 0.6;\n}\n.layer-gnurl:hover {\n    opacity: 0.95;\n}\n\n.active-layer {\n    background-color: #46bbf8;\n    border-style: solid;\n    border-color: white;\n    border-width: 1px;\n/*    box-shadow: 0 0 10px 3px rgba(255,255,255,0.18);*/\n\n}\n\n.active-soundLayer {\n    background-color: #60e5b6;\n}\n\n.layer-lock-button {\n    border-radius: 7px;\n    width: 15px;\n    height: 15px;\n    position: absolute;\n    top: 5px;\n    left: 19px;\n    background-color: transparent;\n    background-image: url('../resources/lock-layer.svg');\n    background-size: 13px 13px;\n    background-repeat: no-repeat;\n    background-position: center;\n    cursor: pointer;\n    opacity: 0.6;\n}\n.layer-lock-button:hover {\n    background-color: rgba(255,255,255,0.4);\n}\n.layer-lock-button:active {\n    background-color: rgba(255,255,255,0.8);;\n    opacity: 1.0;\n}\n.layer-locked {\n    opacity: 1.0;\n    background-color: rgba(255,255,255,0.5);\n}\n\n.layer-hide-button {\n    border-radius: 7px;\n    width: 15px;\n    height: 15px;\n    position: absolute;\n    top: 5px;\n    left: 36px;\n    background-color: transparent;\n    background-image: url('../resources/hide-layer.svg');\n    background-size: 13px 13px;\n    background-repeat: no-repeat;\n    background-position: center;\n    cursor: pointer;\n    opacity: 0.6;\n}\n.layer-hide-button:hover {\n    background-color: rgba(255,255,255,0.4);\n}\n.layer-hide-button:active {\n    background-color: rgba(255,255,255,0.8);\n    opacity: 1.0;\n}\n.layer-hidden {\n    opacity: 1.0;\n    background-color: rgba(255,255,255,0.5);\n}\n\n.frames-container {\n    background-color: #3C3C3C;\n\n    width: 10000%;\n    height: 1000%;\n    left: var(--layers-width);\n    top: 0px;\n\n    position: absolute;\n    overflow: hidden;\n    \n    display: inline-block;\n\n    box-shadow: var(--border);\n}\n\n.frames-cell {\n    background-color: rgba(0,0,0,0);\n\n    width: var(--frame-width);\n    height: 200px;\n\n    /*box-shadow: inset 0px 0px 1px #555;*/\n    border-left: 1px solid #444;\n\n    position: absolute;\n}\n\n.frames-strip {\n    background-color: #C2C2C2;\n\n    width: 100%;\n    height: calc(var(--layer-height) - var(--frames-strip-padding-vertical)*2);\n\n    margin-top: calc(var(--frames-strip-padding-vertical) * 3);\n    left: 5px;\n    position: absolute;\n\n    box-shadow: var(--border);\n\n    overflow: hidden;\n    \n    border-radius: 5px;\n\n    /*pointer-events:none;*/\n}\n\n.frames-strip-cell {\n    background-color: rgba(0,0,0,0);\n\n    width: var(--frame-width);\n    height: calc(var(--layer-height) - var(--frames-strip-padding-vertical)*2);\n\n    /*box-shadow: inset 0px 0px 1px #555;*/\n    border-left: 1px solid #999;\n\n    position: absolute;\n}\n\n.frames-strip-cell-first {\n    width: calc(var(--frame-width) + var(--frames-cell-first-padding));\n}\n\n.frame {\n    background-color: #FFFFFF;\n/*    opacity: 0.5;*/\n    cursor: move;\n\n    width:  calc(var(--frame-width)      - var(--common-padding));\n    height: calc(var(--layer-height) - var(--common-padding));\n\n    position: absolute;\n    overflow: hidden;\n    margin-top: 7px;\n    margin-left: 15px;\n/*  box-shadow: var(--border), var(--shadow);*/\n    \n    border-radius: 1px;\n}\n\n.frame-thumbnail {\n    max-height: 100%; \n    max-width: 100%;\n    width:  12px;\n    height: 12px;\n    margin-top: 12px;\n    padding: 0px;\n\n    display: block;\n\n    pointer-events: none;\n    border-radius: 3px;\n}\n\n.frame-waveform {\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    width: 600px;\n    height: 30px;\n    pointer-events: none;\n}\n\n.frame-name {\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    width: 100%;\n    height: 100%;\n    pointer-events: none;\n    font-size: 10px;\n    color: black;\n}\n\n.has-scripts-icon {\n    bottom: 0px;\n    left: 0px;\n    width: 13px;\n    height: 13px;\n    position: absolute;\n    background-color: white;\n    border-radius: 4px;\n    border-color: #878787;\n    border-width: 1px;\n    border-style: solid;\n    background-image: url('../resources/code.png');\n    background-size: 13px 13px;\n    background-repeat: no-repeat;\n    background-position: center;\n    cursor: pointer;\n}\n.has-scripts-icon:hover {\n    background-color: #31E19C;\n}\n\n.frame-tween-mode {\n\n}\n\n.frame-extender-handle {\n    background-color: rgba(0,0,0,0);\n\n    cursor: ew-resize;\n    width: var(--frame-handle-width);\n    height: 100%;\n\n/*  opacity: 0.1;*/\n\n    position: absolute;\n    right: 0px;\n    top: 0px;\n}\n\n.frame-extender-handle-right:hover {\n    float: right;\n    background: rgba(249,221,0,0.34);\n    border-right: 2px solid #F9DE00;\n    border-top: 2px solid #F9DE00;\n    border-bottom: 2px solid #F9DE00;\n    box-sizing: border-box;    \n    border-top-right-radius: 0.8;\n    border-bottom-right-radius: 0.8; \n}\n/*\n\n.flame-extender-handle-right:hover {\n    \n}\n*/\n\n/*@ToDo create Left Frame handler grabbers*/\n\n\n.frame-extender-handle-left {\n    background-color: red;\n    position: absolute; \n    left: 0px;\n    top: 0px;\n}\n\n.selection-overlay {\n    width:  100%;\n    height: 100%;\n    position: absolute;\n    pointer-events: none;\n    box-shadow: inset 0px 0px 0px 3px #5BBEDB, 0px 0px 0px 2px #48A5BE; \n/*  background-color: cyan;*/\n/*\n    border-color: red;\n    border-width: 5px;\n*/\n/*  opacity: .1;*/\n    left: 0px;\n    top:0px;\n}\n.selection-overlay-error {\n    box-shadow: inset 0px 0px 0px 3px #FF0000, 0px 0px 0px 2px #EE3333; \n}\n\n.add-frame-overlay {\n    width: calc(var(--frame-width) / 1.5); \n    height: calc(var(--layer-height) / 1.8);\n    position: absolute;\n    margin-left: calc(var(--frame-width)  / 2 - var(--frame-width)  / 1.5 / 2 + 10px);\n    margin-top:  calc(var(--layer-height) / 2 - var(--layer-height) / 1.8 / 2 + 6px);\n    background-color: #ffffff;\n    border-radius: 3px;\n    box-shadow: 0 0 1px 0 rgba(0,0,0,0.12), 0 1px 1px 0 rgba(0,0,0,0.24), 0 0 2px 0 rgba(0,0,0,0.12), 0 2px 2px 0 rgba(0,0,0,0.24); \n    pointer-events: none;\n    z-index: 10;\n}\n\n.add-frame-overlay-img {\n    width: 10px;\n    height: 10px;\n    left: calc(50% - 5px);\n    top: calc(50% - 5px);\n    position: absolute;\n    pointer-events: none;\n}\n\n.selection-box {\n    background-color: #AAAAFF;\n    box-shadow: inset 0px 0px 1px #0000FF;\n    opacity: 0.5;\n    position: absolute;\n    pointer-events: none;\n    width: 0px;\n    height: 0px;\n    left: 0px;\n    top:0px;\n}\n\n.scrollbar {\n    background-color: #2E2E2E;\n    position: absolute;\n    overflow: hidden;\n    outline:none;\n/*    border-color: #878787;\n    border-width: 2px;*/\n    /*border-style: solid;*/\n    border-radius: 3px;\n}\n\n.horizontal-scrollbar {\n    bottom: 0px;\n    right: calc(var(--scrollbar-thickness) + 50px);\n    width: calc(100% - var(--layers-width) - var(--scrollbar-thickness) - 50px);\n    height: var(--scrollbar-thickness);\n    \n\n}\n\n.vertical-scrollbar {\n    top: var(--number-line-height);\n    right: 0px;\n    height: calc(100% - var(--scrollbar-thickness) - var(--number-line-height));\n    width: var(--scrollbar-thickness);\n}\n\n.scrollbar-button {\n    cursor: pointer;\n    width: var(--scrollbar-thickness);\n    height: var(--scrollbar-thickness);\n    position: absolute;\n    background-color: #2E2E2E; \n    opacity: 1.0;\n}\n.scrollbar-button:hover {\n    opacity: 0.7;\n}\n\n.scrollbar-button-left {\n    left: 0px;\n    top: 0px;\n    background-image: url('../resources/scrollbararrow-left.svg');\n    background-repeat: no-repeat;\n    background-position: center;\n\n}\n\n.scrollbar-button-right {\n    color: blue;\n    right: 0px;\n    top: 0px;\n\n    background-image: url('../resources/scrollbararrow-right.svg');\n    background-repeat: no-repeat;\n    background-position: center;\n    \n}\n\n.scrollbar-button-top {\n    right: 0px;\n    top: 0px;\n    background-image: url('../resources/scrollbararrow-up.svg');\n    background-repeat: no-repeat;\n    background-position: center;\n}\n\n.scrollbar-button-bottom {\n    right: 0px;\n    bottom: 0px;\n    background-image: url('../resources/scrollbararrow-down.svg');\n    background-repeat: no-repeat;\n    background-position: center;\n}\n\n.scrollbar-head {\n    cursor: pointer;\n    background-color: #FAFAFA;\n    left: 0px;\n    top: 0px;\n    border-radius: 6px;\n    opacity: 1.0;\n}\n.scrollbar-head:hover {\n    opacity: 0.7;\n}\n\n.scrollbar-head-horizontal {\n    width: 100px;\n    height: calc(var(--scrollbar-thickness) - 4px);\n    margin-top: 2px;\n}\n\n.scrollbar-head-vertical {\n    width: calc(var(--scrollbar-thickness) - 4px);\n    margin: 0 auto;\n    /* Height depends on number of layers */ \n}\n\n.number-line {\n    position: absolute;\n    top: 0px;\n    left: var(--layers-width);\n    width: 10000%;\n    height: var(--number-line-height);\n\n    cursor: default;\n\n    background-color: #252525;\n}\n\n.number-line-cell {\n    position: absolute;\n    height: var(--number-line-height);\n    color: #fafafa;\n}\n\n.number-line-cell-number {\n    position: absolute;\n    top: 1px;\n    left: 10px;\n\n    font-size: 14px;\n    font-weight: bold;\n    /*font-size: vmin;*/\n    font-family: \"Anonymous Pro\" ;\n}\n.number-line-cell-number-small {\n    font-size: 12px;\n}\n\n.number-line-cell-bar {\n    position: absolute;\n    top: 0px;\n    left: 5px;\n\n    width: 1px;\n    height: 100%;\n    background-color: white;\n}\n\n@font-face {\n    font-family: myFirstFont;\n    src: url(sansation_light.woff);\n}\n\n\n.playrange {\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    width: 100px;\n    height: 1000px;/*var(--number-line-height);*/\n\n    background-color: none;\n    opacity: 1.0;\n    \n    color: #FAFAFA;\n\n    /*-webkit-box-shadow:inset 0px 0px 0px 2px #fff;\n    -moz-box-shadow:inset    0px 0px 0px 2px #fff;\n    box-shadow:inset         0px 0px 0px 2px #fff;*/\n}\n\n.playrange-header {\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    width: 100%;\n    height: var(--number-line-height);\n    background-color: red;\n    opacity: 1.0;\n}\n.playrange-body {\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    width: 100%;\n    height: 100%;\n    background-color: red;\n    opacity: 0.3;\n    pointer-events: none;\n}\n\n.playrange-selected {\n    /*opacity: 0.3;*/\n}\n\n.playrange-label {\n    color: rgba(0,0,0,0);\n    opacity: 1;\n\n    overflow: hidden;\n    font-size: 12px;\n    font-weight: bold;\n\n    position: absolute;\n    max-width: 100%;\n    height: var(--number-line-height);\n    left: 50%;\n    top: 1px;\n\n    padding: 2px;\n\n    -webkit-transform: translateX(-50%);\n    transform: translateX(-50%);\n    -ms-transform: translateX(-50%);\n}\n.playrange-label-text {\n    width: 100%;\n    height: 100%;\n    color: white;\n    position: absolute;\n    text-align: center;\n    overflow: hidden;\n    top: 1px;\n    left: 1px;\n}\n.playrange-label-bg {\n    width: 100%;\n    height: calc(100% - 6px);\n    background-color: black;\n    opacity: 0.1;\n    border-radius: 2px;\n    position: absolute;\n    top: 0px;\n    left: 0px;\n}\n\n.playrange-handle {\n    display: inline-block;\n\n    background-color: black;\n    opacity: 0.2;\n    position: absolute;\n\n    width: 15px;\n    height: var(--number-line-height);\n\n    cursor: ew-resize;\n    z-index: 4;\n\n    background-image: url('../resources/layer-handle.svg');\n    background-size: 15px 17px;\n    background-repeat: no-repeat;\n    background-position: left;\n}\n\n.playrange-handle-left {\n    left: 0px;\n    top: 0px;\n}\n\n.playrange-handle-right {\n    right: 0px;\n    top: 0px;\n}\n\n.hide-number-line-piece {\n    position: absolute;\n    width: var(--layers-width);\n    height: var(--number-line-height);\n    top: 0px;\n    left: 0px;\n    background-color: #252525;\n}\n\n.layer-toolbar {\n    position: absolute;\n    width: var(--layers-width);\n    height: var(--scrollbar-thickness);\n    bottom: 0px;\n    left: 0px;\n    border-top: 1px; \n    border-color: black; \n    background-color: #252525;\n}\n\n.hide-scrollbar-connect-piece {\n    position: absolute;\n    width: var(--scrollbar-thickness);\n    height: var(--scrollbar-thickness);\n    bottom: 0px;\n    left: calc(100% - var(--scrollbar-thickness));\n    background-color: #252525;\n}\n\n.resize-timeline-bar {\n    height: var(--scrollbar-thickness);\n    width: 100%;\n    bottom: 0px;\n    position: absolute;\n    left: 0px;\n    cursor: ns-resize;\n}\n\n.zoom-box {\n    position: absolute;\n    width: 62px;\n    height: var(--scrollbar-thickness);\n    bottom: 0px;\n    left: calc(100% - var(--scrollbar-thickness) - 49px);\n    background-color: #252525;\n}\n\n.fps-box {\n    position: absolute;\n    width: 62px;\n    height: var(--scrollbar-thickness);\n    bottom: 0px;\n    left: 80px;\n}\n\n.timeline-fps-icon {\n    width: 15px;\n    height: 100%;\n    background-image: url('../resources/framerate.svg');\n    background-size: 11px 11px;\n    background-repeat: no-repeat;\n    background-position: left;\n    float: left;\n    opacity: 1.0;\n}\n\n.timeline-number-input {\n    position: absolute;\n    width: 30px;\n    height: 12px;\n    border-radius: 3px;\n    font-size: 12px;\n    left: 17px;\n    top: 1px;\n    text-align: center;\n}\n\n.timeline-zoom-icon {\n    width: 15px;\n    height: 15px;\n    background-image: url('../resources/tools/Zoom.svg');\n    background-size: 15px 15px;\n    background-repeat: no-repeat;\n    background-position: left;\n    float: left;\n    cursor: pointer;\n    opacity: 1.0;\n}\n.timeline-zoom-icon:hover {\n    opacity: 0.7;\n}\n\n.timeline-zoom-percent-sign {\n    color: white;\n    position: absolute;\n    width: 12px;\n    height: 12px;\n    font-size: 11px;\n    font-family: arial;\n    left: 48px;\n    top: 1px;\n    font-weight: bold;\n    text-align: center;\n}\n\n/* Breadcrumbs */\n\n#breadcrumbsGUI {\n    top: 30px;\n    left: 46px;\n    width: calc(100% - 266px);\n    height: 15px;\n    background-color: #000;\n    overflow: hidden;\n    color: white;\n    padding-left: 5px;\n}\n\n.breadcrumbs-button {\n    width: auto;\n    border-radius: 4px;\n    color: white;\n    float: left;\n    cursor: pointer;\n    font-size: 14px;\n    margin-top: 2px;\n\n    -webkit-transition: background-color 100ms linear;\n    -ms-transition: background-color 100ms linear;\n    transition: background-color 100ms linear;\n}\n.breadcrumbs-button:hover {\n    background-color: #31E19C;\n    color: black;\n}\n.breadcrumbs-spacer {\n    color:white;\n    float: left;\n    margin-left: 15px;\n    margin-right: 15px;\n}\n\n.numberline-container {\n    position: absolute;\n    left: 0px;\n    top: 0px;\n}\n\n.frames-strip-cell-container {\n    position: absolute;\n    left: 0px;\n    top: 0px;\n}\n\n.tween {\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    width: 14px;\n    height: 14px;\n    margin-top: 6px;\n    margin-left: 3px;\n    background-color: none;\n    cursor: pointer;\n\n    background-image: url('../resources/tweenpoint.svg');\n    background-size: 100%;\n    background-repeat: no-repeat;\n    background-position: left;\n}\n.tween:hover {\n    box-shadow: inset 1px 1px 2px yellow;\n}\n\n.hover-highlight-overlay {\n    position: absolute;\n    width:  calc(var(--frame-width) - var(--common-padding) + 1px);\n    height: calc(var(--layer-height) - var(--common-padding));\n    background-color: cyan;\n    opacity: 0.2;\n    z-index: 999;\n    pointer-events: none;\n    display: none;\n}\n"
  },
  {
    "path": "styles/toolbar.css",
    "content": "#toolbarGUI {\n    top: 30px;\n    left: 0px;\n    height: calc(100%);\n    width: 40px;\n    text-align: left;\n    padding: 3px;\n    padding-top: 5px;\n    overflow: hidden;\n/*    border-left-color: #585757;*/\n/*    border-bottom-color: #585757;*/\n}\n\n#toolOptionsGUI {\n    display: none;\n    bottom: 0px;\n    left: 0px;\n    text-align: left;\n}\n\n#tooltipGUI {\n    position: absolute;\n    top: 0px;\n    left: 0px;\n    background-color: #FFFFFF;\n    display: none;\n    z-index: 11111;\n    border: none;\n    padding-left:5px;\n    padding-right: 5px;\n    box-shadow: 2px 2px 2px #AAA;\n}\n\n.toolButton {\n    height: 28px;\n    width: 28px;\n    border-radius: 5px;\n    padding-bottom: 0px;\n    margin-bottom: 5px;\n    cursor: pointer;\n    margin-left: 6px;\n\n    background-repeat: no-repeat;\n    background-position: center;\n    text-overflow: clip;\n    overflow: hidden;\n    background-size: 100% 100%;\n\n    -webkit-transition: background-color 100ms linear;\n    -ms-transition: background-color 100ms linear;\n    transition: background-color 100ms linear;\n}\n.toolButton:hover {\n    background-color: #31E19C;\n}\n.toolButton:active {\n    background-color: #658a7c;\n}\n\n.toolButtonActive {\n    background-color: #333; /*#31E19C;*/\n    fill: purple;\n}\n\n.drawing-tool-options-container {\n\n}\n\nhr {\n    margin-top: 10px;\n    margin-bottom: 10px;\n}\n\n.toolbar-color-picker-container {\n    width: 35px;\n    height: 35px;\n    position: relative;\n    margin-left: 2px;\n}\n\n.toolbar-color {\n    position: absolute;\n    width: 22px;\n    height: 22px;\n    border-radius: 5px;\n    border: 1px solid white;\n    background-color: green;\n    cursor: pointer;\n}\n\n.toolbar-fill-color {\n    left: 0px;\n    top: 0px;\n}\n\n.toolbar-fill-color-background {\n    position: absolute;\n    background-color: white;\n    background-image:\n      -moz-linear-gradient(45deg, #ddd 25%, transparent 25%), \n      -moz-linear-gradient(-45deg, #ddd 25%, transparent 25%),\n      -moz-linear-gradient(45deg, transparent 75%, #ddd 75%),\n      -moz-linear-gradient(-45deg, transparent 75%, #ddd 75%);\n    background-image:\n      -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, #ddd), color-stop(.25, transparent)), \n      -webkit-gradient(linear, 0 0, 100% 100%, color-stop(.25, #ddd), color-stop(.25, transparent)),\n      -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.75, transparent), color-stop(.75, #ddd)),\n      -webkit-gradient(linear, 0 0, 100% 100%, color-stop(.75, transparent), color-stop(.75, #ddd));\n      -moz-background-size:10px 10px;\n    background-size:10px 10px;\n    -webkit-background-size:10px 11px;\n    overflow: hidden;\n    \n    background-position:0 0, 5px 0, 5px -5px, 0px 5px;\n\n    left: 0px;\n    top: 0px;\n\n    width: 22px;\n    height: 22px;\n    border-radius: 5px;\n    border: 1px solid white;\n    cursor: pointer;\n}\n\n.toolbar-stroke-color {\n    right: 0px;\n    bottom: 0px;\n}\n\n.toolbar-stroke-color-background {\n    position: absolute;\n    background-color: white;\n    background-image:\n      -moz-linear-gradient(45deg, #ddd 25%, transparent 25%), \n      -moz-linear-gradient(-45deg, #ddd 25%, transparent 25%),\n      -moz-linear-gradient(45deg, transparent 75%, #ddd 75%),\n      -moz-linear-gradient(-45deg, transparent 75%, #ddd 75%);\n    background-image:\n      -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, #ddd), color-stop(.25, transparent)), \n      -webkit-gradient(linear, 0 0, 100% 100%, color-stop(.25, #ddd), color-stop(.25, transparent)),\n      -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.75, transparent), color-stop(.75, #ddd)),\n      -webkit-gradient(linear, 0 0, 100% 100%, color-stop(.75, transparent), color-stop(.75, #ddd));\n      -moz-background-size:10px 10px;\n    background-size:10px 10px;\n    -webkit-background-size:10px 11px;\n    overflow: hidden;\n    \n    background-position:0 0, 5px 0, 5px -5px, 0px 5px;\n      \n    right: 0px;\n    bottom: 0px;\n\n    width: 22px;\n    height: 22px;\n    border-radius: 5px;\n    border: 1px solid white;\n    cursor: pointer;\n}\n\n.toolbar-stroke-color-inner-rect {\n    position: absolute;\n    top: 3px;\n    left: 3px;\n    width: 14px;\n    height: 14px;\n    border-radius: 3px;\n    border: 1px solid white;\n    background-color: #555;\n    cursor: pointer;\n}\n\n.toolbar-brush-size-preview-container {\n    margin-top: 12px;\n    margin-left: 2px;\n    border-radius: 3px;\n\n    width: 35px;\n    height: 35px;\n    background-color: white;\n\n    background-image:\n      -moz-linear-gradient(45deg, #ddd 25%, transparent 25%), \n      -moz-linear-gradient(-45deg, #ddd 25%, transparent 25%),\n      -moz-linear-gradient(45deg, transparent 75%, #ddd 75%),\n      -moz-linear-gradient(-45deg, transparent 75%, #ddd 75%);\n    background-image:\n      -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, #ddd), color-stop(.25, transparent)), \n      -webkit-gradient(linear, 0 0, 100% 100%, color-stop(.25, #ddd), color-stop(.25, transparent)),\n      -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.75, transparent), color-stop(.75, #ddd)),\n      -webkit-gradient(linear, 0 0, 100% 100%, color-stop(.75, transparent), color-stop(.75, #ddd));\n\n    -moz-background-size:10px 10px;\n    background-size:10px 10px;\n    -webkit-background-size:10px 11px;\n    overflow: hidden;\n    \n    background-position:0 0, 5px 0, 5px -5px, 0px 5px;\n    cursor: pointer;\n    opacity: 1.0;\n}\n.toolbar-brush-size-preview-container:hover {\n  opacity: 0.8;\n}\n.toolbar-brush-size-preview-container:active {\n  opacity: 0.6;\n}\n\n.toolbar-stroke-width-preview-container {\n    margin-left: 2px;\n    margin-top: 12px;\n    width: 35px;\n    height: 23px;\n    border-radius: 3px;\n    background-color: white;\n    overflow: hidden;\n\n    background-image:\n      -moz-linear-gradient(45deg, #ddd 25%, transparent 25%), \n      -moz-linear-gradient(-45deg, #ddd 25%, transparent 25%),\n      -moz-linear-gradient(45deg, transparent 75%, #ddd 75%),\n      -moz-linear-gradient(-45deg, transparent 75%, #ddd 75%);\n    background-image:\n      -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, #ddd), color-stop(.25, transparent)), \n      -webkit-gradient(linear, 0 0, 100% 100%, color-stop(.25, #ddd), color-stop(.25, transparent)),\n      -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.75, transparent), color-stop(.75, #ddd)),\n      -webkit-gradient(linear, 0 0, 100% 100%, color-stop(.75, transparent), color-stop(.75, #ddd));\n\n    -moz-background-size:10px 10px;\n    background-size:10px 10px;\n    -webkit-background-size:10px 11px;\n    \n    background-position:0 0, 5px 0, 5px -5px, 0px 5px;\n\n    cursor: pointer;\n    opacity: 1.0;\n}\n.toolbar-stroke-width-preview-container:hover {\n  opacity: 0.8;\n}\n.toolbar-stroke-width-preview-container:active {\n  opacity: 0.6;\n}\n\n.toolbar-number-input {\n    margin-left: 2px;\n    height: 15px;\n    width: 35px;\n    cursor: ew-resize;\n    text-align: center;\n    font-size: 13px;\n    border-radius: 3px;\n}\n\n.toolbar-brush-settings-window {\n    width: 200px;\n    height: 35px;\n    position: absolute;\n    left: 0px;\n    top: 0px;\n    border: 1px solid white;\n    z-index: 9;\n    border-radius: 4px;\n    background-color: #444;\n    display: none;\n}\n\n.toolbar-brush-settings-window-smoothness-label {\n  width: 120px;\n  height: 20px;\n  font-family:\"Open Sans\";\n  src: url(\"Open_Sans/OpenSans-Regular.ttf\");\n  color: white;\n  font-size: 12px;\n  position: absolute;\n  left: 10px;\n  top: 8px;\n}\n.toolbar-brush-settings-window-number-input {\n  position: absolute;\n  left: 126px;\n  top: 10px;\n  height: 13px;\n}\n\n.toolbar-brush-settings-window-close-button {\n  width: 20px;\n  height: 20px;\n  float: right;\n  cursor: pointer;\n  background-image: url(\"../resources/close.png\");\n  background-repeat: no-repeat;\n  background-position: center;\n  text-overflow: clip;\n  overflow: hidden;\n  background-size: 12px 12px;\n  opacity: 1.0;\n  margin-top: 3px;\n  margin-right: 3px;\n}\n.toolbar-brush-settings-window-close-button:hover {\n  opacity: 0.6;\n}\n\n.toolbar-corner-radius-preview-container {\n    margin-left: 2px;\n    margin-top: 12px;\n    width: 35px;\n    height: 35px;\n    border-radius: 3px;\n    background-color: white;\n    overflow: hidden;\n    margin-bottom: 1px;\n\n    background-image:\n      -moz-linear-gradient(45deg, #ddd 25%, transparent 25%), \n      -moz-linear-gradient(-45deg, #ddd 25%, transparent 25%),\n      -moz-linear-gradient(45deg, transparent 75%, #ddd 75%),\n      -moz-linear-gradient(-45deg, transparent 75%, #ddd 75%);\n    background-image:\n      -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, #ddd), color-stop(.25, transparent)), \n      -webkit-gradient(linear, 0 0, 100% 100%, color-stop(.25, #ddd), color-stop(.25, transparent)),\n      -webkit-gradient(linear, 0 100%, 100% 0, color-stop(.75, transparent), color-stop(.75, #ddd)),\n      -webkit-gradient(linear, 0 0, 100% 100%, color-stop(.75, transparent), color-stop(.75, #ddd));\n\n    -moz-background-size:10px 10px;\n    background-size:10px 10px;\n    -webkit-background-size:10px 11px;\n    \n    background-position:0 0, 5px 0, 5px -5px, 0px 5px;\n\n    opacity: 1.0;\n}\n.toolbar-corner-radius-preview-rect {\n  background-color: rgba(255,255,255,0.7);\n  border: 1px solid black;\n  width: 100px;\n  height: 100px;\n  margin-left: 12px;\n  margin-top: 12px;\n}\n"
  },
  {
    "path": "styles/videoExporter.css",
    "content": "#videoExportGUI {\n    padding: 20px;\n    border-radius: 3px;\n    left: 50%;\n    top: 50%;\n    width: 500px;\n    height: 106px;\n    position: absolute;\n    z-index: 10;\n    box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n    transform: translateX(-50%) translateY(-50%);\n    display: none;\n}\n\n.sparkText {\n    color: white;\n    height: 15px;\n}\n\n#videoExportProgressBarContainer {\n    width: 95%;\n    margin: auto;\n    margin-top: 10px;\n    margin-bottom: 15px;\n}\n\n#videoExportSettingsContainer {\n    \n}\n\n.quality-container {\n    color: #FFF;\n    display: flex;\n    flex-direction: row;\n    float:left;\n}\n\n#qualitySettingTitle {\n    padding-top: 5px;\n    margin-right: 5px;\n}\n\n.dropbtn {\n    width: 60px;\n    height: 16px;\n    padding: 6px;\n\n    background-color: #3498DB;\n    color: white;\n    \n    border: none;\n    border-radius: 5px;\n    cursor: pointer;\n\n    text-align: center;\n    font-size: 16px;\n}\n\n.dropbtn:hover, .dropbtn:focus {\n    background-color: #2980B9;\n}\n\n.dropdown {\n    position: relative;\n    display: inline-block;\n}\n\n.dropdown-content {\n    display: none;\n    position: absolute;\n    background-color: #f1f1f1;\n    min-width: 120px;\n    overflow: auto;\n    box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);\n    z-index: 1;\n}\n\n.dropdown-item {\n    color: black;\n    padding: 6px 8px;\n    text-decoration: none;\n    display: block; \n    z-index: 12;\n}\n\n.dropdown-item:hover {\n    background-color: #FFF;\n}\n\n.show {\n    display:block;\n}\n\n.videoDownloadButton {\n    border-radius: 5px;\n    cursor: pointer;\n    color: white;\n    font-size: 18px;\n    background-color: #333;\n    text-align: center;\n    padding: 6px;\n    height: 20px;\n    width: 160px;\n    float:right;\n\n    -webkit-transition: background-color 100ms linear;\n    -ms-transition: background-color 100ms linear;\n    transition: background-color 100ms linear;\n}\n\n.videoDownloadButton:hover {\n    background-color: #00D9A7;\n}\n\n.videoDownloadButton:active {\n    background-color: #01C094;\n}\n"
  }
]