Changeset 3265986
- Timestamp:
- 04/03/2025 02:59:33 AM (11 months ago)
- Location:
- popup-more/trunk
- Files:
-
- 1 added
- 9 edited
-
assets/css/style.css (modified) (1 diff)
-
assets/javascript/wheel/Wheel.js (modified) (1 diff)
-
assets/javascript/wheel/WheelCore.js (added)
-
assets/javascript/wheel/admin.js (modified) (1 diff)
-
assets/view/wheel/main.php (modified) (2 diffs)
-
classes/admin/wheel/WheelOptions.php (modified) (6 diffs)
-
classes/frontend/popups/WheelPopup.php (modified) (4 diffs)
-
config/config.php (modified) (1 diff)
-
config/data-config.php (modified) (1 diff)
-
popup-more.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
popup-more/trunk/assets/css/style.css
r3264016 r3265986 1307 1307 cursor: pointer; 1308 1308 } 1309 1309 1310 .ypm-type-color { 1311 width: 80px; 1312 height: 38px; 1313 } -
popup-more/trunk/assets/javascript/wheel/Wheel.js
r3264022 r3265986 1 // WHeel2 1 var ypmWheelCallBack = function() { 3 2 var alertPrize = function(indicatedSegment) { -
popup-more/trunk/assets/javascript/wheel/admin.js
r3254313 r3265986 1 /* 2 Winwheel.js, by Douglas McKechie @ www.dougtesting.net 3 See website for tutorials and other documentation. 4 5 The MIT License (MIT) 6 7 Copyright (c) 2012-2019 Douglas McKechie 8 9 Permission is hereby granted, free of charge, to any person obtaining a copy 10 of this software and associated documentation files (the "Software"), to deal 11 in the Software without restriction, including without limitation the rights 12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 copies of the Software, and to permit persons to whom the Software is 14 furnished to do so, subject to the following conditions: 15 16 The above copyright notice and this permission notice shall be included in all 17 copies or substantial portions of the Software. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 SOFTWARE. 26 */ 27 28 // ==================================================================================================================== 29 // The constructor for the WinWheel object, a JSON-like array of options can be passed in. 30 // By default the wheel is drawn if canvas object exists on the page, but can pass false as second parameter if don't want this to happen. 31 // ==================================================================================================================== 32 function Winwheel(options, drawWheel) 33 { 34 defaultOptions = { 35 'canvasId' : 'canvas', // Id of the canvas which the wheel is to draw on to. 36 'centerX' : null, // X position of the center of the wheel. The default of these are null which means will be placed in center of the canvas. 37 'centerY' : null, // Y position of the wheel center. If left null at time of construct the center of the canvas is used. 38 'outerRadius' : null, // The radius of the outside of the wheel. If left null it will be set to the radius from the center of the canvas to its shortest side. 39 'innerRadius' : 0, // Normally 0. Allows the creation of rings / doughnuts if set to value > 0. Should not exceed outer radius. 40 'numSegments' : 1, // The number of segments. Need at least one to draw. 41 'drawMode' : 'code', // The draw mode. Possible values are 'code', 'image', 'segmentImage'. Default is code which means segments are drawn using canvas arc() function. 42 'rotationAngle' : 0, // The angle of rotation of the wheel - 0 is 12 o'clock position. 43 'textFontFamily' : 'Arial', // Segment text font, you should use web safe fonts. 44 'textFontSize' : 20, // Size of the segment text. 45 'textFontWeight' : 'bold', // Font weight. 46 'textOrientation' : 'horizontal', // Either horizontal, vertical, or curved. 47 'textAlignment' : 'center', // Either center, inner, or outer. 48 'textDirection' : 'normal', // Either normal or reversed. In normal mode for horizontal text in segment at 3 o'clock is correct way up, in reversed text at 9 o'clock segment is correct way up. 49 'textMargin' : null, // Margin between the inner or outer of the wheel (depends on textAlignment). 50 'textFillStyle' : 'black', // This is basically the text colour. 51 'textStrokeStyle' : null, // Basically the line colour for segment text, only looks good for large text so off by default. 52 'textLineWidth' : 1, // Width of the lines around the text. Even though this defaults to 1, a line is only drawn if textStrokeStyle specified. 53 'fillStyle' : 'silver', // The segment background colour. 54 'strokeStyle' : 'black', // Segment line colour. Again segment lines only drawn if this is specified. 55 'lineWidth' : 1, // Width of lines around segments. 56 'clearTheCanvas' : true, // When set to true the canvas will be cleared before the wheel is drawn. 57 'imageOverlay' : false, // If set to true in image drawing mode the outline of the segments will be displayed over the image. Does nothing in code drawMode. 58 'drawText' : true, // By default the text of the segments is rendered in code drawMode and not in image drawMode. 59 'pointerAngle' : 0, // Location of the pointer that indicates the prize when wheel has stopped. Default is 0 so the (corrected) 12 o'clock position. 60 'wheelImage' : null, // Must be set to image data in order to use image to draw the wheel - drawMode must also be 'image'. 61 'imageDirection' : 'N', // Used when drawMode is segmentImage. Default is north, can also be (E)ast, (S)outh, (W)est. 62 'responsive' : false, // If set to true the wheel will resize when the window first loads and also onResize. 63 'scaleFactor' : 1, // Set by the responsive function. Used in many calculations to scale the wheel. 64 }; 65 66 // ----------------------------------------- 67 // Loop through the default options and create properties of this class set to the value for the option passed in 68 // or if not value for the option was passed in then to the default. 69 for (let key in defaultOptions) { 70 if ((options != null) && (typeof(options[key]) !== 'undefined')) { 71 this[key] = options[key]; 72 } else { 73 this[key] = defaultOptions[key]; 74 } 75 } 76 77 // Also loop though the passed in options and add anything specified not part of the class in to it as a property. 78 if (options != null) { 79 for (let key in options) { 80 if (typeof(this[key]) === 'undefined') { 81 this[key] = options[key]; 82 } 83 } 84 } 85 86 87 // ------------------------------------------ 88 // If the id of the canvas is set, try to get the canvas as we need it for drawing. 89 if (this.canvasId) { 90 this.canvas = document.getElementById(this.canvasId); 91 92 if (this.canvas) { 93 // If the centerX and centerY have not been specified in the options then default to center of the canvas 94 // and make the outerRadius half of the canvas width - this means the wheel will fill the canvas. 95 if (this.centerX == null) { 96 this.centerX = this.canvas.width / 2; 97 } 98 99 if (this.centerY == null) { 100 this.centerY = this.canvas.height / 2; 101 } 102 103 if (this.outerRadius == null) { 104 // Need to set to half the width of the shortest dimension of the canvas as the canvas may not be square. 105 // Minus the line segment line width otherwise the lines around the segments on the top,left,bottom,right 106 // side are chopped by the edge of the canvas. 107 if (this.canvas.width < this.canvas.height) { 108 this.outerRadius = (this.canvas.width / 2) - this.lineWidth; 109 } else { 110 this.outerRadius = (this.canvas.height / 2) - this.lineWidth; 111 } 112 } 113 114 // Also get a 2D context to the canvas as we need this to draw with. 115 this.ctx = this.canvas.getContext('2d'); 116 } else { 117 this.canvas = null; 118 this.ctx = null; 119 } 120 } else { 121 this.canvas = null; 122 this.ctx = null; 123 } 124 125 // ------------------------------------------ 126 // Add array of segments to the wheel, then populate with segments if number of segments is specified for this object. 127 this.segments = new Array(null); 128 129 for (let x = 1; x <= this.numSegments; x++) { 130 // If options for the segments have been specified then create a segment sending these options so 131 // the specified values are used instead of the defaults. 132 if ((options != null) && (options['segments']) && (typeof(options['segments'][x-1]) !== 'undefined')) { 133 this.segments[x] = new Segment(options['segments'][x-1]); 134 } else { 135 this.segments[x] = new Segment(); 136 } 137 } 138 139 // ------------------------------------------ 140 // Call function to update the segment sizes setting the starting and ending angles. 141 this.updateSegmentSizes(); 142 143 // If the text margin is null then set to same as font size as we want some by default. 144 if (this.textMargin === null) { 145 this.textMargin = (this.textFontSize / 1.7); 146 } 147 148 // ------------------------------------------ 149 // If the animation options have been passed in then create animation object as a property of this class 150 // and pass the options to it so the animation is set. Otherwise create default animation object. 151 if ((options != null) && (options['animation']) && (typeof(options['animation']) !== 'undefined')) { 152 this.animation = new Animation(options['animation']); 153 } else { 154 this.animation = new Animation(); 155 } 156 157 // ------------------------------------------ 158 // If some pin options then create create a pin object and then pass them in. 159 if ((options != null) && (options['pins']) && (typeof(options['pins']) !== 'undefined')) { 160 this.pins = new Pin(options['pins']); 161 } 162 163 // ------------------------------------------ 164 // If the drawMode is image change some defaults provided a value has not been specified. 165 if ((this.drawMode == 'image') || (this.drawMode == 'segmentImage')) { 166 // Remove grey fillStyle. 167 if (typeof(options['fillStyle']) === 'undefined') { 168 this.fillStyle = null; 169 } 170 171 // Set strokeStyle to red. 172 if (typeof(options['strokeStyle']) === 'undefined') { 173 this.strokeStyle = 'red'; 174 } 175 176 // Set drawText to false as we will assume any text is part of the image. 177 if (typeof(options['drawText']) === 'undefined') { 178 this.drawText = false; 179 } 180 181 // Also set the lineWidth to 1 so that segment overlay will look correct. 182 if (typeof(options['lineWidth']) === 'undefined') { 183 this.lineWidth = 1; 184 } 185 186 // Set drawWheel to false as normally the image needs to be loaded first. 187 if (typeof(drawWheel) === 'undefined') { 188 drawWheel = false; 189 } 190 } else { 191 // When in code drawMode the default is the wheel will draw. 192 if (typeof(drawWheel) === 'undefined') { 193 drawWheel = true; 194 } 195 } 196 197 // Create pointer guide. 198 if ((options != null) && (options['pointerGuide']) && (typeof(options['pointerGuide']) !== 'undefined')) { 199 this.pointerGuide = new PointerGuide(options['pointerGuide']); 200 } else { 201 this.pointerGuide = new PointerGuide(); 202 } 203 204 // Check if the wheel is to be responsive, if so then need to save the original size of the canvas 205 // and also check for data- attributes on the canvas which help control the scaling. 206 if (this.responsive) { 207 winwheelToDrawDuringAnimation = this; 208 209 // Save the original defined width and height of the canvas, this is needed later to work out the scaling. 210 this._originalCanvasWidth = this.canvas.width; 211 this._originalCanvasHeight = this.canvas.height; 212 213 // Get data-attributes on the canvas. 214 this._responsiveScaleHeight = this.canvas.dataset.responsivescaleheight; 215 this._responsiveMinWidth = this.canvas.dataset.responsiveminwidth; 216 this._responsiveMinHeight = this.canvas.dataset.responsiveminheight; 217 this._responsiveMargin = this.canvas.dataset.responsivemargin; 218 219 // Add event listeners for onload and onresize and call a function defined at the bottom 220 // of this script which will handle that and work out the scale factor. 221 window.addEventListener("load", winwheelResize); 222 window.addEventListener("resize", winwheelResize); 223 } 224 225 // Finally if drawWheel is true then call function to render the wheel, segment text, overlay etc. 226 if (drawWheel == true) { 227 this.draw(this.clearTheCanvas); 228 } else if (this.drawMode == 'segmentImage') { 229 // If segment image then loop though all the segments and load the images for them setting a callback 230 // which will call the draw function of the wheel once all the images have been loaded. 231 winwheelToDrawDuringAnimation = this; 232 winhweelAlreadyDrawn = false; 233 234 for (let y = 1; y <= this.numSegments; y ++) { 235 if (this.segments[y].image !== null) { 236 this.segments[y].imgData = new Image(); 237 this.segments[y].imgData.onload = winwheelLoadedImage; 238 this.segments[y].imgData.src = this.segments[y].image; 239 } 240 } 241 } 1 function YpmAdmin() { 2 this.init(); 242 3 } 243 4 244 // ==================================================================================================================== 245 // This function sorts out the segment sizes. Some segments may have set sizes, for the others what is left out of 246 // 360 degrees is shared evenly. What this function actually does is set the start and end angle of the arcs. 247 // ==================================================================================================================== 248 Winwheel.prototype.updateSegmentSizes = function() 249 { 250 // If this object actually contains some segments 251 if (this.segments) { 252 // First add up the arc used for the segments where the size has been set. 253 let arcUsed = 0; 254 let numSet = 0; 255 256 // Remember, to make it easy to access segments, the position of the segments in the array starts from 1 (not 0). 257 for (let x = 1; x <= this.numSegments; x ++) { 258 if (this.segments[x].size !== null) { 259 arcUsed += this.segments[x].size; 260 numSet ++; 261 } 262 } 263 264 let arcLeft = (360 - arcUsed); 265 266 // Create variable to hold how much each segment with non-set size will get in terms of degrees. 267 let degreesEach = 0; 268 269 if (arcLeft > 0) { 270 degreesEach = (arcLeft / (this.numSegments - numSet)); 271 } 272 273 // ------------------------------------------ 274 // Now loop though and set the start and end angle of each segment. 275 let currentDegree = 0; 276 277 for (let x = 1; x <= this.numSegments; x ++) { 278 // Set start angle. 279 this.segments[x].startAngle = currentDegree; 280 281 // If the size is set then add this to the current degree to get the end, else add the degreesEach to it. 282 if (this.segments[x].size) { 283 currentDegree += this.segments[x].size; 284 } else { 285 currentDegree += degreesEach; 286 } 287 288 // Set end angle. 289 this.segments[x].endAngle = currentDegree; 290 } 291 } 5 YpmAdmin.prototype.init = function() { 6 this.calcPercentage(); 7 this.proRedirect(); 292 8 } 293 9 294 // ==================================================================================================================== 295 // This function clears the canvas. Will wipe anything else which happens to be drawn on it. 296 // ==================================================================================================================== 297 Winwheel.prototype.clearCanvas = function() 298 { 299 if (this.ctx) { 300 this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); 301 } 10 YpmAdmin.prototype.proRedirect = function() { 11 jQuery('.disabled-button').on('click', function() { 12 window.open(yrmWheelAdmin.proURL) 13 }) 302 14 } 303 15 304 // ==================================================================================================================== 305 // This function draws / re-draws the wheel on the canvas therefore rendering any changes. 306 // ==================================================================================================================== 307 Winwheel.prototype.draw = function(clearTheCanvas) 308 { 309 // If have the canvas context. 310 if (this.ctx) { 311 // Clear the canvas, unless told not to. 312 if (typeof(clearTheCanvas) !== 'undefined') { 313 if (clearTheCanvas == true) { 314 this.clearCanvas(); 315 } 316 } else { 317 this.clearCanvas(); 16 YpmAdmin.prototype.calcPercentage = function() { 17 jQuery(document).on('change', '.ypm-prize-probability', function(e) { 18 e.preventDefault(); 19 20 var total = 0; 21 jQuery('.ypm-prize-probability').each(function() { 22 total += parseInt(jQuery(this).val()) || 0; 23 }); 24 25 if (total > 100) { 26 var excess = total - 100; 27 var currentValue = parseInt(jQuery(this).val()) || 0; 28 jQuery(this).val(Math.max(0, currentValue - excess)); 318 29 } 319 320 // Call functions to draw the segments and then segment text. 321 if (this.drawMode == 'image') { 322 // Draw the wheel by loading and drawing an image such as a png on the canvas. 323 this.drawWheelImage(); 324 325 // If we are to draw the text, do so before the overlay is drawn 326 // as this allows the overlay to be used to create some interesting effects. 327 if (this.drawText == true) { 328 this.drawSegmentText(); 329 } 330 331 // If image overlay is true then call function to draw the segments over the top of the image. 332 // This is useful during development to check alignment between where the code thinks the segments are and where they appear on the image. 333 if (this.imageOverlay == true) { 334 this.drawSegments(); 335 } 336 } else if (this.drawMode == 'segmentImage') { 337 // Draw the wheel by rendering the image for each segment. 338 this.drawSegmentImages(); 339 340 // If we are to draw the text, do so before the overlay is drawn 341 // as this allows the overlay to be used to create some interesting effects. 342 if (this.drawText == true) { 343 this.drawSegmentText(); 344 } 345 346 // If image overlay is true then call function to draw the segments over the top of the image. 347 // This is useful during development to check alignment between where the code thinks the segments are and where they appear on the image. 348 if (this.imageOverlay == true) { 349 this.drawSegments(); 350 } 351 } else { 352 // The default operation is to draw the segments using code via the canvas arc() method. 353 this.drawSegments(); 354 355 // The text is drawn on top. 356 if (this.drawText == true) { 357 this.drawSegmentText(); 358 } 359 } 360 361 // If this class has pins. 362 if (typeof this.pins !== 'undefined') { 363 // If they are to be visible then draw them. 364 if (this.pins.visible == true) { 365 this.drawPins(); 366 } 367 } 368 369 // If pointer guide is display property is set to true then call function to draw the pointer guide. 370 if (this.pointerGuide.display == true) { 371 this.drawPointerGuide(); 372 } 373 } 30 }); 374 31 } 375 32 376 // ==================================================================================================================== 377 // Draws the pins around the outside of the wheel. 378 // ==================================================================================================================== 379 Winwheel.prototype.drawPins = function() 380 { 381 if ((this.pins) && (this.pins.number)) { 382 // Get scaled centerX and centerY to use in the code below so pins will draw responsively too. 383 let centerX = (this.centerX * this.scaleFactor); 384 let centerY = (this.centerY * this.scaleFactor); 385 let outerRadius = (this.outerRadius * this.scaleFactor); 386 387 // Check if the pin's size is to be responsive too, if so set the pinOuterRadius to a scaled version number. 388 let pinOuterRadius = this.pins.outerRadius; 389 let pinMargin = this.pins.margin; 390 391 if (this.pins.responsive) { 392 pinOuterRadius = (this.pins.outerRadius * this.scaleFactor); 393 pinMargin = (this.pins.margin * this.scaleFactor); 394 } 395 396 // Work out the angle to draw each pin a which is simply 360 / the number of pins as they space evenly around. 397 //++ There is a slight oddity with the pins in that there is a pin at 0 and also one at 360 and these will be drawn 398 //++ directly over the top of each other. Also pins are 0 indexed which could possibly cause some confusion 399 //++ with the getCurrentPin function - for now this is just used for audio so probably not a problem. 400 let pinSpacing = (360 / this.pins.number); 401 402 for(let i=1; i<=this.pins.number; i ++) { 403 this.ctx.save(); 404 405 // Set the stroke style and line width. 406 this.ctx.strokeStyle = this.pins.strokeStyle; 407 this.ctx.lineWidth = this.pins.lineWidth; 408 this.ctx.fillStyle = this.pins.fillStyle; 409 410 // Move to the center. 411 this.ctx.translate(centerX, centerY); 412 413 // Rotate to to the pin location which is i * the pinSpacing. 414 this.ctx.rotate(this.degToRad(i * pinSpacing + this.rotationAngle)); 415 416 // Move back out. 417 this.ctx.translate(-centerX, -centerY); 418 419 // Create a path for the pin circle. 420 this.ctx.beginPath(); 421 // x, y, radius, startAngle, endAngle. 422 this.ctx.arc(centerX,(centerY - outerRadius) + pinOuterRadius + pinMargin, pinOuterRadius, 0, 2*Math.PI); 423 424 if (this.pins.fillStyle) { 425 this.ctx.fill(); 426 } 427 428 if (this.pins.strokeStyle) { 429 this.ctx.stroke(); 430 } 431 432 this.ctx.restore(); 433 } 434 } 435 } 436 437 // ==================================================================================================================== 438 // Draws a line from the center of the wheel to the outside at the angle where the code thinks the pointer is. 439 // ==================================================================================================================== 440 Winwheel.prototype.drawPointerGuide = function() 441 { 442 // If have canvas context. 443 if (this.ctx) { 444 // Get scaled center x an y and also the outer radius. 445 let centerX = (this.centerX * this.scaleFactor); 446 let centerY = (this.centerY * this.scaleFactor); 447 let outerRadius = (this.outerRadius * this.scaleFactor); 448 449 this.ctx.save(); 450 451 // Rotate the canvas to the line goes towards the location of the pointer. 452 this.ctx.translate(centerX, centerY); 453 this.ctx.rotate(this.degToRad(this.pointerAngle)); 454 this.ctx.translate(-centerX, -centerY); 455 456 // Set line colour and width. 457 this.ctx.strokeStyle = this.pointerGuide.strokeStyle; 458 this.ctx.lineWidth = this.pointerGuide.lineWidth; 459 460 // Draw from the center of the wheel outwards past the wheel outer radius. 461 this.ctx.beginPath(); 462 this.ctx.moveTo(centerX, centerY); 463 this.ctx.lineTo(centerX, -(outerRadius / 4)); 464 465 this.ctx.stroke(); 466 this.ctx.restore(); 467 } 468 } 469 470 // ==================================================================================================================== 471 // This function takes an image such as PNG and draws it on the canvas making its center at the centerX and center for the wheel. 472 // ==================================================================================================================== 473 Winwheel.prototype.drawWheelImage = function() 474 { 475 // Double check the wheelImage property of this class is not null. This does not actually detect that an image 476 // source was set and actually loaded so might get error if this is not the case. This is why the initial call 477 // to draw() should be done from a wheelImage.onload callback as detailed in example documentation. 478 if (this.wheelImage != null) { 479 // Get the centerX and centerY in to variables, adjust by the scaleFactor. 480 let centerX = (this.centerX * this.scaleFactor); 481 let centerY = (this.centerY * this.scaleFactor); 482 483 // Get the scaled width and height of the image. 484 let scaledWidth = (this.wheelImage.width * this.scaleFactor); 485 let scaledHeight = (this.wheelImage.height * this.scaleFactor); 486 487 // Work out the correct X and Y to draw the image at. We need to get the center point of the image 488 // aligned over the center point of the wheel, we can't just place it at 0, 0. 489 let imageLeft = (centerX - (scaledWidth / 2)); 490 let imageTop = (centerY - (scaledHeight / 2)); 491 492 // Rotate and then draw the wheel. 493 // We must rotate by the rotationAngle before drawing to ensure that image wheels will spin. 494 this.ctx.save(); 495 this.ctx.translate(centerX, centerY); 496 this.ctx.rotate(this.degToRad(this.rotationAngle)); 497 this.ctx.translate(-centerX, -centerY); 498 499 // Draw the image passing the scaled width and height which will ensure the image will be responsive. 500 this.ctx.drawImage(this.wheelImage, imageLeft, imageTop, scaledWidth, scaledHeight); 501 502 this.ctx.restore(); 503 } 504 } 505 506 // ==================================================================================================================== 507 // This function draws the wheel on the canvas by rendering the image for each segment. 508 // ==================================================================================================================== 509 Winwheel.prototype.drawSegmentImages = function() 510 { 511 // Again check have context in case this function was called directly and not via draw function. 512 if (this.ctx) { 513 // Get the centerX and centerY of the wheel adjusted with the scale factor. 514 let centerX = (this.centerX * this.scaleFactor); 515 let centerY = (this.centerY * this.scaleFactor); 516 517 // Draw the segments if there is at least one in the segments array. 518 if (this.segments) { 519 // Loop though and output all segments - position 0 of the array is not used, so start loop from index 1 520 // this is to avoid confusion when talking about the first segment. 521 for (let x = 1; x <= this.numSegments; x ++) { 522 // Get the segment object as we need it to read options from. 523 let seg = this.segments[x]; 524 525 // Check image has loaded so a property such as height has a value. 526 if (seg.imgData.height) { 527 // Work out the correct X and Y to draw the image at which depends on the direction of the image. 528 // Images can be created in 4 directions. North, South, East, West. 529 // North: Outside at top, inside at bottom. Sits evenly over the 0 degrees angle. 530 // South: Outside at bottom, inside at top. Sits evenly over the 180 degrees angle. 531 // East: Outside at right, inside at left. Sits evenly over the 90 degrees angle. 532 // West: Outside at left, inside at right. Sits evenly over the 270 degrees angle. 533 let imageLeft = 0; 534 let imageTop = 0; 535 let imageAngle = 0; 536 let imageDirection = ''; 537 538 // Get scaled width and height of the segment image. 539 let scaledWidth = (seg.imgData.width * this.scaleFactor); 540 let scaledHeight = (seg.imgData.height * this.scaleFactor); 541 542 if (seg.imageDirection !== null) { 543 imageDirection = seg.imageDirection; 544 } else { 545 imageDirection = this.imageDirection; 546 } 547 548 if (imageDirection == 'S') { 549 // Left set so image sits half/half over the 180 degrees point. 550 imageLeft = (centerX - (scaledWidth / 2)); 551 552 // Top so image starts at the centerY. 553 imageTop = centerY; 554 555 // Angle to draw the image is its starting angle + half its size. 556 // Here we add 180 to the angle to the segment is poistioned correctly. 557 imageAngle = (seg.startAngle + 180 + ((seg.endAngle - seg.startAngle) / 2)); 558 } else if (imageDirection == 'E') { 559 // Left set so image starts and the center point. 560 imageLeft = centerX; 561 562 // Top is so that it sits half/half over the 90 degree point. 563 imageTop = (centerY - (scaledHeight / 2)); 564 565 // Again get the angle in the center of the segment and add it to the rotation angle. 566 // this time we need to add 270 to that to the segment is rendered the correct place. 567 imageAngle = (seg.startAngle + 270 + ((seg.endAngle - seg.startAngle) / 2)); 568 } else if (imageDirection == 'W') { 569 // Left is the centerX minus the width of the image. 570 imageLeft = (centerX - scaledWidth); 571 572 // Top is so that it sits half/half over the 270 degree point. 573 imageTop = (centerY - (scaledHeight / 2)); 574 575 // Again get the angle in the center of the segment and add it to the rotation angle. 576 // this time we need to add 90 to that to the segment is rendered the correct place. 577 imageAngle = (seg.startAngle + 90 + ((seg.endAngle - seg.startAngle) / 2)); 578 } else { 579 // North is the default. 580 // Left set so image sits half/half over the 0 degrees point. 581 imageLeft = (centerX - (scaledWidth / 2)); 582 583 // Top so image is its height out (above) the center point. 584 imageTop = (centerY - scaledHeight); 585 586 // Angle to draw the image is its starting angle + half its size. 587 // this sits it half/half over the center angle of the segment. 588 imageAngle = (seg.startAngle + ((seg.endAngle - seg.startAngle) / 2)); 589 } 590 591 // -------------------------------------------------- 592 // Rotate to the position of the segment and then draw the image. 593 this.ctx.save(); 594 this.ctx.translate(centerX, centerY); 595 596 // So math here is the rotation angle of the wheel plus half way between the start and end angle of the segment. 597 this.ctx.rotate(this.degToRad(this.rotationAngle + imageAngle)); 598 this.ctx.translate(-centerX, -centerY); 599 600 // Draw the image passing the scaled width and height so that it can be responsive. 601 this.ctx.drawImage(seg.imgData, imageLeft, imageTop, scaledWidth, scaledHeight); 602 603 this.ctx.restore(); 604 } else { 605 console.log('Segment ' + x + ' imgData is not loaded'); 606 } 607 } 608 } 609 } 610 } 611 612 // ==================================================================================================================== 613 // This function draws the wheel on the page by rendering the segments on the canvas. 614 // ==================================================================================================================== 615 Winwheel.prototype.drawSegments = function() 616 { 617 // Again check have context in case this function was called directly and not via draw function. 618 if (this.ctx) { 619 // Draw the segments if there is at least one in the segments array. 620 if (this.segments) { 621 // Get scaled centerX and centerY and also scaled inner and outer radius. 622 let centerX = (this.centerX * this.scaleFactor); 623 let centerY = (this.centerY * this.scaleFactor); 624 let innerRadius = (this.innerRadius * this.scaleFactor); 625 let outerRadius = (this.outerRadius * this.scaleFactor); 626 627 // Loop though and output all segments - position 0 of the array is not used, so start loop from index 1 628 // this is to avoid confusion when talking about the first segment. 629 for (let x = 1; x <= this.numSegments; x ++) { 630 // Get the segment object as we need it to read options from. 631 let seg = this.segments[x]; 632 633 let fillStyle; 634 let lineWidth; 635 let strokeStyle; 636 637 // Set the variables that defined in the segment, or use the default options. 638 if (seg.fillStyle !== null) { 639 fillStyle = seg.fillStyle; 640 } else { 641 fillStyle = this.fillStyle; 642 } 643 644 this.ctx.fillStyle = fillStyle; 645 646 if (seg.lineWidth !== null) { 647 lineWidth = seg.lineWidth; 648 } else { 649 lineWidth = this.lineWidth; 650 } 651 652 this.ctx.lineWidth = lineWidth; 653 654 if (seg.strokeStyle !== null) { 655 strokeStyle = seg.strokeStyle; 656 } else { 657 strokeStyle = this.strokeStyle; 658 } 659 660 this.ctx.strokeStyle = strokeStyle; 661 662 663 // Check there is a strokeStyle or fillStyle, if not the segment is invisible so should not try to draw it otherwise a path is began but not ended. 664 if ((strokeStyle) || (fillStyle)) { 665 // Begin a path as the segment consists of an arc and 2 lines. 666 this.ctx.beginPath(); 667 668 // If don't have an inner radius then move to the center of the wheel as we want a line out from the center 669 // to the start of the arc for the outside of the wheel when we arc. Canvas will draw the connecting line for us. 670 if (!this.innerRadius) { 671 this.ctx.moveTo(centerX, centerY); 672 } else { 673 // Work out the x and y values for the starting point of the segment which is at its starting angle 674 // but out from the center point of the wheel by the value of the innerRadius. Some correction for line width is needed. 675 let iX = Math.cos(this.degToRad(seg.startAngle + this.rotationAngle - 90)) * (innerRadius - lineWidth / 2); 676 let iY = Math.sin(this.degToRad(seg.startAngle + this.rotationAngle - 90)) * (innerRadius - lineWidth / 2); 677 678 // Now move here relative to the center point of the wheel. 679 this.ctx.moveTo(centerX + iX, centerY + iY); 680 } 681 682 // Draw the outer arc of the segment clockwise in direction --> 683 this.ctx.arc(centerX, centerY, outerRadius, this.degToRad(seg.startAngle + this.rotationAngle - 90), this.degToRad(seg.endAngle + this.rotationAngle - 90), false); 684 685 if (this.innerRadius) { 686 // Draw another arc, this time anticlockwise <-- at the innerRadius between the end angle and the start angle. 687 // Canvas will draw a connecting line from the end of the outer arc to the beginning of the inner arc completing the shape. 688 this.ctx.arc(centerX, centerY, innerRadius, this.degToRad(seg.endAngle + this.rotationAngle - 90), this.degToRad(seg.startAngle + this.rotationAngle - 90), true); 689 } else { 690 // If no inner radius then we draw a line back to the center of the wheel. 691 this.ctx.lineTo(centerX, centerY); 692 } 693 694 // Fill and stroke the segment. Only do either if a style was specified, if the style is null then 695 // we assume the developer did not want that particular thing. 696 // For example no stroke style so no lines to be drawn. 697 if (fillStyle) { 698 this.ctx.fill(); 699 } 700 701 if (strokeStyle) { 702 this.ctx.stroke(); 703 } 704 } 705 } 706 } 707 } 708 } 709 710 // ==================================================================================================================== 711 // This draws the text on the segments using the specified text options. 712 // ==================================================================================================================== 713 Winwheel.prototype.drawSegmentText = function() 714 { 715 // Again only draw the text if have a canvas context. 716 if (this.ctx) { 717 // Declare variables to hold the values. These are populated either with the value for the specific segment, 718 // or if not specified then the global default value. 719 let fontFamily; 720 let fontSize; 721 let fontWeight; 722 let orientation; 723 let alignment; 724 let direction; 725 let margin; 726 let fillStyle; 727 let strokeStyle; 728 let lineWidth; 729 let fontSetting; 730 731 // Get the centerX and centerY scaled with the scale factor, also the same for outer and inner radius. 732 let centerX = (this.centerX * this.scaleFactor); 733 let centerY = (this.centerY * this.scaleFactor); 734 let outerRadius = (this.outerRadius * this.scaleFactor); 735 let innerRadius = (this.innerRadius * this.scaleFactor); 736 737 // Loop though all the segments. 738 for (let x = 1; x <= this.numSegments; x ++) { 739 // Save the context so it is certain that each segment text option will not affect the other. 740 this.ctx.save(); 741 742 // Get the segment object as we need it to read options from. 743 let seg = this.segments[x]; 744 745 // Check is text as no point trying to draw if there is no text to render. 746 if (seg.text) { 747 // Set values to those for the specific segment or use global default if null. 748 if (seg.textFontFamily !== null) fontFamily = seg.textFontFamily; else fontFamily = this.textFontFamily; 749 if (seg.textFontSize !== null) fontSize = seg.textFontSize; else fontSize = this.textFontSize; 750 if (seg.textFontWeight !== null) fontWeight = seg.textFontWeight; else fontWeight = this.textFontWeight; 751 if (seg.textOrientation !== null) orientation = seg.textOrientation; else orientation = this.textOrientation; 752 if (seg.textAlignment !== null) alignment = seg.textAlignment; else alignment = this.textAlignment; 753 if (seg.textDirection !== null) direction = seg.textDirection; else direction = this.textDirection; 754 if (seg.textMargin !== null) margin = seg.textMargin; else margin = this.textMargin; 755 if (seg.textFillStyle !== null) fillStyle = seg.textFillStyle; else fillStyle = this.textFillStyle; 756 if (seg.textStrokeStyle !== null) strokeStyle = seg.textStrokeStyle; else strokeStyle = this.textStrokeStyle; 757 if (seg.textLineWidth !== null) lineWidth = seg.textLineWidth; else lineWidth = this.textLineWidth; 758 759 // Scale the font size and the margin by the scale factor so the text can be responsive. 760 fontSize = (fontSize * this.scaleFactor); 761 margin = (margin * this.scaleFactor); 762 763 // ------------------------------ 764 // We need to put the font bits together in to one string. 765 let fontSetting = ''; 766 767 if (fontWeight != null) { 768 fontSetting += fontWeight + ' '; 769 } 770 771 if (fontSize != null) { 772 fontSetting += fontSize + 'px '; // Fonts on canvas are always a px value. 773 } 774 775 if (fontFamily != null) { 776 fontSetting += fontFamily; 777 } 778 779 // Now set the canvas context to the decided values. 780 this.ctx.font = fontSetting; 781 this.ctx.fillStyle = fillStyle; 782 this.ctx.strokeStyle = strokeStyle; 783 this.ctx.lineWidth = lineWidth; 784 785 // Split the text in to multiple lines on the \n character. 786 let lines = seg.text.split('\n'); 787 788 // Figure out the starting offset for the lines as when there are multiple lines need to center the text 789 // vertically in the segment (when thinking of normal horozontal text). 790 let lineOffset = 0 - (fontSize * (lines.length / 2)) + (fontSize / 2); 791 792 // The offset works great for horozontal and vertial text, also centered curved. But when the text is curved 793 // and the alignment is outer then the multiline text should not have some text outside the wheel. Same if inner curved. 794 if ((orientation == 'curved') && ((alignment == 'inner') || (alignment == 'outer'))) { 795 lineOffset = 0; 796 } 797 798 for (let i = 0; i < lines.length; i ++) { 799 // If direction is reversed then do things differently than if normal (which is the default - see further down) 800 if (direction == 'reversed') { 801 // When drawing reversed or 'upside down' we need to do some trickery on our part. 802 // The canvas text rendering function still draws the text left to right and the correct way up, 803 // so we need to overcome this with rotating the opposite side of the wheel the correct way up then pulling the text 804 // through the center point to the correct segment it is supposed to be on. 805 if (orientation == 'horizontal') { 806 if (alignment == 'inner') { 807 this.ctx.textAlign = 'right'; 808 } else if (alignment == 'outer') { 809 this.ctx.textAlign = 'left'; 810 } else { 811 this.ctx.textAlign = 'center'; 812 } 813 814 this.ctx.textBaseline = 'middle'; 815 816 // Work out the angle to rotate the wheel, this is in the center of the segment but on the opposite side of the wheel which is why do -180. 817 let textAngle = this.degToRad((seg.endAngle - ((seg.endAngle - seg.startAngle) / 2) + this.rotationAngle - 90) - 180); 818 819 this.ctx.save(); 820 this.ctx.translate(centerX, centerY); 821 this.ctx.rotate(textAngle); 822 this.ctx.translate(-centerX, -centerY); 823 824 if (alignment == 'inner') { 825 // In reversed state the margin is subtracted from the innerX. 826 // When inner the inner radius also comes in to play. 827 if (fillStyle) { 828 this.ctx.fillText(lines[i], centerX - innerRadius - margin, centerY + lineOffset); 829 } 830 831 if (strokeStyle) { 832 this.ctx.strokeText(lines[i], centerX - innerRadius - margin, centerY + lineOffset); 833 } 834 } else if (alignment == 'outer') { 835 // In reversed state the position is the center minus the radius + the margin for outer aligned text. 836 if (fillStyle) { 837 this.ctx.fillText(lines[i], centerX - outerRadius + margin, centerY + lineOffset); 838 } 839 840 if (strokeStyle) { 841 this.ctx.strokeText(lines[i], centerX - outerRadius + margin, centerY + lineOffset); 842 } 843 } else { 844 // In reversed state the everything in minused. 845 if (fillStyle) { 846 this.ctx.fillText(lines[i], centerX - innerRadius - ((outerRadius - innerRadius) / 2) - margin, centerY + lineOffset); 847 } 848 849 if (strokeStyle) { 850 this.ctx.strokeText(lines[i], centerX - innerRadius - ((outerRadius - innerRadius) / 2) - margin, centerY + lineOffset); 851 } 852 } 853 854 this.ctx.restore(); 855 856 } else if (orientation == 'vertical') { 857 // See normal code further down for comments on how it works, this is similar by plus/minus is reversed. 858 this.ctx.textAlign = 'center'; 859 860 // In reversed mode this are reversed. 861 if (alignment == 'inner') { 862 this.ctx.textBaseline = 'top'; 863 } else if (alignment == 'outer') { 864 this.ctx.textBaseline = 'bottom'; 865 } else { 866 this.ctx.textBaseline = 'middle'; 867 } 868 869 let textAngle = (seg.endAngle - ((seg.endAngle - seg.startAngle) / 2) - 180); 870 textAngle += this.rotationAngle; 871 872 this.ctx.save(); 873 this.ctx.translate(centerX, centerY); 874 this.ctx.rotate(this.degToRad(textAngle)); 875 this.ctx.translate(-centerX, -centerY); 876 877 //++ @TODO double-check the default of 0 is correct. 878 let yPos = 0; 879 if (alignment == 'outer') { 880 yPos = (centerY + outerRadius - margin); 881 } else if (alignment == 'inner') { 882 yPos = (centerY + innerRadius + margin); 883 } 884 885 // I have found that the text looks best when a fraction of the font size is shaved off. 886 let yInc = (fontSize - (fontSize / 9)); 887 888 // Loop though and output the characters. 889 if (alignment == 'outer') { 890 // In reversed mode outer means text in 6 o'clock segment sits at bottom of the wheel and we draw up. 891 for (let c = (lines[i].length -1); c >= 0; c--) { 892 let character = lines[i].charAt(c); 893 894 if (fillStyle) { 895 this.ctx.fillText(character, centerX + lineOffset, yPos); 896 } 897 898 if (strokeStyle) { 899 this.ctx.strokeText(character, centerX + lineOffset, yPos); 900 } 901 902 yPos -= yInc; 903 } 904 } else if (alignment == 'inner') { 905 // In reversed mode inner text is drawn from top of segment at 6 o'clock position to bottom of the wheel. 906 for (let c = 0; c < lines[i].length; c++) { 907 let character = lines[i].charAt(c); 908 909 if (fillStyle) { 910 this.ctx.fillText(character, centerX + lineOffset, yPos); 911 } 912 913 if (strokeStyle) { 914 this.ctx.strokeText(character, centerX + lineOffset, yPos); 915 } 916 917 yPos += yInc; 918 } 919 } else if (alignment == 'center') { 920 // Again for reversed this is the opposite of before. 921 // If there is more than one character in the text then an adjustment to the position needs to be done. 922 // What we are aiming for is to position the center of the text at the center point between the inner and outer radius. 923 let centerAdjustment = 0; 924 925 if (lines[i].length > 1) { 926 centerAdjustment = (yInc * (lines[i].length -1) / 2); 927 } 928 929 let yPos = (centerY + innerRadius + ((outerRadius - innerRadius) / 2)) + centerAdjustment + margin; 930 931 for (let c = (lines[i].length -1); c >= 0; c--) { 932 let character = lines[i].charAt(c); 933 934 if (fillStyle) { 935 this.ctx.fillText(character, centerX + lineOffset, yPos); 936 } 937 938 if (strokeStyle) { 939 this.ctx.strokeText(character, centerX + lineOffset, yPos); 940 } 941 942 yPos -= yInc; 943 } 944 } 945 946 this.ctx.restore(); 947 948 } else if (orientation == 'curved') { 949 // There is no built in canvas function to draw text around an arc, 950 // so we need to do this ourselves. 951 let radius = 0; 952 953 // Set the alignment of the text - inner, outer, or center by calculating 954 // how far out from the center point of the wheel the text is drawn. 955 if (alignment == 'inner') { 956 // When alignment is inner the radius is the innerRadius plus any margin. 957 radius = innerRadius + margin; 958 this.ctx.textBaseline = 'top'; 959 } else if (alignment == 'outer') { 960 // Outer it is the outerRadius minus any margin. 961 radius = outerRadius - margin; 962 this.ctx.textBaseline = 'bottom'; 963 964 // We need to adjust the radius in this case to take in to multiline text. 965 // In this case the radius needs to be further out, not at the inner radius. 966 radius -= (fontSize * (lines.length - 1)); 967 } else if (alignment == 'center') { 968 // When center we want the text halfway between the inner and outer radius. 969 radius = innerRadius + margin + ((outerRadius - innerRadius) / 2); 970 this.ctx.textBaseline = 'middle'; 971 } 972 973 // Set the angle to increment by when looping though and outputting the characters in the text 974 // as we do this by rotating the wheel small amounts adding each character. 975 let anglePerChar = 0; 976 let drawAngle = 0; 977 978 // If more than one character in the text then... 979 if (lines[i].length > 1) { 980 // Text is drawn from the left. 981 this.ctx.textAlign = 'left'; 982 983 // Work out how much angle the text rendering loop below needs to rotate by for each character to render them next to each other. 984 // I have discovered that 4 * the font size / 10 at 100px radius is the correct spacing for between the characters 985 // using a monospace font, non monospace may look a little odd as in there will appear to be extra spaces between chars. 986 anglePerChar = (4 * (fontSize / 10)); 987 988 // Work out what percentage the radius the text will be drawn at is of 100px. 989 let radiusPercent = (100 / radius); 990 991 // Then use this to scale up or down the anglePerChar value. 992 // When the radius is less than 100px we need more angle between the letters, when radius is greater (so the text is further 993 // away from the center of the wheel) the angle needs to be less otherwise the characters will appear further apart. 994 anglePerChar = (anglePerChar * radiusPercent); 995 996 // Next we want the text to be drawn in the middle of the segment, without this it would start at the beginning of the segment. 997 // To do this we need to work out how much arc the text will take up in total then subtract half of this from the center 998 // of the segment so that it sits centred. 999 let totalArc = (anglePerChar * lines[i].length); 1000 1001 // Now set initial draw angle to half way between the start and end of the segment. 1002 drawAngle = seg.startAngle + (((seg.endAngle - seg.startAngle) / 2) - (totalArc / 2)); 1003 } else { 1004 // The initial draw angle is the center of the segment when only one character. 1005 drawAngle = (seg.startAngle + ((seg.endAngle - seg.startAngle) / 2)); 1006 1007 // To ensure is dead-center the text alignment also needs to be centered. 1008 this.ctx.textAlign = 'center'; 1009 } 1010 1011 // ---------------------- 1012 // Adjust the initial draw angle as needed to take in to account the rotationAngle of the wheel. 1013 drawAngle += this.rotationAngle; 1014 1015 // And as with other 'reverse' text direction functions we need to subtract 180 degrees from the angle 1016 // because when it comes to draw the characters in the loop below we add the radius instead of subtract it. 1017 drawAngle -= 180; 1018 1019 // ---------------------- 1020 // Now the drawing itself. 1021 // In reversed direction mode we loop through the characters in the text backwards in order for them to appear on screen correctly 1022 for (let c = lines[i].length; c >= 0; c--) { 1023 this.ctx.save(); 1024 1025 let character = lines[i].charAt(c); 1026 1027 // Rotate the wheel to the draw angle as we need to add the character at this location. 1028 this.ctx.translate(centerX, centerY); 1029 this.ctx.rotate(this.degToRad(drawAngle)); 1030 this.ctx.translate(-centerX, -centerY); 1031 1032 // Now draw the character directly below the center point of the wheel at the appropriate radius. 1033 // Note in the reversed mode we add the radius to the this.centerY instead of subtract. 1034 if (strokeStyle) { 1035 this.ctx.strokeText(character, centerX, centerY + radius + lineOffset); 1036 } 1037 1038 if (fillStyle) { 1039 this.ctx.fillText(character, centerX, centerY + radius + lineOffset); 1040 } 1041 1042 // Increment the drawAngle by the angle per character so next loop we rotate 1043 // to the next angle required to draw the character at. 1044 drawAngle += anglePerChar; 1045 1046 this.ctx.restore(); 1047 } 1048 } 1049 } else { 1050 // Normal direction so do things normally. 1051 // Check text orientation, of horizontal then reasonably straight forward, if vertical then a bit more work to do. 1052 if (orientation == 'horizontal') { 1053 // Based on the text alignment, set the correct value in the context. 1054 if (alignment == 'inner') { 1055 this.ctx.textAlign = 'left'; 1056 } else if (alignment == 'outer') { 1057 this.ctx.textAlign = 'right'; 1058 } else { 1059 this.ctx.textAlign = 'center'; 1060 } 1061 1062 // Set this too. 1063 this.ctx.textBaseline = 'middle'; 1064 1065 // Work out the angle around the wheel to draw the text at, which is simply in the middle of the segment the text is for. 1066 // The rotation angle is added in to correct the annoyance with the canvas arc drawing functions which put the 0 degrees at the 3 oclock 1067 let textAngle = this.degToRad(seg.endAngle - ((seg.endAngle - seg.startAngle) / 2) + this.rotationAngle - 90); 1068 1069 // We need to rotate in order to draw the text because it is output horizontally, so to 1070 // place correctly around the wheel for all but a segment at 3 o'clock we need to rotate. 1071 this.ctx.save(); 1072 this.ctx.translate(centerX, centerY); 1073 this.ctx.rotate(textAngle); 1074 this.ctx.translate(-centerX, -centerY); 1075 1076 // -------------------------- 1077 // Draw the text based on its alignment adding margin if inner or outer. 1078 if (alignment == 'inner') { 1079 // Inner means that the text is aligned with the inner of the wheel. If looking at a segment in in the 3 o'clock position 1080 // it would look like the text is left aligned within the segment. 1081 1082 // Because the segments are smaller towards the inner of the wheel, in order for the text to fit is is a good idea that 1083 // a margin is added which pushes the text towards the outer a bit. 1084 1085 // The inner radius also needs to be taken in to account as when inner aligned. 1086 1087 // If fillstyle is set the draw the text filled in. 1088 if (fillStyle) { 1089 this.ctx.fillText(lines[i], centerX + innerRadius + margin, centerY + lineOffset); 1090 } 1091 1092 // If stroke style is set draw the text outline. 1093 if (strokeStyle) { 1094 this.ctx.strokeText(lines[i], centerX + innerRadius + margin, centerY + lineOffset); 1095 } 1096 } else if (alignment == 'outer') { 1097 // Outer means the text is aligned with the outside of the wheel, so if looking at a segment in the 3 o'clock position 1098 // it would appear the text is right aligned. To position we add the radius of the wheel in to the equation 1099 // and subtract the margin this time, rather than add it. 1100 1101 // I don't understand why, but in order of the text to render correctly with stroke and fill, the stroke needs to 1102 // come first when drawing outer, rather than second when doing inner. 1103 if (fillStyle) { 1104 this.ctx.fillText(lines[i], centerX + outerRadius - margin, centerY + lineOffset); 1105 } 1106 1107 // If fillstyle the fill the text. 1108 if (strokeStyle) { 1109 this.ctx.strokeText(lines[i], centerX + outerRadius - margin, centerY + lineOffset); 1110 } 1111 } else { 1112 // In this case the text is to drawn centred in the segment. 1113 // Typically no margin is required, however even though centred the text can look closer to the inner of the wheel 1114 // due to the way the segments narrow in (is optical effect), so if a margin is specified it is placed on the inner 1115 // side so the text is pushed towards the outer. 1116 1117 // If stoke style the stroke the text. 1118 if (fillStyle) { 1119 this.ctx.fillText(lines[i], centerX + innerRadius + ((outerRadius - innerRadius) / 2) + margin, centerY + lineOffset); 1120 } 1121 1122 // If fillstyle the fill the text. 1123 if (strokeStyle) { 1124 this.ctx.strokeText(lines[i], centerX + innerRadius + ((outerRadius - innerRadius) / 2) + margin, centerY + lineOffset); 1125 } 1126 } 1127 1128 // Restore the context so that wheel is returned to original position. 1129 this.ctx.restore(); 1130 1131 } else if (orientation == 'vertical') { 1132 // If vertical then we need to do this ourselves because as far as I am aware there is no option built in to html canvas 1133 // which causes the text to draw downwards or upwards one character after another. 1134 1135 // In this case the textAlign is always center, but the baseline is either top or bottom 1136 // depending on if inner or outer alignment has been specified. 1137 this.ctx.textAlign = 'center'; 1138 1139 if (alignment == 'inner') { 1140 this.ctx.textBaseline = 'bottom'; 1141 } else if (alignment == 'outer') { 1142 this.ctx.textBaseline = 'top'; 1143 } else { 1144 this.ctx.textBaseline = 'middle'; 1145 } 1146 1147 // The angle to draw the text at is halfway between the end and the starting angle of the segment. 1148 let textAngle = seg.endAngle - ((seg.endAngle - seg.startAngle) / 2); 1149 1150 // Ensure the rotation angle of the wheel is added in, otherwise the test placement won't match 1151 // the segments they are supposed to be for. 1152 textAngle += this.rotationAngle; 1153 1154 // Rotate so can begin to place the text. 1155 this.ctx.save(); 1156 this.ctx.translate(centerX, centerY); 1157 this.ctx.rotate(this.degToRad(textAngle)); 1158 this.ctx.translate(-centerX, -centerY); 1159 1160 // Work out the position to start drawing in based on the alignment. 1161 // If outer then when considering a segment at the 12 o'clock position want to start drawing down from the top of the wheel. 1162 //++ TODO check this as yPos did not seem to have a defualt before. 1163 let yPos = 0; 1164 1165 if (alignment == 'outer') { 1166 yPos = (centerY - outerRadius + margin); 1167 } else if (alignment == 'inner') { 1168 yPos = (centerY - innerRadius - margin); 1169 } 1170 1171 // We need to know how much to move the y axis each time. 1172 // This is not quite simply the font size as that puts a larger gap in between the letters 1173 // than expected, especially with monospace fonts. I found that shaving a little off makes it look "right". 1174 let yInc = (fontSize - (fontSize / 9)); 1175 1176 // Loop though and output the characters. 1177 if (alignment == 'outer') { 1178 // For this alignment we draw down from the top of a segment at the 12 o'clock position to simply 1179 // loop though the characters in order. 1180 for (let c = 0; c < lines[i].length; c++) { 1181 let character = lines[i].charAt(c); 1182 1183 if (fillStyle) { 1184 this.ctx.fillText(character, centerX + lineOffset, yPos); 1185 } 1186 1187 if (strokeStyle) { 1188 this.ctx.strokeText(character, centerX + lineOffset, yPos); 1189 } 1190 1191 yPos += yInc; 1192 } 1193 } else if (alignment == 'inner') { 1194 // Here we draw from the inner of the wheel up, but in order for the letters in the text text to 1195 // remain in the correct order when reading, we actually need to loop though the text characters backwards. 1196 for (let c = (lines[i].length -1); c >= 0; c--) { 1197 let character = lines[i].charAt(c); 1198 1199 if (fillStyle) { 1200 this.ctx.fillText(character, centerX + lineOffset, yPos); 1201 } 1202 1203 if (strokeStyle) { 1204 this.ctx.strokeText(character, centerX + lineOffset, yPos); 1205 } 1206 1207 yPos -= yInc; 1208 } 1209 } else if (alignment == 'center') { 1210 // This is the most complex of the three as we need to draw the text top down centred between the inner and outer of the wheel. 1211 // So logically we have to put the middle character of the text in the center then put the others each side of it. 1212 // In reality that is a really bad way to do it, we can achieve the same if not better positioning using a 1213 // variation on the method used for the rendering of outer aligned text once we have figured out the height of the text. 1214 1215 // If there is more than one character in the text then an adjustment to the position needs to be done. 1216 // What we are aiming for is to position the center of the text at the center point between the inner and outer radius. 1217 let centerAdjustment = 0; 1218 1219 if (lines[i].length > 1) { 1220 centerAdjustment = (yInc * (lines[i].length -1) / 2); 1221 } 1222 1223 // Now work out where to start rendering the string. This is half way between the inner and outer of the wheel, with the 1224 // centerAdjustment included to correctly position texts with more than one character over the center. 1225 // If there is a margin it is used to push the text away from the center of the wheel. 1226 let yPos = (centerY - innerRadius - ((outerRadius - innerRadius) / 2)) - centerAdjustment - margin; 1227 1228 // Now loop and draw just like outer text rendering. 1229 for (let c = 0; c < lines[i].length; c++) { 1230 let character = lines[i].charAt(c); 1231 1232 if (fillStyle) { 1233 this.ctx.fillText(character, centerX + lineOffset, yPos); 1234 } 1235 1236 if (strokeStyle) { 1237 this.ctx.strokeText(character, centerX + lineOffset, yPos); 1238 } 1239 1240 yPos += yInc; 1241 } 1242 } 1243 1244 this.ctx.restore(); 1245 1246 } else if (orientation == 'curved') { 1247 // There is no built in canvas function to draw text around an arc, so 1248 // we need to do this ourselves. 1249 let radius = 0; 1250 1251 // Set the alignment of the text - inner, outer, or center by calculating 1252 // how far out from the center point of the wheel the text is drawn. 1253 if (alignment == 'inner') { 1254 // When alignment is inner the radius is the innerRadius plus any margin. 1255 radius = innerRadius + margin; 1256 this.ctx.textBaseline = 'bottom'; 1257 1258 // We need to adjust the radius in this case to take in to multiline text. 1259 // In this case the radius needs to be further out, not at the inner radius. 1260 radius += (fontSize * (lines.length - 1)); 1261 } else if (alignment == 'outer') { 1262 // Outer it is the outerRadius minus any margin. 1263 radius = outerRadius - margin; 1264 this.ctx.textBaseline = 'top'; 1265 } else if (alignment == 'center') { 1266 // When center we want the text halfway between the inner and outer radius. 1267 radius = innerRadius + margin + ((outerRadius - innerRadius) / 2); 1268 this.ctx.textBaseline = 'middle'; 1269 } 1270 1271 // Set the angle to increment by when looping though and outputting the characters in the text 1272 // as we do this by rotating the wheel small amounts adding each character. 1273 let anglePerChar = 0; 1274 let drawAngle = 0; 1275 1276 // If more than one character in the text then... 1277 if (lines[i].length > 1) { 1278 // Text is drawn from the left. 1279 this.ctx.textAlign = 'left'; 1280 1281 // Work out how much angle the text rendering loop below needs to rotate by for each character to render them next to each other. 1282 // I have discovered that 4 * the font size / 10 at 100px radius is the correct spacing for between the characters 1283 // using a monospace font, non monospace may look a little odd as in there will appear to be extra spaces between chars. 1284 anglePerChar = (4 * (fontSize / 10)); 1285 1286 // Work out what percentage the radius the text will be drawn at is of 100px. 1287 let radiusPercent = (100 / radius); 1288 1289 // Then use this to scale up or down the anglePerChar value. 1290 // When the radius is less than 100px we need more angle between the letters, when radius is greater (so the text is further 1291 // away from the center of the wheel) the angle needs to be less otherwise the characters will appear further apart. 1292 anglePerChar = (anglePerChar * radiusPercent); 1293 1294 // Next we want the text to be drawn in the middle of the segment, without this it would start at the beginning of the segment. 1295 // To do this we need to work out how much arc the text will take up in total then subtract half of this from the center 1296 // of the segment so that it sits centred. 1297 let totalArc = (anglePerChar * lines[i].length); 1298 1299 // Now set initial draw angle to half way between the start and end of the segment. 1300 drawAngle = seg.startAngle + (((seg.endAngle - seg.startAngle) / 2) - (totalArc / 2)); 1301 } else { 1302 // The initial draw angle is the center of the segment when only one character. 1303 drawAngle = (seg.startAngle + ((seg.endAngle - seg.startAngle) / 2)); 1304 1305 // To ensure is dead-center the text alignment also needs to be centred. 1306 this.ctx.textAlign = 'center'; 1307 } 1308 1309 // ---------------------- 1310 // Adjust the initial draw angle as needed to take in to account the rotationAngle of the wheel. 1311 drawAngle += this.rotationAngle; 1312 1313 // ---------------------- 1314 // Now the drawing itself. 1315 // Loop for each character in the text. 1316 for (let c = 0; c < (lines[i].length); c++) { 1317 this.ctx.save(); 1318 1319 let character = lines[i].charAt(c); 1320 1321 // Rotate the wheel to the draw angle as we need to add the character at this location. 1322 this.ctx.translate(centerX, centerY); 1323 this.ctx.rotate(this.degToRad(drawAngle)); 1324 this.ctx.translate(-centerX, -centerY); 1325 1326 // Now draw the character directly above the center point of the wheel at the appropriate radius. 1327 if (strokeStyle) { 1328 this.ctx.strokeText(character, centerX, centerY - radius + lineOffset); 1329 } 1330 1331 if (fillStyle) { 1332 this.ctx.fillText(character, centerX, centerY - radius + lineOffset); 1333 } 1334 1335 // Increment the drawAngle by the angle per character so next loop we rotate 1336 // to the next angle required to draw the character at. 1337 drawAngle += anglePerChar; 1338 1339 this.ctx.restore(); 1340 } 1341 } 1342 } 1343 1344 // Increment this ready for the next time. 1345 lineOffset += fontSize; 1346 } 1347 } 1348 1349 // Restore so all text options are reset ready for the next text. 1350 this.ctx.restore(); 1351 } 1352 } 1353 } 1354 1355 // ==================================================================================================================== 1356 // Converts degrees to radians which is what is used when specifying the angles on HTML5 canvas arcs. 1357 // ==================================================================================================================== 1358 Winwheel.prototype.degToRad = function(d) 1359 { 1360 return d * 0.0174532925199432957; 1361 } 1362 1363 // ==================================================================================================================== 1364 // This function sets the center location of the wheel, saves a function call to set x then y. 1365 // ==================================================================================================================== 1366 Winwheel.prototype.setCenter = function(x, y) 1367 { 1368 this.centerX = x; 1369 this.centerY = y; 1370 } 1371 1372 // ==================================================================================================================== 1373 // This function allows a segment to be added to the wheel. The position of the segment is optional, 1374 // if not specified the new segment will be added to the end of the wheel. 1375 // ==================================================================================================================== 1376 Winwheel.prototype.addSegment = function(options, position) 1377 { 1378 // Create a new segment object passing the options in. 1379 let newSegment = new Segment(options); 1380 1381 // Increment the numSegments property of the class since new segment being added. 1382 this.numSegments ++; 1383 let segmentPos; 1384 1385 // Work out where to place the segment, the default is simply as a new segment at the end of the wheel. 1386 if (typeof position !== 'undefined') { 1387 // Because we need to insert the segment at this position, not overwrite it, we need to move all segments after this 1388 // location along one in the segments array, before finally adding this new segment at the specified location. 1389 for (let x = this.numSegments; x > position; x --) { 1390 this.segments[x] = this.segments[x -1]; 1391 } 1392 1393 this.segments[position] = newSegment; 1394 segmentPos = position; 1395 } else { 1396 this.segments[this.numSegments] = newSegment; 1397 segmentPos = this.numSegments; 1398 } 1399 1400 // Since a segment has been added the segment sizes need to be re-computed so call function to do this. 1401 this.updateSegmentSizes(); 1402 1403 // Return the segment object just created in the wheel (JavaScript will return it by reference), so that 1404 // further things can be done with it by the calling code if desired. 1405 return this.segments[segmentPos]; 1406 } 1407 1408 // ==================================================================================================================== 1409 // This function must be used if the canvasId is changed as we also need to get the context of the new canvas. 1410 // ==================================================================================================================== 1411 Winwheel.prototype.setCanvasId = function(canvasId) 1412 { 1413 if (canvasId) { 1414 this.canvasId = canvasId; 1415 this.canvas = document.getElementById(this.canvasId); 1416 1417 if (this.canvas) { 1418 this.ctx = this.canvas.getContext('2d'); 1419 } 1420 } else { 1421 this.canvasId = null 1422 this.ctx = null; 1423 this.canvas = null; 1424 } 1425 } 1426 1427 // ==================================================================================================================== 1428 // This function deletes the specified segment from the wheel by removing it from the segments array. 1429 // It then sorts out the other bits such as update of the numSegments. 1430 // ==================================================================================================================== 1431 Winwheel.prototype.deleteSegment = function(position) 1432 { 1433 // There needs to be at least one segment in order for the wheel to draw, so only allow delete if there 1434 // is more than one segment currently left in the wheel. 1435 1436 //++ check that specifying a position that does not exist - say 10 in a 6 segment wheel does not cause issues. 1437 if (this.numSegments > 1) { 1438 // If the position of the segment to remove has been specified. 1439 if (typeof position !== 'undefined') { 1440 // The array is to be shortened so we need to move all segments after the one 1441 // to be removed down one so there is no gap. 1442 for (let x = position; x < this.numSegments; x ++) { 1443 this.segments[x] = this.segments[x + 1]; 1444 } 1445 } 1446 1447 // Unset the last item in the segments array since there is now one less. 1448 this.segments[this.numSegments] = undefined; 1449 1450 // Decrement the number of segments, 1451 // then call function to update the segment sizes. 1452 this.numSegments --; 1453 this.updateSegmentSizes(); 1454 } 1455 } 1456 1457 // ==================================================================================================================== 1458 // This function takes the x an the y of a mouse event, such as click or move, and converts the x and the y in to 1459 // co-ordinates on the canvas as the raw values are the x and the y from the top and left of the user's browser. 1460 // ==================================================================================================================== 1461 Winwheel.prototype.windowToCanvas = function(x, y) 1462 { 1463 let bbox = this.canvas.getBoundingClientRect(); 1464 1465 return { 1466 x: Math.floor(x - bbox.left * (this.canvas.width / bbox.width)), 1467 y: Math.floor(y - bbox.top * (this.canvas.height / bbox.height)) 1468 }; 1469 } 1470 1471 // ==================================================================================================================== 1472 // This function returns the segment object located at the specified x and y coordinates on the canvas. 1473 // It is used to allow things to be done with a segment clicked by the user, such as highlight, display or change some values, etc. 1474 // ==================================================================================================================== 1475 Winwheel.prototype.getSegmentAt = function(x, y) 1476 { 1477 let foundSegment = null; 1478 1479 // Call function to return segment number. 1480 let segmentNumber = this.getSegmentNumberAt(x, y); 1481 1482 // If found one then set found segment to pointer to the segment object. 1483 if (segmentNumber !== null) { 1484 foundSegment = this.segments[segmentNumber]; 1485 } 1486 1487 return foundSegment; 1488 } 1489 1490 // ==================================================================================================================== 1491 // Returns the number of the segment clicked instead of the segment object. 1492 // This does not work correctly if the canvas width or height is altered by CSS but does work correctly with the scale factor. 1493 // ==================================================================================================================== 1494 Winwheel.prototype.getSegmentNumberAt = function(x, y) 1495 { 1496 // Call function above to convert the raw x and y from the user's browser to canvas coordinates 1497 // i.e. top and left is top and left of canvas, not top and left of the user's browser. 1498 let loc = this.windowToCanvas(x, y); 1499 1500 // ------------------------------------------ 1501 // Now start the process of working out the segment clicked. 1502 // First we need to figure out the angle of an imaginary line between the centerX and centerY of the wheel and 1503 // the X and Y of the location (for example a mouse click). 1504 let topBottom; 1505 let leftRight; 1506 let adjacentSideLength; 1507 let oppositeSideLength; 1508 let hypotenuseSideLength; 1509 1510 // Get the centerX and centerY scaled with the scale factor, also the same for outer and inner radius. 1511 let centerX = (this.centerX * this.scaleFactor); 1512 let centerY = (this.centerY * this.scaleFactor); 1513 let outerRadius = (this.outerRadius * this.scaleFactor); 1514 let innerRadius = (this.innerRadius * this.scaleFactor); 1515 1516 // We will use right triangle maths with the TAN function. 1517 // The start of the triangle is the wheel center, the adjacent side is along the x axis, and the opposite side is along the y axis. 1518 1519 // We only ever use positive numbers to work out the triangle and the center of the wheel needs to be considered as 0 for the numbers 1520 // in the maths which is why there is the subtractions below. We also remember what quadrant of the wheel the location is in as we 1521 // need this information later to add 90, 180, 270 degrees to the angle worked out from the triangle to get the position around a 360 degree wheel. 1522 if (loc.x > centerX) { 1523 adjacentSideLength = (loc.x - centerX); 1524 leftRight = 'R'; // Location is in the right half of the wheel. 1525 } else { 1526 adjacentSideLength = (centerX - loc.x); 1527 leftRight = 'L'; // Location is in the left half of the wheel. 1528 } 1529 1530 if (loc.y > centerY) { 1531 oppositeSideLength = (loc.y - centerY); 1532 topBottom = 'B'; // Bottom half of wheel. 1533 } else { 1534 oppositeSideLength = (centerY - loc.y); 1535 topBottom = 'T'; // Top Half of wheel. 1536 } 1537 1538 // Now divide opposite by adjacent to get tan value. 1539 let tanVal = oppositeSideLength / adjacentSideLength; 1540 1541 // Use the tan function and convert results to degrees since that is what we work with. 1542 let result = (Math.atan(tanVal) * 180/Math.PI); 1543 let locationAngle = 0; 1544 1545 // We also need the length of the hypotenuse as later on we need to compare this to the outerRadius of the segment / circle. 1546 hypotenuseSideLength = Math.sqrt((oppositeSideLength * oppositeSideLength) + (adjacentSideLength * adjacentSideLength)); 1547 1548 // ------------------------------------------ 1549 // Now to make sense around the wheel we need to alter the values based on if the location was in top or bottom half 1550 // and also right or left half of the wheel, by adding 90, 180, 270 etc. Also for some the initial locationAngle needs to be inverted. 1551 if ((topBottom == 'T') && (leftRight == 'R')) { 1552 locationAngle = Math.round(90 - result); 1553 } else if ((topBottom == 'B') && (leftRight == 'R')) { 1554 locationAngle = Math.round(result + 90); 1555 } else if ((topBottom == 'B') && (leftRight == 'L')) { 1556 locationAngle = Math.round((90 - result) + 180); 1557 } else if ((topBottom == 'T') && (leftRight == 'L')) { 1558 locationAngle = Math.round(result + 270); 1559 } 1560 1561 // ------------------------------------------ 1562 // And now we have to adjust to make sense when the wheel is rotated from the 0 degrees either 1563 // positive or negative and it can be many times past 360 degrees. 1564 if (this.rotationAngle != 0) { 1565 let rotatedPosition = this.getRotationPosition(); 1566 1567 // So we have this, now we need to alter the locationAngle as a result of this. 1568 locationAngle = (locationAngle - rotatedPosition); 1569 1570 // If negative then take the location away from 360. 1571 if (locationAngle < 0) { 1572 locationAngle = (360 - Math.abs(locationAngle)); 1573 } 1574 } 1575 1576 // ------------------------------------------ 1577 // OK, so after all of that we have the angle of a line between the centerX and centerY of the wheel and 1578 // the X and Y of the location on the canvas where the mouse was clicked. Now time to work out the segment 1579 // this corresponds to. We can use the segment start and end angles for this. 1580 let foundSegmentNumber = null; 1581 1582 for (let x = 1; x <= this.numSegments; x ++) { 1583 // Due to segments sharing start and end angles, if line is clicked will pick earlier segment. 1584 if ((locationAngle >= this.segments[x].startAngle) && (locationAngle <= this.segments[x].endAngle)) { 1585 // To ensure that a click anywhere on the canvas in the segment direction will not cause a 1586 // segment to be matched, as well as the angles, we need to ensure the click was within the radius 1587 // of the segment (or circle if no segment radius). 1588 1589 // If the hypotenuseSideLength (length of location from the center of the wheel) is with the radius 1590 // then we can assign the segment to the found segment and break out the loop. 1591 1592 // Have to take in to account hollow wheels (doughnuts) so check is greater than innerRadius as 1593 // well as less than or equal to the outerRadius of the wheel. 1594 if ((hypotenuseSideLength >= innerRadius) && (hypotenuseSideLength <= outerRadius)) { 1595 foundSegmentNumber = x; 1596 break; 1597 } 1598 } 1599 } 1600 1601 // Finally return the number. 1602 return foundSegmentNumber; 1603 } 1604 1605 // ==================================================================================================================== 1606 // Returns a reference to the segment that is at the location of the pointer on the wheel. 1607 // ==================================================================================================================== 1608 Winwheel.prototype.getIndicatedSegment = function() 1609 { 1610 // Call function below to work this out and return the prizeNumber. 1611 let prizeNumber = this.getIndicatedSegmentNumber(); 1612 1613 // Then simply return the segment in the segments array at that position. 1614 return this.segments[prizeNumber]; 1615 } 1616 1617 // ==================================================================================================================== 1618 // Works out the segment currently pointed to by the pointer of the wheel. Normally called when the spinning has stopped 1619 // to work out the prize the user has won. Returns the number of the segment in the segments array. 1620 // ==================================================================================================================== 1621 Winwheel.prototype.getIndicatedSegmentNumber = function() 1622 { 1623 let indicatedPrize = 0; 1624 let rawAngle = this.getRotationPosition(); 1625 1626 // Now we have the angle of the wheel, but we need to take in to account where the pointer is because 1627 // will not always be at the 12 o'clock 0 degrees location. 1628 let relativeAngle = Math.floor(this.pointerAngle - rawAngle); 1629 1630 if (relativeAngle < 0) { 1631 relativeAngle = 360 - Math.abs(relativeAngle); 1632 } 1633 1634 // Now we can work out the prize won by seeing what prize segment startAngle and endAngle the relativeAngle is between. 1635 for (let x = 1; x < (this.segments.length); x ++) { 1636 if ((relativeAngle >= this.segments[x]['startAngle']) && (relativeAngle <= this.segments[x]['endAngle'])) { 1637 indicatedPrize = x; 1638 break; 1639 } 1640 } 1641 1642 return indicatedPrize; 1643 } 1644 1645 // ==================================================================================================================== 1646 // Works out what Pin around the wheel is considered the current one which is the one which just passed the pointer. 1647 // Used to work out if the pin has changed during the animation to tigger a sound. 1648 // ==================================================================================================================== 1649 Winwheel.prototype.getCurrentPinNumber = function() 1650 { 1651 let currentPin = 0; 1652 1653 if (this.pins) { 1654 let rawAngle = this.getRotationPosition(); 1655 1656 // Now we have the angle of the wheel, but we need to take in to account where the pointer is because 1657 // will not always be at the 12 o'clock 0 degrees location. 1658 let relativeAngle = Math.floor(this.pointerAngle - rawAngle); 1659 1660 if (relativeAngle < 0) { 1661 relativeAngle = 360 - Math.abs(relativeAngle); 1662 } 1663 1664 // Work out the angle of the pins as this is simply 360 / the number of pins as they space evenly around. 1665 let pinSpacing = (360 / this.pins.number); 1666 let totalPinAngle = 0; 1667 1668 // Now we can work out the pin by seeing what pins relativeAngle is between. 1669 for (let x = 0; x < (this.pins.number); x ++) { 1670 if ((relativeAngle >= totalPinAngle) && (relativeAngle <= (totalPinAngle + pinSpacing))) { 1671 currentPin = x; 1672 break; 1673 } 1674 1675 totalPinAngle += pinSpacing; 1676 } 1677 1678 // Now if rotating clockwise we must add 1 to the current pin as we want the pin which has just passed 1679 // the pointer to be returned as the current pin, not the start of the one we are between. 1680 if (this.animation.direction == 'clockwise') { 1681 currentPin ++; 1682 1683 if (currentPin > this.pins.number) { 1684 currentPin = 0; 1685 } 1686 } 1687 } 1688 1689 return currentPin; 1690 } 1691 1692 // ================================================================================================================================================== 1693 // Returns the rotation angle of the wheel corrected to 0-360 (i.e. removes all the multiples of 360). 1694 // ================================================================================================================================================== 1695 Winwheel.prototype.getRotationPosition = function() 1696 { 1697 let rawAngle = this.rotationAngle; // Get current rotation angle of wheel. 1698 1699 // If positive work out how many times past 360 this is and then take the floor of this off the rawAngle. 1700 if (rawAngle >= 0) { 1701 if (rawAngle > 360) { 1702 // Get floor of the number of times past 360 degrees. 1703 let timesPast360 = Math.floor(rawAngle / 360); 1704 1705 // Take all this extra off to get just the angle 0-360 degrees. 1706 rawAngle = (rawAngle - (360 * timesPast360)); 1707 } 1708 } else { 1709 // Is negative, need to take off the extra then convert in to 0-360 degree value 1710 // so if, for example, was -90 then final value will be (360 - 90) = 270 degrees. 1711 if (rawAngle < -360) { 1712 let timesPast360 = Math.ceil(rawAngle / 360); // Ceil when negative. 1713 1714 rawAngle = (rawAngle - (360 * timesPast360)); // Is minus because dealing with negative. 1715 } 1716 1717 rawAngle = (360 + rawAngle); // Make in the range 0-360. Is plus because raw is still negative. 1718 } 1719 1720 return rawAngle; 1721 } 1722 1723 // ================================================================================================================================================== 1724 // This function starts the wheel's animation by using the properties of the animation object of of the wheel to begin the a greensock tween. 1725 // ================================================================================================================================================== 1726 Winwheel.prototype.startAnimation = function() 1727 { 1728 if (this.animation) { 1729 // Call function to compute the animation properties. 1730 this.computeAnimation(); 1731 1732 // Set this global variable to this object as an external function is required to call the draw() function on the wheel 1733 // each loop of the animation as Greensock cannot call the draw function directly on this class. 1734 winwheelToDrawDuringAnimation = this; 1735 1736 // Put together the properties of the greesock animation. 1737 let properties = new Array(null); 1738 properties[this.animation.propertyName] = this.animation.propertyValue; // Here we set the property to be animated and its value. 1739 properties['yoyo'] = this.animation.yoyo; // Set others. 1740 properties['repeat'] = this.animation.repeat; 1741 properties['ease'] = this.animation.easing; 1742 properties['onUpdate'] = winwheelAnimationLoop; // Call function to re-draw the canvas. 1743 properties['onComplete'] = winwheelStopAnimation; // Call function to perform actions when animation has finished. 1744 1745 // Do the tween animation passing the properties from the animation object as an array of key => value pairs. 1746 // Keep reference to the tween object in the wheel as that allows pausing, resuming, and stopping while the animation is still running. 1747 this.tween = TweenMax.to(this, this.animation.duration, properties); 1748 } 1749 } 1750 1751 // ================================================================================================================================================== 1752 // Use same function which needs to be outside the class for the callback when it stops because is finished. 1753 // ================================================================================================================================================== 1754 Winwheel.prototype.stopAnimation = function(canCallback) 1755 { 1756 // @TODO as part of multiwheel, need to work out how to stop the tween for a single wheel but allow others to continue. 1757 1758 // We can kill the animation using our tween object. 1759 if (winwheelToDrawDuringAnimation) { 1760 // If the wheel has a tween animation then kill it. 1761 if (winwheelToDrawDuringAnimation.tween) { 1762 winwheelToDrawDuringAnimation.tween.kill(); 1763 } 1764 1765 // Call the callback function. 1766 winwheelStopAnimation(canCallback); 1767 } 1768 1769 // Ensure the winwheelToDrawDuringAnimation is set to this class. 1770 winwheelToDrawDuringAnimation = this; 1771 } 1772 1773 // ================================================================================================================================================== 1774 // Pause animation by telling tween to pause. 1775 // ================================================================================================================================================== 1776 Winwheel.prototype.pauseAnimation = function() 1777 { 1778 if (this.tween) { 1779 this.tween.pause(); 1780 } 1781 } 1782 1783 // ================================================================================================================================================== 1784 // Resume the animation by telling tween to continue playing it. 1785 // ================================================================================================================================================== 1786 Winwheel.prototype.resumeAnimation = function() 1787 { 1788 if (this.tween) { 1789 this.tween.play(); 1790 } 1791 } 1792 1793 // ==================================================================================================================== 1794 // Called at the beginning of the startAnimation function and computes the values needed to do the animation 1795 // before it starts. This allows the developer to change the animation properties after the wheel has been created 1796 // and have the animation use the new values of the animation properties. 1797 // ==================================================================================================================== 1798 Winwheel.prototype.computeAnimation = function() 1799 { 1800 if (this.animation) { 1801 // Set the animation parameters for the specified animation type including some sensible defaults if values have not been specified. 1802 if (this.animation.type == 'spinOngoing') { 1803 // When spinning the rotationAngle is the wheel property which is animated. 1804 this.animation.propertyName = 'rotationAngle'; 1805 1806 if (this.animation.spins == null) { 1807 this.animation.spins = 5; 1808 } 1809 1810 if (this.animation.repeat == null) { 1811 this.animation.repeat = -1; // -1 means it will repeat forever. 1812 } 1813 1814 if (this.animation.easing == null) { 1815 this.animation.easing = 'Linear.easeNone'; 1816 } 1817 1818 if (this.animation.yoyo == null) { 1819 this.animation.yoyo = false; 1820 } 1821 1822 // We need to calculate the propertyValue and this is the spins * 360 degrees. 1823 this.animation.propertyValue = (this.animation.spins * 360); 1824 1825 // If the direction is anti-clockwise then make the property value negative. 1826 if (this.animation.direction == 'anti-clockwise') { 1827 this.animation.propertyValue = (0 - this.animation.propertyValue); 1828 } 1829 } else if (this.animation.type == 'spinToStop') { 1830 // Spin to stop the rotation angle is affected. 1831 this.animation.propertyName = 'rotationAngle'; 1832 1833 if (this.animation.spins == null) { 1834 this.animation.spins = 5; 1835 } 1836 1837 if (this.animation.repeat == null) { 1838 this.animation.repeat = 0; // As this is spin to stop we don't normally want it repeated. 1839 } 1840 1841 if (this.animation.easing == null) { 1842 this.animation.easing = 'Power3.easeOut'; // This easing is fast start and slows over time. 1843 } 1844 1845 if (this.animation.stopAngle == null) { 1846 // If the stop angle has not been specified then pick random between 0 and 359. 1847 this.animation._stopAngle = Math.floor((Math.random() * 359)); 1848 } else { 1849 // We need to set the internal to 360 minus what the user entered because the wheel spins past 0 without 1850 // this it would indicate the prize on the opposite side of the wheel. We aslo need to take in to account 1851 // the pointerAngle as the stop angle needs to be relative to that. 1852 this.animation._stopAngle = (360 - this.animation.stopAngle + this.pointerAngle); 1853 } 1854 1855 if (this.animation.yoyo == null) { 1856 this.animation.yoyo = false; 1857 } 1858 1859 // The property value is the spins * 360 then plus or minus the stopAngle depending on if the rotation is clockwise or anti-clockwise. 1860 this.animation.propertyValue = (this.animation.spins * 360); 1861 1862 if (this.animation.direction == 'anti-clockwise') { 1863 this.animation.propertyValue = (0 - this.animation.propertyValue); 1864 1865 // Also if the value is anti-clockwise we need subtract the stopAngle (but to get the wheel to stop in the correct 1866 // place this is 360 minus the stop angle as the wheel is rotating backwards). 1867 this.animation.propertyValue -= (360 - this.animation._stopAngle); 1868 } else { 1869 // Add the stopAngle to the propertyValue as the wheel must rotate around to this place and stop there. 1870 this.animation.propertyValue += this.animation._stopAngle; 1871 } 1872 } else if (this.animation.type == 'spinAndBack') { 1873 // This is basically is a spin for a number of times then the animation reverses and goes back to start. 1874 // If a repeat is specified then this can be used to make the wheel "rock" left and right. 1875 1876 // Again this is a spin so the rotationAngle the property which is animated. 1877 this.animation.propertyName = 'rotationAngle'; 1878 1879 if (this.animation.spins == null) { 1880 this.animation.spins = 5; 1881 } 1882 1883 if (this.animation.repeat == null) { 1884 this.animation.repeat = 1; // This needs to be set to at least 1 in order for the animation to reverse. 1885 } 1886 1887 if (this.animation.easing == null) { 1888 this.animation.easing = 'Power2.easeInOut'; // This is slow at the start and end and fast in the middle. 1889 } 1890 1891 if (this.animation.yoyo == null) { 1892 this.animation.yoyo = true; // This needs to be set to true to have the animation reverse back like a yo-yo. 1893 } 1894 1895 if (this.animation.stopAngle == null) { 1896 this.animation._stopAngle = 0; 1897 } else { 1898 // We need to set the internal to 360 minus what the user entered 1899 // because the wheel spins past 0 without this it would indicate the 1900 // prize on the opposite side of the wheel. 1901 this.animation._stopAngle = (360 - this.animation.stopAngle); 1902 } 1903 1904 // The property value is the spins * 360 then plus or minus the stopAngle depending on if the rotation is clockwise or anti-clockwise. 1905 this.animation.propertyValue = (this.animation.spins * 360); 1906 1907 if (this.animation.direction == 'anti-clockwise') { 1908 this.animation.propertyValue = (0 - this.animation.propertyValue); 1909 1910 // Also if the value is anti-clockwise we need subtract the stopAngle (but to get the wheel to stop in the correct 1911 // place this is 360 minus the stop angle as the wheel is rotating backwards). 1912 this.animation.propertyValue -= (360 - this.animation._stopAngle); 1913 } else { 1914 // Add the stopAngle to the propertyValue as the wheel must rotate around to this place and stop there. 1915 this.animation.propertyValue += this.animation._stopAngle; 1916 } 1917 } else if (this.animation.type == 'custom') { 1918 // Do nothing as all values must be set by the developer in the parameters 1919 // especially the propertyName and propertyValue. 1920 } 1921 } 1922 } 1923 1924 // ==================================================================================================================== 1925 // Calculates and returns a random stop angle inside the specified segment number. Value will always be 1 degree inside 1926 // the start and end of the segment to avoid issue with the segment overlap. 1927 // ==================================================================================================================== 1928 Winwheel.prototype.getRandomForSegment = function(segmentNumber) 1929 { 1930 let stopAngle = 0; 1931 1932 if (segmentNumber) { 1933 if (typeof this.segments[segmentNumber] !== 'undefined') { 1934 let startAngle = this.segments[segmentNumber].startAngle; 1935 let endAngle = this.segments[segmentNumber].endAngle; 1936 let range = (endAngle - startAngle) - 2; 1937 1938 if (range > 0) { 1939 stopAngle = (startAngle + 1 + Math.floor((Math.random() * range))); 1940 } else { 1941 console.log('Segment size is too small to safely get random angle inside it'); 1942 } 1943 } else { 1944 console.log('Segment ' + segmentNumber + ' undefined'); 1945 } 1946 } else { 1947 console.log('Segment number not specified'); 1948 } 1949 1950 return stopAngle; 1951 } 1952 1953 // ==================================================================================================================== 1954 // Class for the wheel pins. 1955 // ==================================================================================================================== 1956 function Pin(options) 1957 { 1958 let defaultOptions = { 1959 'visible' : true, // In future there might be some functionality related to the pins even if they are not displayed. 1960 'number' : 36, // The number of pins. These are evenly distributed around the wheel. 1961 'outerRadius' : 3, // Radius of the pins which determines their size. 1962 'fillStyle' : 'grey', // Fill colour of the pins. 1963 'strokeStyle' : 'black', // Line colour of the pins. 1964 'lineWidth' : 1, // Line width of the pins. 1965 'margin' : 3, // The space between outside edge of the wheel and the pins. 1966 'responsive' : false, // If set to true the diameter of the pin will resize when the wheel is responsive. 1967 }; 1968 1969 // Now loop through the default options and create properties of this class set to the value for 1970 // the option passed in if a value was, or if not then set the value of the default. 1971 for (let key in defaultOptions) { 1972 if ((options != null) && (typeof(options[key]) !== 'undefined')) { 1973 this[key] = options[key]; 1974 } else { 1975 this[key] = defaultOptions[key]; 1976 } 1977 } 1978 1979 // Also loop though the passed in options and add anything specified not part of the class in to it as a property. 1980 if (options != null) { 1981 for (let key in options) { 1982 if (typeof(this[key]) === 'undefined') { 1983 this[key] = options[key]; 1984 } 1985 } 1986 } 1987 } 1988 1989 // ==================================================================================================================== 1990 // Class for the wheel spinning animation which like a segment becomes a property of the wheel. 1991 // ==================================================================================================================== 1992 function Animation(options) 1993 { 1994 // Most of these options are null because the defaults are different depending on the type of animation. 1995 let defaultOptions = { 1996 'type' : 'spinOngoing', // For now there are only supported types are spinOngoing (continuous), spinToStop, spinAndBack, custom. 1997 'direction' : 'clockwise', // clockwise or anti-clockwise. 1998 'propertyName' : null, // The name of the winning wheel property to be affected by the animation. 1999 'propertyValue' : null, // The value the property is to be set to at the end of the animation. 2000 'duration' : 10, // Duration of the animation. 2001 'yoyo' : false, // If the animation is to reverse back again i.e. yo-yo. 2002 'repeat' : null, // The number of times the animation is to repeat, -1 will cause it to repeat forever. 2003 'easing' : null, // The easing to use for the animation, default is the best for spin to stop. Use Linear.easeNone for no easing. 2004 'stopAngle' : null, // Used for spinning, the angle at which the wheel is to stop. 2005 'spins' : null, // Used for spinning, the number of complete 360 degree rotations the wheel is to do. 2006 'clearTheCanvas' : null, // If set to true the canvas will be cleared before the wheel is re-drawn, false it will not, null the animation will abide by the value of this property for the parent wheel object. 2007 'callbackFinished' : null, // Function to callback when the animation has finished. 2008 'callbackBefore' : null, // Function to callback before the wheel is drawn each animation loop. 2009 'callbackAfter' : null, // Function to callback after the wheel is drawn each animation loop. 2010 'callbackSound' : null, // Function to callback if a sound should be triggered on change of segment or pin. 2011 'soundTrigger' : 'segment' // Sound trigger type. Default is segment which triggers when segment changes, can be pin if to trigger when pin passes the pointer. 2012 }; 2013 2014 // Now loop through the default options and create properties of this class set to the value for 2015 // the option passed in if a value was, or if not then set the value of the default. 2016 for (let key in defaultOptions) { 2017 if ((options != null) && (typeof(options[key]) !== 'undefined')) { 2018 this[key] = options[key]; 2019 } else { 2020 this[key] = defaultOptions[key]; 2021 } 2022 } 2023 2024 // Also loop though the passed in options and add anything specified not part of the class in to it as a property. 2025 if (options != null) { 2026 for (let key in options) { 2027 if (typeof(this[key]) === 'undefined') { 2028 this[key] = options[key]; 2029 } 2030 } 2031 } 2032 } 2033 2034 // ==================================================================================================================== 2035 // Class for segments. When creating a json of options can be passed in. 2036 // ==================================================================================================================== 2037 function Segment(options) 2038 { 2039 // Define default options for segments, most are null so that the global defaults for the wheel 2040 // are used if the values for a particular segment are not specifically set. 2041 let defaultOptions = { 2042 'size' : null, // Leave null for automatic. Valid values are degrees 0-360. Use percentToDegrees function if needed to convert. 2043 'text' : '', // Default is blank. 2044 'fillStyle' : null, // If null for the rest the global default will be used. 2045 'strokeStyle' : null, 2046 'lineWidth' : null, 2047 'textFontFamily' : null, 2048 'textFontSize' : null, 2049 'textFontWeight' : null, 2050 'textOrientation' : null, 2051 'textAlignment' : null, 2052 'textDirection' : null, 2053 'textMargin' : null, 2054 'textFillStyle' : null, 2055 'textStrokeStyle' : null, 2056 'textLineWidth' : null, 2057 'image' : null, // Name/path to the image 2058 'imageDirection' : null, // Direction of the image, can be set globally for the whole wheel. 2059 'imgData' : null // Image object created here and loaded with image data. 2060 }; 2061 2062 // Now loop through the default options and create properties of this class set to the value for 2063 // the option passed in if a value was, or if not then set the value of the default. 2064 for (let key in defaultOptions) { 2065 if ((options != null) && (typeof(options[key]) !== 'undefined')) { 2066 this[key] = options[key]; 2067 } else { 2068 this[key] = defaultOptions[key]; 2069 } 2070 } 2071 2072 // Also loop though the passed in options and add anything specified not part of the class in to it as a property. 2073 // This allows the developer to easily add properties to segments at construction time. 2074 if (options != null) { 2075 for (let key in options) { 2076 if (typeof(this[key]) === 'undefined') { 2077 this[key] = options[key]; 2078 } 2079 } 2080 } 2081 2082 // There are 2 additional properties which are set by the code, so need to define them here. 2083 // They are not in the default options because they are not something that should be set by the user, 2084 // the values are updated every time the updateSegmentSizes() function is called. 2085 this.startAngle = 0; 2086 this.endAngle = 0; 2087 } 2088 2089 // ==================================================================================================================== 2090 // Changes an image for a segment by setting a callback to render the wheel once the image has loaded. 2091 // ==================================================================================================================== 2092 Segment.prototype.changeImage = function(image, imageDirection) 2093 { 2094 // Change image name, blank image data. 2095 this.image = image; 2096 this.imgData = null; 2097 2098 // Set direction. 2099 if (imageDirection) { 2100 this.imageDirection = imageDirection; 2101 } 2102 2103 // Set imgData to a new image object, change set callback and change src (just like in wheel constructor). 2104 winhweelAlreadyDrawn = false; 2105 this.imgData = new Image(); 2106 this.imgData.onload = winwheelLoadedImage; 2107 this.imgData.src = this.image; 2108 } 2109 2110 // ==================================================================================================================== 2111 // Class that is created as property of the wheel. Draws line from center of the wheel out to edge of canvas to 2112 // indicate where the code thinks the pointer location is. Helpful to get alignment correct esp when using images. 2113 // ==================================================================================================================== 2114 function PointerGuide(options) 2115 { 2116 let defaultOptions = { 2117 'display' : false, 2118 'strokeStyle' : 'red', 2119 'lineWidth' : 3 2120 }; 2121 2122 // Now loop through the default options and create properties of this class set to the value for 2123 // the option passed in if a value was, or if not then set the value of the default. 2124 for (let key in defaultOptions) { 2125 if ((options != null) && (typeof(options[key]) !== 'undefined')) { 2126 this[key] = options[key]; 2127 } else { 2128 this[key] = defaultOptions[key]; 2129 } 2130 } 2131 } 2132 2133 // ==================================================================================================================== 2134 // This function takes the percent 0-100 and returns the number of degrees 0-360 this equates to. 2135 // ==================================================================================================================== 2136 function winwheelPercentToDegrees(percentValue) 2137 { 2138 let degrees = 0; 2139 2140 if ((percentValue > 0) && (percentValue <= 100)) { 2141 let divider = (percentValue / 100); 2142 degrees = (360 * divider); 2143 } 2144 2145 return degrees; 2146 } 2147 2148 // ==================================================================================================================== 2149 // In order for the wheel to be re-drawn during the spin animation the function greesock calls needs to be outside 2150 // of the class as for some reason it errors if try to call winwheel.draw() directly. 2151 // ==================================================================================================================== 2152 function winwheelAnimationLoop() 2153 { 2154 if (winwheelToDrawDuringAnimation) { 2155 // Check if the clearTheCanvas is specified for this animation, if not or it is not false then clear the canvas. 2156 if (winwheelToDrawDuringAnimation.animation.clearTheCanvas != false) { 2157 winwheelToDrawDuringAnimation.ctx.clearRect(0, 0, winwheelToDrawDuringAnimation.canvas.width, winwheelToDrawDuringAnimation.canvas.height); 2158 } 2159 2160 let callbackBefore = winwheelToDrawDuringAnimation.animation.callbackBefore; 2161 let callbackAfter = winwheelToDrawDuringAnimation.animation.callbackAfter; 2162 2163 // If there is a callback function which is supposed to be called before the wheel is drawn then do that. 2164 if (callbackBefore != null) { 2165 // If the property is a function then call it, otherwise eval the proptery as javascript code. 2166 if (typeof callbackBefore === 'function') { 2167 callbackBefore(); 2168 } else { 2169 eval(callbackBefore); 2170 } 2171 } 2172 2173 // Call code to draw the wheel, pass in false as we never want it to clear the canvas as that would wipe anything drawn in the callbackBefore. 2174 winwheelToDrawDuringAnimation.draw(false); 2175 2176 // If there is a callback function which is supposed to be called after the wheel has been drawn then do that. 2177 if (callbackAfter != null) { 2178 // If the property is a function then call it, otherwise eval the proptery as javascript code. 2179 if (typeof callbackAfter === 'function') { 2180 callbackAfter(); 2181 } else { 2182 eval(callbackAfter); 2183 } 2184 } 2185 2186 // If there is a sound callback then call a function which figures out if the sound should be triggered 2187 // and if so then call the function specified by the developer. 2188 if (winwheelToDrawDuringAnimation.animation.callbackSound) { 2189 winwheelTriggerSound(); 2190 } 2191 } 2192 } 2193 2194 // ==================================================================================================================== 2195 // This function figures out if the callbackSound function needs to be called by working out if the segment or pin 2196 // has changed since the last animation loop. 2197 // ==================================================================================================================== 2198 function winwheelTriggerSound() 2199 { 2200 // If this property does not exist then add it as a property of the winwheel. 2201 if (winwheelToDrawDuringAnimation.hasOwnProperty('_lastSoundTriggerNumber') == false) { 2202 winwheelToDrawDuringAnimation._lastSoundTriggerNumber = 0; 2203 } 2204 2205 let callbackSound = winwheelToDrawDuringAnimation.animation.callbackSound; 2206 let currentTriggerNumber = 0; 2207 2208 // Now figure out if the sound callback should be called depending on the sound trigger type. 2209 if (winwheelToDrawDuringAnimation.animation.soundTrigger == 'pin') { 2210 // So for the pin type we need to work out which pin we are between. 2211 currentTriggerNumber = winwheelToDrawDuringAnimation.getCurrentPinNumber(); 2212 } else { 2213 // Check on the change of segment by working out which segment we are in. 2214 // We can utilise the existing getIndiatedSegmentNumber function. 2215 currentTriggerNumber = winwheelToDrawDuringAnimation.getIndicatedSegmentNumber(); 2216 } 2217 2218 // If the current number is not the same as last time then call the sound callback. 2219 if (currentTriggerNumber != winwheelToDrawDuringAnimation._lastSoundTriggerNumber) { 2220 // If the property is a function then call it, otherwise eval the proptery as javascript code. 2221 if (typeof callbackSound === 'function') { 2222 callbackSound(); 2223 } else { 2224 eval(callbackSound); 2225 } 2226 2227 // Also update the last sound trigger with the current number. 2228 winwheelToDrawDuringAnimation._lastSoundTriggerNumber = currentTriggerNumber; 2229 } 2230 } 2231 2232 // ==================================================================================================================== 2233 // This function is called-back when the greensock animation has finished. 2234 // ==================================================================================================================== 2235 let winwheelToDrawDuringAnimation = null; // This global is set by the winwheel class to the wheel object to be re-drawn. 2236 2237 function winwheelStopAnimation(canCallback) 2238 { 2239 // When the animation is stopped if canCallback is not false then try to call the callback. 2240 // false can be passed in to stop the after happening if the animation has been stopped before it ended normally. 2241 if (canCallback != false) { 2242 let callback = winwheelToDrawDuringAnimation.animation.callbackFinished; 2243 2244 if (callback != null) { 2245 // If the callback is a function then call it, otherwise evaluate the property as javascript code. 2246 if (typeof callback === 'function') { 2247 // Pass back the indicated segment as 99% of the time you will want to know this to inform the user of their prize. 2248 callback(winwheelToDrawDuringAnimation.getIndicatedSegment()); 2249 } else { 2250 eval(callback); 2251 } 2252 } 2253 } 2254 } 2255 2256 // ==================================================================================================================== 2257 // Called after the image has loaded for each segment. Once all the images are loaded it then calls the draw function 2258 // on the wheel to render it. Used in constructor and also when a segment image is changed. 2259 // ==================================================================================================================== 2260 let winhweelAlreadyDrawn = false; 2261 2262 function winwheelLoadedImage() 2263 { 2264 // Prevent multiple drawings of the wheel which ocurrs without this check due to timing of function calls. 2265 if (winhweelAlreadyDrawn == false) { 2266 // Set to 0. 2267 let winwheelImageLoadCount = 0; 2268 2269 // Loop though all the segments of the wheel and check if image data loaded, if so increment counter. 2270 for (let i = 1; i <= winwheelToDrawDuringAnimation.numSegments; i ++) { 2271 // Check the image data object is not null and also that the image has completed loading by checking 2272 // that a property of it such as the height has some sort of true value. 2273 if ((winwheelToDrawDuringAnimation.segments[i].imgData != null) && (winwheelToDrawDuringAnimation.segments[i].imgData.height)) { 2274 winwheelImageLoadCount ++; 2275 } 2276 } 2277 2278 // If number of images loaded matches the segments then all the images for the wheel are loaded. 2279 if (winwheelImageLoadCount == winwheelToDrawDuringAnimation.numSegments) { 2280 // Call draw function to render the wheel. 2281 winhweelAlreadyDrawn = true; 2282 winwheelToDrawDuringAnimation.draw(); 2283 } 2284 } 2285 } 2286 2287 // ==================================================================================================================== 2288 // Called when the wheel is to resize. This is normally called from a onresize of the window, also called from onload 2289 // so the initial size is correct. Here we must re-size the canvas and work out the scaleFactor for the wheel. 2290 // ==================================================================================================================== 2291 function winwheelResize() 2292 { 2293 // By default set the margin to 40px, this can be overridden if needed. 2294 // This is to stop the canvas going right to the right edge of the screen and being overlayed by a scrollbar though 2295 // if the canvas is center aligned, half the magin will be applied to each side since the margin actually reduces the width of the canvas. 2296 let margin = 40; 2297 2298 // If a value has been specified for this then update the margin to it. 2299 if (typeof(winwheelToDrawDuringAnimation._responsiveMargin) !== 'undefined') { 2300 margin = winwheelToDrawDuringAnimation._responsiveMargin; 2301 } 2302 2303 // Get the current width and also optional min and max width properties. 2304 let width = window.innerWidth - margin; 2305 let minWidth = winwheelToDrawDuringAnimation._responsiveMinWidth; 2306 let minHeight = winwheelToDrawDuringAnimation._responsiveMinHeight; 2307 2308 // Adjust the width as it cannot be larger than the original size of the wheel and we don't want 2309 // the canvas and wheel inside it to be too small so check the min width. 2310 if (width < minWidth) { 2311 width = minWidth; 2312 } else if (width > winwheelToDrawDuringAnimation._originalCanvasWidth) { 2313 width = winwheelToDrawDuringAnimation._originalCanvasWidth; 2314 } 2315 2316 // Work out the percent the new width is smaller than the original width. 2317 let percent = (width / winwheelToDrawDuringAnimation._originalCanvasWidth); 2318 2319 // Set the canvas width to the width to a percentage of the original width. 2320 winwheelToDrawDuringAnimation.canvas.width = (winwheelToDrawDuringAnimation._originalCanvasWidth * percent); 2321 2322 // Scale the height if we are supposed to but ensure it does not go below the minHeight. 2323 if (winwheelToDrawDuringAnimation._responsiveScaleHeight) { 2324 let height = (winwheelToDrawDuringAnimation._originalCanvasHeight * percent); 2325 2326 if (height < minHeight) { 2327 height = minHeight; 2328 } else if (height > winwheelToDrawDuringAnimation._originalCanvasHeight) { 2329 height = winwheelToDrawDuringAnimation._originalCanvasHeight; 2330 } 2331 2332 winwheelToDrawDuringAnimation.canvas.height = height; 2333 } 2334 2335 // OK so now we have the percent, set the scaleFactor of the wheel to this. 2336 winwheelToDrawDuringAnimation.scaleFactor = percent; 2337 2338 // Now re-draw the wheel to ensure the changes in size are rendered. 2339 winwheelToDrawDuringAnimation.draw(); 2340 } 2341 2342 /*! 2343 * VERSION: 1.18.0 2344 * DATE: 2015-09-05 2345 * UPDATES AND DOCS AT: http://greensock.com 2346 * 2347 * Includes all of the following: TweenLite, TweenMax, TimelineLite, TimelineMax, EasePack, CSSPlugin, RoundPropsPlugin, BezierPlugin, AttrPlugin, DirectionalRotationPlugin 2348 * 2349 * @license Copyright (c) 2008-2015, GreenSock. All rights reserved. 2350 * This work is subject to the terms at http://greensock.com/standard-license or for 2351 * Club GreenSock members, the software agreement that was issued with your membership. 2352 * 2353 * @author: Jack Doyle, jack@greensock.com 2354 **/ 2355 var _gsScope="undefined"!=typeof module&&module.exports&&"undefined"!=typeof global?global:this||window;(_gsScope._gsQueue||(_gsScope._gsQueue=[])).push(function(){"use strict";_gsScope._gsDefine("TweenMax",["core.Animation","core.SimpleTimeline","TweenLite"],function(t,e,i){var s=function(t){var e,i=[],s=t.length;for(e=0;e!==s;i.push(t[e++]));return i},r=function(t,e,i){var s,r,n=t.cycle;for(s in n)r=n[s],t[s]="function"==typeof r?r.call(e[i],i):r[i%r.length];delete t.cycle},n=function(t,e,s){i.call(this,t,e,s),this._cycle=0,this._yoyo=this.vars.yoyo===!0,this._repeat=this.vars.repeat||0,this._repeatDelay=this.vars.repeatDelay||0,this._dirty=!0,this.render=n.prototype.render},a=1e-10,o=i._internals,l=o.isSelector,h=o.isArray,_=n.prototype=i.to({},.1,{}),u=[];n.version="1.18.0",_.constructor=n,_.kill()._gc=!1,n.killTweensOf=n.killDelayedCallsTo=i.killTweensOf,n.getTweensOf=i.getTweensOf,n.lagSmoothing=i.lagSmoothing,n.ticker=i.ticker,n.render=i.render,_.invalidate=function(){return this._yoyo=this.vars.yoyo===!0,this._repeat=this.vars.repeat||0,this._repeatDelay=this.vars.repeatDelay||0,this._uncache(!0),i.prototype.invalidate.call(this)},_.updateTo=function(t,e){var s,r=this.ratio,n=this.vars.immediateRender||t.immediateRender;e&&this._startTime<this._timeline._time&&(this._startTime=this._timeline._time,this._uncache(!1),this._gc?this._enabled(!0,!1):this._timeline.insert(this,this._startTime-this._delay));for(s in t)this.vars[s]=t[s];if(this._initted||n)if(e)this._initted=!1,n&&this.render(0,!0,!0);else if(this._gc&&this._enabled(!0,!1),this._notifyPluginsOfEnabled&&this._firstPT&&i._onPluginEvent("_onDisable",this),this._time/this._duration>.998){var a=this._time;this.render(0,!0,!1),this._initted=!1,this.render(a,!0,!1)}else if(this._time>0||n){this._initted=!1,this._init();for(var o,l=1/(1-r),h=this._firstPT;h;)o=h.s+h.c,h.c*=l,h.s=o-h.c,h=h._next}return this},_.render=function(t,e,i){this._initted||0===this._duration&&this.vars.repeat&&this.invalidate();var s,r,n,l,h,_,u,c,f=this._dirty?this.totalDuration():this._totalDuration,p=this._time,m=this._totalTime,d=this._cycle,g=this._duration,v=this._rawPrevTime;if(t>=f?(this._totalTime=f,this._cycle=this._repeat,this._yoyo&&0!==(1&this._cycle)?(this._time=0,this.ratio=this._ease._calcEnd?this._ease.getRatio(0):0):(this._time=g,this.ratio=this._ease._calcEnd?this._ease.getRatio(1):1),this._reversed||(s=!0,r="onComplete",i=i||this._timeline.autoRemoveChildren),0===g&&(this._initted||!this.vars.lazy||i)&&(this._startTime===this._timeline._duration&&(t=0),(0===t||0>v||v===a)&&v!==t&&(i=!0,v>a&&(r="onReverseComplete")),this._rawPrevTime=c=!e||t||v===t?t:a)):1e-7>t?(this._totalTime=this._time=this._cycle=0,this.ratio=this._ease._calcEnd?this._ease.getRatio(0):0,(0!==m||0===g&&v>0)&&(r="onReverseComplete",s=this._reversed),0>t&&(this._active=!1,0===g&&(this._initted||!this.vars.lazy||i)&&(v>=0&&(i=!0),this._rawPrevTime=c=!e||t||v===t?t:a)),this._initted||(i=!0)):(this._totalTime=this._time=t,0!==this._repeat&&(l=g+this._repeatDelay,this._cycle=this._totalTime/l>>0,0!==this._cycle&&this._cycle===this._totalTime/l&&this._cycle--,this._time=this._totalTime-this._cycle*l,this._yoyo&&0!==(1&this._cycle)&&(this._time=g-this._time),this._time>g?this._time=g:0>this._time&&(this._time=0)),this._easeType?(h=this._time/g,_=this._easeType,u=this._easePower,(1===_||3===_&&h>=.5)&&(h=1-h),3===_&&(h*=2),1===u?h*=h:2===u?h*=h*h:3===u?h*=h*h*h:4===u&&(h*=h*h*h*h),this.ratio=1===_?1-h:2===_?h:.5>this._time/g?h/2:1-h/2):this.ratio=this._ease.getRatio(this._time/g)),p===this._time&&!i&&d===this._cycle)return m!==this._totalTime&&this._onUpdate&&(e||this._callback("onUpdate")),void 0;if(!this._initted){if(this._init(),!this._initted||this._gc)return;if(!i&&this._firstPT&&(this.vars.lazy!==!1&&this._duration||this.vars.lazy&&!this._duration))return this._time=p,this._totalTime=m,this._rawPrevTime=v,this._cycle=d,o.lazyTweens.push(this),this._lazy=[t,e],void 0;this._time&&!s?this.ratio=this._ease.getRatio(this._time/g):s&&this._ease._calcEnd&&(this.ratio=this._ease.getRatio(0===this._time?0:1))}for(this._lazy!==!1&&(this._lazy=!1),this._active||!this._paused&&this._time!==p&&t>=0&&(this._active=!0),0===m&&(2===this._initted&&t>0&&this._init(),this._startAt&&(t>=0?this._startAt.render(t,e,i):r||(r="_dummyGS")),this.vars.onStart&&(0!==this._totalTime||0===g)&&(e||this._callback("onStart"))),n=this._firstPT;n;)n.f?n.t[n.p](n.c*this.ratio+n.s):n.t[n.p]=n.c*this.ratio+n.s,n=n._next;this._onUpdate&&(0>t&&this._startAt&&this._startTime&&this._startAt.render(t,e,i),e||(this._totalTime!==m||s)&&this._callback("onUpdate")),this._cycle!==d&&(e||this._gc||this.vars.onRepeat&&this._callback("onRepeat")),r&&(!this._gc||i)&&(0>t&&this._startAt&&!this._onUpdate&&this._startTime&&this._startAt.render(t,e,i),s&&(this._timeline.autoRemoveChildren&&this._enabled(!1,!1),this._active=!1),!e&&this.vars[r]&&this._callback(r),0===g&&this._rawPrevTime===a&&c!==a&&(this._rawPrevTime=0))},n.to=function(t,e,i){return new n(t,e,i)},n.from=function(t,e,i){return i.runBackwards=!0,i.immediateRender=0!=i.immediateRender,new n(t,e,i)},n.fromTo=function(t,e,i,s){return s.startAt=i,s.immediateRender=0!=s.immediateRender&&0!=i.immediateRender,new n(t,e,s)},n.staggerTo=n.allTo=function(t,e,a,o,_,c,f){o=o||0;var p,m,d,g,v=a.delay||0,y=[],T=function(){a.onComplete&&a.onComplete.apply(a.onCompleteScope||this,arguments),_.apply(f||a.callbackScope||this,c||u)},x=a.cycle,w=a.startAt&&a.startAt.cycle;for(h(t)||("string"==typeof t&&(t=i.selector(t)||t),l(t)&&(t=s(t))),t=t||[],0>o&&(t=s(t),t.reverse(),o*=-1),p=t.length-1,d=0;p>=d;d++){m={};for(g in a)m[g]=a[g];if(x&&r(m,t,d),w){w=m.startAt={};for(g in a.startAt)w[g]=a.startAt[g];r(m.startAt,t,d)}m.delay=v,d===p&&_&&(m.onComplete=T),y[d]=new n(t[d],e,m),v+=o}return y},n.staggerFrom=n.allFrom=function(t,e,i,s,r,a,o){return i.runBackwards=!0,i.immediateRender=0!=i.immediateRender,n.staggerTo(t,e,i,s,r,a,o)},n.staggerFromTo=n.allFromTo=function(t,e,i,s,r,a,o,l){return s.startAt=i,s.immediateRender=0!=s.immediateRender&&0!=i.immediateRender,n.staggerTo(t,e,s,r,a,o,l)},n.delayedCall=function(t,e,i,s,r){return new n(e,0,{delay:t,onComplete:e,onCompleteParams:i,callbackScope:s,onReverseComplete:e,onReverseCompleteParams:i,immediateRender:!1,useFrames:r,overwrite:0})},n.set=function(t,e){return new n(t,0,e)},n.isTweening=function(t){return i.getTweensOf(t,!0).length>0};var c=function(t,e){for(var s=[],r=0,n=t._first;n;)n instanceof i?s[r++]=n:(e&&(s[r++]=n),s=s.concat(c(n,e)),r=s.length),n=n._next;return s},f=n.getAllTweens=function(e){return c(t._rootTimeline,e).concat(c(t._rootFramesTimeline,e))};n.killAll=function(t,i,s,r){null==i&&(i=!0),null==s&&(s=!0);var n,a,o,l=f(0!=r),h=l.length,_=i&&s&&r;for(o=0;h>o;o++)a=l[o],(_||a instanceof e||(n=a.target===a.vars.onComplete)&&s||i&&!n)&&(t?a.totalTime(a._reversed?0:a.totalDuration()):a._enabled(!1,!1))},n.killChildTweensOf=function(t,e){if(null!=t){var r,a,_,u,c,f=o.tweenLookup;if("string"==typeof t&&(t=i.selector(t)||t),l(t)&&(t=s(t)),h(t))for(u=t.length;--u>-1;)n.killChildTweensOf(t[u],e);else{r=[];for(_ in f)for(a=f[_].target.parentNode;a;)a===t&&(r=r.concat(f[_].tweens)),a=a.parentNode;for(c=r.length,u=0;c>u;u++)e&&r[u].totalTime(r[u].totalDuration()),r[u]._enabled(!1,!1)}}};var p=function(t,i,s,r){i=i!==!1,s=s!==!1,r=r!==!1;for(var n,a,o=f(r),l=i&&s&&r,h=o.length;--h>-1;)a=o[h],(l||a instanceof e||(n=a.target===a.vars.onComplete)&&s||i&&!n)&&a.paused(t)};return n.pauseAll=function(t,e,i){p(!0,t,e,i)},n.resumeAll=function(t,e,i){p(!1,t,e,i)},n.globalTimeScale=function(e){var s=t._rootTimeline,r=i.ticker.time;return arguments.length?(e=e||a,s._startTime=r-(r-s._startTime)*s._timeScale/e,s=t._rootFramesTimeline,r=i.ticker.frame,s._startTime=r-(r-s._startTime)*s._timeScale/e,s._timeScale=t._rootTimeline._timeScale=e,e):s._timeScale},_.progress=function(t){return arguments.length?this.totalTime(this.duration()*(this._yoyo&&0!==(1&this._cycle)?1-t:t)+this._cycle*(this._duration+this._repeatDelay),!1):this._time/this.duration()},_.totalProgress=function(t){return arguments.length?this.totalTime(this.totalDuration()*t,!1):this._totalTime/this.totalDuration()},_.time=function(t,e){return arguments.length?(this._dirty&&this.totalDuration(),t>this._duration&&(t=this._duration),this._yoyo&&0!==(1&this._cycle)?t=this._duration-t+this._cycle*(this._duration+this._repeatDelay):0!==this._repeat&&(t+=this._cycle*(this._duration+this._repeatDelay)),this.totalTime(t,e)):this._time},_.duration=function(e){return arguments.length?t.prototype.duration.call(this,e):this._duration},_.totalDuration=function(t){return arguments.length?-1===this._repeat?this:this.duration((t-this._repeat*this._repeatDelay)/(this._repeat+1)):(this._dirty&&(this._totalDuration=-1===this._repeat?999999999999:this._duration*(this._repeat+1)+this._repeatDelay*this._repeat,this._dirty=!1),this._totalDuration)},_.repeat=function(t){return arguments.length?(this._repeat=t,this._uncache(!0)):this._repeat},_.repeatDelay=function(t){return arguments.length?(this._repeatDelay=t,this._uncache(!0)):this._repeatDelay},_.yoyo=function(t){return arguments.length?(this._yoyo=t,this):this._yoyo},n},!0),_gsScope._gsDefine("TimelineLite",["core.Animation","core.SimpleTimeline","TweenLite"],function(t,e,i){var s=function(t){e.call(this,t),this._labels={},this.autoRemoveChildren=this.vars.autoRemoveChildren===!0,this.smoothChildTiming=this.vars.smoothChildTiming===!0,this._sortChildren=!0,this._onUpdate=this.vars.onUpdate;var i,s,r=this.vars;for(s in r)i=r[s],l(i)&&-1!==i.join("").indexOf("{self}")&&(r[s]=this._swapSelfInParams(i));l(r.tweens)&&this.add(r.tweens,0,r.align,r.stagger)},r=1e-10,n=i._internals,a=s._internals={},o=n.isSelector,l=n.isArray,h=n.lazyTweens,_=n.lazyRender,u=_gsScope._gsDefine.globals,c=function(t){var e,i={};for(e in t)i[e]=t[e];return i},f=function(t,e,i){var s,r,n=t.cycle;for(s in n)r=n[s],t[s]="function"==typeof r?r.call(e[i],i):r[i%r.length];delete t.cycle},p=a.pauseCallback=function(){},m=function(t){var e,i=[],s=t.length;for(e=0;e!==s;i.push(t[e++]));return i},d=s.prototype=new e;return s.version="1.18.0",d.constructor=s,d.kill()._gc=d._forcingPlayhead=d._hasPause=!1,d.to=function(t,e,s,r){var n=s.repeat&&u.TweenMax||i;return e?this.add(new n(t,e,s),r):this.set(t,s,r)},d.from=function(t,e,s,r){return this.add((s.repeat&&u.TweenMax||i).from(t,e,s),r)},d.fromTo=function(t,e,s,r,n){var a=r.repeat&&u.TweenMax||i;return e?this.add(a.fromTo(t,e,s,r),n):this.set(t,r,n)},d.staggerTo=function(t,e,r,n,a,l,h,_){var u,p,d=new s({onComplete:l,onCompleteParams:h,callbackScope:_,smoothChildTiming:this.smoothChildTiming}),g=r.cycle;for("string"==typeof t&&(t=i.selector(t)||t),t=t||[],o(t)&&(t=m(t)),n=n||0,0>n&&(t=m(t),t.reverse(),n*=-1),p=0;t.length>p;p++)u=c(r),u.startAt&&(u.startAt=c(u.startAt),u.startAt.cycle&&f(u.startAt,t,p)),g&&f(u,t,p),d.to(t[p],e,u,p*n);return this.add(d,a)},d.staggerFrom=function(t,e,i,s,r,n,a,o){return i.immediateRender=0!=i.immediateRender,i.runBackwards=!0,this.staggerTo(t,e,i,s,r,n,a,o)},d.staggerFromTo=function(t,e,i,s,r,n,a,o,l){return s.startAt=i,s.immediateRender=0!=s.immediateRender&&0!=i.immediateRender,this.staggerTo(t,e,s,r,n,a,o,l)},d.call=function(t,e,s,r){return this.add(i.delayedCall(0,t,e,s),r)},d.set=function(t,e,s){return s=this._parseTimeOrLabel(s,0,!0),null==e.immediateRender&&(e.immediateRender=s===this._time&&!this._paused),this.add(new i(t,0,e),s)},s.exportRoot=function(t,e){t=t||{},null==t.smoothChildTiming&&(t.smoothChildTiming=!0);var r,n,a=new s(t),o=a._timeline;for(null==e&&(e=!0),o._remove(a,!0),a._startTime=0,a._rawPrevTime=a._time=a._totalTime=o._time,r=o._first;r;)n=r._next,e&&r instanceof i&&r.target===r.vars.onComplete||a.add(r,r._startTime-r._delay),r=n;return o.add(a,0),a},d.add=function(r,n,a,o){var h,_,u,c,f,p;if("number"!=typeof n&&(n=this._parseTimeOrLabel(n,0,!0,r)),!(r instanceof t)){if(r instanceof Array||r&&r.push&&l(r)){for(a=a||"normal",o=o||0,h=n,_=r.length,u=0;_>u;u++)l(c=r[u])&&(c=new s({tweens:c})),this.add(c,h),"string"!=typeof c&&"function"!=typeof c&&("sequence"===a?h=c._startTime+c.totalDuration()/c._timeScale:"start"===a&&(c._startTime-=c.delay())),h+=o;return this._uncache(!0)}if("string"==typeof r)return this.addLabel(r,n);if("function"!=typeof r)throw"Cannot add "+r+" into the timeline; it is not a tween, timeline, function, or string.";r=i.delayedCall(0,r)}if(e.prototype.add.call(this,r,n),(this._gc||this._time===this._duration)&&!this._paused&&this._duration<this.duration())for(f=this,p=f.rawTime()>r._startTime;f._timeline;)p&&f._timeline.smoothChildTiming?f.totalTime(f._totalTime,!0):f._gc&&f._enabled(!0,!1),f=f._timeline;return this},d.remove=function(e){if(e instanceof t){this._remove(e,!1);var i=e._timeline=e.vars.useFrames?t._rootFramesTimeline:t._rootTimeline;return e._startTime=(e._paused?e._pauseTime:i._time)-(e._reversed?e.totalDuration()-e._totalTime:e._totalTime)/e._timeScale,this}if(e instanceof Array||e&&e.push&&l(e)){for(var s=e.length;--s>-1;)this.remove(e[s]);return this}return"string"==typeof e?this.removeLabel(e):this.kill(null,e)},d._remove=function(t,i){e.prototype._remove.call(this,t,i);var s=this._last;return s?this._time>s._startTime+s._totalDuration/s._timeScale&&(this._time=this.duration(),this._totalTime=this._totalDuration):this._time=this._totalTime=this._duration=this._totalDuration=0,this},d.append=function(t,e){return this.add(t,this._parseTimeOrLabel(null,e,!0,t))},d.insert=d.insertMultiple=function(t,e,i,s){return this.add(t,e||0,i,s)},d.appendMultiple=function(t,e,i,s){return this.add(t,this._parseTimeOrLabel(null,e,!0,t),i,s)},d.addLabel=function(t,e){return this._labels[t]=this._parseTimeOrLabel(e),this},d.addPause=function(t,e,s,r){var n=i.delayedCall(0,p,s,r||this);return n.vars.onComplete=n.vars.onReverseComplete=e,n.data="isPause",this._hasPause=!0,this.add(n,t)},d.removeLabel=function(t){return delete this._labels[t],this},d.getLabelTime=function(t){return null!=this._labels[t]?this._labels[t]:-1},d._parseTimeOrLabel=function(e,i,s,r){var n;if(r instanceof t&&r.timeline===this)this.remove(r);else if(r&&(r instanceof Array||r.push&&l(r)))for(n=r.length;--n>-1;)r[n]instanceof t&&r[n].timeline===this&&this.remove(r[n]);if("string"==typeof i)return this._parseTimeOrLabel(i,s&&"number"==typeof e&&null==this._labels[i]?e-this.duration():0,s);if(i=i||0,"string"!=typeof e||!isNaN(e)&&null==this._labels[e])null==e&&(e=this.duration());else{if(n=e.indexOf("="),-1===n)return null==this._labels[e]?s?this._labels[e]=this.duration()+i:i:this._labels[e]+i;i=parseInt(e.charAt(n-1)+"1",10)*Number(e.substr(n+1)),e=n>1?this._parseTimeOrLabel(e.substr(0,n-1),0,s):this.duration()}return Number(e)+i},d.seek=function(t,e){return this.totalTime("number"==typeof t?t:this._parseTimeOrLabel(t),e!==!1)},d.stop=function(){return this.paused(!0)},d.gotoAndPlay=function(t,e){return this.play(t,e)},d.gotoAndStop=function(t,e){return this.pause(t,e)},d.render=function(t,e,i){this._gc&&this._enabled(!0,!1);var s,n,a,o,l,u,c=this._dirty?this.totalDuration():this._totalDuration,f=this._time,p=this._startTime,m=this._timeScale,d=this._paused;if(t>=c)this._totalTime=this._time=c,this._reversed||this._hasPausedChild()||(n=!0,o="onComplete",l=!!this._timeline.autoRemoveChildren,0===this._duration&&(0===t||0>this._rawPrevTime||this._rawPrevTime===r)&&this._rawPrevTime!==t&&this._first&&(l=!0,this._rawPrevTime>r&&(o="onReverseComplete"))),this._rawPrevTime=this._duration||!e||t||this._rawPrevTime===t?t:r,t=c+1e-4;else if(1e-7>t)if(this._totalTime=this._time=0,(0!==f||0===this._duration&&this._rawPrevTime!==r&&(this._rawPrevTime>0||0>t&&this._rawPrevTime>=0))&&(o="onReverseComplete",n=this._reversed),0>t)this._active=!1,this._timeline.autoRemoveChildren&&this._reversed?(l=n=!0,o="onReverseComplete"):this._rawPrevTime>=0&&this._first&&(l=!0),this._rawPrevTime=t;else{if(this._rawPrevTime=this._duration||!e||t||this._rawPrevTime===t?t:r,0===t&&n)for(s=this._first;s&&0===s._startTime;)s._duration||(n=!1),s=s._next;t=0,this._initted||(l=!0)}else{if(this._hasPause&&!this._forcingPlayhead&&!e){if(t>=f)for(s=this._first;s&&t>=s._startTime&&!u;)s._duration||"isPause"!==s.data||s.ratio||0===s._startTime&&0===this._rawPrevTime||(u=s),s=s._next;else for(s=this._last;s&&s._startTime>=t&&!u;)s._duration||"isPause"===s.data&&s._rawPrevTime>0&&(u=s),s=s._prev;u&&(this._time=t=u._startTime,this._totalTime=t+this._cycle*(this._totalDuration+this._repeatDelay))}this._totalTime=this._time=this._rawPrevTime=t}if(this._time!==f&&this._first||i||l||u){if(this._initted||(this._initted=!0),this._active||!this._paused&&this._time!==f&&t>0&&(this._active=!0),0===f&&this.vars.onStart&&0!==this._time&&(e||this._callback("onStart")),this._time>=f)for(s=this._first;s&&(a=s._next,!this._paused||d);)(s._active||s._startTime<=this._time&&!s._paused&&!s._gc)&&(u===s&&this.pause(),s._reversed?s.render((s._dirty?s.totalDuration():s._totalDuration)-(t-s._startTime)*s._timeScale,e,i):s.render((t-s._startTime)*s._timeScale,e,i)),s=a;else for(s=this._last;s&&(a=s._prev,!this._paused||d);){if(s._active||f>=s._startTime&&!s._paused&&!s._gc){if(u===s){for(u=s._prev;u&&u.endTime()>this._time;)u.render(u._reversed?u.totalDuration()-(t-u._startTime)*u._timeScale:(t-u._startTime)*u._timeScale,e,i),u=u._prev;u=null,this.pause()}s._reversed?s.render((s._dirty?s.totalDuration():s._totalDuration)-(t-s._startTime)*s._timeScale,e,i):s.render((t-s._startTime)*s._timeScale,e,i)}s=a}this._onUpdate&&(e||(h.length&&_(),this._callback("onUpdate"))),o&&(this._gc||(p===this._startTime||m!==this._timeScale)&&(0===this._time||c>=this.totalDuration())&&(n&&(h.length&&_(),this._timeline.autoRemoveChildren&&this._enabled(!1,!1),this._active=!1),!e&&this.vars[o]&&this._callback(o)))}},d._hasPausedChild=function(){for(var t=this._first;t;){if(t._paused||t instanceof s&&t._hasPausedChild())return!0;t=t._next}return!1},d.getChildren=function(t,e,s,r){r=r||-9999999999;for(var n=[],a=this._first,o=0;a;)r>a._startTime||(a instanceof i?e!==!1&&(n[o++]=a):(s!==!1&&(n[o++]=a),t!==!1&&(n=n.concat(a.getChildren(!0,e,s)),o=n.length))),a=a._next;return n},d.getTweensOf=function(t,e){var s,r,n=this._gc,a=[],o=0;for(n&&this._enabled(!0,!0),s=i.getTweensOf(t),r=s.length;--r>-1;)(s[r].timeline===this||e&&this._contains(s[r]))&&(a[o++]=s[r]);return n&&this._enabled(!1,!0),a},d.recent=function(){return this._recent},d._contains=function(t){for(var e=t.timeline;e;){if(e===this)return!0;e=e.timeline}return!1},d.shiftChildren=function(t,e,i){i=i||0;for(var s,r=this._first,n=this._labels;r;)r._startTime>=i&&(r._startTime+=t),r=r._next;if(e)for(s in n)n[s]>=i&&(n[s]+=t);return this._uncache(!0)},d._kill=function(t,e){if(!t&&!e)return this._enabled(!1,!1);for(var i=e?this.getTweensOf(e):this.getChildren(!0,!0,!1),s=i.length,r=!1;--s>-1;)i[s]._kill(t,e)&&(r=!0);return r},d.clear=function(t){var e=this.getChildren(!1,!0,!0),i=e.length;for(this._time=this._totalTime=0;--i>-1;)e[i]._enabled(!1,!1);return t!==!1&&(this._labels={}),this._uncache(!0)},d.invalidate=function(){for(var e=this._first;e;)e.invalidate(),e=e._next;return t.prototype.invalidate.call(this)},d._enabled=function(t,i){if(t===this._gc)for(var s=this._first;s;)s._enabled(t,!0),s=s._next;return e.prototype._enabled.call(this,t,i)},d.totalTime=function(){this._forcingPlayhead=!0;var e=t.prototype.totalTime.apply(this,arguments);return this._forcingPlayhead=!1,e},d.duration=function(t){return arguments.length?(0!==this.duration()&&0!==t&&this.timeScale(this._duration/t),this):(this._dirty&&this.totalDuration(),this._duration)},d.totalDuration=function(t){if(!arguments.length){if(this._dirty){for(var e,i,s=0,r=this._last,n=999999999999;r;)e=r._prev,r._dirty&&r.totalDuration(),r._startTime>n&&this._sortChildren&&!r._paused?this.add(r,r._startTime-r._delay):n=r._startTime,0>r._startTime&&!r._paused&&(s-=r._startTime,this._timeline.smoothChildTiming&&(this._startTime+=r._startTime/this._timeScale),this.shiftChildren(-r._startTime,!1,-9999999999),n=0),i=r._startTime+r._totalDuration/r._timeScale,i>s&&(s=i),r=e;this._duration=this._totalDuration=s,this._dirty=!1}return this._totalDuration}return 0!==this.totalDuration()&&0!==t&&this.timeScale(this._totalDuration/t),this},d.paused=function(e){if(!e)for(var i=this._first,s=this._time;i;)i._startTime===s&&"isPause"===i.data&&(i._rawPrevTime=0),i=i._next;return t.prototype.paused.apply(this,arguments)},d.usesFrames=function(){for(var e=this._timeline;e._timeline;)e=e._timeline;return e===t._rootFramesTimeline},d.rawTime=function(){return this._paused?this._totalTime:(this._timeline.rawTime()-this._startTime)*this._timeScale},s},!0),_gsScope._gsDefine("TimelineMax",["TimelineLite","TweenLite","easing.Ease"],function(t,e,i){var s=function(e){t.call(this,e),this._repeat=this.vars.repeat||0,this._repeatDelay=this.vars.repeatDelay||0,this._cycle=0,this._yoyo=this.vars.yoyo===!0,this._dirty=!0},r=1e-10,n=e._internals,a=n.lazyTweens,o=n.lazyRender,l=new i(null,null,1,0),h=s.prototype=new t;return h.constructor=s,h.kill()._gc=!1,s.version="1.18.0",h.invalidate=function(){return this._yoyo=this.vars.yoyo===!0,this._repeat=this.vars.repeat||0,this._repeatDelay=this.vars.repeatDelay||0,this._uncache(!0),t.prototype.invalidate.call(this)},h.addCallback=function(t,i,s,r){return this.add(e.delayedCall(0,t,s,r),i)},h.removeCallback=function(t,e){if(t)if(null==e)this._kill(null,t);else for(var i=this.getTweensOf(t,!1),s=i.length,r=this._parseTimeOrLabel(e);--s>-1;)i[s]._startTime===r&&i[s]._enabled(!1,!1);return this},h.removePause=function(e){return this.removeCallback(t._internals.pauseCallback,e)},h.tweenTo=function(t,i){i=i||{};var s,r,n,a={ease:l,useFrames:this.usesFrames(),immediateRender:!1};for(r in i)a[r]=i[r];return a.time=this._parseTimeOrLabel(t),s=Math.abs(Number(a.time)-this._time)/this._timeScale||.001,n=new e(this,s,a),a.onStart=function(){n.target.paused(!0),n.vars.time!==n.target.time()&&s===n.duration()&&n.duration(Math.abs(n.vars.time-n.target.time())/n.target._timeScale),i.onStart&&n._callback("onStart")},n},h.tweenFromTo=function(t,e,i){i=i||{},t=this._parseTimeOrLabel(t),i.startAt={onComplete:this.seek,onCompleteParams:[t],callbackScope:this},i.immediateRender=i.immediateRender!==!1;var s=this.tweenTo(e,i);return s.duration(Math.abs(s.vars.time-t)/this._timeScale||.001)},h.render=function(t,e,i){this._gc&&this._enabled(!0,!1);var s,n,l,h,_,u,c,f=this._dirty?this.totalDuration():this._totalDuration,p=this._duration,m=this._time,d=this._totalTime,g=this._startTime,v=this._timeScale,y=this._rawPrevTime,T=this._paused,x=this._cycle;if(t>=f)this._locked||(this._totalTime=f,this._cycle=this._repeat),this._reversed||this._hasPausedChild()||(n=!0,h="onComplete",_=!!this._timeline.autoRemoveChildren,0===this._duration&&(0===t||0>y||y===r)&&y!==t&&this._first&&(_=!0,y>r&&(h="onReverseComplete"))),this._rawPrevTime=this._duration||!e||t||this._rawPrevTime===t?t:r,this._yoyo&&0!==(1&this._cycle)?this._time=t=0:(this._time=p,t=p+1e-4);else if(1e-7>t)if(this._locked||(this._totalTime=this._cycle=0),this._time=0,(0!==m||0===p&&y!==r&&(y>0||0>t&&y>=0)&&!this._locked)&&(h="onReverseComplete",n=this._reversed),0>t)this._active=!1,this._timeline.autoRemoveChildren&&this._reversed?(_=n=!0,h="onReverseComplete"):y>=0&&this._first&&(_=!0),this._rawPrevTime=t;else{if(this._rawPrevTime=p||!e||t||this._rawPrevTime===t?t:r,0===t&&n)for(s=this._first;s&&0===s._startTime;)s._duration||(n=!1),s=s._next;t=0,this._initted||(_=!0)}else if(0===p&&0>y&&(_=!0),this._time=this._rawPrevTime=t,this._locked||(this._totalTime=t,0!==this._repeat&&(u=p+this._repeatDelay,this._cycle=this._totalTime/u>>0,0!==this._cycle&&this._cycle===this._totalTime/u&&this._cycle--,this._time=this._totalTime-this._cycle*u,this._yoyo&&0!==(1&this._cycle)&&(this._time=p-this._time),this._time>p?(this._time=p,t=p+1e-4):0>this._time?this._time=t=0:t=this._time)),this._hasPause&&!this._forcingPlayhead&&!e){if(t=this._time,t>=m)for(s=this._first;s&&t>=s._startTime&&!c;)s._duration||"isPause"!==s.data||s.ratio||0===s._startTime&&0===this._rawPrevTime||(c=s),s=s._next;else for(s=this._last;s&&s._startTime>=t&&!c;)s._duration||"isPause"===s.data&&s._rawPrevTime>0&&(c=s),s=s._prev;c&&(this._time=t=c._startTime,this._totalTime=t+this._cycle*(this._totalDuration+this._repeatDelay))}if(this._cycle!==x&&!this._locked){var w=this._yoyo&&0!==(1&x),b=w===(this._yoyo&&0!==(1&this._cycle)),P=this._totalTime,k=this._cycle,S=this._rawPrevTime,R=this._time;if(this._totalTime=x*p,x>this._cycle?w=!w:this._totalTime+=p,this._time=m,this._rawPrevTime=0===p?y-1e-4:y,this._cycle=x,this._locked=!0,m=w?0:p,this.render(m,e,0===p),e||this._gc||this.vars.onRepeat&&this._callback("onRepeat"),b&&(m=w?p+1e-4:-1e-4,this.render(m,!0,!1)),this._locked=!1,this._paused&&!T)return;this._time=R,this._totalTime=P,this._cycle=k,this._rawPrevTime=S}if(!(this._time!==m&&this._first||i||_||c))return d!==this._totalTime&&this._onUpdate&&(e||this._callback("onUpdate")),void 0;if(this._initted||(this._initted=!0),this._active||!this._paused&&this._totalTime!==d&&t>0&&(this._active=!0),0===d&&this.vars.onStart&&0!==this._totalTime&&(e||this._callback("onStart")),this._time>=m)for(s=this._first;s&&(l=s._next,!this._paused||T);)(s._active||s._startTime<=this._time&&!s._paused&&!s._gc)&&(c===s&&this.pause(),s._reversed?s.render((s._dirty?s.totalDuration():s._totalDuration)-(t-s._startTime)*s._timeScale,e,i):s.render((t-s._startTime)*s._timeScale,e,i)),s=l;else for(s=this._last;s&&(l=s._prev,!this._paused||T);){if(s._active||m>=s._startTime&&!s._paused&&!s._gc){if(c===s){for(c=s._prev;c&&c.endTime()>this._time;)c.render(c._reversed?c.totalDuration()-(t-c._startTime)*c._timeScale:(t-c._startTime)*c._timeScale,e,i),c=c._prev;c=null,this.pause()}s._reversed?s.render((s._dirty?s.totalDuration():s._totalDuration)-(t-s._startTime)*s._timeScale,e,i):s.render((t-s._startTime)*s._timeScale,e,i)}s=l}this._onUpdate&&(e||(a.length&&o(),this._callback("onUpdate"))),h&&(this._locked||this._gc||(g===this._startTime||v!==this._timeScale)&&(0===this._time||f>=this.totalDuration())&&(n&&(a.length&&o(),this._timeline.autoRemoveChildren&&this._enabled(!1,!1),this._active=!1),!e&&this.vars[h]&&this._callback(h)))},h.getActive=function(t,e,i){null==t&&(t=!0),null==e&&(e=!0),null==i&&(i=!1);var s,r,n=[],a=this.getChildren(t,e,i),o=0,l=a.length;for(s=0;l>s;s++)r=a[s],r.isActive()&&(n[o++]=r);return n},h.getLabelAfter=function(t){t||0!==t&&(t=this._time);var e,i=this.getLabelsArray(),s=i.length;for(e=0;s>e;e++)if(i[e].time>t)return i[e].name;return null},h.getLabelBefore=function(t){null==t&&(t=this._time);for(var e=this.getLabelsArray(),i=e.length;--i>-1;)if(t>e[i].time)return e[i].name;return null},h.getLabelsArray=function(){var t,e=[],i=0;for(t in this._labels)e[i++]={time:this._labels[t],name:t};return e.sort(function(t,e){return t.time-e.time}),e},h.progress=function(t,e){return arguments.length?this.totalTime(this.duration()*(this._yoyo&&0!==(1&this._cycle)?1-t:t)+this._cycle*(this._duration+this._repeatDelay),e):this._time/this.duration()},h.totalProgress=function(t,e){return arguments.length?this.totalTime(this.totalDuration()*t,e):this._totalTime/this.totalDuration()},h.totalDuration=function(e){return arguments.length?-1===this._repeat?this:this.duration((e-this._repeat*this._repeatDelay)/(this._repeat+1)):(this._dirty&&(t.prototype.totalDuration.call(this),this._totalDuration=-1===this._repeat?999999999999:this._duration*(this._repeat+1)+this._repeatDelay*this._repeat),this._totalDuration)},h.time=function(t,e){return arguments.length?(this._dirty&&this.totalDuration(),t>this._duration&&(t=this._duration),this._yoyo&&0!==(1&this._cycle)?t=this._duration-t+this._cycle*(this._duration+this._repeatDelay):0!==this._repeat&&(t+=this._cycle*(this._duration+this._repeatDelay)),this.totalTime(t,e)):this._time},h.repeat=function(t){return arguments.length?(this._repeat=t,this._uncache(!0)):this._repeat},h.repeatDelay=function(t){return arguments.length?(this._repeatDelay=t,this._uncache(!0)):this._repeatDelay},h.yoyo=function(t){return arguments.length?(this._yoyo=t,this):this._yoyo},h.currentLabel=function(t){return arguments.length?this.seek(t,!0):this.getLabelBefore(this._time+1e-8)},s},!0),function(){var t=180/Math.PI,e=[],i=[],s=[],r={},n=_gsScope._gsDefine.globals,a=function(t,e,i,s){this.a=t,this.b=e,this.c=i,this.d=s,this.da=s-t,this.ca=i-t,this.ba=e-t},o=",x,y,z,left,top,right,bottom,marginTop,marginLeft,marginRight,marginBottom,paddingLeft,paddingTop,paddingRight,paddingBottom,backgroundPosition,backgroundPosition_y,",l=function(t,e,i,s){var r={a:t},n={},a={},o={c:s},l=(t+e)/2,h=(e+i)/2,_=(i+s)/2,u=(l+h)/2,c=(h+_)/2,f=(c-u)/8;return r.b=l+(t-l)/4,n.b=u+f,r.c=n.a=(r.b+n.b)/2,n.c=a.a=(u+c)/2,a.b=c-f,o.b=_+(s-_)/4,a.c=o.a=(a.b+o.b)/2,[r,n,a,o]},h=function(t,r,n,a,o){var h,_,u,c,f,p,m,d,g,v,y,T,x,w=t.length-1,b=0,P=t[0].a;for(h=0;w>h;h++)f=t[b],_=f.a,u=f.d,c=t[b+1].d,o?(y=e[h],T=i[h],x=.25*(T+y)*r/(a?.5:s[h]||.5),p=u-(u-_)*(a?.5*r:0!==y?x/y:0),m=u+(c-u)*(a?.5*r:0!==T?x/T:0),d=u-(p+((m-p)*(3*y/(y+T)+.5)/4||0))):(p=u-.5*(u-_)*r,m=u+.5*(c-u)*r,d=u-(p+m)/2),p+=d,m+=d,f.c=g=p,f.b=0!==h?P:P=f.a+.6*(f.c-f.a),f.da=u-_,f.ca=g-_,f.ba=P-_,n?(v=l(_,P,g,u),t.splice(b,1,v[0],v[1],v[2],v[3]),b+=4):b++,P=m;f=t[b],f.b=P,f.c=P+.4*(f.d-P),f.da=f.d-f.a,f.ca=f.c-f.a,f.ba=P-f.a,n&&(v=l(f.a,P,f.c,f.d),t.splice(b,1,v[0],v[1],v[2],v[3]))},_=function(t,s,r,n){var o,l,h,_,u,c,f=[];if(n)for(t=[n].concat(t),l=t.length;--l>-1;)"string"==typeof(c=t[l][s])&&"="===c.charAt(1)&&(t[l][s]=n[s]+Number(c.charAt(0)+c.substr(2)));if(o=t.length-2,0>o)return f[0]=new a(t[0][s],0,0,t[-1>o?0:1][s]),f;for(l=0;o>l;l++)h=t[l][s],_=t[l+1][s],f[l]=new a(h,0,0,_),r&&(u=t[l+2][s],e[l]=(e[l]||0)+(_-h)*(_-h),i[l]=(i[l]||0)+(u-_)*(u-_));return f[l]=new a(t[l][s],0,0,t[l+1][s]),f},u=function(t,n,a,l,u,c){var f,p,m,d,g,v,y,T,x={},w=[],b=c||t[0];u="string"==typeof u?","+u+",":o,null==n&&(n=1);for(p in t[0])w.push(p);if(t.length>1){for(T=t[t.length-1],y=!0,f=w.length;--f>-1;)if(p=w[f],Math.abs(b[p]-T[p])>.05){y=!1;break}y&&(t=t.concat(),c&&t.unshift(c),t.push(t[1]),c=t[t.length-3])}for(e.length=i.length=s.length=0,f=w.length;--f>-1;)p=w[f],r[p]=-1!==u.indexOf(","+p+","),x[p]=_(t,p,r[p],c);for(f=e.length;--f>-1;)e[f]=Math.sqrt(e[f]),i[f]=Math.sqrt(i[f]);if(!l){for(f=w.length;--f>-1;)if(r[p])for(m=x[w[f]],v=m.length-1,d=0;v>d;d++)g=m[d+1].da/i[d]+m[d].da/e[d],s[d]=(s[d]||0)+g*g;for(f=s.length;--f>-1;)s[f]=Math.sqrt(s[f])}for(f=w.length,d=a?4:1;--f>-1;)p=w[f],m=x[p],h(m,n,a,l,r[p]),y&&(m.splice(0,d),m.splice(m.length-d,d));return x},c=function(t,e,i){e=e||"soft";var s,r,n,o,l,h,_,u,c,f,p,m={},d="cubic"===e?3:2,g="soft"===e,v=[];if(g&&i&&(t=[i].concat(t)),null==t||d+1>t.length)throw"invalid Bezier data";for(c in t[0])v.push(c);for(h=v.length;--h>-1;){for(c=v[h],m[c]=l=[],f=0,u=t.length,_=0;u>_;_++)s=null==i?t[_][c]:"string"==typeof(p=t[_][c])&&"="===p.charAt(1)?i[c]+Number(p.charAt(0)+p.substr(2)):Number(p),g&&_>1&&u-1>_&&(l[f++]=(s+l[f-2])/2),l[f++]=s;for(u=f-d+1,f=0,_=0;u>_;_+=d)s=l[_],r=l[_+1],n=l[_+2],o=2===d?0:l[_+3],l[f++]=p=3===d?new a(s,r,n,o):new a(s,(2*r+s)/3,(2*r+n)/3,n);l.length=f}return m},f=function(t,e,i){for(var s,r,n,a,o,l,h,_,u,c,f,p=1/i,m=t.length;--m>-1;)for(c=t[m],n=c.a,a=c.d-n,o=c.c-n,l=c.b-n,s=r=0,_=1;i>=_;_++)h=p*_,u=1-h,s=r-(r=(h*h*a+3*u*(h*o+u*l))*h),f=m*i+_-1,e[f]=(e[f]||0)+s*s},p=function(t,e){e=e>>0||6;var i,s,r,n,a=[],o=[],l=0,h=0,_=e-1,u=[],c=[];for(i in t)f(t[i],a,e);for(r=a.length,s=0;r>s;s++)l+=Math.sqrt(a[s]),n=s%e,c[n]=l,n===_&&(h+=l,n=s/e>>0,u[n]=c,o[n]=h,l=0,c=[]);return{length:h,lengths:o,segments:u}},m=_gsScope._gsDefine.plugin({propName:"bezier",priority:-1,version:"1.3.4",API:2,global:!0,init:function(t,e,i){this._target=t,e instanceof Array&&(e={values:e}),this._func={},this._round={},this._props=[],this._timeRes=null==e.timeResolution?6:parseInt(e.timeResolution,10);var s,r,n,a,o,l=e.values||[],h={},_=l[0],f=e.autoRotate||i.vars.orientToBezier;this._autoRotate=f?f instanceof Array?f:[["x","y","rotation",f===!0?0:Number(f)||0]]:null; 2356 for(s in _)this._props.push(s);for(n=this._props.length;--n>-1;)s=this._props[n],this._overwriteProps.push(s),r=this._func[s]="function"==typeof t[s],h[s]=r?t[s.indexOf("set")||"function"!=typeof t["get"+s.substr(3)]?s:"get"+s.substr(3)]():parseFloat(t[s]),o||h[s]!==l[0][s]&&(o=h);if(this._beziers="cubic"!==e.type&&"quadratic"!==e.type&&"soft"!==e.type?u(l,isNaN(e.curviness)?1:e.curviness,!1,"thruBasic"===e.type,e.correlate,o):c(l,e.type,h),this._segCount=this._beziers[s].length,this._timeRes){var m=p(this._beziers,this._timeRes);this._length=m.length,this._lengths=m.lengths,this._segments=m.segments,this._l1=this._li=this._s1=this._si=0,this._l2=this._lengths[0],this._curSeg=this._segments[0],this._s2=this._curSeg[0],this._prec=1/this._curSeg.length}if(f=this._autoRotate)for(this._initialRotations=[],f[0]instanceof Array||(this._autoRotate=f=[f]),n=f.length;--n>-1;){for(a=0;3>a;a++)s=f[n][a],this._func[s]="function"==typeof t[s]?t[s.indexOf("set")||"function"!=typeof t["get"+s.substr(3)]?s:"get"+s.substr(3)]:!1;s=f[n][2],this._initialRotations[n]=this._func[s]?this._func[s].call(this._target):this._target[s]}return this._startRatio=i.vars.runBackwards?1:0,!0},set:function(e){var i,s,r,n,a,o,l,h,_,u,c=this._segCount,f=this._func,p=this._target,m=e!==this._startRatio;if(this._timeRes){if(_=this._lengths,u=this._curSeg,e*=this._length,r=this._li,e>this._l2&&c-1>r){for(h=c-1;h>r&&e>=(this._l2=_[++r]););this._l1=_[r-1],this._li=r,this._curSeg=u=this._segments[r],this._s2=u[this._s1=this._si=0]}else if(this._l1>e&&r>0){for(;r>0&&(this._l1=_[--r])>=e;);0===r&&this._l1>e?this._l1=0:r++,this._l2=_[r],this._li=r,this._curSeg=u=this._segments[r],this._s1=u[(this._si=u.length-1)-1]||0,this._s2=u[this._si]}if(i=r,e-=this._l1,r=this._si,e>this._s2&&u.length-1>r){for(h=u.length-1;h>r&&e>=(this._s2=u[++r]););this._s1=u[r-1],this._si=r}else if(this._s1>e&&r>0){for(;r>0&&(this._s1=u[--r])>=e;);0===r&&this._s1>e?this._s1=0:r++,this._s2=u[r],this._si=r}o=(r+(e-this._s1)/(this._s2-this._s1))*this._prec}else i=0>e?0:e>=1?c-1:c*e>>0,o=(e-i*(1/c))*c;for(s=1-o,r=this._props.length;--r>-1;)n=this._props[r],a=this._beziers[n][i],l=(o*o*a.da+3*s*(o*a.ca+s*a.ba))*o+a.a,this._round[n]&&(l=Math.round(l)),f[n]?p[n](l):p[n]=l;if(this._autoRotate){var d,g,v,y,T,x,w,b=this._autoRotate;for(r=b.length;--r>-1;)n=b[r][2],x=b[r][3]||0,w=b[r][4]===!0?1:t,a=this._beziers[b[r][0]],d=this._beziers[b[r][1]],a&&d&&(a=a[i],d=d[i],g=a.a+(a.b-a.a)*o,y=a.b+(a.c-a.b)*o,g+=(y-g)*o,y+=(a.c+(a.d-a.c)*o-y)*o,v=d.a+(d.b-d.a)*o,T=d.b+(d.c-d.b)*o,v+=(T-v)*o,T+=(d.c+(d.d-d.c)*o-T)*o,l=m?Math.atan2(T-v,y-g)*w+x:this._initialRotations[r],f[n]?p[n](l):p[n]=l)}}}),d=m.prototype;m.bezierThrough=u,m.cubicToQuadratic=l,m._autoCSS=!0,m.quadraticToCubic=function(t,e,i){return new a(t,(2*e+t)/3,(2*e+i)/3,i)},m._cssRegister=function(){var t=n.CSSPlugin;if(t){var e=t._internals,i=e._parseToProxy,s=e._setPluginRatio,r=e.CSSPropTween;e._registerComplexSpecialProp("bezier",{parser:function(t,e,n,a,o,l){e instanceof Array&&(e={values:e}),l=new m;var h,_,u,c=e.values,f=c.length-1,p=[],d={};if(0>f)return o;for(h=0;f>=h;h++)u=i(t,c[h],a,o,l,f!==h),p[h]=u.end;for(_ in e)d[_]=e[_];return d.values=p,o=new r(t,"bezier",0,0,u.pt,2),o.data=u,o.plugin=l,o.setRatio=s,0===d.autoRotate&&(d.autoRotate=!0),!d.autoRotate||d.autoRotate instanceof Array||(h=d.autoRotate===!0?0:Number(d.autoRotate),d.autoRotate=null!=u.end.left?[["left","top","rotation",h,!1]]:null!=u.end.x?[["x","y","rotation",h,!1]]:!1),d.autoRotate&&(a._transform||a._enableTransforms(!1),u.autoRotate=a._target._gsTransform),l._onInitTween(u.proxy,d,a._tween),o}})}},d._roundProps=function(t,e){for(var i=this._overwriteProps,s=i.length;--s>-1;)(t[i[s]]||t.bezier||t.bezierThrough)&&(this._round[i[s]]=e)},d._kill=function(t){var e,i,s=this._props;for(e in this._beziers)if(e in t)for(delete this._beziers[e],delete this._func[e],i=s.length;--i>-1;)s[i]===e&&s.splice(i,1);return this._super._kill.call(this,t)}}(),_gsScope._gsDefine("plugins.CSSPlugin",["plugins.TweenPlugin","TweenLite"],function(t,e){var i,s,r,n,a=function(){t.call(this,"css"),this._overwriteProps.length=0,this.setRatio=a.prototype.setRatio},o=_gsScope._gsDefine.globals,l={},h=a.prototype=new t("css");h.constructor=a,a.version="1.18.0",a.API=2,a.defaultTransformPerspective=0,a.defaultSkewType="compensated",a.defaultSmoothOrigin=!0,h="px",a.suffixMap={top:h,right:h,bottom:h,left:h,width:h,height:h,fontSize:h,padding:h,margin:h,perspective:h,lineHeight:""};var _,u,c,f,p,m,d=/(?:\d|\-\d|\.\d|\-\.\d)+/g,g=/(?:\d|\-\d|\.\d|\-\.\d|\+=\d|\-=\d|\+=.\d|\-=\.\d)+/g,v=/(?:\+=|\-=|\-|\b)[\d\-\.]+[a-zA-Z0-9]*(?:%|\b)/gi,y=/(?![+-]?\d*\.?\d+|[+-]|e[+-]\d+)[^0-9]/g,T=/(?:\d|\-|\+|=|#|\.)*/g,x=/opacity *= *([^)]*)/i,w=/opacity:([^;]*)/i,b=/alpha\(opacity *=.+?\)/i,P=/^(rgb|hsl)/,k=/([A-Z])/g,S=/-([a-z])/gi,R=/(^(?:url\(\"|url\())|(?:(\"\))$|\)$)/gi,O=function(t,e){return e.toUpperCase()},A=/(?:Left|Right|Width)/i,C=/(M11|M12|M21|M22)=[\d\-\.e]+/gi,D=/progid\:DXImageTransform\.Microsoft\.Matrix\(.+?\)/i,M=/,(?=[^\)]*(?:\(|$))/gi,z=Math.PI/180,F=180/Math.PI,I={},E=document,N=function(t){return E.createElementNS?E.createElementNS("http://www.w3.org/1999/xhtml",t):E.createElement(t)},L=N("div"),X=N("img"),B=a._internals={_specialProps:l},j=navigator.userAgent,Y=function(){var t=j.indexOf("Android"),e=N("a");return c=-1!==j.indexOf("Safari")&&-1===j.indexOf("Chrome")&&(-1===t||Number(j.substr(t+8,1))>3),p=c&&6>Number(j.substr(j.indexOf("Version/")+8,1)),f=-1!==j.indexOf("Firefox"),(/MSIE ([0-9]{1,}[\.0-9]{0,})/.exec(j)||/Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/.exec(j))&&(m=parseFloat(RegExp.$1)),e?(e.style.cssText="top:1px;opacity:.55;",/^0.55/.test(e.style.opacity)):!1}(),U=function(t){return x.test("string"==typeof t?t:(t.currentStyle?t.currentStyle.filter:t.style.filter)||"")?parseFloat(RegExp.$1)/100:1},q=function(t){window.console&&console.log(t)},V="",G="",W=function(t,e){e=e||L;var i,s,r=e.style;if(void 0!==r[t])return t;for(t=t.charAt(0).toUpperCase()+t.substr(1),i=["O","Moz","ms","Ms","Webkit"],s=5;--s>-1&&void 0===r[i[s]+t];);return s>=0?(G=3===s?"ms":i[s],V="-"+G.toLowerCase()+"-",G+t):null},Z=E.defaultView?E.defaultView.getComputedStyle:function(){},Q=a.getStyle=function(t,e,i,s,r){var n;return Y||"opacity"!==e?(!s&&t.style[e]?n=t.style[e]:(i=i||Z(t))?n=i[e]||i.getPropertyValue(e)||i.getPropertyValue(e.replace(k,"-$1").toLowerCase()):t.currentStyle&&(n=t.currentStyle[e]),null==r||n&&"none"!==n&&"auto"!==n&&"auto auto"!==n?n:r):U(t)},$=B.convertToPixels=function(t,i,s,r,n){if("px"===r||!r)return s;if("auto"===r||!s)return 0;var o,l,h,_=A.test(i),u=t,c=L.style,f=0>s;if(f&&(s=-s),"%"===r&&-1!==i.indexOf("border"))o=s/100*(_?t.clientWidth:t.clientHeight);else{if(c.cssText="border:0 solid red;position:"+Q(t,"position")+";line-height:0;","%"!==r&&u.appendChild&&"v"!==r.charAt(0)&&"rem"!==r)c[_?"borderLeftWidth":"borderTopWidth"]=s+r;else{if(u=t.parentNode||E.body,l=u._gsCache,h=e.ticker.frame,l&&_&&l.time===h)return l.width*s/100;c[_?"width":"height"]=s+r}u.appendChild(L),o=parseFloat(L[_?"offsetWidth":"offsetHeight"]),u.removeChild(L),_&&"%"===r&&a.cacheWidths!==!1&&(l=u._gsCache=u._gsCache||{},l.time=h,l.width=100*(o/s)),0!==o||n||(o=$(t,i,s,r,!0))}return f?-o:o},H=B.calculateOffset=function(t,e,i){if("absolute"!==Q(t,"position",i))return 0;var s="left"===e?"Left":"Top",r=Q(t,"margin"+s,i);return t["offset"+s]-($(t,e,parseFloat(r),r.replace(T,""))||0)},K=function(t,e){var i,s,r,n={};if(e=e||Z(t,null))if(i=e.length)for(;--i>-1;)r=e[i],(-1===r.indexOf("-transform")||ke===r)&&(n[r.replace(S,O)]=e.getPropertyValue(r));else for(i in e)(-1===i.indexOf("Transform")||Pe===i)&&(n[i]=e[i]);else if(e=t.currentStyle||t.style)for(i in e)"string"==typeof i&&void 0===n[i]&&(n[i.replace(S,O)]=e[i]);return Y||(n.opacity=U(t)),s=Ne(t,e,!1),n.rotation=s.rotation,n.skewX=s.skewX,n.scaleX=s.scaleX,n.scaleY=s.scaleY,n.x=s.x,n.y=s.y,Re&&(n.z=s.z,n.rotationX=s.rotationX,n.rotationY=s.rotationY,n.scaleZ=s.scaleZ),n.filters&&delete n.filters,n},J=function(t,e,i,s,r){var n,a,o,l={},h=t.style;for(a in i)"cssText"!==a&&"length"!==a&&isNaN(a)&&(e[a]!==(n=i[a])||r&&r[a])&&-1===a.indexOf("Origin")&&("number"==typeof n||"string"==typeof n)&&(l[a]="auto"!==n||"left"!==a&&"top"!==a?""!==n&&"auto"!==n&&"none"!==n||"string"!=typeof e[a]||""===e[a].replace(y,"")?n:0:H(t,a),void 0!==h[a]&&(o=new pe(h,a,h[a],o)));if(s)for(a in s)"className"!==a&&(l[a]=s[a]);return{difs:l,firstMPT:o}},te={width:["Left","Right"],height:["Top","Bottom"]},ee=["marginLeft","marginRight","marginTop","marginBottom"],ie=function(t,e,i){var s=parseFloat("width"===e?t.offsetWidth:t.offsetHeight),r=te[e],n=r.length;for(i=i||Z(t,null);--n>-1;)s-=parseFloat(Q(t,"padding"+r[n],i,!0))||0,s-=parseFloat(Q(t,"border"+r[n]+"Width",i,!0))||0;return s},se=function(t,e){if("contain"===t||"auto"===t||"auto auto"===t)return t+" ";(null==t||""===t)&&(t="0 0");var i=t.split(" "),s=-1!==t.indexOf("left")?"0%":-1!==t.indexOf("right")?"100%":i[0],r=-1!==t.indexOf("top")?"0%":-1!==t.indexOf("bottom")?"100%":i[1];return null==r?r="center"===s?"50%":"0":"center"===r&&(r="50%"),("center"===s||isNaN(parseFloat(s))&&-1===(s+"").indexOf("="))&&(s="50%"),t=s+" "+r+(i.length>2?" "+i[2]:""),e&&(e.oxp=-1!==s.indexOf("%"),e.oyp=-1!==r.indexOf("%"),e.oxr="="===s.charAt(1),e.oyr="="===r.charAt(1),e.ox=parseFloat(s.replace(y,"")),e.oy=parseFloat(r.replace(y,"")),e.v=t),e||t},re=function(t,e){return"string"==typeof t&&"="===t.charAt(1)?parseInt(t.charAt(0)+"1",10)*parseFloat(t.substr(2)):parseFloat(t)-parseFloat(e)},ne=function(t,e){return null==t?e:"string"==typeof t&&"="===t.charAt(1)?parseInt(t.charAt(0)+"1",10)*parseFloat(t.substr(2))+e:parseFloat(t)},ae=function(t,e,i,s){var r,n,a,o,l,h=1e-6;return null==t?o=e:"number"==typeof t?o=t:(r=360,n=t.split("_"),l="="===t.charAt(1),a=(l?parseInt(t.charAt(0)+"1",10)*parseFloat(n[0].substr(2)):parseFloat(n[0]))*(-1===t.indexOf("rad")?1:F)-(l?0:e),n.length&&(s&&(s[i]=e+a),-1!==t.indexOf("short")&&(a%=r,a!==a%(r/2)&&(a=0>a?a+r:a-r)),-1!==t.indexOf("_cw")&&0>a?a=(a+9999999999*r)%r-(0|a/r)*r:-1!==t.indexOf("ccw")&&a>0&&(a=(a-9999999999*r)%r-(0|a/r)*r)),o=e+a),h>o&&o>-h&&(o=0),o},oe={aqua:[0,255,255],lime:[0,255,0],silver:[192,192,192],black:[0,0,0],maroon:[128,0,0],teal:[0,128,128],blue:[0,0,255],navy:[0,0,128],white:[255,255,255],fuchsia:[255,0,255],olive:[128,128,0],yellow:[255,255,0],orange:[255,165,0],gray:[128,128,128],purple:[128,0,128],green:[0,128,0],red:[255,0,0],pink:[255,192,203],cyan:[0,255,255],transparent:[255,255,255,0]},le=function(t,e,i){return t=0>t?t+1:t>1?t-1:t,0|255*(1>6*t?e+6*(i-e)*t:.5>t?i:2>3*t?e+6*(i-e)*(2/3-t):e)+.5},he=a.parseColor=function(t,e){var i,s,r,n,a,o,l,h,_,u,c;if(t)if("number"==typeof t)i=[t>>16,255&t>>8,255&t];else{if(","===t.charAt(t.length-1)&&(t=t.substr(0,t.length-1)),oe[t])i=oe[t];else if("#"===t.charAt(0))4===t.length&&(s=t.charAt(1),r=t.charAt(2),n=t.charAt(3),t="#"+s+s+r+r+n+n),t=parseInt(t.substr(1),16),i=[t>>16,255&t>>8,255&t];else if("hsl"===t.substr(0,3))if(i=c=t.match(d),e){if(-1!==t.indexOf("="))return t.match(g)}else a=Number(i[0])%360/360,o=Number(i[1])/100,l=Number(i[2])/100,r=.5>=l?l*(o+1):l+o-l*o,s=2*l-r,i.length>3&&(i[3]=Number(t[3])),i[0]=le(a+1/3,s,r),i[1]=le(a,s,r),i[2]=le(a-1/3,s,r);else i=t.match(d)||oe.transparent;i[0]=Number(i[0]),i[1]=Number(i[1]),i[2]=Number(i[2]),i.length>3&&(i[3]=Number(i[3]))}else i=oe.black;return e&&!c&&(s=i[0]/255,r=i[1]/255,n=i[2]/255,h=Math.max(s,r,n),_=Math.min(s,r,n),l=(h+_)/2,h===_?a=o=0:(u=h-_,o=l>.5?u/(2-h-_):u/(h+_),a=h===s?(r-n)/u+(n>r?6:0):h===r?(n-s)/u+2:(s-r)/u+4,a*=60),i[0]=0|a+.5,i[1]=0|100*o+.5,i[2]=0|100*l+.5),i},_e=function(t,e){var i,s,r,n=t.match(ue)||[],a=0,o=n.length?"":t;for(i=0;n.length>i;i++)s=n[i],r=t.substr(a,t.indexOf(s,a)-a),a+=r.length+s.length,s=he(s,e),3===s.length&&s.push(1),o+=r+(e?"hsla("+s[0]+","+s[1]+"%,"+s[2]+"%,"+s[3]:"rgba("+s.join(","))+")";return o},ue="(?:\\b(?:(?:rgb|rgba|hsl|hsla)\\(.+?\\))|\\B#.+?\\b";for(h in oe)ue+="|"+h+"\\b";ue=RegExp(ue+")","gi"),a.colorStringFilter=function(t){var e,i=t[0]+t[1];ue.lastIndex=0,ue.test(i)&&(e=-1!==i.indexOf("hsl(")||-1!==i.indexOf("hsla("),t[0]=_e(t[0],e),t[1]=_e(t[1],e))},e.defaultStringFilter||(e.defaultStringFilter=a.colorStringFilter);var ce=function(t,e,i,s){if(null==t)return function(t){return t};var r,n=e?(t.match(ue)||[""])[0]:"",a=t.split(n).join("").match(v)||[],o=t.substr(0,t.indexOf(a[0])),l=")"===t.charAt(t.length-1)?")":"",h=-1!==t.indexOf(" ")?" ":",",_=a.length,u=_>0?a[0].replace(d,""):"";return _?r=e?function(t){var e,c,f,p;if("number"==typeof t)t+=u;else if(s&&M.test(t)){for(p=t.replace(M,"|").split("|"),f=0;p.length>f;f++)p[f]=r(p[f]);return p.join(",")}if(e=(t.match(ue)||[n])[0],c=t.split(e).join("").match(v)||[],f=c.length,_>f--)for(;_>++f;)c[f]=i?c[0|(f-1)/2]:a[f];return o+c.join(h)+h+e+l+(-1!==t.indexOf("inset")?" inset":"")}:function(t){var e,n,c;if("number"==typeof t)t+=u;else if(s&&M.test(t)){for(n=t.replace(M,"|").split("|"),c=0;n.length>c;c++)n[c]=r(n[c]);return n.join(",")}if(e=t.match(v)||[],c=e.length,_>c--)for(;_>++c;)e[c]=i?e[0|(c-1)/2]:a[c];return o+e.join(h)+l}:function(t){return t}},fe=function(t){return t=t.split(","),function(e,i,s,r,n,a,o){var l,h=(i+"").split(" ");for(o={},l=0;4>l;l++)o[t[l]]=h[l]=h[l]||h[(l-1)/2>>0];return r.parse(e,o,n,a)}},pe=(B._setPluginRatio=function(t){this.plugin.setRatio(t);for(var e,i,s,r,n=this.data,a=n.proxy,o=n.firstMPT,l=1e-6;o;)e=a[o.v],o.r?e=Math.round(e):l>e&&e>-l&&(e=0),o.t[o.p]=e,o=o._next;if(n.autoRotate&&(n.autoRotate.rotation=a.rotation),1===t)for(o=n.firstMPT;o;){if(i=o.t,i.type){if(1===i.type){for(r=i.xs0+i.s+i.xs1,s=1;i.l>s;s++)r+=i["xn"+s]+i["xs"+(s+1)];i.e=r}}else i.e=i.s+i.xs0;o=o._next}},function(t,e,i,s,r){this.t=t,this.p=e,this.v=i,this.r=r,s&&(s._prev=this,this._next=s)}),me=(B._parseToProxy=function(t,e,i,s,r,n){var a,o,l,h,_,u=s,c={},f={},p=i._transform,m=I;for(i._transform=null,I=e,s=_=i.parse(t,e,s,r),I=m,n&&(i._transform=p,u&&(u._prev=null,u._prev&&(u._prev._next=null)));s&&s!==u;){if(1>=s.type&&(o=s.p,f[o]=s.s+s.c,c[o]=s.s,n||(h=new pe(s,"s",o,h,s.r),s.c=0),1===s.type))for(a=s.l;--a>0;)l="xn"+a,o=s.p+"_"+l,f[o]=s.data[l],c[o]=s[l],n||(h=new pe(s,l,o,h,s.rxp[l]));s=s._next}return{proxy:c,end:f,firstMPT:h,pt:_}},B.CSSPropTween=function(t,e,s,r,a,o,l,h,_,u,c){this.t=t,this.p=e,this.s=s,this.c=r,this.n=l||e,t instanceof me||n.push(this.n),this.r=h,this.type=o||0,_&&(this.pr=_,i=!0),this.b=void 0===u?s:u,this.e=void 0===c?s+r:c,a&&(this._next=a,a._prev=this)}),de=function(t,e,i,s,r,n){var a=new me(t,e,i,s-i,r,-1,n);return a.b=i,a.e=a.xs0=s,a},ge=a.parseComplex=function(t,e,i,s,r,n,a,o,l,h){i=i||n||"",a=new me(t,e,0,0,a,h?2:1,null,!1,o,i,s),s+="";var u,c,f,p,m,v,y,T,x,w,b,P,k,S=i.split(", ").join(",").split(" "),R=s.split(", ").join(",").split(" "),O=S.length,A=_!==!1;for((-1!==s.indexOf(",")||-1!==i.indexOf(","))&&(S=S.join(" ").replace(M,", ").split(" "),R=R.join(" ").replace(M,", ").split(" "),O=S.length),O!==R.length&&(S=(n||"").split(" "),O=S.length),a.plugin=l,a.setRatio=h,ue.lastIndex=0,u=0;O>u;u++)if(p=S[u],m=R[u],T=parseFloat(p),T||0===T)a.appendXtra("",T,re(m,T),m.replace(g,""),A&&-1!==m.indexOf("px"),!0);else if(r&&ue.test(p))P=","===m.charAt(m.length-1)?"),":")",k=-1!==m.indexOf("hsl")&&Y,p=he(p,k),m=he(m,k),x=p.length+m.length>6,x&&!Y&&0===m[3]?(a["xs"+a.l]+=a.l?" transparent":"transparent",a.e=a.e.split(R[u]).join("transparent")):(Y||(x=!1),k?a.appendXtra(x?"hsla(":"hsl(",p[0],re(m[0],p[0]),",",!1,!0).appendXtra("",p[1],re(m[1],p[1]),"%,",!1).appendXtra("",p[2],re(m[2],p[2]),x?"%,":"%"+P,!1):a.appendXtra(x?"rgba(":"rgb(",p[0],m[0]-p[0],",",!0,!0).appendXtra("",p[1],m[1]-p[1],",",!0).appendXtra("",p[2],m[2]-p[2],x?",":P,!0),x&&(p=4>p.length?1:p[3],a.appendXtra("",p,(4>m.length?1:m[3])-p,P,!1))),ue.lastIndex=0;else if(v=p.match(d)){if(y=m.match(g),!y||y.length!==v.length)return a;for(f=0,c=0;v.length>c;c++)b=v[c],w=p.indexOf(b,f),a.appendXtra(p.substr(f,w-f),Number(b),re(y[c],b),"",A&&"px"===p.substr(w+b.length,2),0===c),f=w+b.length;a["xs"+a.l]+=p.substr(f)}else a["xs"+a.l]+=a.l?" "+p:p;if(-1!==s.indexOf("=")&&a.data){for(P=a.xs0+a.data.s,u=1;a.l>u;u++)P+=a["xs"+u]+a.data["xn"+u];a.e=P+a["xs"+u]}return a.l||(a.type=-1,a.xs0=a.e),a.xfirst||a},ve=9;for(h=me.prototype,h.l=h.pr=0;--ve>0;)h["xn"+ve]=0,h["xs"+ve]="";h.xs0="",h._next=h._prev=h.xfirst=h.data=h.plugin=h.setRatio=h.rxp=null,h.appendXtra=function(t,e,i,s,r,n){var a=this,o=a.l;return a["xs"+o]+=n&&o?" "+t:t||"",i||0===o||a.plugin?(a.l++,a.type=a.setRatio?2:1,a["xs"+a.l]=s||"",o>0?(a.data["xn"+o]=e+i,a.rxp["xn"+o]=r,a["xn"+o]=e,a.plugin||(a.xfirst=new me(a,"xn"+o,e,i,a.xfirst||a,0,a.n,r,a.pr),a.xfirst.xs0=0),a):(a.data={s:e+i},a.rxp={},a.s=e,a.c=i,a.r=r,a)):(a["xs"+o]+=e+(s||""),a)};var ye=function(t,e){e=e||{},this.p=e.prefix?W(t)||t:t,l[t]=l[this.p]=this,this.format=e.formatter||ce(e.defaultValue,e.color,e.collapsible,e.multi),e.parser&&(this.parse=e.parser),this.clrs=e.color,this.multi=e.multi,this.keyword=e.keyword,this.dflt=e.defaultValue,this.pr=e.priority||0},Te=B._registerComplexSpecialProp=function(t,e,i){"object"!=typeof e&&(e={parser:i});var s,r,n=t.split(","),a=e.defaultValue;for(i=i||[a],s=0;n.length>s;s++)e.prefix=0===s&&e.prefix,e.defaultValue=i[s]||a,r=new ye(n[s],e)},xe=function(t){if(!l[t]){var e=t.charAt(0).toUpperCase()+t.substr(1)+"Plugin";Te(t,{parser:function(t,i,s,r,n,a,h){var _=o.com.greensock.plugins[e];return _?(_._cssRegister(),l[s].parse(t,i,s,r,n,a,h)):(q("Error: "+e+" js file not loaded."),n)}})}};h=ye.prototype,h.parseComplex=function(t,e,i,s,r,n){var a,o,l,h,_,u,c=this.keyword;if(this.multi&&(M.test(i)||M.test(e)?(o=e.replace(M,"|").split("|"),l=i.replace(M,"|").split("|")):c&&(o=[e],l=[i])),l){for(h=l.length>o.length?l.length:o.length,a=0;h>a;a++)e=o[a]=o[a]||this.dflt,i=l[a]=l[a]||this.dflt,c&&(_=e.indexOf(c),u=i.indexOf(c),_!==u&&(-1===u?o[a]=o[a].split(c).join(""):-1===_&&(o[a]+=" "+c)));e=o.join(", "),i=l.join(", ")}return ge(t,this.p,e,i,this.clrs,this.dflt,s,this.pr,r,n)},h.parse=function(t,e,i,s,n,a){return this.parseComplex(t.style,this.format(Q(t,this.p,r,!1,this.dflt)),this.format(e),n,a)},a.registerSpecialProp=function(t,e,i){Te(t,{parser:function(t,s,r,n,a,o){var l=new me(t,r,0,0,a,2,r,!1,i);return l.plugin=o,l.setRatio=e(t,s,n._tween,r),l},priority:i})},a.useSVGTransformAttr=c||f;var we,be="scaleX,scaleY,scaleZ,x,y,z,skewX,skewY,rotation,rotationX,rotationY,perspective,xPercent,yPercent".split(","),Pe=W("transform"),ke=V+"transform",Se=W("transformOrigin"),Re=null!==W("perspective"),Oe=B.Transform=function(){this.perspective=parseFloat(a.defaultTransformPerspective)||0,this.force3D=a.defaultForce3D!==!1&&Re?a.defaultForce3D||"auto":!1},Ae=window.SVGElement,Ce=function(t,e,i){var s,r=E.createElementNS("http://www.w3.org/2000/svg",t),n=/([a-z])([A-Z])/g;for(s in i)r.setAttributeNS(null,s.replace(n,"$1-$2").toLowerCase(),i[s]);return e.appendChild(r),r},De=E.documentElement,Me=function(){var t,e,i,s=m||/Android/i.test(j)&&!window.chrome;return E.createElementNS&&!s&&(t=Ce("svg",De),e=Ce("rect",t,{width:100,height:50,x:100}),i=e.getBoundingClientRect().width,e.style[Se]="50% 50%",e.style[Pe]="scaleX(0.5)",s=i===e.getBoundingClientRect().width&&!(f&&Re),De.removeChild(t)),s}(),ze=function(t,e,i,s,r){var n,o,l,h,_,u,c,f,p,m,d,g,v,y,T=t._gsTransform,x=Ee(t,!0);T&&(v=T.xOrigin,y=T.yOrigin),(!s||2>(n=s.split(" ")).length)&&(c=t.getBBox(),e=se(e).split(" "),n=[(-1!==e[0].indexOf("%")?parseFloat(e[0])/100*c.width:parseFloat(e[0]))+c.x,(-1!==e[1].indexOf("%")?parseFloat(e[1])/100*c.height:parseFloat(e[1]))+c.y]),i.xOrigin=h=parseFloat(n[0]),i.yOrigin=_=parseFloat(n[1]),s&&x!==Ie&&(u=x[0],c=x[1],f=x[2],p=x[3],m=x[4],d=x[5],g=u*p-c*f,o=h*(p/g)+_*(-f/g)+(f*d-p*m)/g,l=h*(-c/g)+_*(u/g)-(u*d-c*m)/g,h=i.xOrigin=n[0]=o,_=i.yOrigin=n[1]=l),T&&(r||r!==!1&&a.defaultSmoothOrigin!==!1?(o=h-v,l=_-y,T.xOffset+=o*x[0]+l*x[2]-o,T.yOffset+=o*x[1]+l*x[3]-l):T.xOffset=T.yOffset=0),t.setAttribute("data-svg-origin",n.join(" "))},Fe=function(t){return!!(Ae&&"function"==typeof t.getBBox&&t.getCTM&&(!t.parentNode||t.parentNode.getBBox&&t.parentNode.getCTM))},Ie=[1,0,0,1,0,0],Ee=function(t,e){var i,s,r,n,a,o=t._gsTransform||new Oe,l=1e5;if(Pe?s=Q(t,ke,null,!0):t.currentStyle&&(s=t.currentStyle.filter.match(C),s=s&&4===s.length?[s[0].substr(4),Number(s[2].substr(4)),Number(s[1].substr(4)),s[3].substr(4),o.x||0,o.y||0].join(","):""),i=!s||"none"===s||"matrix(1, 0, 0, 1, 0, 0)"===s,(o.svg||t.getBBox&&Fe(t))&&(i&&-1!==(t.style[Pe]+"").indexOf("matrix")&&(s=t.style[Pe],i=0),r=t.getAttribute("transform"),i&&r&&(-1!==r.indexOf("matrix")?(s=r,i=0):-1!==r.indexOf("translate")&&(s="matrix(1,0,0,1,"+r.match(/(?:\-|\b)[\d\-\.e]+\b/gi).join(",")+")",i=0))),i)return Ie;for(r=(s||"").match(/(?:\-|\b)[\d\-\.e]+\b/gi)||[],ve=r.length;--ve>-1;)n=Number(r[ve]),r[ve]=(a=n-(n|=0))?(0|a*l+(0>a?-.5:.5))/l+n:n;return e&&r.length>6?[r[0],r[1],r[4],r[5],r[12],r[13]]:r},Ne=B.getTransform=function(t,i,s,n){if(t._gsTransform&&s&&!n)return t._gsTransform;var o,l,h,_,u,c,f=s?t._gsTransform||new Oe:new Oe,p=0>f.scaleX,m=2e-5,d=1e5,g=Re?parseFloat(Q(t,Se,i,!1,"0 0 0").split(" ")[2])||f.zOrigin||0:0,v=parseFloat(a.defaultTransformPerspective)||0;if(f.svg=!(!t.getBBox||!Fe(t)),f.svg&&(ze(t,Q(t,Se,r,!1,"50% 50%")+"",f,t.getAttribute("data-svg-origin")),we=a.useSVGTransformAttr||Me),o=Ee(t),o!==Ie){if(16===o.length){var y,T,x,w,b,P=o[0],k=o[1],S=o[2],R=o[3],O=o[4],A=o[5],C=o[6],D=o[7],M=o[8],z=o[9],I=o[10],E=o[12],N=o[13],L=o[14],X=o[11],B=Math.atan2(C,I);f.zOrigin&&(L=-f.zOrigin,E=M*L-o[12],N=z*L-o[13],L=I*L+f.zOrigin-o[14]),f.rotationX=B*F,B&&(w=Math.cos(-B),b=Math.sin(-B),y=O*w+M*b,T=A*w+z*b,x=C*w+I*b,M=O*-b+M*w,z=A*-b+z*w,I=C*-b+I*w,X=D*-b+X*w,O=y,A=T,C=x),B=Math.atan2(M,I),f.rotationY=B*F,B&&(w=Math.cos(-B),b=Math.sin(-B),y=P*w-M*b,T=k*w-z*b,x=S*w-I*b,z=k*b+z*w,I=S*b+I*w,X=R*b+X*w,P=y,k=T,S=x),B=Math.atan2(k,P),f.rotation=B*F,B&&(w=Math.cos(-B),b=Math.sin(-B),P=P*w+O*b,T=k*w+A*b,A=k*-b+A*w,C=S*-b+C*w,k=T),f.rotationX&&Math.abs(f.rotationX)+Math.abs(f.rotation)>359.9&&(f.rotationX=f.rotation=0,f.rotationY+=180),f.scaleX=(0|Math.sqrt(P*P+k*k)*d+.5)/d,f.scaleY=(0|Math.sqrt(A*A+z*z)*d+.5)/d,f.scaleZ=(0|Math.sqrt(C*C+I*I)*d+.5)/d,f.skewX=0,f.perspective=X?1/(0>X?-X:X):0,f.x=E,f.y=N,f.z=L,f.svg&&(f.x-=f.xOrigin-(f.xOrigin*P-f.yOrigin*O),f.y-=f.yOrigin-(f.yOrigin*k-f.xOrigin*A))}else if(!(Re&&!n&&o.length&&f.x===o[4]&&f.y===o[5]&&(f.rotationX||f.rotationY)||void 0!==f.x&&"none"===Q(t,"display",i))){var j=o.length>=6,Y=j?o[0]:1,U=o[1]||0,q=o[2]||0,V=j?o[3]:1;f.x=o[4]||0,f.y=o[5]||0,h=Math.sqrt(Y*Y+U*U),_=Math.sqrt(V*V+q*q),u=Y||U?Math.atan2(U,Y)*F:f.rotation||0,c=q||V?Math.atan2(q,V)*F+u:f.skewX||0,Math.abs(c)>90&&270>Math.abs(c)&&(p?(h*=-1,c+=0>=u?180:-180,u+=0>=u?180:-180):(_*=-1,c+=0>=c?180:-180)),f.scaleX=h,f.scaleY=_,f.rotation=u,f.skewX=c,Re&&(f.rotationX=f.rotationY=f.z=0,f.perspective=v,f.scaleZ=1),f.svg&&(f.x-=f.xOrigin-(f.xOrigin*Y+f.yOrigin*q),f.y-=f.yOrigin-(f.xOrigin*U+f.yOrigin*V))}f.zOrigin=g;for(l in f)m>f[l]&&f[l]>-m&&(f[l]=0)}return s&&(t._gsTransform=f,f.svg&&(we&&t.style[Pe]?e.delayedCall(.001,function(){je(t.style,Pe)}):!we&&t.getAttribute("transform")&&e.delayedCall(.001,function(){t.removeAttribute("transform")}))),f},Le=function(t){var e,i,s=this.data,r=-s.rotation*z,n=r+s.skewX*z,a=1e5,o=(0|Math.cos(r)*s.scaleX*a)/a,l=(0|Math.sin(r)*s.scaleX*a)/a,h=(0|Math.sin(n)*-s.scaleY*a)/a,_=(0|Math.cos(n)*s.scaleY*a)/a,u=this.t.style,c=this.t.currentStyle;if(c){i=l,l=-h,h=-i,e=c.filter,u.filter="";var f,p,d=this.t.offsetWidth,g=this.t.offsetHeight,v="absolute"!==c.position,y="progid:DXImageTransform.Microsoft.Matrix(M11="+o+", M12="+l+", M21="+h+", M22="+_,w=s.x+d*s.xPercent/100,b=s.y+g*s.yPercent/100;if(null!=s.ox&&(f=(s.oxp?.01*d*s.ox:s.ox)-d/2,p=(s.oyp?.01*g*s.oy:s.oy)-g/2,w+=f-(f*o+p*l),b+=p-(f*h+p*_)),v?(f=d/2,p=g/2,y+=", Dx="+(f-(f*o+p*l)+w)+", Dy="+(p-(f*h+p*_)+b)+")"):y+=", sizingMethod='auto expand')",u.filter=-1!==e.indexOf("DXImageTransform.Microsoft.Matrix(")?e.replace(D,y):y+" "+e,(0===t||1===t)&&1===o&&0===l&&0===h&&1===_&&(v&&-1===y.indexOf("Dx=0, Dy=0")||x.test(e)&&100!==parseFloat(RegExp.$1)||-1===e.indexOf("gradient("&&e.indexOf("Alpha"))&&u.removeAttribute("filter")),!v){var P,k,S,R=8>m?1:-1;for(f=s.ieOffsetX||0,p=s.ieOffsetY||0,s.ieOffsetX=Math.round((d-((0>o?-o:o)*d+(0>l?-l:l)*g))/2+w),s.ieOffsetY=Math.round((g-((0>_?-_:_)*g+(0>h?-h:h)*d))/2+b),ve=0;4>ve;ve++)k=ee[ve],P=c[k],i=-1!==P.indexOf("px")?parseFloat(P):$(this.t,k,parseFloat(P),P.replace(T,""))||0,S=i!==s[k]?2>ve?-s.ieOffsetX:-s.ieOffsetY:2>ve?f-s.ieOffsetX:p-s.ieOffsetY,u[k]=(s[k]=Math.round(i-S*(0===ve||2===ve?1:R)))+"px"}}},Xe=B.set3DTransformRatio=B.setTransformRatio=function(t){var e,i,s,r,n,a,o,l,h,_,u,c,p,m,d,g,v,y,T,x,w,b,P,k=this.data,S=this.t.style,R=k.rotation,O=k.rotationX,A=k.rotationY,C=k.scaleX,D=k.scaleY,M=k.scaleZ,F=k.x,I=k.y,E=k.z,N=k.svg,L=k.perspective,X=k.force3D;if(!(((1!==t&&0!==t||"auto"!==X||this.tween._totalTime!==this.tween._totalDuration&&this.tween._totalTime)&&X||E||L||A||O)&&(!we||!N)&&Re))return R||k.skewX||N?(R*=z,b=k.skewX*z,P=1e5,e=Math.cos(R)*C,r=Math.sin(R)*C,i=Math.sin(R-b)*-D,n=Math.cos(R-b)*D,b&&"simple"===k.skewType&&(v=Math.tan(b),v=Math.sqrt(1+v*v),i*=v,n*=v,k.skewY&&(e*=v,r*=v)),N&&(F+=k.xOrigin-(k.xOrigin*e+k.yOrigin*i)+k.xOffset,I+=k.yOrigin-(k.xOrigin*r+k.yOrigin*n)+k.yOffset,we&&(k.xPercent||k.yPercent)&&(m=this.t.getBBox(),F+=.01*k.xPercent*m.width,I+=.01*k.yPercent*m.height),m=1e-6,m>F&&F>-m&&(F=0),m>I&&I>-m&&(I=0)),T=(0|e*P)/P+","+(0|r*P)/P+","+(0|i*P)/P+","+(0|n*P)/P+","+F+","+I+")",N&&we?this.t.setAttribute("transform","matrix("+T):S[Pe]=(k.xPercent||k.yPercent?"translate("+k.xPercent+"%,"+k.yPercent+"%) matrix(":"matrix(")+T):S[Pe]=(k.xPercent||k.yPercent?"translate("+k.xPercent+"%,"+k.yPercent+"%) matrix(":"matrix(")+C+",0,0,"+D+","+F+","+I+")",void 0;if(f&&(m=1e-4,m>C&&C>-m&&(C=M=2e-5),m>D&&D>-m&&(D=M=2e-5),!L||k.z||k.rotationX||k.rotationY||(L=0)),R||k.skewX)R*=z,d=e=Math.cos(R),g=r=Math.sin(R),k.skewX&&(R-=k.skewX*z,d=Math.cos(R),g=Math.sin(R),"simple"===k.skewType&&(v=Math.tan(k.skewX*z),v=Math.sqrt(1+v*v),d*=v,g*=v,k.skewY&&(e*=v,r*=v))),i=-g,n=d;else{if(!(A||O||1!==M||L||N))return S[Pe]=(k.xPercent||k.yPercent?"translate("+k.xPercent+"%,"+k.yPercent+"%) translate3d(":"translate3d(")+F+"px,"+I+"px,"+E+"px)"+(1!==C||1!==D?" scale("+C+","+D+")":""),void 0;e=n=1,i=r=0}h=1,s=a=o=l=_=u=0,c=L?-1/L:0,p=k.zOrigin,m=1e-6,x=",",w="0",R=A*z,R&&(d=Math.cos(R),g=Math.sin(R),o=-g,_=c*-g,s=e*g,a=r*g,h=d,c*=d,e*=d,r*=d),R=O*z,R&&(d=Math.cos(R),g=Math.sin(R),v=i*d+s*g,y=n*d+a*g,l=h*g,u=c*g,s=i*-g+s*d,a=n*-g+a*d,h*=d,c*=d,i=v,n=y),1!==M&&(s*=M,a*=M,h*=M,c*=M),1!==D&&(i*=D,n*=D,l*=D,u*=D),1!==C&&(e*=C,r*=C,o*=C,_*=C),(p||N)&&(p&&(F+=s*-p,I+=a*-p,E+=h*-p+p),N&&(F+=k.xOrigin-(k.xOrigin*e+k.yOrigin*i)+k.xOffset,I+=k.yOrigin-(k.xOrigin*r+k.yOrigin*n)+k.yOffset),m>F&&F>-m&&(F=w),m>I&&I>-m&&(I=w),m>E&&E>-m&&(E=0)),T=k.xPercent||k.yPercent?"translate("+k.xPercent+"%,"+k.yPercent+"%) matrix3d(":"matrix3d(",T+=(m>e&&e>-m?w:e)+x+(m>r&&r>-m?w:r)+x+(m>o&&o>-m?w:o),T+=x+(m>_&&_>-m?w:_)+x+(m>i&&i>-m?w:i)+x+(m>n&&n>-m?w:n),O||A?(T+=x+(m>l&&l>-m?w:l)+x+(m>u&&u>-m?w:u)+x+(m>s&&s>-m?w:s),T+=x+(m>a&&a>-m?w:a)+x+(m>h&&h>-m?w:h)+x+(m>c&&c>-m?w:c)+x):T+=",0,0,0,0,1,0,",T+=F+x+I+x+E+x+(L?1+-E/L:1)+")",S[Pe]=T};h=Oe.prototype,h.x=h.y=h.z=h.skewX=h.skewY=h.rotation=h.rotationX=h.rotationY=h.zOrigin=h.xPercent=h.yPercent=h.xOffset=h.yOffset=0,h.scaleX=h.scaleY=h.scaleZ=1,Te("transform,scale,scaleX,scaleY,scaleZ,x,y,z,rotation,rotationX,rotationY,rotationZ,skewX,skewY,shortRotation,shortRotationX,shortRotationY,shortRotationZ,transformOrigin,svgOrigin,transformPerspective,directionalRotation,parseTransform,force3D,skewType,xPercent,yPercent,smoothOrigin",{parser:function(t,e,i,s,n,o,l){if(s._lastParsedTransform===l)return n;s._lastParsedTransform=l;var h,_,u,c,f,p,m,d,g,v,y=t._gsTransform,T=t.style,x=1e-6,w=be.length,b=l,P={},k="transformOrigin";if(l.display?(c=Q(t,"display"),T.display="block",h=Ne(t,r,!0,l.parseTransform),T.display=c):h=Ne(t,r,!0,l.parseTransform),s._transform=h,"string"==typeof b.transform&&Pe)c=L.style,c[Pe]=b.transform,c.display="block",c.position="absolute",E.body.appendChild(L),_=Ne(L,null,!1),E.body.removeChild(L),_.perspective||(_.perspective=h.perspective),null!=b.xPercent&&(_.xPercent=ne(b.xPercent,h.xPercent)),null!=b.yPercent&&(_.yPercent=ne(b.yPercent,h.yPercent));else if("object"==typeof b){if(_={scaleX:ne(null!=b.scaleX?b.scaleX:b.scale,h.scaleX),scaleY:ne(null!=b.scaleY?b.scaleY:b.scale,h.scaleY),scaleZ:ne(b.scaleZ,h.scaleZ),x:ne(b.x,h.x),y:ne(b.y,h.y),z:ne(b.z,h.z),xPercent:ne(b.xPercent,h.xPercent),yPercent:ne(b.yPercent,h.yPercent),perspective:ne(b.transformPerspective,h.perspective)},d=b.directionalRotation,null!=d)if("object"==typeof d)for(c in d)b[c]=d[c];else b.rotation=d;"string"==typeof b.x&&-1!==b.x.indexOf("%")&&(_.x=0,_.xPercent=ne(b.x,h.xPercent)),"string"==typeof b.y&&-1!==b.y.indexOf("%")&&(_.y=0,_.yPercent=ne(b.y,h.yPercent)),_.rotation=ae("rotation"in b?b.rotation:"shortRotation"in b?b.shortRotation+"_short":"rotationZ"in b?b.rotationZ:h.rotation,h.rotation,"rotation",P),Re&&(_.rotationX=ae("rotationX"in b?b.rotationX:"shortRotationX"in b?b.shortRotationX+"_short":h.rotationX||0,h.rotationX,"rotationX",P),_.rotationY=ae("rotationY"in b?b.rotationY:"shortRotationY"in b?b.shortRotationY+"_short":h.rotationY||0,h.rotationY,"rotationY",P)),_.skewX=null==b.skewX?h.skewX:ae(b.skewX,h.skewX),_.skewY=null==b.skewY?h.skewY:ae(b.skewY,h.skewY),(u=_.skewY-h.skewY)&&(_.skewX+=u,_.rotation+=u)}for(Re&&null!=b.force3D&&(h.force3D=b.force3D,m=!0),h.skewType=b.skewType||h.skewType||a.defaultSkewType,p=h.force3D||h.z||h.rotationX||h.rotationY||_.z||_.rotationX||_.rotationY||_.perspective,p||null==b.scale||(_.scaleZ=1);--w>-1;)i=be[w],f=_[i]-h[i],(f>x||-x>f||null!=b[i]||null!=I[i])&&(m=!0,n=new me(h,i,h[i],f,n),i in P&&(n.e=P[i]),n.xs0=0,n.plugin=o,s._overwriteProps.push(n.n));return f=b.transformOrigin,h.svg&&(f||b.svgOrigin)&&(g=h.xOffset,v=h.yOffset,ze(t,se(f),_,b.svgOrigin,b.smoothOrigin),n=de(h,"xOrigin",(y?h:_).xOrigin,_.xOrigin,n,k),n=de(h,"yOrigin",(y?h:_).yOrigin,_.yOrigin,n,k),(g!==h.xOffset||v!==h.yOffset)&&(n=de(h,"xOffset",y?g:h.xOffset,h.xOffset,n,k),n=de(h,"yOffset",y?v:h.yOffset,h.yOffset,n,k)),f=we?null:"0px 0px"),(f||Re&&p&&h.zOrigin)&&(Pe?(m=!0,i=Se,f=(f||Q(t,i,r,!1,"50% 50%"))+"",n=new me(T,i,0,0,n,-1,k),n.b=T[i],n.plugin=o,Re?(c=h.zOrigin,f=f.split(" "),h.zOrigin=(f.length>2&&(0===c||"0px"!==f[2])?parseFloat(f[2]):c)||0,n.xs0=n.e=f[0]+" "+(f[1]||"50%")+" 0px",n=new me(h,"zOrigin",0,0,n,-1,n.n),n.b=c,n.xs0=n.e=h.zOrigin):n.xs0=n.e=f):se(f+"",h)),m&&(s._transformType=h.svg&&we||!p&&3!==this._transformType?2:3),n},prefix:!0}),Te("boxShadow",{defaultValue:"0px 0px 0px 0px #999",prefix:!0,color:!0,multi:!0,keyword:"inset"}),Te("borderRadius",{defaultValue:"0px",parser:function(t,e,i,n,a){e=this.format(e);var o,l,h,_,u,c,f,p,m,d,g,v,y,T,x,w,b=["borderTopLeftRadius","borderTopRightRadius","borderBottomRightRadius","borderBottomLeftRadius"],P=t.style;for(m=parseFloat(t.offsetWidth),d=parseFloat(t.offsetHeight),o=e.split(" "),l=0;b.length>l;l++)this.p.indexOf("border")&&(b[l]=W(b[l])),u=_=Q(t,b[l],r,!1,"0px"),-1!==u.indexOf(" ")&&(_=u.split(" "),u=_[0],_=_[1]),c=h=o[l],f=parseFloat(u),v=u.substr((f+"").length),y="="===c.charAt(1),y?(p=parseInt(c.charAt(0)+"1",10),c=c.substr(2),p*=parseFloat(c),g=c.substr((p+"").length-(0>p?1:0))||""):(p=parseFloat(c),g=c.substr((p+"").length)),""===g&&(g=s[i]||v),g!==v&&(T=$(t,"borderLeft",f,v),x=$(t,"borderTop",f,v),"%"===g?(u=100*(T/m)+"%",_=100*(x/d)+"%"):"em"===g?(w=$(t,"borderLeft",1,"em"),u=T/w+"em",_=x/w+"em"):(u=T+"px",_=x+"px"),y&&(c=parseFloat(u)+p+g,h=parseFloat(_)+p+g)),a=ge(P,b[l],u+" "+_,c+" "+h,!1,"0px",a);return a},prefix:!0,formatter:ce("0px 0px 0px 0px",!1,!0)}),Te("backgroundPosition",{defaultValue:"0 0",parser:function(t,e,i,s,n,a){var o,l,h,_,u,c,f="background-position",p=r||Z(t,null),d=this.format((p?m?p.getPropertyValue(f+"-x")+" "+p.getPropertyValue(f+"-y"):p.getPropertyValue(f):t.currentStyle.backgroundPositionX+" "+t.currentStyle.backgroundPositionY)||"0 0"),g=this.format(e); 2357 if(-1!==d.indexOf("%")!=(-1!==g.indexOf("%"))&&(c=Q(t,"backgroundImage").replace(R,""),c&&"none"!==c)){for(o=d.split(" "),l=g.split(" "),X.setAttribute("src",c),h=2;--h>-1;)d=o[h],_=-1!==d.indexOf("%"),_!==(-1!==l[h].indexOf("%"))&&(u=0===h?t.offsetWidth-X.width:t.offsetHeight-X.height,o[h]=_?parseFloat(d)/100*u+"px":100*(parseFloat(d)/u)+"%");d=o.join(" ")}return this.parseComplex(t.style,d,g,n,a)},formatter:se}),Te("backgroundSize",{defaultValue:"0 0",formatter:se}),Te("perspective",{defaultValue:"0px",prefix:!0}),Te("perspectiveOrigin",{defaultValue:"50% 50%",prefix:!0}),Te("transformStyle",{prefix:!0}),Te("backfaceVisibility",{prefix:!0}),Te("userSelect",{prefix:!0}),Te("margin",{parser:fe("marginTop,marginRight,marginBottom,marginLeft")}),Te("padding",{parser:fe("paddingTop,paddingRight,paddingBottom,paddingLeft")}),Te("clip",{defaultValue:"rect(0px,0px,0px,0px)",parser:function(t,e,i,s,n,a){var o,l,h;return 9>m?(l=t.currentStyle,h=8>m?" ":",",o="rect("+l.clipTop+h+l.clipRight+h+l.clipBottom+h+l.clipLeft+")",e=this.format(e).split(",").join(h)):(o=this.format(Q(t,this.p,r,!1,this.dflt)),e=this.format(e)),this.parseComplex(t.style,o,e,n,a)}}),Te("textShadow",{defaultValue:"0px 0px 0px #999",color:!0,multi:!0}),Te("autoRound,strictUnits",{parser:function(t,e,i,s,r){return r}}),Te("border",{defaultValue:"0px solid #000",parser:function(t,e,i,s,n,a){return this.parseComplex(t.style,this.format(Q(t,"borderTopWidth",r,!1,"0px")+" "+Q(t,"borderTopStyle",r,!1,"solid")+" "+Q(t,"borderTopColor",r,!1,"#000")),this.format(e),n,a)},color:!0,formatter:function(t){var e=t.split(" ");return e[0]+" "+(e[1]||"solid")+" "+(t.match(ue)||["#000"])[0]}}),Te("borderWidth",{parser:fe("borderTopWidth,borderRightWidth,borderBottomWidth,borderLeftWidth")}),Te("float,cssFloat,styleFloat",{parser:function(t,e,i,s,r){var n=t.style,a="cssFloat"in n?"cssFloat":"styleFloat";return new me(n,a,0,0,r,-1,i,!1,0,n[a],e)}});var Be=function(t){var e,i=this.t,s=i.filter||Q(this.data,"filter")||"",r=0|this.s+this.c*t;100===r&&(-1===s.indexOf("atrix(")&&-1===s.indexOf("radient(")&&-1===s.indexOf("oader(")?(i.removeAttribute("filter"),e=!Q(this.data,"filter")):(i.filter=s.replace(b,""),e=!0)),e||(this.xn1&&(i.filter=s=s||"alpha(opacity="+r+")"),-1===s.indexOf("pacity")?0===r&&this.xn1||(i.filter=s+" alpha(opacity="+r+")"):i.filter=s.replace(x,"opacity="+r))};Te("opacity,alpha,autoAlpha",{defaultValue:"1",parser:function(t,e,i,s,n,a){var o=parseFloat(Q(t,"opacity",r,!1,"1")),l=t.style,h="autoAlpha"===i;return"string"==typeof e&&"="===e.charAt(1)&&(e=("-"===e.charAt(0)?-1:1)*parseFloat(e.substr(2))+o),h&&1===o&&"hidden"===Q(t,"visibility",r)&&0!==e&&(o=0),Y?n=new me(l,"opacity",o,e-o,n):(n=new me(l,"opacity",100*o,100*(e-o),n),n.xn1=h?1:0,l.zoom=1,n.type=2,n.b="alpha(opacity="+n.s+")",n.e="alpha(opacity="+(n.s+n.c)+")",n.data=t,n.plugin=a,n.setRatio=Be),h&&(n=new me(l,"visibility",0,0,n,-1,null,!1,0,0!==o?"inherit":"hidden",0===e?"hidden":"inherit"),n.xs0="inherit",s._overwriteProps.push(n.n),s._overwriteProps.push(i)),n}});var je=function(t,e){e&&(t.removeProperty?(("ms"===e.substr(0,2)||"webkit"===e.substr(0,6))&&(e="-"+e),t.removeProperty(e.replace(k,"-$1").toLowerCase())):t.removeAttribute(e))},Ye=function(t){if(this.t._gsClassPT=this,1===t||0===t){this.t.setAttribute("class",0===t?this.b:this.e);for(var e=this.data,i=this.t.style;e;)e.v?i[e.p]=e.v:je(i,e.p),e=e._next;1===t&&this.t._gsClassPT===this&&(this.t._gsClassPT=null)}else this.t.getAttribute("class")!==this.e&&this.t.setAttribute("class",this.e)};Te("className",{parser:function(t,e,s,n,a,o,l){var h,_,u,c,f,p=t.getAttribute("class")||"",m=t.style.cssText;if(a=n._classNamePT=new me(t,s,0,0,a,2),a.setRatio=Ye,a.pr=-11,i=!0,a.b=p,_=K(t,r),u=t._gsClassPT){for(c={},f=u.data;f;)c[f.p]=1,f=f._next;u.setRatio(1)}return t._gsClassPT=a,a.e="="!==e.charAt(1)?e:p.replace(RegExp("\\s*\\b"+e.substr(2)+"\\b"),"")+("+"===e.charAt(0)?" "+e.substr(2):""),t.setAttribute("class",a.e),h=J(t,_,K(t),l,c),t.setAttribute("class",p),a.data=h.firstMPT,t.style.cssText=m,a=a.xfirst=n.parse(t,h.difs,a,o)}});var Ue=function(t){if((1===t||0===t)&&this.data._totalTime===this.data._totalDuration&&"isFromStart"!==this.data.data){var e,i,s,r,n,a=this.t.style,o=l.transform.parse;if("all"===this.e)a.cssText="",r=!0;else for(e=this.e.split(" ").join("").split(","),s=e.length;--s>-1;)i=e[s],l[i]&&(l[i].parse===o?r=!0:i="transformOrigin"===i?Se:l[i].p),je(a,i);r&&(je(a,Pe),n=this.t._gsTransform,n&&(n.svg&&this.t.removeAttribute("data-svg-origin"),delete this.t._gsTransform))}};for(Te("clearProps",{parser:function(t,e,s,r,n){return n=new me(t,s,0,0,n,2),n.setRatio=Ue,n.e=e,n.pr=-10,n.data=r._tween,i=!0,n}}),h="bezier,throwProps,physicsProps,physics2D".split(","),ve=h.length;ve--;)xe(h[ve]);h=a.prototype,h._firstPT=h._lastParsedTransform=h._transform=null,h._onInitTween=function(t,e,o){if(!t.nodeType)return!1;this._target=t,this._tween=o,this._vars=e,_=e.autoRound,i=!1,s=e.suffixMap||a.suffixMap,r=Z(t,""),n=this._overwriteProps;var h,f,m,d,g,v,y,T,x,b=t.style;if(u&&""===b.zIndex&&(h=Q(t,"zIndex",r),("auto"===h||""===h)&&this._addLazySet(b,"zIndex",0)),"string"==typeof e&&(d=b.cssText,h=K(t,r),b.cssText=d+";"+e,h=J(t,h,K(t)).difs,!Y&&w.test(e)&&(h.opacity=parseFloat(RegExp.$1)),e=h,b.cssText=d),this._firstPT=f=e.className?l.className.parse(t,e.className,"className",this,null,null,e):this.parse(t,e,null),this._transformType){for(x=3===this._transformType,Pe?c&&(u=!0,""===b.zIndex&&(y=Q(t,"zIndex",r),("auto"===y||""===y)&&this._addLazySet(b,"zIndex",0)),p&&this._addLazySet(b,"WebkitBackfaceVisibility",this._vars.WebkitBackfaceVisibility||(x?"visible":"hidden"))):b.zoom=1,m=f;m&&m._next;)m=m._next;T=new me(t,"transform",0,0,null,2),this._linkCSSP(T,null,m),T.setRatio=Pe?Xe:Le,T.data=this._transform||Ne(t,r,!0),T.tween=o,T.pr=-1,n.pop()}if(i){for(;f;){for(v=f._next,m=d;m&&m.pr>f.pr;)m=m._next;(f._prev=m?m._prev:g)?f._prev._next=f:d=f,(f._next=m)?m._prev=f:g=f,f=v}this._firstPT=d}return!0},h.parse=function(t,e,i,n){var a,o,h,u,c,f,p,m,d,g,v=t.style;for(a in e)f=e[a],o=l[a],o?i=o.parse(t,f,a,this,i,n,e):(c=Q(t,a,r)+"",d="string"==typeof f,"color"===a||"fill"===a||"stroke"===a||-1!==a.indexOf("Color")||d&&P.test(f)?(d||(f=he(f),f=(f.length>3?"rgba(":"rgb(")+f.join(",")+")"),i=ge(v,a,c,f,!0,"transparent",i,0,n)):!d||-1===f.indexOf(" ")&&-1===f.indexOf(",")?(h=parseFloat(c),p=h||0===h?c.substr((h+"").length):"",(""===c||"auto"===c)&&("width"===a||"height"===a?(h=ie(t,a,r),p="px"):"left"===a||"top"===a?(h=H(t,a,r),p="px"):(h="opacity"!==a?0:1,p="")),g=d&&"="===f.charAt(1),g?(u=parseInt(f.charAt(0)+"1",10),f=f.substr(2),u*=parseFloat(f),m=f.replace(T,"")):(u=parseFloat(f),m=d?f.replace(T,""):""),""===m&&(m=a in s?s[a]:p),f=u||0===u?(g?u+h:u)+m:e[a],p!==m&&""!==m&&(u||0===u)&&h&&(h=$(t,a,h,p),"%"===m?(h/=$(t,a,100,"%")/100,e.strictUnits!==!0&&(c=h+"%")):"em"===m||"rem"===m?h/=$(t,a,1,m):"px"!==m&&(u=$(t,a,u,m),m="px"),g&&(u||0===u)&&(f=u+h+m)),g&&(u+=h),!h&&0!==h||!u&&0!==u?void 0!==v[a]&&(f||"NaN"!=f+""&&null!=f)?(i=new me(v,a,u||h||0,0,i,-1,a,!1,0,c,f),i.xs0="none"!==f||"display"!==a&&-1===a.indexOf("Style")?f:c):q("invalid "+a+" tween value: "+e[a]):(i=new me(v,a,h,u-h,i,0,a,_!==!1&&("px"===m||"zIndex"===a),0,c,f),i.xs0=m)):i=ge(v,a,c,f,!0,null,i,0,n)),n&&i&&!i.plugin&&(i.plugin=n);return i},h.setRatio=function(t){var e,i,s,r=this._firstPT,n=1e-6;if(1!==t||this._tween._time!==this._tween._duration&&0!==this._tween._time)if(t||this._tween._time!==this._tween._duration&&0!==this._tween._time||this._tween._rawPrevTime===-1e-6)for(;r;){if(e=r.c*t+r.s,r.r?e=Math.round(e):n>e&&e>-n&&(e=0),r.type)if(1===r.type)if(s=r.l,2===s)r.t[r.p]=r.xs0+e+r.xs1+r.xn1+r.xs2;else if(3===s)r.t[r.p]=r.xs0+e+r.xs1+r.xn1+r.xs2+r.xn2+r.xs3;else if(4===s)r.t[r.p]=r.xs0+e+r.xs1+r.xn1+r.xs2+r.xn2+r.xs3+r.xn3+r.xs4;else if(5===s)r.t[r.p]=r.xs0+e+r.xs1+r.xn1+r.xs2+r.xn2+r.xs3+r.xn3+r.xs4+r.xn4+r.xs5;else{for(i=r.xs0+e+r.xs1,s=1;r.l>s;s++)i+=r["xn"+s]+r["xs"+(s+1)];r.t[r.p]=i}else-1===r.type?r.t[r.p]=r.xs0:r.setRatio&&r.setRatio(t);else r.t[r.p]=e+r.xs0;r=r._next}else for(;r;)2!==r.type?r.t[r.p]=r.b:r.setRatio(t),r=r._next;else for(;r;){if(2!==r.type)if(r.r&&-1!==r.type)if(e=Math.round(r.s+r.c),r.type){if(1===r.type){for(s=r.l,i=r.xs0+e+r.xs1,s=1;r.l>s;s++)i+=r["xn"+s]+r["xs"+(s+1)];r.t[r.p]=i}}else r.t[r.p]=e+r.xs0;else r.t[r.p]=r.e;else r.setRatio(t);r=r._next}},h._enableTransforms=function(t){this._transform=this._transform||Ne(this._target,r,!0),this._transformType=this._transform.svg&&we||!t&&3!==this._transformType?2:3};var qe=function(){this.t[this.p]=this.e,this.data._linkCSSP(this,this._next,null,!0)};h._addLazySet=function(t,e,i){var s=this._firstPT=new me(t,e,0,0,this._firstPT,2);s.e=i,s.setRatio=qe,s.data=this},h._linkCSSP=function(t,e,i,s){return t&&(e&&(e._prev=t),t._next&&(t._next._prev=t._prev),t._prev?t._prev._next=t._next:this._firstPT===t&&(this._firstPT=t._next,s=!0),i?i._next=t:s||null!==this._firstPT||(this._firstPT=t),t._next=e,t._prev=i),t},h._kill=function(e){var i,s,r,n=e;if(e.autoAlpha||e.alpha){n={};for(s in e)n[s]=e[s];n.opacity=1,n.autoAlpha&&(n.visibility=1)}return e.className&&(i=this._classNamePT)&&(r=i.xfirst,r&&r._prev?this._linkCSSP(r._prev,i._next,r._prev._prev):r===this._firstPT&&(this._firstPT=i._next),i._next&&this._linkCSSP(i._next,i._next._next,r._prev),this._classNamePT=null),t.prototype._kill.call(this,n)};var Ve=function(t,e,i){var s,r,n,a;if(t.slice)for(r=t.length;--r>-1;)Ve(t[r],e,i);else for(s=t.childNodes,r=s.length;--r>-1;)n=s[r],a=n.type,n.style&&(e.push(K(n)),i&&i.push(n)),1!==a&&9!==a&&11!==a||!n.childNodes.length||Ve(n,e,i)};return a.cascadeTo=function(t,i,s){var r,n,a,o,l=e.to(t,i,s),h=[l],_=[],u=[],c=[],f=e._internals.reservedProps;for(t=l._targets||l.target,Ve(t,_,c),l.render(i,!0,!0),Ve(t,u),l.render(0,!0,!0),l._enabled(!0),r=c.length;--r>-1;)if(n=J(c[r],_[r],u[r]),n.firstMPT){n=n.difs;for(a in s)f[a]&&(n[a]=s[a]);o={};for(a in n)o[a]=_[r][a];h.push(e.fromTo(c[r],i,o,n))}return h},t.activate([a]),a},!0),function(){var t=_gsScope._gsDefine.plugin({propName:"roundProps",version:"1.5",priority:-1,API:2,init:function(t,e,i){return this._tween=i,!0}}),e=function(t){for(;t;)t.f||t.blob||(t.r=1),t=t._next},i=t.prototype;i._onInitAllProps=function(){for(var t,i,s,r=this._tween,n=r.vars.roundProps.join?r.vars.roundProps:r.vars.roundProps.split(","),a=n.length,o={},l=r._propLookup.roundProps;--a>-1;)o[n[a]]=1;for(a=n.length;--a>-1;)for(t=n[a],i=r._firstPT;i;)s=i._next,i.pg?i.t._roundProps(o,!0):i.n===t&&(2===i.f&&i.t?e(i.t._firstPT):(this._add(i.t,t,i.s,i.c),s&&(s._prev=i._prev),i._prev?i._prev._next=s:r._firstPT===i&&(r._firstPT=s),i._next=i._prev=null,r._propLookup[t]=l)),i=s;return!1},i._add=function(t,e,i,s){this._addTween(t,e,i,i+s,e,!0),this._overwriteProps.push(e)}}(),function(){_gsScope._gsDefine.plugin({propName:"attr",API:2,version:"0.5.0",init:function(t,e){var i;if("function"!=typeof t.setAttribute)return!1;for(i in e)this._addTween(t,"setAttribute",t.getAttribute(i)+"",e[i]+"",i,!1,i),this._overwriteProps.push(i);return!0}})}(),_gsScope._gsDefine.plugin({propName:"directionalRotation",version:"0.2.1",API:2,init:function(t,e){"object"!=typeof e&&(e={rotation:e}),this.finals={};var i,s,r,n,a,o,l=e.useRadians===!0?2*Math.PI:360,h=1e-6;for(i in e)"useRadians"!==i&&(o=(e[i]+"").split("_"),s=o[0],r=parseFloat("function"!=typeof t[i]?t[i]:t[i.indexOf("set")||"function"!=typeof t["get"+i.substr(3)]?i:"get"+i.substr(3)]()),n=this.finals[i]="string"==typeof s&&"="===s.charAt(1)?r+parseInt(s.charAt(0)+"1",10)*Number(s.substr(2)):Number(s)||0,a=n-r,o.length&&(s=o.join("_"),-1!==s.indexOf("short")&&(a%=l,a!==a%(l/2)&&(a=0>a?a+l:a-l)),-1!==s.indexOf("_cw")&&0>a?a=(a+9999999999*l)%l-(0|a/l)*l:-1!==s.indexOf("ccw")&&a>0&&(a=(a-9999999999*l)%l-(0|a/l)*l)),(a>h||-h>a)&&(this._addTween(t,i,r,r+a,i),this._overwriteProps.push(i)));return!0},set:function(t){var e;if(1!==t)this._super.setRatio.call(this,t);else for(e=this._firstPT;e;)e.f?e.t[e.p](this.finals[e.p]):e.t[e.p]=this.finals[e.p],e=e._next}})._autoCSS=!0,_gsScope._gsDefine("easing.Back",["easing.Ease"],function(t){var e,i,s,r=_gsScope.GreenSockGlobals||_gsScope,n=r.com.greensock,a=2*Math.PI,o=Math.PI/2,l=n._class,h=function(e,i){var s=l("easing."+e,function(){},!0),r=s.prototype=new t;return r.constructor=s,r.getRatio=i,s},_=t.register||function(){},u=function(t,e,i,s){var r=l("easing."+t,{easeOut:new e,easeIn:new i,easeInOut:new s},!0);return _(r,t),r},c=function(t,e,i){this.t=t,this.v=e,i&&(this.next=i,i.prev=this,this.c=i.v-e,this.gap=i.t-t)},f=function(e,i){var s=l("easing."+e,function(t){this._p1=t||0===t?t:1.70158,this._p2=1.525*this._p1},!0),r=s.prototype=new t;return r.constructor=s,r.getRatio=i,r.config=function(t){return new s(t)},s},p=u("Back",f("BackOut",function(t){return(t-=1)*t*((this._p1+1)*t+this._p1)+1}),f("BackIn",function(t){return t*t*((this._p1+1)*t-this._p1)}),f("BackInOut",function(t){return 1>(t*=2)?.5*t*t*((this._p2+1)*t-this._p2):.5*((t-=2)*t*((this._p2+1)*t+this._p2)+2)})),m=l("easing.SlowMo",function(t,e,i){e=e||0===e?e:.7,null==t?t=.7:t>1&&(t=1),this._p=1!==t?e:0,this._p1=(1-t)/2,this._p2=t,this._p3=this._p1+this._p2,this._calcEnd=i===!0},!0),d=m.prototype=new t;return d.constructor=m,d.getRatio=function(t){var e=t+(.5-t)*this._p;return this._p1>t?this._calcEnd?1-(t=1-t/this._p1)*t:e-(t=1-t/this._p1)*t*t*t*e:t>this._p3?this._calcEnd?1-(t=(t-this._p3)/this._p1)*t:e+(t-e)*(t=(t-this._p3)/this._p1)*t*t*t:this._calcEnd?1:e},m.ease=new m(.7,.7),d.config=m.config=function(t,e,i){return new m(t,e,i)},e=l("easing.SteppedEase",function(t){t=t||1,this._p1=1/t,this._p2=t+1},!0),d=e.prototype=new t,d.constructor=e,d.getRatio=function(t){return 0>t?t=0:t>=1&&(t=.999999999),(this._p2*t>>0)*this._p1},d.config=e.config=function(t){return new e(t)},i=l("easing.RoughEase",function(e){e=e||{};for(var i,s,r,n,a,o,l=e.taper||"none",h=[],_=0,u=0|(e.points||20),f=u,p=e.randomize!==!1,m=e.clamp===!0,d=e.template instanceof t?e.template:null,g="number"==typeof e.strength?.4*e.strength:.4;--f>-1;)i=p?Math.random():1/u*f,s=d?d.getRatio(i):i,"none"===l?r=g:"out"===l?(n=1-i,r=n*n*g):"in"===l?r=i*i*g:.5>i?(n=2*i,r=.5*n*n*g):(n=2*(1-i),r=.5*n*n*g),p?s+=Math.random()*r-.5*r:f%2?s+=.5*r:s-=.5*r,m&&(s>1?s=1:0>s&&(s=0)),h[_++]={x:i,y:s};for(h.sort(function(t,e){return t.x-e.x}),o=new c(1,1,null),f=u;--f>-1;)a=h[f],o=new c(a.x,a.y,o);this._prev=new c(0,0,0!==o.t?o:o.next)},!0),d=i.prototype=new t,d.constructor=i,d.getRatio=function(t){var e=this._prev;if(t>e.t){for(;e.next&&t>=e.t;)e=e.next;e=e.prev}else for(;e.prev&&e.t>=t;)e=e.prev;return this._prev=e,e.v+(t-e.t)/e.gap*e.c},d.config=function(t){return new i(t)},i.ease=new i,u("Bounce",h("BounceOut",function(t){return 1/2.75>t?7.5625*t*t:2/2.75>t?7.5625*(t-=1.5/2.75)*t+.75:2.5/2.75>t?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375}),h("BounceIn",function(t){return 1/2.75>(t=1-t)?1-7.5625*t*t:2/2.75>t?1-(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?1-(7.5625*(t-=2.25/2.75)*t+.9375):1-(7.5625*(t-=2.625/2.75)*t+.984375)}),h("BounceInOut",function(t){var e=.5>t;return t=e?1-2*t:2*t-1,t=1/2.75>t?7.5625*t*t:2/2.75>t?7.5625*(t-=1.5/2.75)*t+.75:2.5/2.75>t?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375,e?.5*(1-t):.5*t+.5})),u("Circ",h("CircOut",function(t){return Math.sqrt(1-(t-=1)*t)}),h("CircIn",function(t){return-(Math.sqrt(1-t*t)-1)}),h("CircInOut",function(t){return 1>(t*=2)?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)})),s=function(e,i,s){var r=l("easing."+e,function(t,e){this._p1=t>=1?t:1,this._p2=(e||s)/(1>t?t:1),this._p3=this._p2/a*(Math.asin(1/this._p1)||0),this._p2=a/this._p2},!0),n=r.prototype=new t;return n.constructor=r,n.getRatio=i,n.config=function(t,e){return new r(t,e)},r},u("Elastic",s("ElasticOut",function(t){return this._p1*Math.pow(2,-10*t)*Math.sin((t-this._p3)*this._p2)+1},.3),s("ElasticIn",function(t){return-(this._p1*Math.pow(2,10*(t-=1))*Math.sin((t-this._p3)*this._p2))},.3),s("ElasticInOut",function(t){return 1>(t*=2)?-.5*this._p1*Math.pow(2,10*(t-=1))*Math.sin((t-this._p3)*this._p2):.5*this._p1*Math.pow(2,-10*(t-=1))*Math.sin((t-this._p3)*this._p2)+1},.45)),u("Expo",h("ExpoOut",function(t){return 1-Math.pow(2,-10*t)}),h("ExpoIn",function(t){return Math.pow(2,10*(t-1))-.001}),h("ExpoInOut",function(t){return 1>(t*=2)?.5*Math.pow(2,10*(t-1)):.5*(2-Math.pow(2,-10*(t-1)))})),u("Sine",h("SineOut",function(t){return Math.sin(t*o)}),h("SineIn",function(t){return-Math.cos(t*o)+1}),h("SineInOut",function(t){return-.5*(Math.cos(Math.PI*t)-1)})),l("easing.EaseLookup",{find:function(e){return t.map[e]}},!0),_(r.SlowMo,"SlowMo","ease,"),_(i,"RoughEase","ease,"),_(e,"SteppedEase","ease,"),p},!0)}),_gsScope._gsDefine&&_gsScope._gsQueue.pop()(),function(t,e){"use strict";var i=t.GreenSockGlobals=t.GreenSockGlobals||t;if(!i.TweenLite){var s,r,n,a,o,l=function(t){var e,s=t.split("."),r=i;for(e=0;s.length>e;e++)r[s[e]]=r=r[s[e]]||{};return r},h=l("com.greensock"),_=1e-10,u=function(t){var e,i=[],s=t.length;for(e=0;e!==s;i.push(t[e++]));return i},c=function(){},f=function(){var t=Object.prototype.toString,e=t.call([]);return function(i){return null!=i&&(i instanceof Array||"object"==typeof i&&!!i.push&&t.call(i)===e)}}(),p={},m=function(s,r,n,a){this.sc=p[s]?p[s].sc:[],p[s]=this,this.gsClass=null,this.func=n;var o=[];this.check=function(h){for(var _,u,c,f,d,g=r.length,v=g;--g>-1;)(_=p[r[g]]||new m(r[g],[])).gsClass?(o[g]=_.gsClass,v--):h&&_.sc.push(this);if(0===v&&n)for(u=("com.greensock."+s).split("."),c=u.pop(),f=l(u.join("."))[c]=this.gsClass=n.apply(n,o),a&&(i[c]=f,d="undefined"!=typeof module&&module.exports,!d&&"function"==typeof define&&define.amd?define((t.GreenSockAMDPath?t.GreenSockAMDPath+"/":"")+s.split(".").pop(),[],function(){return f}):s===e&&d&&(module.exports=f)),g=0;this.sc.length>g;g++)this.sc[g].check()},this.check(!0)},d=t._gsDefine=function(t,e,i,s){return new m(t,e,i,s)},g=h._class=function(t,e,i){return e=e||function(){},d(t,[],function(){return e},i),e};d.globals=i;var v=[0,0,1,1],y=[],T=g("easing.Ease",function(t,e,i,s){this._func=t,this._type=i||0,this._power=s||0,this._params=e?v.concat(e):v},!0),x=T.map={},w=T.register=function(t,e,i,s){for(var r,n,a,o,l=e.split(","),_=l.length,u=(i||"easeIn,easeOut,easeInOut").split(",");--_>-1;)for(n=l[_],r=s?g("easing."+n,null,!0):h.easing[n]||{},a=u.length;--a>-1;)o=u[a],x[n+"."+o]=x[o+n]=r[o]=t.getRatio?t:t[o]||new t};for(n=T.prototype,n._calcEnd=!1,n.getRatio=function(t){if(this._func)return this._params[0]=t,this._func.apply(null,this._params);var e=this._type,i=this._power,s=1===e?1-t:2===e?t:.5>t?2*t:2*(1-t);return 1===i?s*=s:2===i?s*=s*s:3===i?s*=s*s*s:4===i&&(s*=s*s*s*s),1===e?1-s:2===e?s:.5>t?s/2:1-s/2},s=["Linear","Quad","Cubic","Quart","Quint,Strong"],r=s.length;--r>-1;)n=s[r]+",Power"+r,w(new T(null,null,1,r),n,"easeOut",!0),w(new T(null,null,2,r),n,"easeIn"+(0===r?",easeNone":"")),w(new T(null,null,3,r),n,"easeInOut");x.linear=h.easing.Linear.easeIn,x.swing=h.easing.Quad.easeInOut;var b=g("events.EventDispatcher",function(t){this._listeners={},this._eventTarget=t||this});n=b.prototype,n.addEventListener=function(t,e,i,s,r){r=r||0;var n,l,h=this._listeners[t],_=0;for(null==h&&(this._listeners[t]=h=[]),l=h.length;--l>-1;)n=h[l],n.c===e&&n.s===i?h.splice(l,1):0===_&&r>n.pr&&(_=l+1);h.splice(_,0,{c:e,s:i,up:s,pr:r}),this!==a||o||a.wake()},n.removeEventListener=function(t,e){var i,s=this._listeners[t];if(s)for(i=s.length;--i>-1;)if(s[i].c===e)return s.splice(i,1),void 0},n.dispatchEvent=function(t){var e,i,s,r=this._listeners[t];if(r)for(e=r.length,i=this._eventTarget;--e>-1;)s=r[e],s&&(s.up?s.c.call(s.s||i,{type:t,target:i}):s.c.call(s.s||i))};var P=t.requestAnimationFrame,k=t.cancelAnimationFrame,S=Date.now||function(){return(new Date).getTime()},R=S();for(s=["ms","moz","webkit","o"],r=s.length;--r>-1&&!P;)P=t[s[r]+"RequestAnimationFrame"],k=t[s[r]+"CancelAnimationFrame"]||t[s[r]+"CancelRequestAnimationFrame"];g("Ticker",function(t,e){var i,s,r,n,l,h=this,u=S(),f=e!==!1&&P,p=500,m=33,d="tick",g=function(t){var e,a,o=S()-R;o>p&&(u+=o-m),R+=o,h.time=(R-u)/1e3,e=h.time-l,(!i||e>0||t===!0)&&(h.frame++,l+=e+(e>=n?.004:n-e),a=!0),t!==!0&&(r=s(g)),a&&h.dispatchEvent(d)};b.call(h),h.time=h.frame=0,h.tick=function(){g(!0)},h.lagSmoothing=function(t,e){p=t||1/_,m=Math.min(e,p,0)},h.sleep=function(){null!=r&&(f&&k?k(r):clearTimeout(r),s=c,r=null,h===a&&(o=!1))},h.wake=function(){null!==r?h.sleep():h.frame>10&&(R=S()-p+5),s=0===i?c:f&&P?P:function(t){return setTimeout(t,0|1e3*(l-h.time)+1)},h===a&&(o=!0),g(2)},h.fps=function(t){return arguments.length?(i=t,n=1/(i||60),l=this.time+n,h.wake(),void 0):i},h.useRAF=function(t){return arguments.length?(h.sleep(),f=t,h.fps(i),void 0):f},h.fps(t),setTimeout(function(){f&&5>h.frame&&h.useRAF(!1)},1500)}),n=h.Ticker.prototype=new h.events.EventDispatcher,n.constructor=h.Ticker;var O=g("core.Animation",function(t,e){if(this.vars=e=e||{},this._duration=this._totalDuration=t||0,this._delay=Number(e.delay)||0,this._timeScale=1,this._active=e.immediateRender===!0,this.data=e.data,this._reversed=e.reversed===!0,W){o||a.wake();var i=this.vars.useFrames?G:W;i.add(this,i._time),this.vars.paused&&this.paused(!0)}});a=O.ticker=new h.Ticker,n=O.prototype,n._dirty=n._gc=n._initted=n._paused=!1,n._totalTime=n._time=0,n._rawPrevTime=-1,n._next=n._last=n._onUpdate=n._timeline=n.timeline=null,n._paused=!1;var A=function(){o&&S()-R>2e3&&a.wake(),setTimeout(A,2e3)};A(),n.play=function(t,e){return null!=t&&this.seek(t,e),this.reversed(!1).paused(!1)},n.pause=function(t,e){return null!=t&&this.seek(t,e),this.paused(!0)},n.resume=function(t,e){return null!=t&&this.seek(t,e),this.paused(!1)},n.seek=function(t,e){return this.totalTime(Number(t),e!==!1)},n.restart=function(t,e){return this.reversed(!1).paused(!1).totalTime(t?-this._delay:0,e!==!1,!0)},n.reverse=function(t,e){return null!=t&&this.seek(t||this.totalDuration(),e),this.reversed(!0).paused(!1)},n.render=function(){},n.invalidate=function(){return this._time=this._totalTime=0,this._initted=this._gc=!1,this._rawPrevTime=-1,(this._gc||!this.timeline)&&this._enabled(!0),this},n.isActive=function(){var t,e=this._timeline,i=this._startTime;return!e||!this._gc&&!this._paused&&e.isActive()&&(t=e.rawTime())>=i&&i+this.totalDuration()/this._timeScale>t},n._enabled=function(t,e){return o||a.wake(),this._gc=!t,this._active=this.isActive(),e!==!0&&(t&&!this.timeline?this._timeline.add(this,this._startTime-this._delay):!t&&this.timeline&&this._timeline._remove(this,!0)),!1},n._kill=function(){return this._enabled(!1,!1)},n.kill=function(t,e){return this._kill(t,e),this},n._uncache=function(t){for(var e=t?this:this.timeline;e;)e._dirty=!0,e=e.timeline;return this},n._swapSelfInParams=function(t){for(var e=t.length,i=t.concat();--e>-1;)"{self}"===t[e]&&(i[e]=this);return i},n._callback=function(t){var e=this.vars;e[t].apply(e[t+"Scope"]||e.callbackScope||this,e[t+"Params"]||y)},n.eventCallback=function(t,e,i,s){if("on"===(t||"").substr(0,2)){var r=this.vars;if(1===arguments.length)return r[t];null==e?delete r[t]:(r[t]=e,r[t+"Params"]=f(i)&&-1!==i.join("").indexOf("{self}")?this._swapSelfInParams(i):i,r[t+"Scope"]=s),"onUpdate"===t&&(this._onUpdate=e)}return this},n.delay=function(t){return arguments.length?(this._timeline.smoothChildTiming&&this.startTime(this._startTime+t-this._delay),this._delay=t,this):this._delay},n.duration=function(t){return arguments.length?(this._duration=this._totalDuration=t,this._uncache(!0),this._timeline.smoothChildTiming&&this._time>0&&this._time<this._duration&&0!==t&&this.totalTime(this._totalTime*(t/this._duration),!0),this):(this._dirty=!1,this._duration)},n.totalDuration=function(t){return this._dirty=!1,arguments.length?this.duration(t):this._totalDuration},n.time=function(t,e){return arguments.length?(this._dirty&&this.totalDuration(),this.totalTime(t>this._duration?this._duration:t,e)):this._time},n.totalTime=function(t,e,i){if(o||a.wake(),!arguments.length)return this._totalTime;if(this._timeline){if(0>t&&!i&&(t+=this.totalDuration()),this._timeline.smoothChildTiming){this._dirty&&this.totalDuration();var s=this._totalDuration,r=this._timeline;if(t>s&&!i&&(t=s),this._startTime=(this._paused?this._pauseTime:r._time)-(this._reversed?s-t:t)/this._timeScale,r._dirty||this._uncache(!1),r._timeline)for(;r._timeline;)r._timeline._time!==(r._startTime+r._totalTime)/r._timeScale&&r.totalTime(r._totalTime,!0),r=r._timeline}this._gc&&this._enabled(!0,!1),(this._totalTime!==t||0===this._duration)&&(F.length&&Q(),this.render(t,e,!1),F.length&&Q())}return this},n.progress=n.totalProgress=function(t,e){var i=this.duration();return arguments.length?this.totalTime(i*t,e):i?this._time/i:this.ratio},n.startTime=function(t){return arguments.length?(t!==this._startTime&&(this._startTime=t,this.timeline&&this.timeline._sortChildren&&this.timeline.add(this,t-this._delay)),this):this._startTime},n.endTime=function(t){return this._startTime+(0!=t?this.totalDuration():this.duration())/this._timeScale},n.timeScale=function(t){if(!arguments.length)return this._timeScale;if(t=t||_,this._timeline&&this._timeline.smoothChildTiming){var e=this._pauseTime,i=e||0===e?e:this._timeline.totalTime();this._startTime=i-(i-this._startTime)*this._timeScale/t}return this._timeScale=t,this._uncache(!1)},n.reversed=function(t){return arguments.length?(t!=this._reversed&&(this._reversed=t,this.totalTime(this._timeline&&!this._timeline.smoothChildTiming?this.totalDuration()-this._totalTime:this._totalTime,!0)),this):this._reversed},n.paused=function(t){if(!arguments.length)return this._paused;var e,i,s=this._timeline;return t!=this._paused&&s&&(o||t||a.wake(),e=s.rawTime(),i=e-this._pauseTime,!t&&s.smoothChildTiming&&(this._startTime+=i,this._uncache(!1)),this._pauseTime=t?e:null,this._paused=t,this._active=this.isActive(),!t&&0!==i&&this._initted&&this.duration()&&(e=s.smoothChildTiming?this._totalTime:(e-this._startTime)/this._timeScale,this.render(e,e===this._totalTime,!0))),this._gc&&!t&&this._enabled(!0,!1),this};var C=g("core.SimpleTimeline",function(t){O.call(this,0,t),this.autoRemoveChildren=this.smoothChildTiming=!0});n=C.prototype=new O,n.constructor=C,n.kill()._gc=!1,n._first=n._last=n._recent=null,n._sortChildren=!1,n.add=n.insert=function(t,e){var i,s;if(t._startTime=Number(e||0)+t._delay,t._paused&&this!==t._timeline&&(t._pauseTime=t._startTime+(this.rawTime()-t._startTime)/t._timeScale),t.timeline&&t.timeline._remove(t,!0),t.timeline=t._timeline=this,t._gc&&t._enabled(!0,!0),i=this._last,this._sortChildren)for(s=t._startTime;i&&i._startTime>s;)i=i._prev;return i?(t._next=i._next,i._next=t):(t._next=this._first,this._first=t),t._next?t._next._prev=t:this._last=t,t._prev=i,this._recent=t,this._timeline&&this._uncache(!0),this},n._remove=function(t,e){return t.timeline===this&&(e||t._enabled(!1,!0),t._prev?t._prev._next=t._next:this._first===t&&(this._first=t._next),t._next?t._next._prev=t._prev:this._last===t&&(this._last=t._prev),t._next=t._prev=t.timeline=null,t===this._recent&&(this._recent=this._last),this._timeline&&this._uncache(!0)),this},n.render=function(t,e,i){var s,r=this._first;for(this._totalTime=this._time=this._rawPrevTime=t;r;)s=r._next,(r._active||t>=r._startTime&&!r._paused)&&(r._reversed?r.render((r._dirty?r.totalDuration():r._totalDuration)-(t-r._startTime)*r._timeScale,e,i):r.render((t-r._startTime)*r._timeScale,e,i)),r=s},n.rawTime=function(){return o||a.wake(),this._totalTime};var D=g("TweenLite",function(e,i,s){if(O.call(this,i,s),this.render=D.prototype.render,null==e)throw"Cannot tween a null target.";this.target=e="string"!=typeof e?e:D.selector(e)||e;var r,n,a,o=e.jquery||e.length&&e!==t&&e[0]&&(e[0]===t||e[0].nodeType&&e[0].style&&!e.nodeType),l=this.vars.overwrite;if(this._overwrite=l=null==l?V[D.defaultOverwrite]:"number"==typeof l?l>>0:V[l],(o||e instanceof Array||e.push&&f(e))&&"number"!=typeof e[0])for(this._targets=a=u(e),this._propLookup=[],this._siblings=[],r=0;a.length>r;r++)n=a[r],n?"string"!=typeof n?n.length&&n!==t&&n[0]&&(n[0]===t||n[0].nodeType&&n[0].style&&!n.nodeType)?(a.splice(r--,1),this._targets=a=a.concat(u(n))):(this._siblings[r]=$(n,this,!1),1===l&&this._siblings[r].length>1&&K(n,this,null,1,this._siblings[r])):(n=a[r--]=D.selector(n),"string"==typeof n&&a.splice(r+1,1)):a.splice(r--,1);else this._propLookup={},this._siblings=$(e,this,!1),1===l&&this._siblings.length>1&&K(e,this,null,1,this._siblings);(this.vars.immediateRender||0===i&&0===this._delay&&this.vars.immediateRender!==!1)&&(this._time=-_,this.render(-this._delay))},!0),M=function(e){return e&&e.length&&e!==t&&e[0]&&(e[0]===t||e[0].nodeType&&e[0].style&&!e.nodeType)},z=function(t,e){var i,s={};for(i in t)q[i]||i in e&&"transform"!==i&&"x"!==i&&"y"!==i&&"width"!==i&&"height"!==i&&"className"!==i&&"border"!==i||!(!j[i]||j[i]&&j[i]._autoCSS)||(s[i]=t[i],delete t[i]);t.css=s};n=D.prototype=new O,n.constructor=D,n.kill()._gc=!1,n.ratio=0,n._firstPT=n._targets=n._overwrittenProps=n._startAt=null,n._notifyPluginsOfEnabled=n._lazy=!1,D.version="1.18.0",D.defaultEase=n._ease=new T(null,null,1,1),D.defaultOverwrite="auto",D.ticker=a,D.autoSleep=120,D.lagSmoothing=function(t,e){a.lagSmoothing(t,e)},D.selector=t.$||t.jQuery||function(e){var i=t.$||t.jQuery;return i?(D.selector=i,i(e)):"undefined"==typeof document?e:document.querySelectorAll?document.querySelectorAll(e):document.getElementById("#"===e.charAt(0)?e.substr(1):e)};var F=[],I={},E=/(?:(-|-=|\+=)?\d*\.?\d*(?:e[\-+]?\d+)?)[0-9]/gi,N=function(t){for(var e,i=this._firstPT,s=1e-6;i;)e=i.blob?t?this.join(""):this.start:i.c*t+i.s,i.r?e=Math.round(e):s>e&&e>-s&&(e=0),i.f?i.fp?i.t[i.p](i.fp,e):i.t[i.p](e):i.t[i.p]=e,i=i._next},L=function(t,e,i,s){var r,n,a,o,l,h,_,u=[t,e],c=0,f="",p=0;for(u.start=t,i&&(i(u),t=u[0],e=u[1]),u.length=0,r=t.match(E)||[],n=e.match(E)||[],s&&(s._next=null,s.blob=1,u._firstPT=s),l=n.length,o=0;l>o;o++)_=n[o],h=e.substr(c,e.indexOf(_,c)-c),f+=h||!o?h:",",c+=h.length,p?p=(p+1)%5:"rgba("===h.substr(-5)&&(p=1),_===r[o]||o>=r.length?f+=_:(f&&(u.push(f),f=""),a=parseFloat(r[o]),u.push(a),u._firstPT={_next:u._firstPT,t:u,p:u.length-1,s:a,c:("="===_.charAt(1)?parseInt(_.charAt(0)+"1",10)*parseFloat(_.substr(2)):parseFloat(_)-a)||0,f:0,r:p&&4>p}),c+=_.length;return f+=e.substr(c),f&&u.push(f),u.setRatio=N,u},X=function(t,e,i,s,r,n,a,o){var l,h,_="get"===i?t[e]:i,u=typeof t[e],c="string"==typeof s&&"="===s.charAt(1),f={t:t,p:e,s:_,f:"function"===u,pg:0,n:r||e,r:n,pr:0,c:c?parseInt(s.charAt(0)+"1",10)*parseFloat(s.substr(2)):parseFloat(s)-_||0};return"number"!==u&&("function"===u&&"get"===i&&(h=e.indexOf("set")||"function"!=typeof t["get"+e.substr(3)]?e:"get"+e.substr(3),f.s=_=a?t[h](a):t[h]()),"string"==typeof _&&(a||isNaN(_))?(f.fp=a,l=L(_,s,o||D.defaultStringFilter,f),f={t:l,p:"setRatio",s:0,c:1,f:2,pg:0,n:r||e,pr:0}):c||(f.c=parseFloat(s)-parseFloat(_)||0)),f.c?((f._next=this._firstPT)&&(f._next._prev=f),this._firstPT=f,f):void 0},B=D._internals={isArray:f,isSelector:M,lazyTweens:F,blobDif:L},j=D._plugins={},Y=B.tweenLookup={},U=0,q=B.reservedProps={ease:1,delay:1,overwrite:1,onComplete:1,onCompleteParams:1,onCompleteScope:1,useFrames:1,runBackwards:1,startAt:1,onUpdate:1,onUpdateParams:1,onUpdateScope:1,onStart:1,onStartParams:1,onStartScope:1,onReverseComplete:1,onReverseCompleteParams:1,onReverseCompleteScope:1,onRepeat:1,onRepeatParams:1,onRepeatScope:1,easeParams:1,yoyo:1,immediateRender:1,repeat:1,repeatDelay:1,data:1,paused:1,reversed:1,autoCSS:1,lazy:1,onOverwrite:1,callbackScope:1,stringFilter:1},V={none:0,all:1,auto:2,concurrent:3,allOnStart:4,preexisting:5,"true":1,"false":0},G=O._rootFramesTimeline=new C,W=O._rootTimeline=new C,Z=30,Q=B.lazyRender=function(){var t,e=F.length;for(I={};--e>-1;)t=F[e],t&&t._lazy!==!1&&(t.render(t._lazy[0],t._lazy[1],!0),t._lazy=!1);F.length=0};W._startTime=a.time,G._startTime=a.frame,W._active=G._active=!0,setTimeout(Q,1),O._updateRoot=D.render=function(){var t,e,i;if(F.length&&Q(),W.render((a.time-W._startTime)*W._timeScale,!1,!1),G.render((a.frame-G._startTime)*G._timeScale,!1,!1),F.length&&Q(),a.frame>=Z){Z=a.frame+(parseInt(D.autoSleep,10)||120); 2358 for(i in Y){for(e=Y[i].tweens,t=e.length;--t>-1;)e[t]._gc&&e.splice(t,1);0===e.length&&delete Y[i]}if(i=W._first,(!i||i._paused)&&D.autoSleep&&!G._first&&1===a._listeners.tick.length){for(;i&&i._paused;)i=i._next;i||a.sleep()}}},a.addEventListener("tick",O._updateRoot);var $=function(t,e,i){var s,r,n=t._gsTweenID;if(Y[n||(t._gsTweenID=n="t"+U++)]||(Y[n]={target:t,tweens:[]}),e&&(s=Y[n].tweens,s[r=s.length]=e,i))for(;--r>-1;)s[r]===e&&s.splice(r,1);return Y[n].tweens},H=function(t,e,i,s){var r,n,a=t.vars.onOverwrite;return a&&(r=a(t,e,i,s)),a=D.onOverwrite,a&&(n=a(t,e,i,s)),r!==!1&&n!==!1},K=function(t,e,i,s,r){var n,a,o,l;if(1===s||s>=4){for(l=r.length,n=0;l>n;n++)if((o=r[n])!==e)o._gc||o._kill(null,t,e)&&(a=!0);else if(5===s)break;return a}var h,u=e._startTime+_,c=[],f=0,p=0===e._duration;for(n=r.length;--n>-1;)(o=r[n])===e||o._gc||o._paused||(o._timeline!==e._timeline?(h=h||J(e,0,p),0===J(o,h,p)&&(c[f++]=o)):u>=o._startTime&&o._startTime+o.totalDuration()/o._timeScale>u&&((p||!o._initted)&&2e-10>=u-o._startTime||(c[f++]=o)));for(n=f;--n>-1;)if(o=c[n],2===s&&o._kill(i,t,e)&&(a=!0),2!==s||!o._firstPT&&o._initted){if(2!==s&&!H(o,e))continue;o._enabled(!1,!1)&&(a=!0)}return a},J=function(t,e,i){for(var s=t._timeline,r=s._timeScale,n=t._startTime;s._timeline;){if(n+=s._startTime,r*=s._timeScale,s._paused)return-100;s=s._timeline}return n/=r,n>e?n-e:i&&n===e||!t._initted&&2*_>n-e?_:(n+=t.totalDuration()/t._timeScale/r)>e+_?0:n-e-_};n._init=function(){var t,e,i,s,r,n=this.vars,a=this._overwrittenProps,o=this._duration,l=!!n.immediateRender,h=n.ease;if(n.startAt){this._startAt&&(this._startAt.render(-1,!0),this._startAt.kill()),r={};for(s in n.startAt)r[s]=n.startAt[s];if(r.overwrite=!1,r.immediateRender=!0,r.lazy=l&&n.lazy!==!1,r.startAt=r.delay=null,this._startAt=D.to(this.target,0,r),l)if(this._time>0)this._startAt=null;else if(0!==o)return}else if(n.runBackwards&&0!==o)if(this._startAt)this._startAt.render(-1,!0),this._startAt.kill(),this._startAt=null;else{0!==this._time&&(l=!1),i={};for(s in n)q[s]&&"autoCSS"!==s||(i[s]=n[s]);if(i.overwrite=0,i.data="isFromStart",i.lazy=l&&n.lazy!==!1,i.immediateRender=l,this._startAt=D.to(this.target,0,i),l){if(0===this._time)return}else this._startAt._init(),this._startAt._enabled(!1),this.vars.immediateRender&&(this._startAt=null)}if(this._ease=h=h?h instanceof T?h:"function"==typeof h?new T(h,n.easeParams):x[h]||D.defaultEase:D.defaultEase,n.easeParams instanceof Array&&h.config&&(this._ease=h.config.apply(h,n.easeParams)),this._easeType=this._ease._type,this._easePower=this._ease._power,this._firstPT=null,this._targets)for(t=this._targets.length;--t>-1;)this._initProps(this._targets[t],this._propLookup[t]={},this._siblings[t],a?a[t]:null)&&(e=!0);else e=this._initProps(this.target,this._propLookup,this._siblings,a);if(e&&D._onPluginEvent("_onInitAllProps",this),a&&(this._firstPT||"function"!=typeof this.target&&this._enabled(!1,!1)),n.runBackwards)for(i=this._firstPT;i;)i.s+=i.c,i.c=-i.c,i=i._next;this._onUpdate=n.onUpdate,this._initted=!0},n._initProps=function(e,i,s,r){var n,a,o,l,h,_;if(null==e)return!1;I[e._gsTweenID]&&Q(),this.vars.css||e.style&&e!==t&&e.nodeType&&j.css&&this.vars.autoCSS!==!1&&z(this.vars,e);for(n in this.vars)if(_=this.vars[n],q[n])_&&(_ instanceof Array||_.push&&f(_))&&-1!==_.join("").indexOf("{self}")&&(this.vars[n]=_=this._swapSelfInParams(_,this));else if(j[n]&&(l=new j[n])._onInitTween(e,this.vars[n],this)){for(this._firstPT=h={_next:this._firstPT,t:l,p:"setRatio",s:0,c:1,f:1,n:n,pg:1,pr:l._priority},a=l._overwriteProps.length;--a>-1;)i[l._overwriteProps[a]]=this._firstPT;(l._priority||l._onInitAllProps)&&(o=!0),(l._onDisable||l._onEnable)&&(this._notifyPluginsOfEnabled=!0),h._next&&(h._next._prev=h)}else i[n]=X.call(this,e,n,"get",_,n,0,null,this.vars.stringFilter);return r&&this._kill(r,e)?this._initProps(e,i,s,r):this._overwrite>1&&this._firstPT&&s.length>1&&K(e,this,i,this._overwrite,s)?(this._kill(i,e),this._initProps(e,i,s,r)):(this._firstPT&&(this.vars.lazy!==!1&&this._duration||this.vars.lazy&&!this._duration)&&(I[e._gsTweenID]=!0),o)},n.render=function(t,e,i){var s,r,n,a,o=this._time,l=this._duration,h=this._rawPrevTime;if(t>=l)this._totalTime=this._time=l,this.ratio=this._ease._calcEnd?this._ease.getRatio(1):1,this._reversed||(s=!0,r="onComplete",i=i||this._timeline.autoRemoveChildren),0===l&&(this._initted||!this.vars.lazy||i)&&(this._startTime===this._timeline._duration&&(t=0),(0===t||0>h||h===_&&"isPause"!==this.data)&&h!==t&&(i=!0,h>_&&(r="onReverseComplete")),this._rawPrevTime=a=!e||t||h===t?t:_);else if(1e-7>t)this._totalTime=this._time=0,this.ratio=this._ease._calcEnd?this._ease.getRatio(0):0,(0!==o||0===l&&h>0)&&(r="onReverseComplete",s=this._reversed),0>t&&(this._active=!1,0===l&&(this._initted||!this.vars.lazy||i)&&(h>=0&&(h!==_||"isPause"!==this.data)&&(i=!0),this._rawPrevTime=a=!e||t||h===t?t:_)),this._initted||(i=!0);else if(this._totalTime=this._time=t,this._easeType){var u=t/l,c=this._easeType,f=this._easePower;(1===c||3===c&&u>=.5)&&(u=1-u),3===c&&(u*=2),1===f?u*=u:2===f?u*=u*u:3===f?u*=u*u*u:4===f&&(u*=u*u*u*u),this.ratio=1===c?1-u:2===c?u:.5>t/l?u/2:1-u/2}else this.ratio=this._ease.getRatio(t/l);if(this._time!==o||i){if(!this._initted){if(this._init(),!this._initted||this._gc)return;if(!i&&this._firstPT&&(this.vars.lazy!==!1&&this._duration||this.vars.lazy&&!this._duration))return this._time=this._totalTime=o,this._rawPrevTime=h,F.push(this),this._lazy=[t,e],void 0;this._time&&!s?this.ratio=this._ease.getRatio(this._time/l):s&&this._ease._calcEnd&&(this.ratio=this._ease.getRatio(0===this._time?0:1))}for(this._lazy!==!1&&(this._lazy=!1),this._active||!this._paused&&this._time!==o&&t>=0&&(this._active=!0),0===o&&(this._startAt&&(t>=0?this._startAt.render(t,e,i):r||(r="_dummyGS")),this.vars.onStart&&(0!==this._time||0===l)&&(e||this._callback("onStart"))),n=this._firstPT;n;)n.f?n.t[n.p](n.c*this.ratio+n.s):n.t[n.p]=n.c*this.ratio+n.s,n=n._next;this._onUpdate&&(0>t&&this._startAt&&t!==-1e-4&&this._startAt.render(t,e,i),e||(this._time!==o||s)&&this._callback("onUpdate")),r&&(!this._gc||i)&&(0>t&&this._startAt&&!this._onUpdate&&t!==-1e-4&&this._startAt.render(t,e,i),s&&(this._timeline.autoRemoveChildren&&this._enabled(!1,!1),this._active=!1),!e&&this.vars[r]&&this._callback(r),0===l&&this._rawPrevTime===_&&a!==_&&(this._rawPrevTime=0))}},n._kill=function(t,e,i){if("all"===t&&(t=null),null==t&&(null==e||e===this.target))return this._lazy=!1,this._enabled(!1,!1);e="string"!=typeof e?e||this._targets||this.target:D.selector(e)||e;var s,r,n,a,o,l,h,_,u,c=i&&this._time&&i._startTime===this._startTime&&this._timeline===i._timeline;if((f(e)||M(e))&&"number"!=typeof e[0])for(s=e.length;--s>-1;)this._kill(t,e[s],i)&&(l=!0);else{if(this._targets){for(s=this._targets.length;--s>-1;)if(e===this._targets[s]){o=this._propLookup[s]||{},this._overwrittenProps=this._overwrittenProps||[],r=this._overwrittenProps[s]=t?this._overwrittenProps[s]||{}:"all";break}}else{if(e!==this.target)return!1;o=this._propLookup,r=this._overwrittenProps=t?this._overwrittenProps||{}:"all"}if(o){if(h=t||o,_=t!==r&&"all"!==r&&t!==o&&("object"!=typeof t||!t._tempKill),i&&(D.onOverwrite||this.vars.onOverwrite)){for(n in h)o[n]&&(u||(u=[]),u.push(n));if((u||!t)&&!H(this,i,e,u))return!1}for(n in h)(a=o[n])&&(c&&(a.f?a.t[a.p](a.s):a.t[a.p]=a.s,l=!0),a.pg&&a.t._kill(h)&&(l=!0),a.pg&&0!==a.t._overwriteProps.length||(a._prev?a._prev._next=a._next:a===this._firstPT&&(this._firstPT=a._next),a._next&&(a._next._prev=a._prev),a._next=a._prev=null),delete o[n]),_&&(r[n]=1);!this._firstPT&&this._initted&&this._enabled(!1,!1)}}return l},n.invalidate=function(){return this._notifyPluginsOfEnabled&&D._onPluginEvent("_onDisable",this),this._firstPT=this._overwrittenProps=this._startAt=this._onUpdate=null,this._notifyPluginsOfEnabled=this._active=this._lazy=!1,this._propLookup=this._targets?{}:[],O.prototype.invalidate.call(this),this.vars.immediateRender&&(this._time=-_,this.render(-this._delay)),this},n._enabled=function(t,e){if(o||a.wake(),t&&this._gc){var i,s=this._targets;if(s)for(i=s.length;--i>-1;)this._siblings[i]=$(s[i],this,!0);else this._siblings=$(this.target,this,!0)}return O.prototype._enabled.call(this,t,e),this._notifyPluginsOfEnabled&&this._firstPT?D._onPluginEvent(t?"_onEnable":"_onDisable",this):!1},D.to=function(t,e,i){return new D(t,e,i)},D.from=function(t,e,i){return i.runBackwards=!0,i.immediateRender=0!=i.immediateRender,new D(t,e,i)},D.fromTo=function(t,e,i,s){return s.startAt=i,s.immediateRender=0!=s.immediateRender&&0!=i.immediateRender,new D(t,e,s)},D.delayedCall=function(t,e,i,s,r){return new D(e,0,{delay:t,onComplete:e,onCompleteParams:i,callbackScope:s,onReverseComplete:e,onReverseCompleteParams:i,immediateRender:!1,lazy:!1,useFrames:r,overwrite:0})},D.set=function(t,e){return new D(t,0,e)},D.getTweensOf=function(t,e){if(null==t)return[];t="string"!=typeof t?t:D.selector(t)||t;var i,s,r,n;if((f(t)||M(t))&&"number"!=typeof t[0]){for(i=t.length,s=[];--i>-1;)s=s.concat(D.getTweensOf(t[i],e));for(i=s.length;--i>-1;)for(n=s[i],r=i;--r>-1;)n===s[r]&&s.splice(i,1)}else for(s=$(t).concat(),i=s.length;--i>-1;)(s[i]._gc||e&&!s[i].isActive())&&s.splice(i,1);return s},D.killTweensOf=D.killDelayedCallsTo=function(t,e,i){"object"==typeof e&&(i=e,e=!1);for(var s=D.getTweensOf(t,e),r=s.length;--r>-1;)s[r]._kill(i,t)};var te=g("plugins.TweenPlugin",function(t,e){this._overwriteProps=(t||"").split(","),this._propName=this._overwriteProps[0],this._priority=e||0,this._super=te.prototype},!0);if(n=te.prototype,te.version="1.18.0",te.API=2,n._firstPT=null,n._addTween=X,n.setRatio=N,n._kill=function(t){var e,i=this._overwriteProps,s=this._firstPT;if(null!=t[this._propName])this._overwriteProps=[];else for(e=i.length;--e>-1;)null!=t[i[e]]&&i.splice(e,1);for(;s;)null!=t[s.n]&&(s._next&&(s._next._prev=s._prev),s._prev?(s._prev._next=s._next,s._prev=null):this._firstPT===s&&(this._firstPT=s._next)),s=s._next;return!1},n._roundProps=function(t,e){for(var i=this._firstPT;i;)(t[this._propName]||null!=i.n&&t[i.n.split(this._propName+"_").join("")])&&(i.r=e),i=i._next},D._onPluginEvent=function(t,e){var i,s,r,n,a,o=e._firstPT;if("_onInitAllProps"===t){for(;o;){for(a=o._next,s=r;s&&s.pr>o.pr;)s=s._next;(o._prev=s?s._prev:n)?o._prev._next=o:r=o,(o._next=s)?s._prev=o:n=o,o=a}o=e._firstPT=r}for(;o;)o.pg&&"function"==typeof o.t[t]&&o.t[t]()&&(i=!0),o=o._next;return i},te.activate=function(t){for(var e=t.length;--e>-1;)t[e].API===te.API&&(j[(new t[e])._propName]=t[e]);return!0},d.plugin=function(t){if(!(t&&t.propName&&t.init&&t.API))throw"illegal plugin definition.";var e,i=t.propName,s=t.priority||0,r=t.overwriteProps,n={init:"_onInitTween",set:"setRatio",kill:"_kill",round:"_roundProps",initAll:"_onInitAllProps"},a=g("plugins."+i.charAt(0).toUpperCase()+i.substr(1)+"Plugin",function(){te.call(this,i,s),this._overwriteProps=r||[]},t.global===!0),o=a.prototype=new te(i);o.constructor=a,a.API=t.API;for(e in n)"function"==typeof t[e]&&(o[n[e]]=t[e]);return a.version=t.version,te.activate([a]),a},s=t._gsQueue){for(r=0;s.length>r;r++)s[r]();for(n in p)p[n].func||t.console.log("GSAP encountered missing dependency: com.greensock."+n)}o=!1}}("undefined"!=typeof module&&module.exports&&"undefined"!=typeof global?global:this||window,"TweenMax"); 33 jQuery(document).ready(function() { 34 new YpmAdmin(); 35 }); -
popup-more/trunk/assets/view/wheel/main.php
r3264016 r3265986 22 22 <h3 class="ypm-subtitle">General Settings</h3> 23 23 <div class="row form-group"> 24 <div class="col-md- 4">24 <div class="col-md-5"> 25 25 <label for="ypm-wheel-sound" class="ypm-option-label"> 26 26 <?php esc_attr_e('Enable Wheel Spin Sound', 'popup_master'); ?>: 27 27 </label> 28 28 </div> 29 <label class="ypm-switch"> 30 <input type="checkbox" id="ypm-wheel-sound" name="ypm-wheel-sound" class="js-ypm-accordion" <?php echo esc_attr($popupTypeObj->getOptionValue('ypm-wheel-sound')) ?>> 31 <span class="ypm-slider ypm-round"></span> 32 </label> 29 <div class="col-md-5"> 30 <label class="ypm-switch"> 31 <input type="checkbox" id="ypm-wheel-sound" name="ypm-wheel-sound" class="js-ypm-accordion" <?php echo esc_attr($popupTypeObj->getOptionValue('ypm-wheel-sound')) ?>> 32 <span class="ypm-slider ypm-round"></span> 33 </label> 34 </div> 33 35 </div> 34 36 <div class="ypm-accordion-content ypm-hide-content"> … … 90 92 </div> 91 93 </div> 94 <div class="row form-group"> 95 <div class="col-md-5"> 96 <label for="ypm-wheel-button-color" class="ypm-option-label"> 97 <?php esc_attr_e('Color', 'popup_master'); ?>: 98 </label> 99 </div> 100 <div class="col-md-5"> 101 <input type="color" name="ypm-wheel-button-color" value="<?php esc_attr_e($popupTypeObj->getOptionValue('ypm-wheel-button-color'))?>" class="ypm-type-color" /> 102 </div> 103 </div> 104 <div class="row form-group"> 105 <div class="col-md-5"> 106 <label for="ypm-wheel-button-bg-color" class="ypm-option-label"> 107 <?php esc_attr_e('Background Color', 'popup_master'); ?>: 108 </label> 109 </div> 110 <div class="col-md-5"> 111 <input type="color" name="ypm-wheel-button-bg-color" id="ypm-wheel-button-bg-color" value="<?php esc_attr_e($popupTypeObj->getOptionValue('ypm-wheel-button-bg-color'))?>" class="ypm-type-color" /> 112 </div> 113 </div> 114 </div> 115 <div class="ypm-section-general"> 116 <h3 class="ypm-subtitle">Arrow Settings</h3> 117 <div class="row form-group"> 118 <div class="col-md-5"> 119 <label for="ypm-wheel-arrow-size" class="ypm-option-label"> 120 <?php esc_attr_e('Arrow Size', 'popup_master'); ?>: 121 </label> 122 </div> 123 <div class="col-md-5"> 124 <?php 125 $options = YpmAdminHelper::selectBox(array('0.5' => 'Small', '1' => 'Normal', '2' => 'Large', '4' => 'Extra large'), esc_attr($popupTypeObj->getOptionValue('ypm-wheel-arrow-size')), array('name' => 'ypm-wheel-arrow-size', 'class' => 'js-ycd-select')); 126 echo wp_kses($options, YpmAdminHelper::getAllowedTags()) 127 ?> 128 </div> 129 </div> 130 <div class="row form-group"> 131 <div class="col-md-5"> 132 <label for="ypm-wheel-arrow-color" class="ypm-option-label"> 133 <?php esc_attr_e('Arrow color', 'popup_master'); ?>: 134 </label> 135 </div> 136 <div class="col-md-5"> 137 <input type="color" name="ypm-wheel-arrow-color" value="<?php esc_attr_e($popupTypeObj->getOptionValue('ypm-wheel-arrow-color'))?>" class="ypm-type-color" /> 138 </div> 139 </div> 92 140 </div> 93 141 </div> -
popup-more/trunk/classes/admin/wheel/WheelOptions.php
r3256169 r3265986 3 3 class WheelOptionsRenderer { 4 4 private $wheelOptions; 5 private $isFree; 5 6 6 7 public function __construct($options = []) { 7 8 $this->wheelOptions = $options; 9 $this->isFree = ypm_is_free(); // Check if the plugin is in free mode 8 10 } 9 11 … … 23 25 .wheel-option { 24 26 display: grid; 25 grid-template-columns: 2fr 1fr 1fr 1fr 2fr ;27 grid-template-columns: 2fr 1fr 1fr 1fr 2fr auto; 26 28 gap: 10px; 27 29 align-items: center; … … 73 75 display: block; 74 76 } 77 .disabled-button { 78 opacity: 0.5; 79 cursor: not-allowed; 80 } 75 81 </style> 76 82 … … 78 84 <ul id="wheel-options-list"> 79 85 <li class="wheel-option column-labels"> 80 <div> 81 <span class="column-label">Label</span> 82 </div> 83 <div> 84 <span class="column-label">Background Color</span> 85 </div> 86 <div> 87 <span class="column-label">Text Color</span> 88 </div> 89 <div> 90 <span class="column-label">Probability</span> 91 </div> 92 <div> 93 <span class="column-label">Prize</span> 94 </div> 86 <div><span class="column-label">Label</span></div> 87 <div><span class="column-label">Background Color</span></div> 88 <div><span class="column-label">Text Color</span></div> 89 <div><span class="column-label">Probability</span></div> 90 <div><span class="column-label">Prize</span></div> 91 <div><span class="column-label">Action</span></div> 95 92 </li> 96 93 <?php foreach ($this->wheelOptions as $key => $option): ?> … … 113 110 </div> 114 111 <div> 115 <input type="number" name="ypm-wheeloptions[<?php echo esc_attr($key); ?>][probability]" value="<?php echo esc_attr($probability); ?>" min="1" max="100" placeholder="Probability" />112 <input type="number" name="ypm-wheeloptions[<?php echo esc_attr($key); ?>][probability]" value="<?php echo esc_attr($probability); ?>" min="1" max="100" class="ypm-prize-probability" placeholder="Probability" /> 116 113 </div> 117 114 <div> 118 115 <input type="text" name="ypm-wheeloptions[<?php echo esc_attr($key); ?>][prize]" value="<?php echo esc_attr($prize); ?>" placeholder="Prize" /> 119 116 </div> 117 <div> 118 <button type="button" class="delete-option <?php echo $this->isFree ? 'disabled-button' : ''; ?>" 119 > 120 Delete 121 <?php echo $this->isFree ? '(Pro)' : ''; ?> 122 </button> 123 </div> 120 124 </li> 121 125 <?php endforeach; ?> 122 126 </ul> 127 128 <button type="button" class="add-option-button <?php echo $this->isFree ? 'disabled-button' : ''; ?>" id="add-option"> 129 Add Option 130 <?php echo $this->isFree ? '(Pro)' : ''; ?> 131 </button> 123 132 </div> 124 133 134 <script> 135 document.addEventListener('DOMContentLoaded', function () { 136 const list = document.getElementById('wheel-options-list'); 137 const addButton = document.getElementById('add-option'); 138 let index = <?php echo count($this->wheelOptions); ?>; 139 const isFree = <?php echo json_encode($this->isFree); ?>; 125 140 141 if (!isFree) { 142 addButton.addEventListener('click', function() { 143 const newItem = document.createElement('li'); 144 newItem.className = 'wheel-option'; 145 newItem.setAttribute('data-key', index); 146 147 newItem.innerHTML = ` 148 <div> 149 <input type="text" name="ypm-wheeloptions[${index}][label]" placeholder="Label" /> 150 </div> 151 <div> 152 <input type="color" name="ypm-wheeloptions[${index}][color]" value="#ffffff" /> 153 </div> 154 <div> 155 <input type="color" name="ypm-wheeloptions[${index}][textColor]" value="#000000" /> 156 </div> 157 <div> 158 <input type="number" name="ypm-wheeloptions[${index}][probability]" value="10" min="1" max="100" class="ypm-prize-probability" placeholder="Probability" /> 159 </div> 160 <div> 161 <input type="text" name="ypm-wheeloptions[${index}][prize]" placeholder="Prize" /> 162 </div> 163 <div> 164 <button type="button" class="delete-option">Delete</button> 165 </div> 166 `; 167 list.appendChild(newItem); 168 index++; 169 }); 170 171 list.addEventListener('click', function (e) { 172 if (e.target.classList.contains('delete-option')) { 173 const option = e.target.closest('.wheel-option'); 174 if (!option.classList.contains('column-labels')) { 175 option.remove(); 176 } 177 } 178 }); 179 } 180 }); 181 </script> 126 182 <?php 183 127 184 $content = ob_get_contents(); 128 185 ob_end_clean(); … … 130 187 } 131 188 } 189 ?> -
popup-more/trunk/classes/frontend/popups/WheelPopup.php
r3264016 r3265986 34 34 35 35 public function includeAdminScripts() { 36 if (is_admin()) { 37 wp_register_script('ypmWheelAdminJs', YPM_POPUP_JS_URL.'wheel/admin.js', array('jquery', 'jquery-ui-sortable')); 38 $backLocalizeData = array( 39 'proURL' => YPM_POPUP_PRO_URL 40 ); 41 wp_localize_script('ypmWheelAdminJs', 'yrmWheelAdmin', $backLocalizeData); 42 wp_enqueue_script('ypmWheelAdminJs'); 36 43 37 wp_register_script('ypmWheelAdminJs', YPM_POPUP_JS_URL.'wheel/admin.js', array('jquery', 'jquery-ui-sortable')); 44 if (!ypm_is_free()) { 45 wp_register_script('ypmWheelAdminPROJs', YPM_POPUP_JS_URL.'wheel/adminPro.js', array('jquery', 'jquery-ui-sortable')); 46 wp_enqueue_script('ypmWheelAdminPROJs'); 47 } 48 } 49 wp_register_script('ypmWheelCoreJs', YPM_POPUP_JS_URL.'wheel/WheelCore.js', array('jquery', 'jquery-ui-sortable')); 38 50 $backLocalizeData = array( 39 51 'ajaxNonce' => wp_create_nonce('ycfAjaxNonce') 40 52 ); 41 wp_localize_script('ypmWheel AdminJs', 'ycfBackendLocalization', $backLocalizeData);42 wp_enqueue_script('ypmWheel AdminJs');53 wp_localize_script('ypmWheelCoreJs', 'ycfBackendLocalization', $backLocalizeData); 54 wp_enqueue_script('ypmWheelCoreJs'); 43 55 } 44 56 … … 69 81 $this->includeJs(); 70 82 $id = $this->getId(); 83 $arrowSize = $this->getOptionValue('ypm-wheel-arrow-size'); 84 71 85 ob_start(); 72 86 ?> … … 93 107 #ycd-wheel-pointer { 94 108 position: absolute; 95 top: - 30px; /* Adjust based on wheel position */109 top: -<?php echo esc_attr($arrowSize)*30; ?>px; /* Adjust based on wheel position */ 96 110 left: 50%; 97 111 transform: translateX(-50%) rotate(180deg); 98 112 width: 0; 99 113 height: 0; 100 border-left: 20px solid transparent;101 border-right: 20px solid transparent;102 border-bottom: 30px solid red; /* Arrow color */114 border-left: <?php echo esc_attr($arrowSize)*20; ?>px solid transparent; 115 border-right: <?php echo esc_attr($arrowSize)*20; ?>px solid transparent; 116 border-bottom: <?php echo esc_attr($arrowSize)*30; ?>px solid <?php esc_attr_e($this->getOptionValue('ypm-wheel-arrow-color'))?>; /* Arrow color */ 103 117 z-index: 10; /* Ensure it appears above the wheel */ 104 118 } … … 117 131 height: <?php esc_attr_e($this->getOptionValue('ypm-wheel-button-height')); ?>; 118 132 font-size: <?php esc_attr_e($this->getOptionValue('ypm-wheel-button-font-size')); ?>; 133 color: <?php esc_attr_e($this->getOptionValue('ypm-wheel-button-color')); ?> !important; 134 background-color: <?php esc_attr_e($this->getOptionValue('ypm-wheel-button-bg-color')); ?> !important; 119 135 } 120 136 </style> -
popup-more/trunk/config/config.php
r3264016 r3265986 75 75 require_once(dirname(__FILE__).'/config-pkg.php'); 76 76 77 self::define('YPM_POPUP_VERSION', 2.5 2);78 self::define('YPM_POPUP_PRO_VERSION', 4.2 01);77 self::define('YPM_POPUP_VERSION', 2.53); 78 self::define('YPM_POPUP_PRO_VERSION', 4.22); 79 79 80 80 self::define('YPM_POPUP_PRO_URL', 'https://popup-more.com/'); -
popup-more/trunk/config/data-config.php
r3264016 r3265986 641 641 $options[] = array('name' => 'ypm-wheel-sound-url', 'type' => 'text', 'defaultValue' => esc_attr(YPM_POPUP_SOUNDS_URL."tick.mp3")); 642 642 $options[] = array('name' => 'ypm-wheel-button-title', 'type' => 'text', 'defaultValue' => 'Spin'); 643 $options[] = array('name' => 'ypm-wheel-button-color', 'type' => 'text', 'defaultValue' => '#ffffff'); 644 $options[] = array('name' => 'ypm-wheel-button-bg-color', 'type' => 'text', 'defaultValue' => '#cd2653'); 645 $options[] = array('name' => 'ypm-wheel-arrow-size', 'type' => 'text', 'defaultValue' => '1'); 643 646 644 647 $YpmDefaults = apply_filters('ypmDefaultOptions', $options); -
popup-more/trunk/popup-more.php
r3264016 r3265986 3 3 * Plugin Name: Popup More 4 4 * Description: Popup More is the most complete pop up plugin in the WordPress popup plugins. 5 * Version: 2.5. 25 * Version: 2.5.3 6 6 * Author: Felix Moira 7 7 * Author URI:
Note: See TracChangeset
for help on using the changeset viewer.