├── .gitignore ├── .settings └── org.eclipse.core.resources.prefs ├── README ├── bin-debug ├── TextureAtlas.html ├── TextureAtlas.swf ├── history │ ├── history.css │ ├── history.js │ └── historyFrame.html ├── playerProductInstall.swf └── swfobject.js ├── bin-release ├── TextureAtlas.html ├── TextureAtlas.swf ├── history │ ├── history.css │ ├── history.js │ └── historyFrame.html ├── playerProductInstall.swf └── swfobject.js ├── deploy ├── TextureAtlas.html ├── TextureAtlas.swf ├── TextureAtlasGenerator.swf └── swfobject.js ├── html-template ├── history │ ├── history.css │ ├── history.js │ └── historyFrame.html ├── index.template.html ├── playerProductInstall.swf └── swfobject.js ├── src └── com │ └── pixelrevision │ └── textureAtlas │ ├── LUAGenerator.as │ ├── SWFFileLoader.as │ ├── ScrollWindow.as │ ├── Settings.as │ ├── TextureAtlas.as │ ├── TextureAtlasMenu.as │ ├── TextureItem.as │ ├── TextureLayout.as │ └── events │ └── TextureAtlasEvent.as └── swc ├── MinimalComps.swc ├── as3corelib.swc └── fzip.swc /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .project 3 | .actionScriptProperties -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | #Tue Dec 07 14:12:03 PST 2010 2 | eclipse.preferences.version=1 3 | encoding/=utf-8 4 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Texture atlas maker 2 | This tool is used to convert timeline based animation into a spritesheet from an swf. it is very handy for creating texture atlas files that can be used with the sparrow framework 3 | 4 | Steps: 5 | Create a new fla and make sure it is minimum flash 9 using as3. 6 | Start creating movieclips that you want to be written to a sprite sheet. Be sure to avoid using actionscript, and if you have sub clips use graphics as opposed to movieclips so that they get picked up. 7 | Drag all the movieclips you want rendered to the main stage and name them. 8 | Export the swf and load it into the tool. 9 | Modify the size of the sprite sheet to fit your needs. Power of 2 textures are recommended:1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, etc.. 10 | Save the file. You will now have a zip containing your image a piece of xml and a piece of json you can use for your project. 11 | 12 | A demo swf can be downloaded at: 13 | http://pixelrevision.com/8bit/texture_atlas_creator/mario_example.zip -------------------------------------------------------------------------------- /bin-debug/TextureAtlas.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 58 | 59 | 60 | 64 |
65 |

66 | To view this page ensure that Adobe Flash Player version 67 | 10.0.0 or greater is installed. 68 |

69 | 74 |
75 | 76 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /bin-debug/TextureAtlas.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pixelrevision/texture_atlas_generator/bf13b9d3edc9dfcbcf509d914f1036f14037b4d3/bin-debug/TextureAtlas.swf -------------------------------------------------------------------------------- /bin-debug/history/history.css: -------------------------------------------------------------------------------- 1 | /* This CSS stylesheet defines styles used by required elements in a flex application page that supports browser history */ 2 | 3 | #ie_historyFrame { width: 0px; height: 0px; display:none } 4 | #firefox_anchorDiv { width: 0px; height: 0px; display:none } 5 | #safari_formDiv { width: 0px; height: 0px; display:none } 6 | #safari_rememberDiv { width: 0px; height: 0px; display:none } 7 | -------------------------------------------------------------------------------- /bin-debug/history/history.js: -------------------------------------------------------------------------------- 1 | BrowserHistoryUtils = { 2 | addEvent: function(elm, evType, fn, useCapture) { 3 | useCapture = useCapture || false; 4 | if (elm.addEventListener) { 5 | elm.addEventListener(evType, fn, useCapture); 6 | return true; 7 | } 8 | else if (elm.attachEvent) { 9 | var r = elm.attachEvent('on' + evType, fn); 10 | return r; 11 | } 12 | else { 13 | elm['on' + evType] = fn; 14 | } 15 | } 16 | } 17 | 18 | BrowserHistory = (function() { 19 | // type of browser 20 | var browser = { 21 | ie: false, 22 | ie8: false, 23 | firefox: false, 24 | safari: false, 25 | opera: false, 26 | version: -1 27 | }; 28 | 29 | // if setDefaultURL has been called, our first clue 30 | // that the SWF is ready and listening 31 | //var swfReady = false; 32 | 33 | // the URL we'll send to the SWF once it is ready 34 | //var pendingURL = ''; 35 | 36 | // Default app state URL to use when no fragment ID present 37 | var defaultHash = ''; 38 | 39 | // Last-known app state URL 40 | var currentHref = document.location.href; 41 | 42 | // Initial URL (used only by IE) 43 | var initialHref = document.location.href; 44 | 45 | // Initial URL (used only by IE) 46 | var initialHash = document.location.hash; 47 | 48 | // History frame source URL prefix (used only by IE) 49 | var historyFrameSourcePrefix = 'history/historyFrame.html?'; 50 | 51 | // History maintenance (used only by Safari) 52 | var currentHistoryLength = -1; 53 | 54 | var historyHash = []; 55 | 56 | var initialState = createState(initialHref, initialHref + '#' + initialHash, initialHash); 57 | 58 | var backStack = []; 59 | var forwardStack = []; 60 | 61 | var currentObjectId = null; 62 | 63 | //UserAgent detection 64 | var useragent = navigator.userAgent.toLowerCase(); 65 | 66 | if (useragent.indexOf("opera") != -1) { 67 | browser.opera = true; 68 | } else if (useragent.indexOf("msie") != -1) { 69 | browser.ie = true; 70 | browser.version = parseFloat(useragent.substring(useragent.indexOf('msie') + 4)); 71 | if (browser.version == 8) 72 | { 73 | browser.ie = false; 74 | browser.ie8 = true; 75 | } 76 | } else if (useragent.indexOf("safari") != -1) { 77 | browser.safari = true; 78 | browser.version = parseFloat(useragent.substring(useragent.indexOf('safari') + 7)); 79 | } else if (useragent.indexOf("gecko") != -1) { 80 | browser.firefox = true; 81 | } 82 | 83 | if (browser.ie == true && browser.version == 7) { 84 | window["_ie_firstload"] = false; 85 | } 86 | 87 | function hashChangeHandler() 88 | { 89 | currentHref = document.location.href; 90 | var flexAppUrl = getHash(); 91 | //ADR: to fix multiple 92 | if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) { 93 | var pl = getPlayers(); 94 | for (var i = 0; i < pl.length; i++) { 95 | pl[i].browserURLChange(flexAppUrl); 96 | } 97 | } else { 98 | getPlayer().browserURLChange(flexAppUrl); 99 | } 100 | } 101 | 102 | // Accessor functions for obtaining specific elements of the page. 103 | function getHistoryFrame() 104 | { 105 | return document.getElementById('ie_historyFrame'); 106 | } 107 | 108 | function getAnchorElement() 109 | { 110 | return document.getElementById('firefox_anchorDiv'); 111 | } 112 | 113 | function getFormElement() 114 | { 115 | return document.getElementById('safari_formDiv'); 116 | } 117 | 118 | function getRememberElement() 119 | { 120 | return document.getElementById("safari_remember_field"); 121 | } 122 | 123 | // Get the Flash player object for performing ExternalInterface callbacks. 124 | // Updated for changes to SWFObject2. 125 | function getPlayer(id) { 126 | var i; 127 | 128 | if (id && document.getElementById(id)) { 129 | var r = document.getElementById(id); 130 | if (typeof r.SetVariable != "undefined") { 131 | return r; 132 | } 133 | else { 134 | var o = r.getElementsByTagName("object"); 135 | var e = r.getElementsByTagName("embed"); 136 | for (i = 0; i < o.length; i++) { 137 | if (typeof o[i].browserURLChange != "undefined") 138 | return o[i]; 139 | } 140 | for (i = 0; i < e.length; i++) { 141 | if (typeof e[i].browserURLChange != "undefined") 142 | return e[i]; 143 | } 144 | } 145 | } 146 | else { 147 | var o = document.getElementsByTagName("object"); 148 | var e = document.getElementsByTagName("embed"); 149 | for (i = 0; i < e.length; i++) { 150 | if (typeof e[i].browserURLChange != "undefined") 151 | { 152 | return e[i]; 153 | } 154 | } 155 | for (i = 0; i < o.length; i++) { 156 | if (typeof o[i].browserURLChange != "undefined") 157 | { 158 | return o[i]; 159 | } 160 | } 161 | } 162 | return undefined; 163 | } 164 | 165 | function getPlayers() { 166 | var i; 167 | var players = []; 168 | if (players.length == 0) { 169 | var tmp = document.getElementsByTagName('object'); 170 | for (i = 0; i < tmp.length; i++) 171 | { 172 | if (typeof tmp[i].browserURLChange != "undefined") 173 | players.push(tmp[i]); 174 | } 175 | } 176 | if (players.length == 0 || players[0].object == null) { 177 | var tmp = document.getElementsByTagName('embed'); 178 | for (i = 0; i < tmp.length; i++) 179 | { 180 | if (typeof tmp[i].browserURLChange != "undefined") 181 | players.push(tmp[i]); 182 | } 183 | } 184 | return players; 185 | } 186 | 187 | function getIframeHash() { 188 | var doc = getHistoryFrame().contentWindow.document; 189 | var hash = String(doc.location.search); 190 | if (hash.length == 1 && hash.charAt(0) == "?") { 191 | hash = ""; 192 | } 193 | else if (hash.length >= 2 && hash.charAt(0) == "?") { 194 | hash = hash.substring(1); 195 | } 196 | return hash; 197 | } 198 | 199 | /* Get the current location hash excluding the '#' symbol. */ 200 | function getHash() { 201 | // It would be nice if we could use document.location.hash here, 202 | // but it's faulty sometimes. 203 | var idx = document.location.href.indexOf('#'); 204 | return (idx >= 0) ? document.location.href.substr(idx+1) : ''; 205 | } 206 | 207 | /* Get the current location hash excluding the '#' symbol. */ 208 | function setHash(hash) { 209 | // It would be nice if we could use document.location.hash here, 210 | // but it's faulty sometimes. 211 | if (hash == '') hash = '#' 212 | document.location.hash = hash; 213 | } 214 | 215 | function createState(baseUrl, newUrl, flexAppUrl) { 216 | return { 'baseUrl': baseUrl, 'newUrl': newUrl, 'flexAppUrl': flexAppUrl, 'title': null }; 217 | } 218 | 219 | /* Add a history entry to the browser. 220 | * baseUrl: the portion of the location prior to the '#' 221 | * newUrl: the entire new URL, including '#' and following fragment 222 | * flexAppUrl: the portion of the location following the '#' only 223 | */ 224 | function addHistoryEntry(baseUrl, newUrl, flexAppUrl) { 225 | 226 | //delete all the history entries 227 | forwardStack = []; 228 | 229 | if (browser.ie) { 230 | //Check to see if we are being asked to do a navigate for the first 231 | //history entry, and if so ignore, because it's coming from the creation 232 | //of the history iframe 233 | if (flexAppUrl == defaultHash && document.location.href == initialHref && window['_ie_firstload']) { 234 | currentHref = initialHref; 235 | return; 236 | } 237 | if ((!flexAppUrl || flexAppUrl == defaultHash) && window['_ie_firstload']) { 238 | newUrl = baseUrl + '#' + defaultHash; 239 | flexAppUrl = defaultHash; 240 | } else { 241 | // for IE, tell the history frame to go somewhere without a '#' 242 | // in order to get this entry into the browser history. 243 | getHistoryFrame().src = historyFrameSourcePrefix + flexAppUrl; 244 | } 245 | setHash(flexAppUrl); 246 | } else { 247 | 248 | //ADR 249 | if (backStack.length == 0 && initialState.flexAppUrl == flexAppUrl) { 250 | initialState = createState(baseUrl, newUrl, flexAppUrl); 251 | } else if(backStack.length > 0 && backStack[backStack.length - 1].flexAppUrl == flexAppUrl) { 252 | backStack[backStack.length - 1] = createState(baseUrl, newUrl, flexAppUrl); 253 | } 254 | 255 | if (browser.safari) { 256 | // for Safari, submit a form whose action points to the desired URL 257 | if (browser.version <= 419.3) { 258 | var file = window.location.pathname.toString(); 259 | file = file.substring(file.lastIndexOf("/")+1); 260 | getFormElement().innerHTML = '
'; 261 | //get the current elements and add them to the form 262 | var qs = window.location.search.substring(1); 263 | var qs_arr = qs.split("&"); 264 | for (var i = 0; i < qs_arr.length; i++) { 265 | var tmp = qs_arr[i].split("="); 266 | var elem = document.createElement("input"); 267 | elem.type = "hidden"; 268 | elem.name = tmp[0]; 269 | elem.value = tmp[1]; 270 | document.forms.historyForm.appendChild(elem); 271 | } 272 | document.forms.historyForm.submit(); 273 | } else { 274 | top.location.hash = flexAppUrl; 275 | } 276 | // We also have to maintain the history by hand for Safari 277 | historyHash[history.length] = flexAppUrl; 278 | _storeStates(); 279 | } else { 280 | // Otherwise, write an anchor into the page and tell the browser to go there 281 | addAnchor(flexAppUrl); 282 | setHash(flexAppUrl); 283 | 284 | // For IE8 we must restore full focus/activation to our invoking player instance. 285 | if (browser.ie8) 286 | getPlayer().focus(); 287 | } 288 | } 289 | backStack.push(createState(baseUrl, newUrl, flexAppUrl)); 290 | } 291 | 292 | function _storeStates() { 293 | if (browser.safari) { 294 | getRememberElement().value = historyHash.join(","); 295 | } 296 | } 297 | 298 | function handleBackButton() { 299 | //The "current" page is always at the top of the history stack. 300 | var current = backStack.pop(); 301 | if (!current) { return; } 302 | var last = backStack[backStack.length - 1]; 303 | if (!last && backStack.length == 0){ 304 | last = initialState; 305 | } 306 | forwardStack.push(current); 307 | } 308 | 309 | function handleForwardButton() { 310 | //summary: private method. Do not call this directly. 311 | 312 | var last = forwardStack.pop(); 313 | if (!last) { return; } 314 | backStack.push(last); 315 | } 316 | 317 | function handleArbitraryUrl() { 318 | //delete all the history entries 319 | forwardStack = []; 320 | } 321 | 322 | /* Called periodically to poll to see if we need to detect navigation that has occurred */ 323 | function checkForUrlChange() { 324 | 325 | if (browser.ie) { 326 | if (currentHref != document.location.href && currentHref + '#' != document.location.href) { 327 | //This occurs when the user has navigated to a specific URL 328 | //within the app, and didn't use browser back/forward 329 | //IE seems to have a bug where it stops updating the URL it 330 | //shows the end-user at this point, but programatically it 331 | //appears to be correct. Do a full app reload to get around 332 | //this issue. 333 | if (browser.version < 7) { 334 | currentHref = document.location.href; 335 | document.location.reload(); 336 | } else { 337 | if (getHash() != getIframeHash()) { 338 | // this.iframe.src = this.blankURL + hash; 339 | var sourceToSet = historyFrameSourcePrefix + getHash(); 340 | getHistoryFrame().src = sourceToSet; 341 | currentHref = document.location.href; 342 | } 343 | } 344 | } 345 | } 346 | 347 | if (browser.safari) { 348 | // For Safari, we have to check to see if history.length changed. 349 | if (currentHistoryLength >= 0 && history.length != currentHistoryLength) { 350 | //alert("did change: " + history.length + ", " + historyHash.length + "|" + historyHash[history.length] + "|>" + historyHash.join("|")); 351 | var flexAppUrl = getHash(); 352 | if (browser.version < 528.16 /* Anything earlier than Safari 4.0 */) 353 | { 354 | // If it did change and we're running Safari 3.x or earlier, 355 | // then we have to look the old state up in our hand-maintained 356 | // array since document.location.hash won't have changed, 357 | // then call back into BrowserManager. 358 | currentHistoryLength = history.length; 359 | flexAppUrl = historyHash[currentHistoryLength]; 360 | } 361 | 362 | //ADR: to fix multiple 363 | if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) { 364 | var pl = getPlayers(); 365 | for (var i = 0; i < pl.length; i++) { 366 | pl[i].browserURLChange(flexAppUrl); 367 | } 368 | } else { 369 | getPlayer().browserURLChange(flexAppUrl); 370 | } 371 | _storeStates(); 372 | } 373 | } 374 | if (browser.firefox) { 375 | if (currentHref != document.location.href) { 376 | var bsl = backStack.length; 377 | 378 | var urlActions = { 379 | back: false, 380 | forward: false, 381 | set: false 382 | } 383 | 384 | if ((window.location.hash == initialHash || window.location.href == initialHref) && (bsl == 1)) { 385 | urlActions.back = true; 386 | // FIXME: could this ever be a forward button? 387 | // we can't clear it because we still need to check for forwards. Ugg. 388 | // clearInterval(this.locationTimer); 389 | handleBackButton(); 390 | } 391 | 392 | // first check to see if we could have gone forward. We always halt on 393 | // a no-hash item. 394 | if (forwardStack.length > 0) { 395 | if (forwardStack[forwardStack.length-1].flexAppUrl == getHash()) { 396 | urlActions.forward = true; 397 | handleForwardButton(); 398 | } 399 | } 400 | 401 | // ok, that didn't work, try someplace back in the history stack 402 | if ((bsl >= 2) && (backStack[bsl - 2])) { 403 | if (backStack[bsl - 2].flexAppUrl == getHash()) { 404 | urlActions.back = true; 405 | handleBackButton(); 406 | } 407 | } 408 | 409 | if (!urlActions.back && !urlActions.forward) { 410 | var foundInStacks = { 411 | back: -1, 412 | forward: -1 413 | } 414 | 415 | for (var i = 0; i < backStack.length; i++) { 416 | if (backStack[i].flexAppUrl == getHash() && i != (bsl - 2)) { 417 | arbitraryUrl = true; 418 | foundInStacks.back = i; 419 | } 420 | } 421 | for (var i = 0; i < forwardStack.length; i++) { 422 | if (forwardStack[i].flexAppUrl == getHash() && i != (bsl - 2)) { 423 | arbitraryUrl = true; 424 | foundInStacks.forward = i; 425 | } 426 | } 427 | handleArbitraryUrl(); 428 | } 429 | 430 | // Firefox changed; do a callback into BrowserManager to tell it. 431 | currentHref = document.location.href; 432 | var flexAppUrl = getHash(); 433 | //ADR: to fix multiple 434 | if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) { 435 | var pl = getPlayers(); 436 | for (var i = 0; i < pl.length; i++) { 437 | pl[i].browserURLChange(flexAppUrl); 438 | } 439 | } else { 440 | getPlayer().browserURLChange(flexAppUrl); 441 | } 442 | } 443 | } 444 | //setTimeout(checkForUrlChange, 50); 445 | } 446 | 447 | /* Write an anchor into the page to legitimize it as a URL for Firefox et al. */ 448 | function addAnchor(flexAppUrl) 449 | { 450 | if (document.getElementsByName(flexAppUrl).length == 0) { 451 | getAnchorElement().innerHTML += "" + flexAppUrl + ""; 452 | } 453 | } 454 | 455 | var _initialize = function () { 456 | if (browser.ie) 457 | { 458 | var scripts = document.getElementsByTagName('script'); 459 | for (var i = 0, s; s = scripts[i]; i++) { 460 | if (s.src.indexOf("history.js") > -1) { 461 | var iframe_location = (new String(s.src)).replace("history.js", "historyFrame.html"); 462 | } 463 | } 464 | historyFrameSourcePrefix = iframe_location + "?"; 465 | var src = historyFrameSourcePrefix; 466 | 467 | var iframe = document.createElement("iframe"); 468 | iframe.id = 'ie_historyFrame'; 469 | iframe.name = 'ie_historyFrame'; 470 | iframe.src = 'javascript:false;'; 471 | 472 | try { 473 | document.body.appendChild(iframe); 474 | } catch(e) { 475 | setTimeout(function() { 476 | document.body.appendChild(iframe); 477 | }, 0); 478 | } 479 | } 480 | 481 | if (browser.safari) 482 | { 483 | var rememberDiv = document.createElement("div"); 484 | rememberDiv.id = 'safari_rememberDiv'; 485 | document.body.appendChild(rememberDiv); 486 | rememberDiv.innerHTML = ''; 487 | 488 | var formDiv = document.createElement("div"); 489 | formDiv.id = 'safari_formDiv'; 490 | document.body.appendChild(formDiv); 491 | 492 | var reloader_content = document.createElement('div'); 493 | reloader_content.id = 'safarireloader'; 494 | var scripts = document.getElementsByTagName('script'); 495 | for (var i = 0, s; s = scripts[i]; i++) { 496 | if (s.src.indexOf("history.js") > -1) { 497 | html = (new String(s.src)).replace(".js", ".html"); 498 | } 499 | } 500 | reloader_content.innerHTML = ''; 501 | document.body.appendChild(reloader_content); 502 | reloader_content.style.position = 'absolute'; 503 | reloader_content.style.left = reloader_content.style.top = '-9999px'; 504 | iframe = reloader_content.getElementsByTagName('iframe')[0]; 505 | 506 | if (document.getElementById("safari_remember_field").value != "" ) { 507 | historyHash = document.getElementById("safari_remember_field").value.split(","); 508 | } 509 | 510 | } 511 | 512 | if (browser.firefox || browser.ie8) 513 | { 514 | var anchorDiv = document.createElement("div"); 515 | anchorDiv.id = 'firefox_anchorDiv'; 516 | document.body.appendChild(anchorDiv); 517 | } 518 | 519 | if (browser.ie8) 520 | document.body.onhashchange = hashChangeHandler; 521 | //setTimeout(checkForUrlChange, 50); 522 | } 523 | 524 | return { 525 | historyHash: historyHash, 526 | backStack: function() { return backStack; }, 527 | forwardStack: function() { return forwardStack }, 528 | getPlayer: getPlayer, 529 | initialize: function(src) { 530 | _initialize(src); 531 | }, 532 | setURL: function(url) { 533 | document.location.href = url; 534 | }, 535 | getURL: function() { 536 | return document.location.href; 537 | }, 538 | getTitle: function() { 539 | return document.title; 540 | }, 541 | setTitle: function(title) { 542 | try { 543 | backStack[backStack.length - 1].title = title; 544 | } catch(e) { } 545 | //if on safari, set the title to be the empty string. 546 | if (browser.safari) { 547 | if (title == "") { 548 | try { 549 | var tmp = window.location.href.toString(); 550 | title = tmp.substring((tmp.lastIndexOf("/")+1), tmp.lastIndexOf("#")); 551 | } catch(e) { 552 | title = ""; 553 | } 554 | } 555 | } 556 | document.title = title; 557 | }, 558 | setDefaultURL: function(def) 559 | { 560 | defaultHash = def; 561 | def = getHash(); 562 | //trailing ? is important else an extra frame gets added to the history 563 | //when navigating back to the first page. Alternatively could check 564 | //in history frame navigation to compare # and ?. 565 | if (browser.ie) 566 | { 567 | window['_ie_firstload'] = true; 568 | var sourceToSet = historyFrameSourcePrefix + def; 569 | var func = function() { 570 | getHistoryFrame().src = sourceToSet; 571 | window.location.replace("#" + def); 572 | setInterval(checkForUrlChange, 50); 573 | } 574 | try { 575 | func(); 576 | } catch(e) { 577 | window.setTimeout(function() { func(); }, 0); 578 | } 579 | } 580 | 581 | if (browser.safari) 582 | { 583 | currentHistoryLength = history.length; 584 | if (historyHash.length == 0) { 585 | historyHash[currentHistoryLength] = def; 586 | var newloc = "#" + def; 587 | window.location.replace(newloc); 588 | } else { 589 | //alert(historyHash[historyHash.length-1]); 590 | } 591 | //setHash(def); 592 | setInterval(checkForUrlChange, 50); 593 | } 594 | 595 | 596 | if (browser.firefox || browser.opera) 597 | { 598 | var reg = new RegExp("#" + def + "$"); 599 | if (window.location.toString().match(reg)) { 600 | } else { 601 | var newloc ="#" + def; 602 | window.location.replace(newloc); 603 | } 604 | setInterval(checkForUrlChange, 50); 605 | //setHash(def); 606 | } 607 | 608 | }, 609 | 610 | /* Set the current browser URL; called from inside BrowserManager to propagate 611 | * the application state out to the container. 612 | */ 613 | setBrowserURL: function(flexAppUrl, objectId) { 614 | if (browser.ie && typeof objectId != "undefined") { 615 | currentObjectId = objectId; 616 | } 617 | //fromIframe = fromIframe || false; 618 | //fromFlex = fromFlex || false; 619 | //alert("setBrowserURL: " + flexAppUrl); 620 | //flexAppUrl = (flexAppUrl == "") ? defaultHash : flexAppUrl ; 621 | 622 | var pos = document.location.href.indexOf('#'); 623 | var baseUrl = pos != -1 ? document.location.href.substr(0, pos) : document.location.href; 624 | var newUrl = baseUrl + '#' + flexAppUrl; 625 | 626 | if (document.location.href != newUrl && document.location.href + '#' != newUrl) { 627 | currentHref = newUrl; 628 | addHistoryEntry(baseUrl, newUrl, flexAppUrl); 629 | currentHistoryLength = history.length; 630 | } 631 | }, 632 | 633 | browserURLChange: function(flexAppUrl) { 634 | var objectId = null; 635 | if (browser.ie && currentObjectId != null) { 636 | objectId = currentObjectId; 637 | } 638 | pendingURL = ''; 639 | 640 | if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) { 641 | var pl = getPlayers(); 642 | for (var i = 0; i < pl.length; i++) { 643 | try { 644 | pl[i].browserURLChange(flexAppUrl); 645 | } catch(e) { } 646 | } 647 | } else { 648 | try { 649 | getPlayer(objectId).browserURLChange(flexAppUrl); 650 | } catch(e) { } 651 | } 652 | 653 | currentObjectId = null; 654 | }, 655 | getUserAgent: function() { 656 | return navigator.userAgent; 657 | }, 658 | getPlatform: function() { 659 | return navigator.platform; 660 | } 661 | 662 | } 663 | 664 | })(); 665 | 666 | // Initialization 667 | 668 | // Automated unit testing and other diagnostics 669 | 670 | function setURL(url) 671 | { 672 | document.location.href = url; 673 | } 674 | 675 | function backButton() 676 | { 677 | history.back(); 678 | } 679 | 680 | function forwardButton() 681 | { 682 | history.forward(); 683 | } 684 | 685 | function goForwardOrBackInHistory(step) 686 | { 687 | history.go(step); 688 | } 689 | 690 | //BrowserHistoryUtils.addEvent(window, "load", function() { BrowserHistory.initialize(); }); 691 | (function(i) { 692 | var u =navigator.userAgent;var e=/*@cc_on!@*/false; 693 | var st = setTimeout; 694 | if(/webkit/i.test(u)){ 695 | st(function(){ 696 | var dr=document.readyState; 697 | if(dr=="loaded"||dr=="complete"){i()} 698 | else{st(arguments.callee,10);}},10); 699 | } else if((/mozilla/i.test(u)&&!/(compati)/.test(u)) || (/opera/i.test(u))){ 700 | document.addEventListener("DOMContentLoaded",i,false); 701 | } else if(e){ 702 | (function(){ 703 | var t=document.createElement('doc:rdy'); 704 | try{t.doScroll('left'); 705 | i();t=null; 706 | }catch(e){st(arguments.callee,0);}})(); 707 | } else{ 708 | window.onload=i; 709 | } 710 | })( function() {BrowserHistory.initialize();} ); 711 | -------------------------------------------------------------------------------- /bin-debug/history/historyFrame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 27 | Hidden frame for Browser History support. 28 | 29 | 30 | -------------------------------------------------------------------------------- /bin-debug/playerProductInstall.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pixelrevision/texture_atlas_generator/bf13b9d3edc9dfcbcf509d914f1036f14037b4d3/bin-debug/playerProductInstall.swf -------------------------------------------------------------------------------- /bin-debug/swfobject.js: -------------------------------------------------------------------------------- 1 | /*! SWFObject v2.2 2 | is released under the MIT License 3 | */ 4 | 5 | var swfobject = function() { 6 | 7 | var UNDEF = "undefined", 8 | OBJECT = "object", 9 | SHOCKWAVE_FLASH = "Shockwave Flash", 10 | SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash", 11 | FLASH_MIME_TYPE = "application/x-shockwave-flash", 12 | EXPRESS_INSTALL_ID = "SWFObjectExprInst", 13 | ON_READY_STATE_CHANGE = "onreadystatechange", 14 | 15 | win = window, 16 | doc = document, 17 | nav = navigator, 18 | 19 | plugin = false, 20 | domLoadFnArr = [main], 21 | regObjArr = [], 22 | objIdArr = [], 23 | listenersArr = [], 24 | storedAltContent, 25 | storedAltContentId, 26 | storedCallbackFn, 27 | storedCallbackObj, 28 | isDomLoaded = false, 29 | isExpressInstallActive = false, 30 | dynamicStylesheet, 31 | dynamicStylesheetMedia, 32 | autoHideShow = true, 33 | 34 | /* Centralized function for browser feature detection 35 | - User agent string detection is only used when no good alternative is possible 36 | - Is executed directly for optimal performance 37 | */ 38 | ua = function() { 39 | var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF, 40 | u = nav.userAgent.toLowerCase(), 41 | p = nav.platform.toLowerCase(), 42 | windows = p ? /win/.test(p) : /win/.test(u), 43 | mac = p ? /mac/.test(p) : /mac/.test(u), 44 | webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, // returns either the webkit version or false if not webkit 45 | ie = !+"\v1", // feature detection based on Andrea Giammarchi's solution: http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html 46 | playerVersion = [0,0,0], 47 | d = null; 48 | if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) { 49 | d = nav.plugins[SHOCKWAVE_FLASH].description; 50 | if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { // navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin indicates whether plug-ins are enabled or disabled in Safari 3+ 51 | plugin = true; 52 | ie = false; // cascaded feature detection for Internet Explorer 53 | d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1"); 54 | playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10); 55 | playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10); 56 | playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0; 57 | } 58 | } 59 | else if (typeof win.ActiveXObject != UNDEF) { 60 | try { 61 | var a = new ActiveXObject(SHOCKWAVE_FLASH_AX); 62 | if (a) { // a will return null when ActiveX is disabled 63 | d = a.GetVariable("$version"); 64 | if (d) { 65 | ie = true; // cascaded feature detection for Internet Explorer 66 | d = d.split(" ")[1].split(","); 67 | playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)]; 68 | } 69 | } 70 | } 71 | catch(e) {} 72 | } 73 | return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac }; 74 | }(), 75 | 76 | /* Cross-browser onDomLoad 77 | - Will fire an event as soon as the DOM of a web page is loaded 78 | - Internet Explorer workaround based on Diego Perini's solution: http://javascript.nwbox.com/IEContentLoaded/ 79 | - Regular onload serves as fallback 80 | */ 81 | onDomLoad = function() { 82 | if (!ua.w3) { return; } 83 | if ((typeof doc.readyState != UNDEF && doc.readyState == "complete") || (typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) { // function is fired after onload, e.g. when script is inserted dynamically 84 | callDomLoadFunctions(); 85 | } 86 | if (!isDomLoaded) { 87 | if (typeof doc.addEventListener != UNDEF) { 88 | doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false); 89 | } 90 | if (ua.ie && ua.win) { 91 | doc.attachEvent(ON_READY_STATE_CHANGE, function() { 92 | if (doc.readyState == "complete") { 93 | doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee); 94 | callDomLoadFunctions(); 95 | } 96 | }); 97 | if (win == top) { // if not inside an iframe 98 | (function(){ 99 | if (isDomLoaded) { return; } 100 | try { 101 | doc.documentElement.doScroll("left"); 102 | } 103 | catch(e) { 104 | setTimeout(arguments.callee, 0); 105 | return; 106 | } 107 | callDomLoadFunctions(); 108 | })(); 109 | } 110 | } 111 | if (ua.wk) { 112 | (function(){ 113 | if (isDomLoaded) { return; } 114 | if (!/loaded|complete/.test(doc.readyState)) { 115 | setTimeout(arguments.callee, 0); 116 | return; 117 | } 118 | callDomLoadFunctions(); 119 | })(); 120 | } 121 | addLoadEvent(callDomLoadFunctions); 122 | } 123 | }(); 124 | 125 | function callDomLoadFunctions() { 126 | if (isDomLoaded) { return; } 127 | try { // test if we can really add/remove elements to/from the DOM; we don't want to fire it too early 128 | var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span")); 129 | t.parentNode.removeChild(t); 130 | } 131 | catch (e) { return; } 132 | isDomLoaded = true; 133 | var dl = domLoadFnArr.length; 134 | for (var i = 0; i < dl; i++) { 135 | domLoadFnArr[i](); 136 | } 137 | } 138 | 139 | function addDomLoadEvent(fn) { 140 | if (isDomLoaded) { 141 | fn(); 142 | } 143 | else { 144 | domLoadFnArr[domLoadFnArr.length] = fn; // Array.push() is only available in IE5.5+ 145 | } 146 | } 147 | 148 | /* Cross-browser onload 149 | - Based on James Edwards' solution: http://brothercake.com/site/resources/scripts/onload/ 150 | - Will fire an event as soon as a web page including all of its assets are loaded 151 | */ 152 | function addLoadEvent(fn) { 153 | if (typeof win.addEventListener != UNDEF) { 154 | win.addEventListener("load", fn, false); 155 | } 156 | else if (typeof doc.addEventListener != UNDEF) { 157 | doc.addEventListener("load", fn, false); 158 | } 159 | else if (typeof win.attachEvent != UNDEF) { 160 | addListener(win, "onload", fn); 161 | } 162 | else if (typeof win.onload == "function") { 163 | var fnOld = win.onload; 164 | win.onload = function() { 165 | fnOld(); 166 | fn(); 167 | }; 168 | } 169 | else { 170 | win.onload = fn; 171 | } 172 | } 173 | 174 | /* Main function 175 | - Will preferably execute onDomLoad, otherwise onload (as a fallback) 176 | */ 177 | function main() { 178 | if (plugin) { 179 | testPlayerVersion(); 180 | } 181 | else { 182 | matchVersions(); 183 | } 184 | } 185 | 186 | /* Detect the Flash Player version for non-Internet Explorer browsers 187 | - Detecting the plug-in version via the object element is more precise than using the plugins collection item's description: 188 | a. Both release and build numbers can be detected 189 | b. Avoid wrong descriptions by corrupt installers provided by Adobe 190 | c. Avoid wrong descriptions by multiple Flash Player entries in the plugin Array, caused by incorrect browser imports 191 | - Disadvantage of this method is that it depends on the availability of the DOM, while the plugins collection is immediately available 192 | */ 193 | function testPlayerVersion() { 194 | var b = doc.getElementsByTagName("body")[0]; 195 | var o = createElement(OBJECT); 196 | o.setAttribute("type", FLASH_MIME_TYPE); 197 | var t = b.appendChild(o); 198 | if (t) { 199 | var counter = 0; 200 | (function(){ 201 | if (typeof t.GetVariable != UNDEF) { 202 | var d = t.GetVariable("$version"); 203 | if (d) { 204 | d = d.split(" ")[1].split(","); 205 | ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)]; 206 | } 207 | } 208 | else if (counter < 10) { 209 | counter++; 210 | setTimeout(arguments.callee, 10); 211 | return; 212 | } 213 | b.removeChild(o); 214 | t = null; 215 | matchVersions(); 216 | })(); 217 | } 218 | else { 219 | matchVersions(); 220 | } 221 | } 222 | 223 | /* Perform Flash Player and SWF version matching; static publishing only 224 | */ 225 | function matchVersions() { 226 | var rl = regObjArr.length; 227 | if (rl > 0) { 228 | for (var i = 0; i < rl; i++) { // for each registered object element 229 | var id = regObjArr[i].id; 230 | var cb = regObjArr[i].callbackFn; 231 | var cbObj = {success:false, id:id}; 232 | if (ua.pv[0] > 0) { 233 | var obj = getElementById(id); 234 | if (obj) { 235 | if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { // Flash Player version >= published SWF version: Houston, we have a match! 236 | setVisibility(id, true); 237 | if (cb) { 238 | cbObj.success = true; 239 | cbObj.ref = getObjectById(id); 240 | cb(cbObj); 241 | } 242 | } 243 | else if (regObjArr[i].expressInstall && canExpressInstall()) { // show the Adobe Express Install dialog if set by the web page author and if supported 244 | var att = {}; 245 | att.data = regObjArr[i].expressInstall; 246 | att.width = obj.getAttribute("width") || "0"; 247 | att.height = obj.getAttribute("height") || "0"; 248 | if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); } 249 | if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); } 250 | // parse HTML object param element's name-value pairs 251 | var par = {}; 252 | var p = obj.getElementsByTagName("param"); 253 | var pl = p.length; 254 | for (var j = 0; j < pl; j++) { 255 | if (p[j].getAttribute("name").toLowerCase() != "movie") { 256 | par[p[j].getAttribute("name")] = p[j].getAttribute("value"); 257 | } 258 | } 259 | showExpressInstall(att, par, id, cb); 260 | } 261 | else { // Flash Player and SWF version mismatch or an older Webkit engine that ignores the HTML object element's nested param elements: display alternative content instead of SWF 262 | displayAltContent(obj); 263 | if (cb) { cb(cbObj); } 264 | } 265 | } 266 | } 267 | else { // if no Flash Player is installed or the fp version cannot be detected we let the HTML object element do its job (either show a SWF or alternative content) 268 | setVisibility(id, true); 269 | if (cb) { 270 | var o = getObjectById(id); // test whether there is an HTML object element or not 271 | if (o && typeof o.SetVariable != UNDEF) { 272 | cbObj.success = true; 273 | cbObj.ref = o; 274 | } 275 | cb(cbObj); 276 | } 277 | } 278 | } 279 | } 280 | } 281 | 282 | function getObjectById(objectIdStr) { 283 | var r = null; 284 | var o = getElementById(objectIdStr); 285 | if (o && o.nodeName == "OBJECT") { 286 | if (typeof o.SetVariable != UNDEF) { 287 | r = o; 288 | } 289 | else { 290 | var n = o.getElementsByTagName(OBJECT)[0]; 291 | if (n) { 292 | r = n; 293 | } 294 | } 295 | } 296 | return r; 297 | } 298 | 299 | /* Requirements for Adobe Express Install 300 | - only one instance can be active at a time 301 | - fp 6.0.65 or higher 302 | - Win/Mac OS only 303 | - no Webkit engines older than version 312 304 | */ 305 | function canExpressInstall() { 306 | return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312); 307 | } 308 | 309 | /* Show the Adobe Express Install dialog 310 | - Reference: http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=6a253b75 311 | */ 312 | function showExpressInstall(att, par, replaceElemIdStr, callbackFn) { 313 | isExpressInstallActive = true; 314 | storedCallbackFn = callbackFn || null; 315 | storedCallbackObj = {success:false, id:replaceElemIdStr}; 316 | var obj = getElementById(replaceElemIdStr); 317 | if (obj) { 318 | if (obj.nodeName == "OBJECT") { // static publishing 319 | storedAltContent = abstractAltContent(obj); 320 | storedAltContentId = null; 321 | } 322 | else { // dynamic publishing 323 | storedAltContent = obj; 324 | storedAltContentId = replaceElemIdStr; 325 | } 326 | att.id = EXPRESS_INSTALL_ID; 327 | if (typeof att.width == UNDEF || (!/%$/.test(att.width) && parseInt(att.width, 10) < 310)) { att.width = "310"; } 328 | if (typeof att.height == UNDEF || (!/%$/.test(att.height) && parseInt(att.height, 10) < 137)) { att.height = "137"; } 329 | doc.title = doc.title.slice(0, 47) + " - Flash Player Installation"; 330 | var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn", 331 | fv = "MMredirectURL=" + encodeURI(window.location).toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title; 332 | if (typeof par.flashvars != UNDEF) { 333 | par.flashvars += "&" + fv; 334 | } 335 | else { 336 | par.flashvars = fv; 337 | } 338 | // IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it, 339 | // because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work 340 | if (ua.ie && ua.win && obj.readyState != 4) { 341 | var newObj = createElement("div"); 342 | replaceElemIdStr += "SWFObjectNew"; 343 | newObj.setAttribute("id", replaceElemIdStr); 344 | obj.parentNode.insertBefore(newObj, obj); // insert placeholder div that will be replaced by the object element that loads expressinstall.swf 345 | obj.style.display = "none"; 346 | (function(){ 347 | if (obj.readyState == 4) { 348 | obj.parentNode.removeChild(obj); 349 | } 350 | else { 351 | setTimeout(arguments.callee, 10); 352 | } 353 | })(); 354 | } 355 | createSWF(att, par, replaceElemIdStr); 356 | } 357 | } 358 | 359 | /* Functions to abstract and display alternative content 360 | */ 361 | function displayAltContent(obj) { 362 | if (ua.ie && ua.win && obj.readyState != 4) { 363 | // IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it, 364 | // because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work 365 | var el = createElement("div"); 366 | obj.parentNode.insertBefore(el, obj); // insert placeholder div that will be replaced by the alternative content 367 | el.parentNode.replaceChild(abstractAltContent(obj), el); 368 | obj.style.display = "none"; 369 | (function(){ 370 | if (obj.readyState == 4) { 371 | obj.parentNode.removeChild(obj); 372 | } 373 | else { 374 | setTimeout(arguments.callee, 10); 375 | } 376 | })(); 377 | } 378 | else { 379 | obj.parentNode.replaceChild(abstractAltContent(obj), obj); 380 | } 381 | } 382 | 383 | function abstractAltContent(obj) { 384 | var ac = createElement("div"); 385 | if (ua.win && ua.ie) { 386 | ac.innerHTML = obj.innerHTML; 387 | } 388 | else { 389 | var nestedObj = obj.getElementsByTagName(OBJECT)[0]; 390 | if (nestedObj) { 391 | var c = nestedObj.childNodes; 392 | if (c) { 393 | var cl = c.length; 394 | for (var i = 0; i < cl; i++) { 395 | if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) { 396 | ac.appendChild(c[i].cloneNode(true)); 397 | } 398 | } 399 | } 400 | } 401 | } 402 | return ac; 403 | } 404 | 405 | /* Cross-browser dynamic SWF creation 406 | */ 407 | function createSWF(attObj, parObj, id) { 408 | var r, el = getElementById(id); 409 | if (ua.wk && ua.wk < 312) { return r; } 410 | if (el) { 411 | if (typeof attObj.id == UNDEF) { // if no 'id' is defined for the object element, it will inherit the 'id' from the alternative content 412 | attObj.id = id; 413 | } 414 | if (ua.ie && ua.win) { // Internet Explorer + the HTML object element + W3C DOM methods do not combine: fall back to outerHTML 415 | var att = ""; 416 | for (var i in attObj) { 417 | if (attObj[i] != Object.prototype[i]) { // filter out prototype additions from other potential libraries 418 | if (i.toLowerCase() == "data") { 419 | parObj.movie = attObj[i]; 420 | } 421 | else if (i.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword 422 | att += ' class="' + attObj[i] + '"'; 423 | } 424 | else if (i.toLowerCase() != "classid") { 425 | att += ' ' + i + '="' + attObj[i] + '"'; 426 | } 427 | } 428 | } 429 | var par = ""; 430 | for (var j in parObj) { 431 | if (parObj[j] != Object.prototype[j]) { // filter out prototype additions from other potential libraries 432 | par += ''; 433 | } 434 | } 435 | el.outerHTML = '' + par + ''; 436 | objIdArr[objIdArr.length] = attObj.id; // stored to fix object 'leaks' on unload (dynamic publishing only) 437 | r = getElementById(attObj.id); 438 | } 439 | else { // well-behaving browsers 440 | var o = createElement(OBJECT); 441 | o.setAttribute("type", FLASH_MIME_TYPE); 442 | for (var m in attObj) { 443 | if (attObj[m] != Object.prototype[m]) { // filter out prototype additions from other potential libraries 444 | if (m.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword 445 | o.setAttribute("class", attObj[m]); 446 | } 447 | else if (m.toLowerCase() != "classid") { // filter out IE specific attribute 448 | o.setAttribute(m, attObj[m]); 449 | } 450 | } 451 | } 452 | for (var n in parObj) { 453 | if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { // filter out prototype additions from other potential libraries and IE specific param element 454 | createObjParam(o, n, parObj[n]); 455 | } 456 | } 457 | el.parentNode.replaceChild(o, el); 458 | r = o; 459 | } 460 | } 461 | return r; 462 | } 463 | 464 | function createObjParam(el, pName, pValue) { 465 | var p = createElement("param"); 466 | p.setAttribute("name", pName); 467 | p.setAttribute("value", pValue); 468 | el.appendChild(p); 469 | } 470 | 471 | /* Cross-browser SWF removal 472 | - Especially needed to safely and completely remove a SWF in Internet Explorer 473 | */ 474 | function removeSWF(id) { 475 | var obj = getElementById(id); 476 | if (obj && obj.nodeName == "OBJECT") { 477 | if (ua.ie && ua.win) { 478 | obj.style.display = "none"; 479 | (function(){ 480 | if (obj.readyState == 4) { 481 | removeObjectInIE(id); 482 | } 483 | else { 484 | setTimeout(arguments.callee, 10); 485 | } 486 | })(); 487 | } 488 | else { 489 | obj.parentNode.removeChild(obj); 490 | } 491 | } 492 | } 493 | 494 | function removeObjectInIE(id) { 495 | var obj = getElementById(id); 496 | if (obj) { 497 | for (var i in obj) { 498 | if (typeof obj[i] == "function") { 499 | obj[i] = null; 500 | } 501 | } 502 | obj.parentNode.removeChild(obj); 503 | } 504 | } 505 | 506 | /* Functions to optimize JavaScript compression 507 | */ 508 | function getElementById(id) { 509 | var el = null; 510 | try { 511 | el = doc.getElementById(id); 512 | } 513 | catch (e) {} 514 | return el; 515 | } 516 | 517 | function createElement(el) { 518 | return doc.createElement(el); 519 | } 520 | 521 | /* Updated attachEvent function for Internet Explorer 522 | - Stores attachEvent information in an Array, so on unload the detachEvent functions can be called to avoid memory leaks 523 | */ 524 | function addListener(target, eventType, fn) { 525 | target.attachEvent(eventType, fn); 526 | listenersArr[listenersArr.length] = [target, eventType, fn]; 527 | } 528 | 529 | /* Flash Player and SWF content version matching 530 | */ 531 | function hasPlayerVersion(rv) { 532 | var pv = ua.pv, v = rv.split("."); 533 | v[0] = parseInt(v[0], 10); 534 | v[1] = parseInt(v[1], 10) || 0; // supports short notation, e.g. "9" instead of "9.0.0" 535 | v[2] = parseInt(v[2], 10) || 0; 536 | return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false; 537 | } 538 | 539 | /* Cross-browser dynamic CSS creation 540 | - Based on Bobby van der Sluis' solution: http://www.bobbyvandersluis.com/articles/dynamicCSS.php 541 | */ 542 | function createCSS(sel, decl, media, newStyle) { 543 | if (ua.ie && ua.mac) { return; } 544 | var h = doc.getElementsByTagName("head")[0]; 545 | if (!h) { return; } // to also support badly authored HTML pages that lack a head element 546 | var m = (media && typeof media == "string") ? media : "screen"; 547 | if (newStyle) { 548 | dynamicStylesheet = null; 549 | dynamicStylesheetMedia = null; 550 | } 551 | if (!dynamicStylesheet || dynamicStylesheetMedia != m) { 552 | // create dynamic stylesheet + get a global reference to it 553 | var s = createElement("style"); 554 | s.setAttribute("type", "text/css"); 555 | s.setAttribute("media", m); 556 | dynamicStylesheet = h.appendChild(s); 557 | if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) { 558 | dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1]; 559 | } 560 | dynamicStylesheetMedia = m; 561 | } 562 | // add style rule 563 | if (ua.ie && ua.win) { 564 | if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) { 565 | dynamicStylesheet.addRule(sel, decl); 566 | } 567 | } 568 | else { 569 | if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) { 570 | dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}")); 571 | } 572 | } 573 | } 574 | 575 | function setVisibility(id, isVisible) { 576 | if (!autoHideShow) { return; } 577 | var v = isVisible ? "visible" : "hidden"; 578 | if (isDomLoaded && getElementById(id)) { 579 | getElementById(id).style.visibility = v; 580 | } 581 | else { 582 | createCSS("#" + id, "visibility:" + v); 583 | } 584 | } 585 | 586 | /* Filter to avoid XSS attacks 587 | */ 588 | function urlEncodeIfNecessary(s) { 589 | var regex = /[\\\"<>\.;]/; 590 | var hasBadChars = regex.exec(s) != null; 591 | return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s; 592 | } 593 | 594 | /* Release memory to avoid memory leaks caused by closures, fix hanging audio/video threads and force open sockets/NetConnections to disconnect (Internet Explorer only) 595 | */ 596 | var cleanup = function() { 597 | if (ua.ie && ua.win) { 598 | window.attachEvent("onunload", function() { 599 | // remove listeners to avoid memory leaks 600 | var ll = listenersArr.length; 601 | for (var i = 0; i < ll; i++) { 602 | listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]); 603 | } 604 | // cleanup dynamically embedded objects to fix audio/video threads and force open sockets and NetConnections to disconnect 605 | var il = objIdArr.length; 606 | for (var j = 0; j < il; j++) { 607 | removeSWF(objIdArr[j]); 608 | } 609 | // cleanup library's main closures to avoid memory leaks 610 | for (var k in ua) { 611 | ua[k] = null; 612 | } 613 | ua = null; 614 | for (var l in swfobject) { 615 | swfobject[l] = null; 616 | } 617 | swfobject = null; 618 | }); 619 | } 620 | }(); 621 | 622 | return { 623 | /* Public API 624 | - Reference: http://code.google.com/p/swfobject/wiki/documentation 625 | */ 626 | registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) { 627 | if (ua.w3 && objectIdStr && swfVersionStr) { 628 | var regObj = {}; 629 | regObj.id = objectIdStr; 630 | regObj.swfVersion = swfVersionStr; 631 | regObj.expressInstall = xiSwfUrlStr; 632 | regObj.callbackFn = callbackFn; 633 | regObjArr[regObjArr.length] = regObj; 634 | setVisibility(objectIdStr, false); 635 | } 636 | else if (callbackFn) { 637 | callbackFn({success:false, id:objectIdStr}); 638 | } 639 | }, 640 | 641 | getObjectById: function(objectIdStr) { 642 | if (ua.w3) { 643 | return getObjectById(objectIdStr); 644 | } 645 | }, 646 | 647 | embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) { 648 | var callbackObj = {success:false, id:replaceElemIdStr}; 649 | if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) { 650 | setVisibility(replaceElemIdStr, false); 651 | addDomLoadEvent(function() { 652 | widthStr += ""; // auto-convert to string 653 | heightStr += ""; 654 | var att = {}; 655 | if (attObj && typeof attObj === OBJECT) { 656 | for (var i in attObj) { // copy object to avoid the use of references, because web authors often reuse attObj for multiple SWFs 657 | att[i] = attObj[i]; 658 | } 659 | } 660 | att.data = swfUrlStr; 661 | att.width = widthStr; 662 | att.height = heightStr; 663 | var par = {}; 664 | if (parObj && typeof parObj === OBJECT) { 665 | for (var j in parObj) { // copy object to avoid the use of references, because web authors often reuse parObj for multiple SWFs 666 | par[j] = parObj[j]; 667 | } 668 | } 669 | if (flashvarsObj && typeof flashvarsObj === OBJECT) { 670 | for (var k in flashvarsObj) { // copy object to avoid the use of references, because web authors often reuse flashvarsObj for multiple SWFs 671 | if (typeof par.flashvars != UNDEF) { 672 | par.flashvars += "&" + k + "=" + flashvarsObj[k]; 673 | } 674 | else { 675 | par.flashvars = k + "=" + flashvarsObj[k]; 676 | } 677 | } 678 | } 679 | if (hasPlayerVersion(swfVersionStr)) { // create SWF 680 | var obj = createSWF(att, par, replaceElemIdStr); 681 | if (att.id == replaceElemIdStr) { 682 | setVisibility(replaceElemIdStr, true); 683 | } 684 | callbackObj.success = true; 685 | callbackObj.ref = obj; 686 | } 687 | else if (xiSwfUrlStr && canExpressInstall()) { // show Adobe Express Install 688 | att.data = xiSwfUrlStr; 689 | showExpressInstall(att, par, replaceElemIdStr, callbackFn); 690 | return; 691 | } 692 | else { // show alternative content 693 | setVisibility(replaceElemIdStr, true); 694 | } 695 | if (callbackFn) { callbackFn(callbackObj); } 696 | }); 697 | } 698 | else if (callbackFn) { callbackFn(callbackObj); } 699 | }, 700 | 701 | switchOffAutoHideShow: function() { 702 | autoHideShow = false; 703 | }, 704 | 705 | ua: ua, 706 | 707 | getFlashPlayerVersion: function() { 708 | return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] }; 709 | }, 710 | 711 | hasFlashPlayerVersion: hasPlayerVersion, 712 | 713 | createSWF: function(attObj, parObj, replaceElemIdStr) { 714 | if (ua.w3) { 715 | return createSWF(attObj, parObj, replaceElemIdStr); 716 | } 717 | else { 718 | return undefined; 719 | } 720 | }, 721 | 722 | showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) { 723 | if (ua.w3 && canExpressInstall()) { 724 | showExpressInstall(att, par, replaceElemIdStr, callbackFn); 725 | } 726 | }, 727 | 728 | removeSWF: function(objElemIdStr) { 729 | if (ua.w3) { 730 | removeSWF(objElemIdStr); 731 | } 732 | }, 733 | 734 | createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) { 735 | if (ua.w3) { 736 | createCSS(selStr, declStr, mediaStr, newStyleBoolean); 737 | } 738 | }, 739 | 740 | addDomLoadEvent: addDomLoadEvent, 741 | 742 | addLoadEvent: addLoadEvent, 743 | 744 | getQueryParamValue: function(param) { 745 | var q = doc.location.search || doc.location.hash; 746 | if (q) { 747 | if (/\?/.test(q)) { q = q.split("?")[1]; } // strip question mark 748 | if (param == null) { 749 | return urlEncodeIfNecessary(q); 750 | } 751 | var pairs = q.split("&"); 752 | for (var i = 0; i < pairs.length; i++) { 753 | if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) { 754 | return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1))); 755 | } 756 | } 757 | } 758 | return ""; 759 | }, 760 | 761 | // For internal usage only 762 | expressInstallCallback: function() { 763 | if (isExpressInstallActive) { 764 | var obj = getElementById(EXPRESS_INSTALL_ID); 765 | if (obj && storedAltContent) { 766 | obj.parentNode.replaceChild(storedAltContent, obj); 767 | if (storedAltContentId) { 768 | setVisibility(storedAltContentId, true); 769 | if (ua.ie && ua.win) { storedAltContent.style.display = "block"; } 770 | } 771 | if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); } 772 | } 773 | isExpressInstallActive = false; 774 | } 775 | } 776 | }; 777 | }(); 778 | -------------------------------------------------------------------------------- /bin-release/TextureAtlas.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 58 | 59 | 60 | 64 |
65 |

66 | To view this page ensure that Adobe Flash Player version 67 | 10.0.0 or greater is installed. 68 |

69 | 74 |
75 | 76 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /bin-release/TextureAtlas.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pixelrevision/texture_atlas_generator/bf13b9d3edc9dfcbcf509d914f1036f14037b4d3/bin-release/TextureAtlas.swf -------------------------------------------------------------------------------- /bin-release/history/history.css: -------------------------------------------------------------------------------- 1 | /* This CSS stylesheet defines styles used by required elements in a flex application page that supports browser history */ 2 | 3 | #ie_historyFrame { width: 0px; height: 0px; display:none } 4 | #firefox_anchorDiv { width: 0px; height: 0px; display:none } 5 | #safari_formDiv { width: 0px; height: 0px; display:none } 6 | #safari_rememberDiv { width: 0px; height: 0px; display:none } 7 | -------------------------------------------------------------------------------- /bin-release/history/history.js: -------------------------------------------------------------------------------- 1 | BrowserHistoryUtils = { 2 | addEvent: function(elm, evType, fn, useCapture) { 3 | useCapture = useCapture || false; 4 | if (elm.addEventListener) { 5 | elm.addEventListener(evType, fn, useCapture); 6 | return true; 7 | } 8 | else if (elm.attachEvent) { 9 | var r = elm.attachEvent('on' + evType, fn); 10 | return r; 11 | } 12 | else { 13 | elm['on' + evType] = fn; 14 | } 15 | } 16 | } 17 | 18 | BrowserHistory = (function() { 19 | // type of browser 20 | var browser = { 21 | ie: false, 22 | ie8: false, 23 | firefox: false, 24 | safari: false, 25 | opera: false, 26 | version: -1 27 | }; 28 | 29 | // if setDefaultURL has been called, our first clue 30 | // that the SWF is ready and listening 31 | //var swfReady = false; 32 | 33 | // the URL we'll send to the SWF once it is ready 34 | //var pendingURL = ''; 35 | 36 | // Default app state URL to use when no fragment ID present 37 | var defaultHash = ''; 38 | 39 | // Last-known app state URL 40 | var currentHref = document.location.href; 41 | 42 | // Initial URL (used only by IE) 43 | var initialHref = document.location.href; 44 | 45 | // Initial URL (used only by IE) 46 | var initialHash = document.location.hash; 47 | 48 | // History frame source URL prefix (used only by IE) 49 | var historyFrameSourcePrefix = 'history/historyFrame.html?'; 50 | 51 | // History maintenance (used only by Safari) 52 | var currentHistoryLength = -1; 53 | 54 | var historyHash = []; 55 | 56 | var initialState = createState(initialHref, initialHref + '#' + initialHash, initialHash); 57 | 58 | var backStack = []; 59 | var forwardStack = []; 60 | 61 | var currentObjectId = null; 62 | 63 | //UserAgent detection 64 | var useragent = navigator.userAgent.toLowerCase(); 65 | 66 | if (useragent.indexOf("opera") != -1) { 67 | browser.opera = true; 68 | } else if (useragent.indexOf("msie") != -1) { 69 | browser.ie = true; 70 | browser.version = parseFloat(useragent.substring(useragent.indexOf('msie') + 4)); 71 | if (browser.version == 8) 72 | { 73 | browser.ie = false; 74 | browser.ie8 = true; 75 | } 76 | } else if (useragent.indexOf("safari") != -1) { 77 | browser.safari = true; 78 | browser.version = parseFloat(useragent.substring(useragent.indexOf('safari') + 7)); 79 | } else if (useragent.indexOf("gecko") != -1) { 80 | browser.firefox = true; 81 | } 82 | 83 | if (browser.ie == true && browser.version == 7) { 84 | window["_ie_firstload"] = false; 85 | } 86 | 87 | function hashChangeHandler() 88 | { 89 | currentHref = document.location.href; 90 | var flexAppUrl = getHash(); 91 | //ADR: to fix multiple 92 | if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) { 93 | var pl = getPlayers(); 94 | for (var i = 0; i < pl.length; i++) { 95 | pl[i].browserURLChange(flexAppUrl); 96 | } 97 | } else { 98 | getPlayer().browserURLChange(flexAppUrl); 99 | } 100 | } 101 | 102 | // Accessor functions for obtaining specific elements of the page. 103 | function getHistoryFrame() 104 | { 105 | return document.getElementById('ie_historyFrame'); 106 | } 107 | 108 | function getAnchorElement() 109 | { 110 | return document.getElementById('firefox_anchorDiv'); 111 | } 112 | 113 | function getFormElement() 114 | { 115 | return document.getElementById('safari_formDiv'); 116 | } 117 | 118 | function getRememberElement() 119 | { 120 | return document.getElementById("safari_remember_field"); 121 | } 122 | 123 | // Get the Flash player object for performing ExternalInterface callbacks. 124 | // Updated for changes to SWFObject2. 125 | function getPlayer(id) { 126 | var i; 127 | 128 | if (id && document.getElementById(id)) { 129 | var r = document.getElementById(id); 130 | if (typeof r.SetVariable != "undefined") { 131 | return r; 132 | } 133 | else { 134 | var o = r.getElementsByTagName("object"); 135 | var e = r.getElementsByTagName("embed"); 136 | for (i = 0; i < o.length; i++) { 137 | if (typeof o[i].browserURLChange != "undefined") 138 | return o[i]; 139 | } 140 | for (i = 0; i < e.length; i++) { 141 | if (typeof e[i].browserURLChange != "undefined") 142 | return e[i]; 143 | } 144 | } 145 | } 146 | else { 147 | var o = document.getElementsByTagName("object"); 148 | var e = document.getElementsByTagName("embed"); 149 | for (i = 0; i < e.length; i++) { 150 | if (typeof e[i].browserURLChange != "undefined") 151 | { 152 | return e[i]; 153 | } 154 | } 155 | for (i = 0; i < o.length; i++) { 156 | if (typeof o[i].browserURLChange != "undefined") 157 | { 158 | return o[i]; 159 | } 160 | } 161 | } 162 | return undefined; 163 | } 164 | 165 | function getPlayers() { 166 | var i; 167 | var players = []; 168 | if (players.length == 0) { 169 | var tmp = document.getElementsByTagName('object'); 170 | for (i = 0; i < tmp.length; i++) 171 | { 172 | if (typeof tmp[i].browserURLChange != "undefined") 173 | players.push(tmp[i]); 174 | } 175 | } 176 | if (players.length == 0 || players[0].object == null) { 177 | var tmp = document.getElementsByTagName('embed'); 178 | for (i = 0; i < tmp.length; i++) 179 | { 180 | if (typeof tmp[i].browserURLChange != "undefined") 181 | players.push(tmp[i]); 182 | } 183 | } 184 | return players; 185 | } 186 | 187 | function getIframeHash() { 188 | var doc = getHistoryFrame().contentWindow.document; 189 | var hash = String(doc.location.search); 190 | if (hash.length == 1 && hash.charAt(0) == "?") { 191 | hash = ""; 192 | } 193 | else if (hash.length >= 2 && hash.charAt(0) == "?") { 194 | hash = hash.substring(1); 195 | } 196 | return hash; 197 | } 198 | 199 | /* Get the current location hash excluding the '#' symbol. */ 200 | function getHash() { 201 | // It would be nice if we could use document.location.hash here, 202 | // but it's faulty sometimes. 203 | var idx = document.location.href.indexOf('#'); 204 | return (idx >= 0) ? document.location.href.substr(idx+1) : ''; 205 | } 206 | 207 | /* Get the current location hash excluding the '#' symbol. */ 208 | function setHash(hash) { 209 | // It would be nice if we could use document.location.hash here, 210 | // but it's faulty sometimes. 211 | if (hash == '') hash = '#' 212 | document.location.hash = hash; 213 | } 214 | 215 | function createState(baseUrl, newUrl, flexAppUrl) { 216 | return { 'baseUrl': baseUrl, 'newUrl': newUrl, 'flexAppUrl': flexAppUrl, 'title': null }; 217 | } 218 | 219 | /* Add a history entry to the browser. 220 | * baseUrl: the portion of the location prior to the '#' 221 | * newUrl: the entire new URL, including '#' and following fragment 222 | * flexAppUrl: the portion of the location following the '#' only 223 | */ 224 | function addHistoryEntry(baseUrl, newUrl, flexAppUrl) { 225 | 226 | //delete all the history entries 227 | forwardStack = []; 228 | 229 | if (browser.ie) { 230 | //Check to see if we are being asked to do a navigate for the first 231 | //history entry, and if so ignore, because it's coming from the creation 232 | //of the history iframe 233 | if (flexAppUrl == defaultHash && document.location.href == initialHref && window['_ie_firstload']) { 234 | currentHref = initialHref; 235 | return; 236 | } 237 | if ((!flexAppUrl || flexAppUrl == defaultHash) && window['_ie_firstload']) { 238 | newUrl = baseUrl + '#' + defaultHash; 239 | flexAppUrl = defaultHash; 240 | } else { 241 | // for IE, tell the history frame to go somewhere without a '#' 242 | // in order to get this entry into the browser history. 243 | getHistoryFrame().src = historyFrameSourcePrefix + flexAppUrl; 244 | } 245 | setHash(flexAppUrl); 246 | } else { 247 | 248 | //ADR 249 | if (backStack.length == 0 && initialState.flexAppUrl == flexAppUrl) { 250 | initialState = createState(baseUrl, newUrl, flexAppUrl); 251 | } else if(backStack.length > 0 && backStack[backStack.length - 1].flexAppUrl == flexAppUrl) { 252 | backStack[backStack.length - 1] = createState(baseUrl, newUrl, flexAppUrl); 253 | } 254 | 255 | if (browser.safari) { 256 | // for Safari, submit a form whose action points to the desired URL 257 | if (browser.version <= 419.3) { 258 | var file = window.location.pathname.toString(); 259 | file = file.substring(file.lastIndexOf("/")+1); 260 | getFormElement().innerHTML = '
'; 261 | //get the current elements and add them to the form 262 | var qs = window.location.search.substring(1); 263 | var qs_arr = qs.split("&"); 264 | for (var i = 0; i < qs_arr.length; i++) { 265 | var tmp = qs_arr[i].split("="); 266 | var elem = document.createElement("input"); 267 | elem.type = "hidden"; 268 | elem.name = tmp[0]; 269 | elem.value = tmp[1]; 270 | document.forms.historyForm.appendChild(elem); 271 | } 272 | document.forms.historyForm.submit(); 273 | } else { 274 | top.location.hash = flexAppUrl; 275 | } 276 | // We also have to maintain the history by hand for Safari 277 | historyHash[history.length] = flexAppUrl; 278 | _storeStates(); 279 | } else { 280 | // Otherwise, write an anchor into the page and tell the browser to go there 281 | addAnchor(flexAppUrl); 282 | setHash(flexAppUrl); 283 | 284 | // For IE8 we must restore full focus/activation to our invoking player instance. 285 | if (browser.ie8) 286 | getPlayer().focus(); 287 | } 288 | } 289 | backStack.push(createState(baseUrl, newUrl, flexAppUrl)); 290 | } 291 | 292 | function _storeStates() { 293 | if (browser.safari) { 294 | getRememberElement().value = historyHash.join(","); 295 | } 296 | } 297 | 298 | function handleBackButton() { 299 | //The "current" page is always at the top of the history stack. 300 | var current = backStack.pop(); 301 | if (!current) { return; } 302 | var last = backStack[backStack.length - 1]; 303 | if (!last && backStack.length == 0){ 304 | last = initialState; 305 | } 306 | forwardStack.push(current); 307 | } 308 | 309 | function handleForwardButton() { 310 | //summary: private method. Do not call this directly. 311 | 312 | var last = forwardStack.pop(); 313 | if (!last) { return; } 314 | backStack.push(last); 315 | } 316 | 317 | function handleArbitraryUrl() { 318 | //delete all the history entries 319 | forwardStack = []; 320 | } 321 | 322 | /* Called periodically to poll to see if we need to detect navigation that has occurred */ 323 | function checkForUrlChange() { 324 | 325 | if (browser.ie) { 326 | if (currentHref != document.location.href && currentHref + '#' != document.location.href) { 327 | //This occurs when the user has navigated to a specific URL 328 | //within the app, and didn't use browser back/forward 329 | //IE seems to have a bug where it stops updating the URL it 330 | //shows the end-user at this point, but programatically it 331 | //appears to be correct. Do a full app reload to get around 332 | //this issue. 333 | if (browser.version < 7) { 334 | currentHref = document.location.href; 335 | document.location.reload(); 336 | } else { 337 | if (getHash() != getIframeHash()) { 338 | // this.iframe.src = this.blankURL + hash; 339 | var sourceToSet = historyFrameSourcePrefix + getHash(); 340 | getHistoryFrame().src = sourceToSet; 341 | currentHref = document.location.href; 342 | } 343 | } 344 | } 345 | } 346 | 347 | if (browser.safari) { 348 | // For Safari, we have to check to see if history.length changed. 349 | if (currentHistoryLength >= 0 && history.length != currentHistoryLength) { 350 | //alert("did change: " + history.length + ", " + historyHash.length + "|" + historyHash[history.length] + "|>" + historyHash.join("|")); 351 | var flexAppUrl = getHash(); 352 | if (browser.version < 528.16 /* Anything earlier than Safari 4.0 */) 353 | { 354 | // If it did change and we're running Safari 3.x or earlier, 355 | // then we have to look the old state up in our hand-maintained 356 | // array since document.location.hash won't have changed, 357 | // then call back into BrowserManager. 358 | currentHistoryLength = history.length; 359 | flexAppUrl = historyHash[currentHistoryLength]; 360 | } 361 | 362 | //ADR: to fix multiple 363 | if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) { 364 | var pl = getPlayers(); 365 | for (var i = 0; i < pl.length; i++) { 366 | pl[i].browserURLChange(flexAppUrl); 367 | } 368 | } else { 369 | getPlayer().browserURLChange(flexAppUrl); 370 | } 371 | _storeStates(); 372 | } 373 | } 374 | if (browser.firefox) { 375 | if (currentHref != document.location.href) { 376 | var bsl = backStack.length; 377 | 378 | var urlActions = { 379 | back: false, 380 | forward: false, 381 | set: false 382 | } 383 | 384 | if ((window.location.hash == initialHash || window.location.href == initialHref) && (bsl == 1)) { 385 | urlActions.back = true; 386 | // FIXME: could this ever be a forward button? 387 | // we can't clear it because we still need to check for forwards. Ugg. 388 | // clearInterval(this.locationTimer); 389 | handleBackButton(); 390 | } 391 | 392 | // first check to see if we could have gone forward. We always halt on 393 | // a no-hash item. 394 | if (forwardStack.length > 0) { 395 | if (forwardStack[forwardStack.length-1].flexAppUrl == getHash()) { 396 | urlActions.forward = true; 397 | handleForwardButton(); 398 | } 399 | } 400 | 401 | // ok, that didn't work, try someplace back in the history stack 402 | if ((bsl >= 2) && (backStack[bsl - 2])) { 403 | if (backStack[bsl - 2].flexAppUrl == getHash()) { 404 | urlActions.back = true; 405 | handleBackButton(); 406 | } 407 | } 408 | 409 | if (!urlActions.back && !urlActions.forward) { 410 | var foundInStacks = { 411 | back: -1, 412 | forward: -1 413 | } 414 | 415 | for (var i = 0; i < backStack.length; i++) { 416 | if (backStack[i].flexAppUrl == getHash() && i != (bsl - 2)) { 417 | arbitraryUrl = true; 418 | foundInStacks.back = i; 419 | } 420 | } 421 | for (var i = 0; i < forwardStack.length; i++) { 422 | if (forwardStack[i].flexAppUrl == getHash() && i != (bsl - 2)) { 423 | arbitraryUrl = true; 424 | foundInStacks.forward = i; 425 | } 426 | } 427 | handleArbitraryUrl(); 428 | } 429 | 430 | // Firefox changed; do a callback into BrowserManager to tell it. 431 | currentHref = document.location.href; 432 | var flexAppUrl = getHash(); 433 | //ADR: to fix multiple 434 | if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) { 435 | var pl = getPlayers(); 436 | for (var i = 0; i < pl.length; i++) { 437 | pl[i].browserURLChange(flexAppUrl); 438 | } 439 | } else { 440 | getPlayer().browserURLChange(flexAppUrl); 441 | } 442 | } 443 | } 444 | //setTimeout(checkForUrlChange, 50); 445 | } 446 | 447 | /* Write an anchor into the page to legitimize it as a URL for Firefox et al. */ 448 | function addAnchor(flexAppUrl) 449 | { 450 | if (document.getElementsByName(flexAppUrl).length == 0) { 451 | getAnchorElement().innerHTML += "" + flexAppUrl + ""; 452 | } 453 | } 454 | 455 | var _initialize = function () { 456 | if (browser.ie) 457 | { 458 | var scripts = document.getElementsByTagName('script'); 459 | for (var i = 0, s; s = scripts[i]; i++) { 460 | if (s.src.indexOf("history.js") > -1) { 461 | var iframe_location = (new String(s.src)).replace("history.js", "historyFrame.html"); 462 | } 463 | } 464 | historyFrameSourcePrefix = iframe_location + "?"; 465 | var src = historyFrameSourcePrefix; 466 | 467 | var iframe = document.createElement("iframe"); 468 | iframe.id = 'ie_historyFrame'; 469 | iframe.name = 'ie_historyFrame'; 470 | iframe.src = 'javascript:false;'; 471 | 472 | try { 473 | document.body.appendChild(iframe); 474 | } catch(e) { 475 | setTimeout(function() { 476 | document.body.appendChild(iframe); 477 | }, 0); 478 | } 479 | } 480 | 481 | if (browser.safari) 482 | { 483 | var rememberDiv = document.createElement("div"); 484 | rememberDiv.id = 'safari_rememberDiv'; 485 | document.body.appendChild(rememberDiv); 486 | rememberDiv.innerHTML = ''; 487 | 488 | var formDiv = document.createElement("div"); 489 | formDiv.id = 'safari_formDiv'; 490 | document.body.appendChild(formDiv); 491 | 492 | var reloader_content = document.createElement('div'); 493 | reloader_content.id = 'safarireloader'; 494 | var scripts = document.getElementsByTagName('script'); 495 | for (var i = 0, s; s = scripts[i]; i++) { 496 | if (s.src.indexOf("history.js") > -1) { 497 | html = (new String(s.src)).replace(".js", ".html"); 498 | } 499 | } 500 | reloader_content.innerHTML = ''; 501 | document.body.appendChild(reloader_content); 502 | reloader_content.style.position = 'absolute'; 503 | reloader_content.style.left = reloader_content.style.top = '-9999px'; 504 | iframe = reloader_content.getElementsByTagName('iframe')[0]; 505 | 506 | if (document.getElementById("safari_remember_field").value != "" ) { 507 | historyHash = document.getElementById("safari_remember_field").value.split(","); 508 | } 509 | 510 | } 511 | 512 | if (browser.firefox || browser.ie8) 513 | { 514 | var anchorDiv = document.createElement("div"); 515 | anchorDiv.id = 'firefox_anchorDiv'; 516 | document.body.appendChild(anchorDiv); 517 | } 518 | 519 | if (browser.ie8) 520 | document.body.onhashchange = hashChangeHandler; 521 | //setTimeout(checkForUrlChange, 50); 522 | } 523 | 524 | return { 525 | historyHash: historyHash, 526 | backStack: function() { return backStack; }, 527 | forwardStack: function() { return forwardStack }, 528 | getPlayer: getPlayer, 529 | initialize: function(src) { 530 | _initialize(src); 531 | }, 532 | setURL: function(url) { 533 | document.location.href = url; 534 | }, 535 | getURL: function() { 536 | return document.location.href; 537 | }, 538 | getTitle: function() { 539 | return document.title; 540 | }, 541 | setTitle: function(title) { 542 | try { 543 | backStack[backStack.length - 1].title = title; 544 | } catch(e) { } 545 | //if on safari, set the title to be the empty string. 546 | if (browser.safari) { 547 | if (title == "") { 548 | try { 549 | var tmp = window.location.href.toString(); 550 | title = tmp.substring((tmp.lastIndexOf("/")+1), tmp.lastIndexOf("#")); 551 | } catch(e) { 552 | title = ""; 553 | } 554 | } 555 | } 556 | document.title = title; 557 | }, 558 | setDefaultURL: function(def) 559 | { 560 | defaultHash = def; 561 | def = getHash(); 562 | //trailing ? is important else an extra frame gets added to the history 563 | //when navigating back to the first page. Alternatively could check 564 | //in history frame navigation to compare # and ?. 565 | if (browser.ie) 566 | { 567 | window['_ie_firstload'] = true; 568 | var sourceToSet = historyFrameSourcePrefix + def; 569 | var func = function() { 570 | getHistoryFrame().src = sourceToSet; 571 | window.location.replace("#" + def); 572 | setInterval(checkForUrlChange, 50); 573 | } 574 | try { 575 | func(); 576 | } catch(e) { 577 | window.setTimeout(function() { func(); }, 0); 578 | } 579 | } 580 | 581 | if (browser.safari) 582 | { 583 | currentHistoryLength = history.length; 584 | if (historyHash.length == 0) { 585 | historyHash[currentHistoryLength] = def; 586 | var newloc = "#" + def; 587 | window.location.replace(newloc); 588 | } else { 589 | //alert(historyHash[historyHash.length-1]); 590 | } 591 | //setHash(def); 592 | setInterval(checkForUrlChange, 50); 593 | } 594 | 595 | 596 | if (browser.firefox || browser.opera) 597 | { 598 | var reg = new RegExp("#" + def + "$"); 599 | if (window.location.toString().match(reg)) { 600 | } else { 601 | var newloc ="#" + def; 602 | window.location.replace(newloc); 603 | } 604 | setInterval(checkForUrlChange, 50); 605 | //setHash(def); 606 | } 607 | 608 | }, 609 | 610 | /* Set the current browser URL; called from inside BrowserManager to propagate 611 | * the application state out to the container. 612 | */ 613 | setBrowserURL: function(flexAppUrl, objectId) { 614 | if (browser.ie && typeof objectId != "undefined") { 615 | currentObjectId = objectId; 616 | } 617 | //fromIframe = fromIframe || false; 618 | //fromFlex = fromFlex || false; 619 | //alert("setBrowserURL: " + flexAppUrl); 620 | //flexAppUrl = (flexAppUrl == "") ? defaultHash : flexAppUrl ; 621 | 622 | var pos = document.location.href.indexOf('#'); 623 | var baseUrl = pos != -1 ? document.location.href.substr(0, pos) : document.location.href; 624 | var newUrl = baseUrl + '#' + flexAppUrl; 625 | 626 | if (document.location.href != newUrl && document.location.href + '#' != newUrl) { 627 | currentHref = newUrl; 628 | addHistoryEntry(baseUrl, newUrl, flexAppUrl); 629 | currentHistoryLength = history.length; 630 | } 631 | }, 632 | 633 | browserURLChange: function(flexAppUrl) { 634 | var objectId = null; 635 | if (browser.ie && currentObjectId != null) { 636 | objectId = currentObjectId; 637 | } 638 | pendingURL = ''; 639 | 640 | if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) { 641 | var pl = getPlayers(); 642 | for (var i = 0; i < pl.length; i++) { 643 | try { 644 | pl[i].browserURLChange(flexAppUrl); 645 | } catch(e) { } 646 | } 647 | } else { 648 | try { 649 | getPlayer(objectId).browserURLChange(flexAppUrl); 650 | } catch(e) { } 651 | } 652 | 653 | currentObjectId = null; 654 | }, 655 | getUserAgent: function() { 656 | return navigator.userAgent; 657 | }, 658 | getPlatform: function() { 659 | return navigator.platform; 660 | } 661 | 662 | } 663 | 664 | })(); 665 | 666 | // Initialization 667 | 668 | // Automated unit testing and other diagnostics 669 | 670 | function setURL(url) 671 | { 672 | document.location.href = url; 673 | } 674 | 675 | function backButton() 676 | { 677 | history.back(); 678 | } 679 | 680 | function forwardButton() 681 | { 682 | history.forward(); 683 | } 684 | 685 | function goForwardOrBackInHistory(step) 686 | { 687 | history.go(step); 688 | } 689 | 690 | //BrowserHistoryUtils.addEvent(window, "load", function() { BrowserHistory.initialize(); }); 691 | (function(i) { 692 | var u =navigator.userAgent;var e=/*@cc_on!@*/false; 693 | var st = setTimeout; 694 | if(/webkit/i.test(u)){ 695 | st(function(){ 696 | var dr=document.readyState; 697 | if(dr=="loaded"||dr=="complete"){i()} 698 | else{st(arguments.callee,10);}},10); 699 | } else if((/mozilla/i.test(u)&&!/(compati)/.test(u)) || (/opera/i.test(u))){ 700 | document.addEventListener("DOMContentLoaded",i,false); 701 | } else if(e){ 702 | (function(){ 703 | var t=document.createElement('doc:rdy'); 704 | try{t.doScroll('left'); 705 | i();t=null; 706 | }catch(e){st(arguments.callee,0);}})(); 707 | } else{ 708 | window.onload=i; 709 | } 710 | })( function() {BrowserHistory.initialize();} ); 711 | -------------------------------------------------------------------------------- /bin-release/history/historyFrame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 27 | Hidden frame for Browser History support. 28 | 29 | 30 | -------------------------------------------------------------------------------- /bin-release/playerProductInstall.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pixelrevision/texture_atlas_generator/bf13b9d3edc9dfcbcf509d914f1036f14037b4d3/bin-release/playerProductInstall.swf -------------------------------------------------------------------------------- /bin-release/swfobject.js: -------------------------------------------------------------------------------- 1 | /*! SWFObject v2.2 2 | is released under the MIT License 3 | */ 4 | 5 | var swfobject = function() { 6 | 7 | var UNDEF = "undefined", 8 | OBJECT = "object", 9 | SHOCKWAVE_FLASH = "Shockwave Flash", 10 | SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash", 11 | FLASH_MIME_TYPE = "application/x-shockwave-flash", 12 | EXPRESS_INSTALL_ID = "SWFObjectExprInst", 13 | ON_READY_STATE_CHANGE = "onreadystatechange", 14 | 15 | win = window, 16 | doc = document, 17 | nav = navigator, 18 | 19 | plugin = false, 20 | domLoadFnArr = [main], 21 | regObjArr = [], 22 | objIdArr = [], 23 | listenersArr = [], 24 | storedAltContent, 25 | storedAltContentId, 26 | storedCallbackFn, 27 | storedCallbackObj, 28 | isDomLoaded = false, 29 | isExpressInstallActive = false, 30 | dynamicStylesheet, 31 | dynamicStylesheetMedia, 32 | autoHideShow = true, 33 | 34 | /* Centralized function for browser feature detection 35 | - User agent string detection is only used when no good alternative is possible 36 | - Is executed directly for optimal performance 37 | */ 38 | ua = function() { 39 | var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF, 40 | u = nav.userAgent.toLowerCase(), 41 | p = nav.platform.toLowerCase(), 42 | windows = p ? /win/.test(p) : /win/.test(u), 43 | mac = p ? /mac/.test(p) : /mac/.test(u), 44 | webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, // returns either the webkit version or false if not webkit 45 | ie = !+"\v1", // feature detection based on Andrea Giammarchi's solution: http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html 46 | playerVersion = [0,0,0], 47 | d = null; 48 | if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) { 49 | d = nav.plugins[SHOCKWAVE_FLASH].description; 50 | if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { // navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin indicates whether plug-ins are enabled or disabled in Safari 3+ 51 | plugin = true; 52 | ie = false; // cascaded feature detection for Internet Explorer 53 | d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1"); 54 | playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10); 55 | playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10); 56 | playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0; 57 | } 58 | } 59 | else if (typeof win.ActiveXObject != UNDEF) { 60 | try { 61 | var a = new ActiveXObject(SHOCKWAVE_FLASH_AX); 62 | if (a) { // a will return null when ActiveX is disabled 63 | d = a.GetVariable("$version"); 64 | if (d) { 65 | ie = true; // cascaded feature detection for Internet Explorer 66 | d = d.split(" ")[1].split(","); 67 | playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)]; 68 | } 69 | } 70 | } 71 | catch(e) {} 72 | } 73 | return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac }; 74 | }(), 75 | 76 | /* Cross-browser onDomLoad 77 | - Will fire an event as soon as the DOM of a web page is loaded 78 | - Internet Explorer workaround based on Diego Perini's solution: http://javascript.nwbox.com/IEContentLoaded/ 79 | - Regular onload serves as fallback 80 | */ 81 | onDomLoad = function() { 82 | if (!ua.w3) { return; } 83 | if ((typeof doc.readyState != UNDEF && doc.readyState == "complete") || (typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) { // function is fired after onload, e.g. when script is inserted dynamically 84 | callDomLoadFunctions(); 85 | } 86 | if (!isDomLoaded) { 87 | if (typeof doc.addEventListener != UNDEF) { 88 | doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false); 89 | } 90 | if (ua.ie && ua.win) { 91 | doc.attachEvent(ON_READY_STATE_CHANGE, function() { 92 | if (doc.readyState == "complete") { 93 | doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee); 94 | callDomLoadFunctions(); 95 | } 96 | }); 97 | if (win == top) { // if not inside an iframe 98 | (function(){ 99 | if (isDomLoaded) { return; } 100 | try { 101 | doc.documentElement.doScroll("left"); 102 | } 103 | catch(e) { 104 | setTimeout(arguments.callee, 0); 105 | return; 106 | } 107 | callDomLoadFunctions(); 108 | })(); 109 | } 110 | } 111 | if (ua.wk) { 112 | (function(){ 113 | if (isDomLoaded) { return; } 114 | if (!/loaded|complete/.test(doc.readyState)) { 115 | setTimeout(arguments.callee, 0); 116 | return; 117 | } 118 | callDomLoadFunctions(); 119 | })(); 120 | } 121 | addLoadEvent(callDomLoadFunctions); 122 | } 123 | }(); 124 | 125 | function callDomLoadFunctions() { 126 | if (isDomLoaded) { return; } 127 | try { // test if we can really add/remove elements to/from the DOM; we don't want to fire it too early 128 | var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span")); 129 | t.parentNode.removeChild(t); 130 | } 131 | catch (e) { return; } 132 | isDomLoaded = true; 133 | var dl = domLoadFnArr.length; 134 | for (var i = 0; i < dl; i++) { 135 | domLoadFnArr[i](); 136 | } 137 | } 138 | 139 | function addDomLoadEvent(fn) { 140 | if (isDomLoaded) { 141 | fn(); 142 | } 143 | else { 144 | domLoadFnArr[domLoadFnArr.length] = fn; // Array.push() is only available in IE5.5+ 145 | } 146 | } 147 | 148 | /* Cross-browser onload 149 | - Based on James Edwards' solution: http://brothercake.com/site/resources/scripts/onload/ 150 | - Will fire an event as soon as a web page including all of its assets are loaded 151 | */ 152 | function addLoadEvent(fn) { 153 | if (typeof win.addEventListener != UNDEF) { 154 | win.addEventListener("load", fn, false); 155 | } 156 | else if (typeof doc.addEventListener != UNDEF) { 157 | doc.addEventListener("load", fn, false); 158 | } 159 | else if (typeof win.attachEvent != UNDEF) { 160 | addListener(win, "onload", fn); 161 | } 162 | else if (typeof win.onload == "function") { 163 | var fnOld = win.onload; 164 | win.onload = function() { 165 | fnOld(); 166 | fn(); 167 | }; 168 | } 169 | else { 170 | win.onload = fn; 171 | } 172 | } 173 | 174 | /* Main function 175 | - Will preferably execute onDomLoad, otherwise onload (as a fallback) 176 | */ 177 | function main() { 178 | if (plugin) { 179 | testPlayerVersion(); 180 | } 181 | else { 182 | matchVersions(); 183 | } 184 | } 185 | 186 | /* Detect the Flash Player version for non-Internet Explorer browsers 187 | - Detecting the plug-in version via the object element is more precise than using the plugins collection item's description: 188 | a. Both release and build numbers can be detected 189 | b. Avoid wrong descriptions by corrupt installers provided by Adobe 190 | c. Avoid wrong descriptions by multiple Flash Player entries in the plugin Array, caused by incorrect browser imports 191 | - Disadvantage of this method is that it depends on the availability of the DOM, while the plugins collection is immediately available 192 | */ 193 | function testPlayerVersion() { 194 | var b = doc.getElementsByTagName("body")[0]; 195 | var o = createElement(OBJECT); 196 | o.setAttribute("type", FLASH_MIME_TYPE); 197 | var t = b.appendChild(o); 198 | if (t) { 199 | var counter = 0; 200 | (function(){ 201 | if (typeof t.GetVariable != UNDEF) { 202 | var d = t.GetVariable("$version"); 203 | if (d) { 204 | d = d.split(" ")[1].split(","); 205 | ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)]; 206 | } 207 | } 208 | else if (counter < 10) { 209 | counter++; 210 | setTimeout(arguments.callee, 10); 211 | return; 212 | } 213 | b.removeChild(o); 214 | t = null; 215 | matchVersions(); 216 | })(); 217 | } 218 | else { 219 | matchVersions(); 220 | } 221 | } 222 | 223 | /* Perform Flash Player and SWF version matching; static publishing only 224 | */ 225 | function matchVersions() { 226 | var rl = regObjArr.length; 227 | if (rl > 0) { 228 | for (var i = 0; i < rl; i++) { // for each registered object element 229 | var id = regObjArr[i].id; 230 | var cb = regObjArr[i].callbackFn; 231 | var cbObj = {success:false, id:id}; 232 | if (ua.pv[0] > 0) { 233 | var obj = getElementById(id); 234 | if (obj) { 235 | if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { // Flash Player version >= published SWF version: Houston, we have a match! 236 | setVisibility(id, true); 237 | if (cb) { 238 | cbObj.success = true; 239 | cbObj.ref = getObjectById(id); 240 | cb(cbObj); 241 | } 242 | } 243 | else if (regObjArr[i].expressInstall && canExpressInstall()) { // show the Adobe Express Install dialog if set by the web page author and if supported 244 | var att = {}; 245 | att.data = regObjArr[i].expressInstall; 246 | att.width = obj.getAttribute("width") || "0"; 247 | att.height = obj.getAttribute("height") || "0"; 248 | if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); } 249 | if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); } 250 | // parse HTML object param element's name-value pairs 251 | var par = {}; 252 | var p = obj.getElementsByTagName("param"); 253 | var pl = p.length; 254 | for (var j = 0; j < pl; j++) { 255 | if (p[j].getAttribute("name").toLowerCase() != "movie") { 256 | par[p[j].getAttribute("name")] = p[j].getAttribute("value"); 257 | } 258 | } 259 | showExpressInstall(att, par, id, cb); 260 | } 261 | else { // Flash Player and SWF version mismatch or an older Webkit engine that ignores the HTML object element's nested param elements: display alternative content instead of SWF 262 | displayAltContent(obj); 263 | if (cb) { cb(cbObj); } 264 | } 265 | } 266 | } 267 | else { // if no Flash Player is installed or the fp version cannot be detected we let the HTML object element do its job (either show a SWF or alternative content) 268 | setVisibility(id, true); 269 | if (cb) { 270 | var o = getObjectById(id); // test whether there is an HTML object element or not 271 | if (o && typeof o.SetVariable != UNDEF) { 272 | cbObj.success = true; 273 | cbObj.ref = o; 274 | } 275 | cb(cbObj); 276 | } 277 | } 278 | } 279 | } 280 | } 281 | 282 | function getObjectById(objectIdStr) { 283 | var r = null; 284 | var o = getElementById(objectIdStr); 285 | if (o && o.nodeName == "OBJECT") { 286 | if (typeof o.SetVariable != UNDEF) { 287 | r = o; 288 | } 289 | else { 290 | var n = o.getElementsByTagName(OBJECT)[0]; 291 | if (n) { 292 | r = n; 293 | } 294 | } 295 | } 296 | return r; 297 | } 298 | 299 | /* Requirements for Adobe Express Install 300 | - only one instance can be active at a time 301 | - fp 6.0.65 or higher 302 | - Win/Mac OS only 303 | - no Webkit engines older than version 312 304 | */ 305 | function canExpressInstall() { 306 | return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312); 307 | } 308 | 309 | /* Show the Adobe Express Install dialog 310 | - Reference: http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=6a253b75 311 | */ 312 | function showExpressInstall(att, par, replaceElemIdStr, callbackFn) { 313 | isExpressInstallActive = true; 314 | storedCallbackFn = callbackFn || null; 315 | storedCallbackObj = {success:false, id:replaceElemIdStr}; 316 | var obj = getElementById(replaceElemIdStr); 317 | if (obj) { 318 | if (obj.nodeName == "OBJECT") { // static publishing 319 | storedAltContent = abstractAltContent(obj); 320 | storedAltContentId = null; 321 | } 322 | else { // dynamic publishing 323 | storedAltContent = obj; 324 | storedAltContentId = replaceElemIdStr; 325 | } 326 | att.id = EXPRESS_INSTALL_ID; 327 | if (typeof att.width == UNDEF || (!/%$/.test(att.width) && parseInt(att.width, 10) < 310)) { att.width = "310"; } 328 | if (typeof att.height == UNDEF || (!/%$/.test(att.height) && parseInt(att.height, 10) < 137)) { att.height = "137"; } 329 | doc.title = doc.title.slice(0, 47) + " - Flash Player Installation"; 330 | var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn", 331 | fv = "MMredirectURL=" + encodeURI(window.location).toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title; 332 | if (typeof par.flashvars != UNDEF) { 333 | par.flashvars += "&" + fv; 334 | } 335 | else { 336 | par.flashvars = fv; 337 | } 338 | // IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it, 339 | // because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work 340 | if (ua.ie && ua.win && obj.readyState != 4) { 341 | var newObj = createElement("div"); 342 | replaceElemIdStr += "SWFObjectNew"; 343 | newObj.setAttribute("id", replaceElemIdStr); 344 | obj.parentNode.insertBefore(newObj, obj); // insert placeholder div that will be replaced by the object element that loads expressinstall.swf 345 | obj.style.display = "none"; 346 | (function(){ 347 | if (obj.readyState == 4) { 348 | obj.parentNode.removeChild(obj); 349 | } 350 | else { 351 | setTimeout(arguments.callee, 10); 352 | } 353 | })(); 354 | } 355 | createSWF(att, par, replaceElemIdStr); 356 | } 357 | } 358 | 359 | /* Functions to abstract and display alternative content 360 | */ 361 | function displayAltContent(obj) { 362 | if (ua.ie && ua.win && obj.readyState != 4) { 363 | // IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it, 364 | // because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work 365 | var el = createElement("div"); 366 | obj.parentNode.insertBefore(el, obj); // insert placeholder div that will be replaced by the alternative content 367 | el.parentNode.replaceChild(abstractAltContent(obj), el); 368 | obj.style.display = "none"; 369 | (function(){ 370 | if (obj.readyState == 4) { 371 | obj.parentNode.removeChild(obj); 372 | } 373 | else { 374 | setTimeout(arguments.callee, 10); 375 | } 376 | })(); 377 | } 378 | else { 379 | obj.parentNode.replaceChild(abstractAltContent(obj), obj); 380 | } 381 | } 382 | 383 | function abstractAltContent(obj) { 384 | var ac = createElement("div"); 385 | if (ua.win && ua.ie) { 386 | ac.innerHTML = obj.innerHTML; 387 | } 388 | else { 389 | var nestedObj = obj.getElementsByTagName(OBJECT)[0]; 390 | if (nestedObj) { 391 | var c = nestedObj.childNodes; 392 | if (c) { 393 | var cl = c.length; 394 | for (var i = 0; i < cl; i++) { 395 | if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) { 396 | ac.appendChild(c[i].cloneNode(true)); 397 | } 398 | } 399 | } 400 | } 401 | } 402 | return ac; 403 | } 404 | 405 | /* Cross-browser dynamic SWF creation 406 | */ 407 | function createSWF(attObj, parObj, id) { 408 | var r, el = getElementById(id); 409 | if (ua.wk && ua.wk < 312) { return r; } 410 | if (el) { 411 | if (typeof attObj.id == UNDEF) { // if no 'id' is defined for the object element, it will inherit the 'id' from the alternative content 412 | attObj.id = id; 413 | } 414 | if (ua.ie && ua.win) { // Internet Explorer + the HTML object element + W3C DOM methods do not combine: fall back to outerHTML 415 | var att = ""; 416 | for (var i in attObj) { 417 | if (attObj[i] != Object.prototype[i]) { // filter out prototype additions from other potential libraries 418 | if (i.toLowerCase() == "data") { 419 | parObj.movie = attObj[i]; 420 | } 421 | else if (i.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword 422 | att += ' class="' + attObj[i] + '"'; 423 | } 424 | else if (i.toLowerCase() != "classid") { 425 | att += ' ' + i + '="' + attObj[i] + '"'; 426 | } 427 | } 428 | } 429 | var par = ""; 430 | for (var j in parObj) { 431 | if (parObj[j] != Object.prototype[j]) { // filter out prototype additions from other potential libraries 432 | par += ''; 433 | } 434 | } 435 | el.outerHTML = '' + par + ''; 436 | objIdArr[objIdArr.length] = attObj.id; // stored to fix object 'leaks' on unload (dynamic publishing only) 437 | r = getElementById(attObj.id); 438 | } 439 | else { // well-behaving browsers 440 | var o = createElement(OBJECT); 441 | o.setAttribute("type", FLASH_MIME_TYPE); 442 | for (var m in attObj) { 443 | if (attObj[m] != Object.prototype[m]) { // filter out prototype additions from other potential libraries 444 | if (m.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword 445 | o.setAttribute("class", attObj[m]); 446 | } 447 | else if (m.toLowerCase() != "classid") { // filter out IE specific attribute 448 | o.setAttribute(m, attObj[m]); 449 | } 450 | } 451 | } 452 | for (var n in parObj) { 453 | if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { // filter out prototype additions from other potential libraries and IE specific param element 454 | createObjParam(o, n, parObj[n]); 455 | } 456 | } 457 | el.parentNode.replaceChild(o, el); 458 | r = o; 459 | } 460 | } 461 | return r; 462 | } 463 | 464 | function createObjParam(el, pName, pValue) { 465 | var p = createElement("param"); 466 | p.setAttribute("name", pName); 467 | p.setAttribute("value", pValue); 468 | el.appendChild(p); 469 | } 470 | 471 | /* Cross-browser SWF removal 472 | - Especially needed to safely and completely remove a SWF in Internet Explorer 473 | */ 474 | function removeSWF(id) { 475 | var obj = getElementById(id); 476 | if (obj && obj.nodeName == "OBJECT") { 477 | if (ua.ie && ua.win) { 478 | obj.style.display = "none"; 479 | (function(){ 480 | if (obj.readyState == 4) { 481 | removeObjectInIE(id); 482 | } 483 | else { 484 | setTimeout(arguments.callee, 10); 485 | } 486 | })(); 487 | } 488 | else { 489 | obj.parentNode.removeChild(obj); 490 | } 491 | } 492 | } 493 | 494 | function removeObjectInIE(id) { 495 | var obj = getElementById(id); 496 | if (obj) { 497 | for (var i in obj) { 498 | if (typeof obj[i] == "function") { 499 | obj[i] = null; 500 | } 501 | } 502 | obj.parentNode.removeChild(obj); 503 | } 504 | } 505 | 506 | /* Functions to optimize JavaScript compression 507 | */ 508 | function getElementById(id) { 509 | var el = null; 510 | try { 511 | el = doc.getElementById(id); 512 | } 513 | catch (e) {} 514 | return el; 515 | } 516 | 517 | function createElement(el) { 518 | return doc.createElement(el); 519 | } 520 | 521 | /* Updated attachEvent function for Internet Explorer 522 | - Stores attachEvent information in an Array, so on unload the detachEvent functions can be called to avoid memory leaks 523 | */ 524 | function addListener(target, eventType, fn) { 525 | target.attachEvent(eventType, fn); 526 | listenersArr[listenersArr.length] = [target, eventType, fn]; 527 | } 528 | 529 | /* Flash Player and SWF content version matching 530 | */ 531 | function hasPlayerVersion(rv) { 532 | var pv = ua.pv, v = rv.split("."); 533 | v[0] = parseInt(v[0], 10); 534 | v[1] = parseInt(v[1], 10) || 0; // supports short notation, e.g. "9" instead of "9.0.0" 535 | v[2] = parseInt(v[2], 10) || 0; 536 | return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false; 537 | } 538 | 539 | /* Cross-browser dynamic CSS creation 540 | - Based on Bobby van der Sluis' solution: http://www.bobbyvandersluis.com/articles/dynamicCSS.php 541 | */ 542 | function createCSS(sel, decl, media, newStyle) { 543 | if (ua.ie && ua.mac) { return; } 544 | var h = doc.getElementsByTagName("head")[0]; 545 | if (!h) { return; } // to also support badly authored HTML pages that lack a head element 546 | var m = (media && typeof media == "string") ? media : "screen"; 547 | if (newStyle) { 548 | dynamicStylesheet = null; 549 | dynamicStylesheetMedia = null; 550 | } 551 | if (!dynamicStylesheet || dynamicStylesheetMedia != m) { 552 | // create dynamic stylesheet + get a global reference to it 553 | var s = createElement("style"); 554 | s.setAttribute("type", "text/css"); 555 | s.setAttribute("media", m); 556 | dynamicStylesheet = h.appendChild(s); 557 | if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) { 558 | dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1]; 559 | } 560 | dynamicStylesheetMedia = m; 561 | } 562 | // add style rule 563 | if (ua.ie && ua.win) { 564 | if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) { 565 | dynamicStylesheet.addRule(sel, decl); 566 | } 567 | } 568 | else { 569 | if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) { 570 | dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}")); 571 | } 572 | } 573 | } 574 | 575 | function setVisibility(id, isVisible) { 576 | if (!autoHideShow) { return; } 577 | var v = isVisible ? "visible" : "hidden"; 578 | if (isDomLoaded && getElementById(id)) { 579 | getElementById(id).style.visibility = v; 580 | } 581 | else { 582 | createCSS("#" + id, "visibility:" + v); 583 | } 584 | } 585 | 586 | /* Filter to avoid XSS attacks 587 | */ 588 | function urlEncodeIfNecessary(s) { 589 | var regex = /[\\\"<>\.;]/; 590 | var hasBadChars = regex.exec(s) != null; 591 | return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s; 592 | } 593 | 594 | /* Release memory to avoid memory leaks caused by closures, fix hanging audio/video threads and force open sockets/NetConnections to disconnect (Internet Explorer only) 595 | */ 596 | var cleanup = function() { 597 | if (ua.ie && ua.win) { 598 | window.attachEvent("onunload", function() { 599 | // remove listeners to avoid memory leaks 600 | var ll = listenersArr.length; 601 | for (var i = 0; i < ll; i++) { 602 | listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]); 603 | } 604 | // cleanup dynamically embedded objects to fix audio/video threads and force open sockets and NetConnections to disconnect 605 | var il = objIdArr.length; 606 | for (var j = 0; j < il; j++) { 607 | removeSWF(objIdArr[j]); 608 | } 609 | // cleanup library's main closures to avoid memory leaks 610 | for (var k in ua) { 611 | ua[k] = null; 612 | } 613 | ua = null; 614 | for (var l in swfobject) { 615 | swfobject[l] = null; 616 | } 617 | swfobject = null; 618 | }); 619 | } 620 | }(); 621 | 622 | return { 623 | /* Public API 624 | - Reference: http://code.google.com/p/swfobject/wiki/documentation 625 | */ 626 | registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) { 627 | if (ua.w3 && objectIdStr && swfVersionStr) { 628 | var regObj = {}; 629 | regObj.id = objectIdStr; 630 | regObj.swfVersion = swfVersionStr; 631 | regObj.expressInstall = xiSwfUrlStr; 632 | regObj.callbackFn = callbackFn; 633 | regObjArr[regObjArr.length] = regObj; 634 | setVisibility(objectIdStr, false); 635 | } 636 | else if (callbackFn) { 637 | callbackFn({success:false, id:objectIdStr}); 638 | } 639 | }, 640 | 641 | getObjectById: function(objectIdStr) { 642 | if (ua.w3) { 643 | return getObjectById(objectIdStr); 644 | } 645 | }, 646 | 647 | embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) { 648 | var callbackObj = {success:false, id:replaceElemIdStr}; 649 | if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) { 650 | setVisibility(replaceElemIdStr, false); 651 | addDomLoadEvent(function() { 652 | widthStr += ""; // auto-convert to string 653 | heightStr += ""; 654 | var att = {}; 655 | if (attObj && typeof attObj === OBJECT) { 656 | for (var i in attObj) { // copy object to avoid the use of references, because web authors often reuse attObj for multiple SWFs 657 | att[i] = attObj[i]; 658 | } 659 | } 660 | att.data = swfUrlStr; 661 | att.width = widthStr; 662 | att.height = heightStr; 663 | var par = {}; 664 | if (parObj && typeof parObj === OBJECT) { 665 | for (var j in parObj) { // copy object to avoid the use of references, because web authors often reuse parObj for multiple SWFs 666 | par[j] = parObj[j]; 667 | } 668 | } 669 | if (flashvarsObj && typeof flashvarsObj === OBJECT) { 670 | for (var k in flashvarsObj) { // copy object to avoid the use of references, because web authors often reuse flashvarsObj for multiple SWFs 671 | if (typeof par.flashvars != UNDEF) { 672 | par.flashvars += "&" + k + "=" + flashvarsObj[k]; 673 | } 674 | else { 675 | par.flashvars = k + "=" + flashvarsObj[k]; 676 | } 677 | } 678 | } 679 | if (hasPlayerVersion(swfVersionStr)) { // create SWF 680 | var obj = createSWF(att, par, replaceElemIdStr); 681 | if (att.id == replaceElemIdStr) { 682 | setVisibility(replaceElemIdStr, true); 683 | } 684 | callbackObj.success = true; 685 | callbackObj.ref = obj; 686 | } 687 | else if (xiSwfUrlStr && canExpressInstall()) { // show Adobe Express Install 688 | att.data = xiSwfUrlStr; 689 | showExpressInstall(att, par, replaceElemIdStr, callbackFn); 690 | return; 691 | } 692 | else { // show alternative content 693 | setVisibility(replaceElemIdStr, true); 694 | } 695 | if (callbackFn) { callbackFn(callbackObj); } 696 | }); 697 | } 698 | else if (callbackFn) { callbackFn(callbackObj); } 699 | }, 700 | 701 | switchOffAutoHideShow: function() { 702 | autoHideShow = false; 703 | }, 704 | 705 | ua: ua, 706 | 707 | getFlashPlayerVersion: function() { 708 | return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] }; 709 | }, 710 | 711 | hasFlashPlayerVersion: hasPlayerVersion, 712 | 713 | createSWF: function(attObj, parObj, replaceElemIdStr) { 714 | if (ua.w3) { 715 | return createSWF(attObj, parObj, replaceElemIdStr); 716 | } 717 | else { 718 | return undefined; 719 | } 720 | }, 721 | 722 | showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) { 723 | if (ua.w3 && canExpressInstall()) { 724 | showExpressInstall(att, par, replaceElemIdStr, callbackFn); 725 | } 726 | }, 727 | 728 | removeSWF: function(objElemIdStr) { 729 | if (ua.w3) { 730 | removeSWF(objElemIdStr); 731 | } 732 | }, 733 | 734 | createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) { 735 | if (ua.w3) { 736 | createCSS(selStr, declStr, mediaStr, newStyleBoolean); 737 | } 738 | }, 739 | 740 | addDomLoadEvent: addDomLoadEvent, 741 | 742 | addLoadEvent: addLoadEvent, 743 | 744 | getQueryParamValue: function(param) { 745 | var q = doc.location.search || doc.location.hash; 746 | if (q) { 747 | if (/\?/.test(q)) { q = q.split("?")[1]; } // strip question mark 748 | if (param == null) { 749 | return urlEncodeIfNecessary(q); 750 | } 751 | var pairs = q.split("&"); 752 | for (var i = 0; i < pairs.length; i++) { 753 | if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) { 754 | return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1))); 755 | } 756 | } 757 | } 758 | return ""; 759 | }, 760 | 761 | // For internal usage only 762 | expressInstallCallback: function() { 763 | if (isExpressInstallActive) { 764 | var obj = getElementById(EXPRESS_INSTALL_ID); 765 | if (obj && storedAltContent) { 766 | obj.parentNode.replaceChild(storedAltContent, obj); 767 | if (storedAltContentId) { 768 | setVisibility(storedAltContentId, true); 769 | if (ua.ie && ua.win) { storedAltContent.style.display = "block"; } 770 | } 771 | if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); } 772 | } 773 | isExpressInstallActive = false; 774 | } 775 | } 776 | }; 777 | }(); 778 | -------------------------------------------------------------------------------- /deploy/TextureAtlas.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | 15 | 16 | 21 | 27 | 28 | 29 | 33 | 34 | 35 | 58 | 59 | 60 | 64 |
65 |

66 | To view this page ensure that Adobe Flash Player version 67 | 0.0.0 or greater is installed. 68 |

69 | 74 |
75 | 76 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /deploy/TextureAtlas.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pixelrevision/texture_atlas_generator/bf13b9d3edc9dfcbcf509d914f1036f14037b4d3/deploy/TextureAtlas.swf -------------------------------------------------------------------------------- /deploy/TextureAtlasGenerator.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pixelrevision/texture_atlas_generator/bf13b9d3edc9dfcbcf509d914f1036f14037b4d3/deploy/TextureAtlasGenerator.swf -------------------------------------------------------------------------------- /deploy/swfobject.js: -------------------------------------------------------------------------------- 1 | /*! SWFObject v2.2 2 | is released under the MIT License 3 | */ 4 | 5 | var swfobject = function() { 6 | 7 | var UNDEF = "undefined", 8 | OBJECT = "object", 9 | SHOCKWAVE_FLASH = "Shockwave Flash", 10 | SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash", 11 | FLASH_MIME_TYPE = "application/x-shockwave-flash", 12 | EXPRESS_INSTALL_ID = "SWFObjectExprInst", 13 | ON_READY_STATE_CHANGE = "onreadystatechange", 14 | 15 | win = window, 16 | doc = document, 17 | nav = navigator, 18 | 19 | plugin = false, 20 | domLoadFnArr = [main], 21 | regObjArr = [], 22 | objIdArr = [], 23 | listenersArr = [], 24 | storedAltContent, 25 | storedAltContentId, 26 | storedCallbackFn, 27 | storedCallbackObj, 28 | isDomLoaded = false, 29 | isExpressInstallActive = false, 30 | dynamicStylesheet, 31 | dynamicStylesheetMedia, 32 | autoHideShow = true, 33 | 34 | /* Centralized function for browser feature detection 35 | - User agent string detection is only used when no good alternative is possible 36 | - Is executed directly for optimal performance 37 | */ 38 | ua = function() { 39 | var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF, 40 | u = nav.userAgent.toLowerCase(), 41 | p = nav.platform.toLowerCase(), 42 | windows = p ? /win/.test(p) : /win/.test(u), 43 | mac = p ? /mac/.test(p) : /mac/.test(u), 44 | webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, // returns either the webkit version or false if not webkit 45 | ie = !+"\v1", // feature detection based on Andrea Giammarchi's solution: http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html 46 | playerVersion = [0,0,0], 47 | d = null; 48 | if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) { 49 | d = nav.plugins[SHOCKWAVE_FLASH].description; 50 | if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { // navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin indicates whether plug-ins are enabled or disabled in Safari 3+ 51 | plugin = true; 52 | ie = false; // cascaded feature detection for Internet Explorer 53 | d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1"); 54 | playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10); 55 | playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10); 56 | playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0; 57 | } 58 | } 59 | else if (typeof win.ActiveXObject != UNDEF) { 60 | try { 61 | var a = new ActiveXObject(SHOCKWAVE_FLASH_AX); 62 | if (a) { // a will return null when ActiveX is disabled 63 | d = a.GetVariable("$version"); 64 | if (d) { 65 | ie = true; // cascaded feature detection for Internet Explorer 66 | d = d.split(" ")[1].split(","); 67 | playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)]; 68 | } 69 | } 70 | } 71 | catch(e) {} 72 | } 73 | return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac }; 74 | }(), 75 | 76 | /* Cross-browser onDomLoad 77 | - Will fire an event as soon as the DOM of a web page is loaded 78 | - Internet Explorer workaround based on Diego Perini's solution: http://javascript.nwbox.com/IEContentLoaded/ 79 | - Regular onload serves as fallback 80 | */ 81 | onDomLoad = function() { 82 | if (!ua.w3) { return; } 83 | if ((typeof doc.readyState != UNDEF && doc.readyState == "complete") || (typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) { // function is fired after onload, e.g. when script is inserted dynamically 84 | callDomLoadFunctions(); 85 | } 86 | if (!isDomLoaded) { 87 | if (typeof doc.addEventListener != UNDEF) { 88 | doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false); 89 | } 90 | if (ua.ie && ua.win) { 91 | doc.attachEvent(ON_READY_STATE_CHANGE, function() { 92 | if (doc.readyState == "complete") { 93 | doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee); 94 | callDomLoadFunctions(); 95 | } 96 | }); 97 | if (win == top) { // if not inside an iframe 98 | (function(){ 99 | if (isDomLoaded) { return; } 100 | try { 101 | doc.documentElement.doScroll("left"); 102 | } 103 | catch(e) { 104 | setTimeout(arguments.callee, 0); 105 | return; 106 | } 107 | callDomLoadFunctions(); 108 | })(); 109 | } 110 | } 111 | if (ua.wk) { 112 | (function(){ 113 | if (isDomLoaded) { return; } 114 | if (!/loaded|complete/.test(doc.readyState)) { 115 | setTimeout(arguments.callee, 0); 116 | return; 117 | } 118 | callDomLoadFunctions(); 119 | })(); 120 | } 121 | addLoadEvent(callDomLoadFunctions); 122 | } 123 | }(); 124 | 125 | function callDomLoadFunctions() { 126 | if (isDomLoaded) { return; } 127 | try { // test if we can really add/remove elements to/from the DOM; we don't want to fire it too early 128 | var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span")); 129 | t.parentNode.removeChild(t); 130 | } 131 | catch (e) { return; } 132 | isDomLoaded = true; 133 | var dl = domLoadFnArr.length; 134 | for (var i = 0; i < dl; i++) { 135 | domLoadFnArr[i](); 136 | } 137 | } 138 | 139 | function addDomLoadEvent(fn) { 140 | if (isDomLoaded) { 141 | fn(); 142 | } 143 | else { 144 | domLoadFnArr[domLoadFnArr.length] = fn; // Array.push() is only available in IE5.5+ 145 | } 146 | } 147 | 148 | /* Cross-browser onload 149 | - Based on James Edwards' solution: http://brothercake.com/site/resources/scripts/onload/ 150 | - Will fire an event as soon as a web page including all of its assets are loaded 151 | */ 152 | function addLoadEvent(fn) { 153 | if (typeof win.addEventListener != UNDEF) { 154 | win.addEventListener("load", fn, false); 155 | } 156 | else if (typeof doc.addEventListener != UNDEF) { 157 | doc.addEventListener("load", fn, false); 158 | } 159 | else if (typeof win.attachEvent != UNDEF) { 160 | addListener(win, "onload", fn); 161 | } 162 | else if (typeof win.onload == "function") { 163 | var fnOld = win.onload; 164 | win.onload = function() { 165 | fnOld(); 166 | fn(); 167 | }; 168 | } 169 | else { 170 | win.onload = fn; 171 | } 172 | } 173 | 174 | /* Main function 175 | - Will preferably execute onDomLoad, otherwise onload (as a fallback) 176 | */ 177 | function main() { 178 | if (plugin) { 179 | testPlayerVersion(); 180 | } 181 | else { 182 | matchVersions(); 183 | } 184 | } 185 | 186 | /* Detect the Flash Player version for non-Internet Explorer browsers 187 | - Detecting the plug-in version via the object element is more precise than using the plugins collection item's description: 188 | a. Both release and build numbers can be detected 189 | b. Avoid wrong descriptions by corrupt installers provided by Adobe 190 | c. Avoid wrong descriptions by multiple Flash Player entries in the plugin Array, caused by incorrect browser imports 191 | - Disadvantage of this method is that it depends on the availability of the DOM, while the plugins collection is immediately available 192 | */ 193 | function testPlayerVersion() { 194 | var b = doc.getElementsByTagName("body")[0]; 195 | var o = createElement(OBJECT); 196 | o.setAttribute("type", FLASH_MIME_TYPE); 197 | var t = b.appendChild(o); 198 | if (t) { 199 | var counter = 0; 200 | (function(){ 201 | if (typeof t.GetVariable != UNDEF) { 202 | var d = t.GetVariable("$version"); 203 | if (d) { 204 | d = d.split(" ")[1].split(","); 205 | ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)]; 206 | } 207 | } 208 | else if (counter < 10) { 209 | counter++; 210 | setTimeout(arguments.callee, 10); 211 | return; 212 | } 213 | b.removeChild(o); 214 | t = null; 215 | matchVersions(); 216 | })(); 217 | } 218 | else { 219 | matchVersions(); 220 | } 221 | } 222 | 223 | /* Perform Flash Player and SWF version matching; static publishing only 224 | */ 225 | function matchVersions() { 226 | var rl = regObjArr.length; 227 | if (rl > 0) { 228 | for (var i = 0; i < rl; i++) { // for each registered object element 229 | var id = regObjArr[i].id; 230 | var cb = regObjArr[i].callbackFn; 231 | var cbObj = {success:false, id:id}; 232 | if (ua.pv[0] > 0) { 233 | var obj = getElementById(id); 234 | if (obj) { 235 | if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { // Flash Player version >= published SWF version: Houston, we have a match! 236 | setVisibility(id, true); 237 | if (cb) { 238 | cbObj.success = true; 239 | cbObj.ref = getObjectById(id); 240 | cb(cbObj); 241 | } 242 | } 243 | else if (regObjArr[i].expressInstall && canExpressInstall()) { // show the Adobe Express Install dialog if set by the web page author and if supported 244 | var att = {}; 245 | att.data = regObjArr[i].expressInstall; 246 | att.width = obj.getAttribute("width") || "0"; 247 | att.height = obj.getAttribute("height") || "0"; 248 | if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); } 249 | if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); } 250 | // parse HTML object param element's name-value pairs 251 | var par = {}; 252 | var p = obj.getElementsByTagName("param"); 253 | var pl = p.length; 254 | for (var j = 0; j < pl; j++) { 255 | if (p[j].getAttribute("name").toLowerCase() != "movie") { 256 | par[p[j].getAttribute("name")] = p[j].getAttribute("value"); 257 | } 258 | } 259 | showExpressInstall(att, par, id, cb); 260 | } 261 | else { // Flash Player and SWF version mismatch or an older Webkit engine that ignores the HTML object element's nested param elements: display alternative content instead of SWF 262 | displayAltContent(obj); 263 | if (cb) { cb(cbObj); } 264 | } 265 | } 266 | } 267 | else { // if no Flash Player is installed or the fp version cannot be detected we let the HTML object element do its job (either show a SWF or alternative content) 268 | setVisibility(id, true); 269 | if (cb) { 270 | var o = getObjectById(id); // test whether there is an HTML object element or not 271 | if (o && typeof o.SetVariable != UNDEF) { 272 | cbObj.success = true; 273 | cbObj.ref = o; 274 | } 275 | cb(cbObj); 276 | } 277 | } 278 | } 279 | } 280 | } 281 | 282 | function getObjectById(objectIdStr) { 283 | var r = null; 284 | var o = getElementById(objectIdStr); 285 | if (o && o.nodeName == "OBJECT") { 286 | if (typeof o.SetVariable != UNDEF) { 287 | r = o; 288 | } 289 | else { 290 | var n = o.getElementsByTagName(OBJECT)[0]; 291 | if (n) { 292 | r = n; 293 | } 294 | } 295 | } 296 | return r; 297 | } 298 | 299 | /* Requirements for Adobe Express Install 300 | - only one instance can be active at a time 301 | - fp 6.0.65 or higher 302 | - Win/Mac OS only 303 | - no Webkit engines older than version 312 304 | */ 305 | function canExpressInstall() { 306 | return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312); 307 | } 308 | 309 | /* Show the Adobe Express Install dialog 310 | - Reference: http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=6a253b75 311 | */ 312 | function showExpressInstall(att, par, replaceElemIdStr, callbackFn) { 313 | isExpressInstallActive = true; 314 | storedCallbackFn = callbackFn || null; 315 | storedCallbackObj = {success:false, id:replaceElemIdStr}; 316 | var obj = getElementById(replaceElemIdStr); 317 | if (obj) { 318 | if (obj.nodeName == "OBJECT") { // static publishing 319 | storedAltContent = abstractAltContent(obj); 320 | storedAltContentId = null; 321 | } 322 | else { // dynamic publishing 323 | storedAltContent = obj; 324 | storedAltContentId = replaceElemIdStr; 325 | } 326 | att.id = EXPRESS_INSTALL_ID; 327 | if (typeof att.width == UNDEF || (!/%$/.test(att.width) && parseInt(att.width, 10) < 310)) { att.width = "310"; } 328 | if (typeof att.height == UNDEF || (!/%$/.test(att.height) && parseInt(att.height, 10) < 137)) { att.height = "137"; } 329 | doc.title = doc.title.slice(0, 47) + " - Flash Player Installation"; 330 | var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn", 331 | fv = "MMredirectURL=" + encodeURI(window.location).toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title; 332 | if (typeof par.flashvars != UNDEF) { 333 | par.flashvars += "&" + fv; 334 | } 335 | else { 336 | par.flashvars = fv; 337 | } 338 | // IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it, 339 | // because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work 340 | if (ua.ie && ua.win && obj.readyState != 4) { 341 | var newObj = createElement("div"); 342 | replaceElemIdStr += "SWFObjectNew"; 343 | newObj.setAttribute("id", replaceElemIdStr); 344 | obj.parentNode.insertBefore(newObj, obj); // insert placeholder div that will be replaced by the object element that loads expressinstall.swf 345 | obj.style.display = "none"; 346 | (function(){ 347 | if (obj.readyState == 4) { 348 | obj.parentNode.removeChild(obj); 349 | } 350 | else { 351 | setTimeout(arguments.callee, 10); 352 | } 353 | })(); 354 | } 355 | createSWF(att, par, replaceElemIdStr); 356 | } 357 | } 358 | 359 | /* Functions to abstract and display alternative content 360 | */ 361 | function displayAltContent(obj) { 362 | if (ua.ie && ua.win && obj.readyState != 4) { 363 | // IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it, 364 | // because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work 365 | var el = createElement("div"); 366 | obj.parentNode.insertBefore(el, obj); // insert placeholder div that will be replaced by the alternative content 367 | el.parentNode.replaceChild(abstractAltContent(obj), el); 368 | obj.style.display = "none"; 369 | (function(){ 370 | if (obj.readyState == 4) { 371 | obj.parentNode.removeChild(obj); 372 | } 373 | else { 374 | setTimeout(arguments.callee, 10); 375 | } 376 | })(); 377 | } 378 | else { 379 | obj.parentNode.replaceChild(abstractAltContent(obj), obj); 380 | } 381 | } 382 | 383 | function abstractAltContent(obj) { 384 | var ac = createElement("div"); 385 | if (ua.win && ua.ie) { 386 | ac.innerHTML = obj.innerHTML; 387 | } 388 | else { 389 | var nestedObj = obj.getElementsByTagName(OBJECT)[0]; 390 | if (nestedObj) { 391 | var c = nestedObj.childNodes; 392 | if (c) { 393 | var cl = c.length; 394 | for (var i = 0; i < cl; i++) { 395 | if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) { 396 | ac.appendChild(c[i].cloneNode(true)); 397 | } 398 | } 399 | } 400 | } 401 | } 402 | return ac; 403 | } 404 | 405 | /* Cross-browser dynamic SWF creation 406 | */ 407 | function createSWF(attObj, parObj, id) { 408 | var r, el = getElementById(id); 409 | if (ua.wk && ua.wk < 312) { return r; } 410 | if (el) { 411 | if (typeof attObj.id == UNDEF) { // if no 'id' is defined for the object element, it will inherit the 'id' from the alternative content 412 | attObj.id = id; 413 | } 414 | if (ua.ie && ua.win) { // Internet Explorer + the HTML object element + W3C DOM methods do not combine: fall back to outerHTML 415 | var att = ""; 416 | for (var i in attObj) { 417 | if (attObj[i] != Object.prototype[i]) { // filter out prototype additions from other potential libraries 418 | if (i.toLowerCase() == "data") { 419 | parObj.movie = attObj[i]; 420 | } 421 | else if (i.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword 422 | att += ' class="' + attObj[i] + '"'; 423 | } 424 | else if (i.toLowerCase() != "classid") { 425 | att += ' ' + i + '="' + attObj[i] + '"'; 426 | } 427 | } 428 | } 429 | var par = ""; 430 | for (var j in parObj) { 431 | if (parObj[j] != Object.prototype[j]) { // filter out prototype additions from other potential libraries 432 | par += ''; 433 | } 434 | } 435 | el.outerHTML = '' + par + ''; 436 | objIdArr[objIdArr.length] = attObj.id; // stored to fix object 'leaks' on unload (dynamic publishing only) 437 | r = getElementById(attObj.id); 438 | } 439 | else { // well-behaving browsers 440 | var o = createElement(OBJECT); 441 | o.setAttribute("type", FLASH_MIME_TYPE); 442 | for (var m in attObj) { 443 | if (attObj[m] != Object.prototype[m]) { // filter out prototype additions from other potential libraries 444 | if (m.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword 445 | o.setAttribute("class", attObj[m]); 446 | } 447 | else if (m.toLowerCase() != "classid") { // filter out IE specific attribute 448 | o.setAttribute(m, attObj[m]); 449 | } 450 | } 451 | } 452 | for (var n in parObj) { 453 | if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { // filter out prototype additions from other potential libraries and IE specific param element 454 | createObjParam(o, n, parObj[n]); 455 | } 456 | } 457 | el.parentNode.replaceChild(o, el); 458 | r = o; 459 | } 460 | } 461 | return r; 462 | } 463 | 464 | function createObjParam(el, pName, pValue) { 465 | var p = createElement("param"); 466 | p.setAttribute("name", pName); 467 | p.setAttribute("value", pValue); 468 | el.appendChild(p); 469 | } 470 | 471 | /* Cross-browser SWF removal 472 | - Especially needed to safely and completely remove a SWF in Internet Explorer 473 | */ 474 | function removeSWF(id) { 475 | var obj = getElementById(id); 476 | if (obj && obj.nodeName == "OBJECT") { 477 | if (ua.ie && ua.win) { 478 | obj.style.display = "none"; 479 | (function(){ 480 | if (obj.readyState == 4) { 481 | removeObjectInIE(id); 482 | } 483 | else { 484 | setTimeout(arguments.callee, 10); 485 | } 486 | })(); 487 | } 488 | else { 489 | obj.parentNode.removeChild(obj); 490 | } 491 | } 492 | } 493 | 494 | function removeObjectInIE(id) { 495 | var obj = getElementById(id); 496 | if (obj) { 497 | for (var i in obj) { 498 | if (typeof obj[i] == "function") { 499 | obj[i] = null; 500 | } 501 | } 502 | obj.parentNode.removeChild(obj); 503 | } 504 | } 505 | 506 | /* Functions to optimize JavaScript compression 507 | */ 508 | function getElementById(id) { 509 | var el = null; 510 | try { 511 | el = doc.getElementById(id); 512 | } 513 | catch (e) {} 514 | return el; 515 | } 516 | 517 | function createElement(el) { 518 | return doc.createElement(el); 519 | } 520 | 521 | /* Updated attachEvent function for Internet Explorer 522 | - Stores attachEvent information in an Array, so on unload the detachEvent functions can be called to avoid memory leaks 523 | */ 524 | function addListener(target, eventType, fn) { 525 | target.attachEvent(eventType, fn); 526 | listenersArr[listenersArr.length] = [target, eventType, fn]; 527 | } 528 | 529 | /* Flash Player and SWF content version matching 530 | */ 531 | function hasPlayerVersion(rv) { 532 | var pv = ua.pv, v = rv.split("."); 533 | v[0] = parseInt(v[0], 10); 534 | v[1] = parseInt(v[1], 10) || 0; // supports short notation, e.g. "9" instead of "9.0.0" 535 | v[2] = parseInt(v[2], 10) || 0; 536 | return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false; 537 | } 538 | 539 | /* Cross-browser dynamic CSS creation 540 | - Based on Bobby van der Sluis' solution: http://www.bobbyvandersluis.com/articles/dynamicCSS.php 541 | */ 542 | function createCSS(sel, decl, media, newStyle) { 543 | if (ua.ie && ua.mac) { return; } 544 | var h = doc.getElementsByTagName("head")[0]; 545 | if (!h) { return; } // to also support badly authored HTML pages that lack a head element 546 | var m = (media && typeof media == "string") ? media : "screen"; 547 | if (newStyle) { 548 | dynamicStylesheet = null; 549 | dynamicStylesheetMedia = null; 550 | } 551 | if (!dynamicStylesheet || dynamicStylesheetMedia != m) { 552 | // create dynamic stylesheet + get a global reference to it 553 | var s = createElement("style"); 554 | s.setAttribute("type", "text/css"); 555 | s.setAttribute("media", m); 556 | dynamicStylesheet = h.appendChild(s); 557 | if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) { 558 | dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1]; 559 | } 560 | dynamicStylesheetMedia = m; 561 | } 562 | // add style rule 563 | if (ua.ie && ua.win) { 564 | if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) { 565 | dynamicStylesheet.addRule(sel, decl); 566 | } 567 | } 568 | else { 569 | if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) { 570 | dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}")); 571 | } 572 | } 573 | } 574 | 575 | function setVisibility(id, isVisible) { 576 | if (!autoHideShow) { return; } 577 | var v = isVisible ? "visible" : "hidden"; 578 | if (isDomLoaded && getElementById(id)) { 579 | getElementById(id).style.visibility = v; 580 | } 581 | else { 582 | createCSS("#" + id, "visibility:" + v); 583 | } 584 | } 585 | 586 | /* Filter to avoid XSS attacks 587 | */ 588 | function urlEncodeIfNecessary(s) { 589 | var regex = /[\\\"<>\.;]/; 590 | var hasBadChars = regex.exec(s) != null; 591 | return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s; 592 | } 593 | 594 | /* Release memory to avoid memory leaks caused by closures, fix hanging audio/video threads and force open sockets/NetConnections to disconnect (Internet Explorer only) 595 | */ 596 | var cleanup = function() { 597 | if (ua.ie && ua.win) { 598 | window.attachEvent("onunload", function() { 599 | // remove listeners to avoid memory leaks 600 | var ll = listenersArr.length; 601 | for (var i = 0; i < ll; i++) { 602 | listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]); 603 | } 604 | // cleanup dynamically embedded objects to fix audio/video threads and force open sockets and NetConnections to disconnect 605 | var il = objIdArr.length; 606 | for (var j = 0; j < il; j++) { 607 | removeSWF(objIdArr[j]); 608 | } 609 | // cleanup library's main closures to avoid memory leaks 610 | for (var k in ua) { 611 | ua[k] = null; 612 | } 613 | ua = null; 614 | for (var l in swfobject) { 615 | swfobject[l] = null; 616 | } 617 | swfobject = null; 618 | }); 619 | } 620 | }(); 621 | 622 | return { 623 | /* Public API 624 | - Reference: http://code.google.com/p/swfobject/wiki/documentation 625 | */ 626 | registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) { 627 | if (ua.w3 && objectIdStr && swfVersionStr) { 628 | var regObj = {}; 629 | regObj.id = objectIdStr; 630 | regObj.swfVersion = swfVersionStr; 631 | regObj.expressInstall = xiSwfUrlStr; 632 | regObj.callbackFn = callbackFn; 633 | regObjArr[regObjArr.length] = regObj; 634 | setVisibility(objectIdStr, false); 635 | } 636 | else if (callbackFn) { 637 | callbackFn({success:false, id:objectIdStr}); 638 | } 639 | }, 640 | 641 | getObjectById: function(objectIdStr) { 642 | if (ua.w3) { 643 | return getObjectById(objectIdStr); 644 | } 645 | }, 646 | 647 | embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) { 648 | var callbackObj = {success:false, id:replaceElemIdStr}; 649 | if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) { 650 | setVisibility(replaceElemIdStr, false); 651 | addDomLoadEvent(function() { 652 | widthStr += ""; // auto-convert to string 653 | heightStr += ""; 654 | var att = {}; 655 | if (attObj && typeof attObj === OBJECT) { 656 | for (var i in attObj) { // copy object to avoid the use of references, because web authors often reuse attObj for multiple SWFs 657 | att[i] = attObj[i]; 658 | } 659 | } 660 | att.data = swfUrlStr; 661 | att.width = widthStr; 662 | att.height = heightStr; 663 | var par = {}; 664 | if (parObj && typeof parObj === OBJECT) { 665 | for (var j in parObj) { // copy object to avoid the use of references, because web authors often reuse parObj for multiple SWFs 666 | par[j] = parObj[j]; 667 | } 668 | } 669 | if (flashvarsObj && typeof flashvarsObj === OBJECT) { 670 | for (var k in flashvarsObj) { // copy object to avoid the use of references, because web authors often reuse flashvarsObj for multiple SWFs 671 | if (typeof par.flashvars != UNDEF) { 672 | par.flashvars += "&" + k + "=" + flashvarsObj[k]; 673 | } 674 | else { 675 | par.flashvars = k + "=" + flashvarsObj[k]; 676 | } 677 | } 678 | } 679 | if (hasPlayerVersion(swfVersionStr)) { // create SWF 680 | var obj = createSWF(att, par, replaceElemIdStr); 681 | if (att.id == replaceElemIdStr) { 682 | setVisibility(replaceElemIdStr, true); 683 | } 684 | callbackObj.success = true; 685 | callbackObj.ref = obj; 686 | } 687 | else if (xiSwfUrlStr && canExpressInstall()) { // show Adobe Express Install 688 | att.data = xiSwfUrlStr; 689 | showExpressInstall(att, par, replaceElemIdStr, callbackFn); 690 | return; 691 | } 692 | else { // show alternative content 693 | setVisibility(replaceElemIdStr, true); 694 | } 695 | if (callbackFn) { callbackFn(callbackObj); } 696 | }); 697 | } 698 | else if (callbackFn) { callbackFn(callbackObj); } 699 | }, 700 | 701 | switchOffAutoHideShow: function() { 702 | autoHideShow = false; 703 | }, 704 | 705 | ua: ua, 706 | 707 | getFlashPlayerVersion: function() { 708 | return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] }; 709 | }, 710 | 711 | hasFlashPlayerVersion: hasPlayerVersion, 712 | 713 | createSWF: function(attObj, parObj, replaceElemIdStr) { 714 | if (ua.w3) { 715 | return createSWF(attObj, parObj, replaceElemIdStr); 716 | } 717 | else { 718 | return undefined; 719 | } 720 | }, 721 | 722 | showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) { 723 | if (ua.w3 && canExpressInstall()) { 724 | showExpressInstall(att, par, replaceElemIdStr, callbackFn); 725 | } 726 | }, 727 | 728 | removeSWF: function(objElemIdStr) { 729 | if (ua.w3) { 730 | removeSWF(objElemIdStr); 731 | } 732 | }, 733 | 734 | createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) { 735 | if (ua.w3) { 736 | createCSS(selStr, declStr, mediaStr, newStyleBoolean); 737 | } 738 | }, 739 | 740 | addDomLoadEvent: addDomLoadEvent, 741 | 742 | addLoadEvent: addLoadEvent, 743 | 744 | getQueryParamValue: function(param) { 745 | var q = doc.location.search || doc.location.hash; 746 | if (q) { 747 | if (/\?/.test(q)) { q = q.split("?")[1]; } // strip question mark 748 | if (param == null) { 749 | return urlEncodeIfNecessary(q); 750 | } 751 | var pairs = q.split("&"); 752 | for (var i = 0; i < pairs.length; i++) { 753 | if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) { 754 | return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1))); 755 | } 756 | } 757 | } 758 | return ""; 759 | }, 760 | 761 | // For internal usage only 762 | expressInstallCallback: function() { 763 | if (isExpressInstallActive) { 764 | var obj = getElementById(EXPRESS_INSTALL_ID); 765 | if (obj && storedAltContent) { 766 | obj.parentNode.replaceChild(storedAltContent, obj); 767 | if (storedAltContentId) { 768 | setVisibility(storedAltContentId, true); 769 | if (ua.ie && ua.win) { storedAltContent.style.display = "block"; } 770 | } 771 | if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); } 772 | } 773 | isExpressInstallActive = false; 774 | } 775 | } 776 | }; 777 | }(); 778 | -------------------------------------------------------------------------------- /html-template/history/history.css: -------------------------------------------------------------------------------- 1 | /* This CSS stylesheet defines styles used by required elements in a flex application page that supports browser history */ 2 | 3 | #ie_historyFrame { width: 0px; height: 0px; display:none } 4 | #firefox_anchorDiv { width: 0px; height: 0px; display:none } 5 | #safari_formDiv { width: 0px; height: 0px; display:none } 6 | #safari_rememberDiv { width: 0px; height: 0px; display:none } 7 | -------------------------------------------------------------------------------- /html-template/history/history.js: -------------------------------------------------------------------------------- 1 | BrowserHistoryUtils = { 2 | addEvent: function(elm, evType, fn, useCapture) { 3 | useCapture = useCapture || false; 4 | if (elm.addEventListener) { 5 | elm.addEventListener(evType, fn, useCapture); 6 | return true; 7 | } 8 | else if (elm.attachEvent) { 9 | var r = elm.attachEvent('on' + evType, fn); 10 | return r; 11 | } 12 | else { 13 | elm['on' + evType] = fn; 14 | } 15 | } 16 | } 17 | 18 | BrowserHistory = (function() { 19 | // type of browser 20 | var browser = { 21 | ie: false, 22 | ie8: false, 23 | firefox: false, 24 | safari: false, 25 | opera: false, 26 | version: -1 27 | }; 28 | 29 | // if setDefaultURL has been called, our first clue 30 | // that the SWF is ready and listening 31 | //var swfReady = false; 32 | 33 | // the URL we'll send to the SWF once it is ready 34 | //var pendingURL = ''; 35 | 36 | // Default app state URL to use when no fragment ID present 37 | var defaultHash = ''; 38 | 39 | // Last-known app state URL 40 | var currentHref = document.location.href; 41 | 42 | // Initial URL (used only by IE) 43 | var initialHref = document.location.href; 44 | 45 | // Initial URL (used only by IE) 46 | var initialHash = document.location.hash; 47 | 48 | // History frame source URL prefix (used only by IE) 49 | var historyFrameSourcePrefix = 'history/historyFrame.html?'; 50 | 51 | // History maintenance (used only by Safari) 52 | var currentHistoryLength = -1; 53 | 54 | var historyHash = []; 55 | 56 | var initialState = createState(initialHref, initialHref + '#' + initialHash, initialHash); 57 | 58 | var backStack = []; 59 | var forwardStack = []; 60 | 61 | var currentObjectId = null; 62 | 63 | //UserAgent detection 64 | var useragent = navigator.userAgent.toLowerCase(); 65 | 66 | if (useragent.indexOf("opera") != -1) { 67 | browser.opera = true; 68 | } else if (useragent.indexOf("msie") != -1) { 69 | browser.ie = true; 70 | browser.version = parseFloat(useragent.substring(useragent.indexOf('msie') + 4)); 71 | if (browser.version == 8) 72 | { 73 | browser.ie = false; 74 | browser.ie8 = true; 75 | } 76 | } else if (useragent.indexOf("safari") != -1) { 77 | browser.safari = true; 78 | browser.version = parseFloat(useragent.substring(useragent.indexOf('safari') + 7)); 79 | } else if (useragent.indexOf("gecko") != -1) { 80 | browser.firefox = true; 81 | } 82 | 83 | if (browser.ie == true && browser.version == 7) { 84 | window["_ie_firstload"] = false; 85 | } 86 | 87 | function hashChangeHandler() 88 | { 89 | currentHref = document.location.href; 90 | var flexAppUrl = getHash(); 91 | //ADR: to fix multiple 92 | if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) { 93 | var pl = getPlayers(); 94 | for (var i = 0; i < pl.length; i++) { 95 | pl[i].browserURLChange(flexAppUrl); 96 | } 97 | } else { 98 | getPlayer().browserURLChange(flexAppUrl); 99 | } 100 | } 101 | 102 | // Accessor functions for obtaining specific elements of the page. 103 | function getHistoryFrame() 104 | { 105 | return document.getElementById('ie_historyFrame'); 106 | } 107 | 108 | function getAnchorElement() 109 | { 110 | return document.getElementById('firefox_anchorDiv'); 111 | } 112 | 113 | function getFormElement() 114 | { 115 | return document.getElementById('safari_formDiv'); 116 | } 117 | 118 | function getRememberElement() 119 | { 120 | return document.getElementById("safari_remember_field"); 121 | } 122 | 123 | // Get the Flash player object for performing ExternalInterface callbacks. 124 | // Updated for changes to SWFObject2. 125 | function getPlayer(id) { 126 | var i; 127 | 128 | if (id && document.getElementById(id)) { 129 | var r = document.getElementById(id); 130 | if (typeof r.SetVariable != "undefined") { 131 | return r; 132 | } 133 | else { 134 | var o = r.getElementsByTagName("object"); 135 | var e = r.getElementsByTagName("embed"); 136 | for (i = 0; i < o.length; i++) { 137 | if (typeof o[i].browserURLChange != "undefined") 138 | return o[i]; 139 | } 140 | for (i = 0; i < e.length; i++) { 141 | if (typeof e[i].browserURLChange != "undefined") 142 | return e[i]; 143 | } 144 | } 145 | } 146 | else { 147 | var o = document.getElementsByTagName("object"); 148 | var e = document.getElementsByTagName("embed"); 149 | for (i = 0; i < e.length; i++) { 150 | if (typeof e[i].browserURLChange != "undefined") 151 | { 152 | return e[i]; 153 | } 154 | } 155 | for (i = 0; i < o.length; i++) { 156 | if (typeof o[i].browserURLChange != "undefined") 157 | { 158 | return o[i]; 159 | } 160 | } 161 | } 162 | return undefined; 163 | } 164 | 165 | function getPlayers() { 166 | var i; 167 | var players = []; 168 | if (players.length == 0) { 169 | var tmp = document.getElementsByTagName('object'); 170 | for (i = 0; i < tmp.length; i++) 171 | { 172 | if (typeof tmp[i].browserURLChange != "undefined") 173 | players.push(tmp[i]); 174 | } 175 | } 176 | if (players.length == 0 || players[0].object == null) { 177 | var tmp = document.getElementsByTagName('embed'); 178 | for (i = 0; i < tmp.length; i++) 179 | { 180 | if (typeof tmp[i].browserURLChange != "undefined") 181 | players.push(tmp[i]); 182 | } 183 | } 184 | return players; 185 | } 186 | 187 | function getIframeHash() { 188 | var doc = getHistoryFrame().contentWindow.document; 189 | var hash = String(doc.location.search); 190 | if (hash.length == 1 && hash.charAt(0) == "?") { 191 | hash = ""; 192 | } 193 | else if (hash.length >= 2 && hash.charAt(0) == "?") { 194 | hash = hash.substring(1); 195 | } 196 | return hash; 197 | } 198 | 199 | /* Get the current location hash excluding the '#' symbol. */ 200 | function getHash() { 201 | // It would be nice if we could use document.location.hash here, 202 | // but it's faulty sometimes. 203 | var idx = document.location.href.indexOf('#'); 204 | return (idx >= 0) ? document.location.href.substr(idx+1) : ''; 205 | } 206 | 207 | /* Get the current location hash excluding the '#' symbol. */ 208 | function setHash(hash) { 209 | // It would be nice if we could use document.location.hash here, 210 | // but it's faulty sometimes. 211 | if (hash == '') hash = '#' 212 | document.location.hash = hash; 213 | } 214 | 215 | function createState(baseUrl, newUrl, flexAppUrl) { 216 | return { 'baseUrl': baseUrl, 'newUrl': newUrl, 'flexAppUrl': flexAppUrl, 'title': null }; 217 | } 218 | 219 | /* Add a history entry to the browser. 220 | * baseUrl: the portion of the location prior to the '#' 221 | * newUrl: the entire new URL, including '#' and following fragment 222 | * flexAppUrl: the portion of the location following the '#' only 223 | */ 224 | function addHistoryEntry(baseUrl, newUrl, flexAppUrl) { 225 | 226 | //delete all the history entries 227 | forwardStack = []; 228 | 229 | if (browser.ie) { 230 | //Check to see if we are being asked to do a navigate for the first 231 | //history entry, and if so ignore, because it's coming from the creation 232 | //of the history iframe 233 | if (flexAppUrl == defaultHash && document.location.href == initialHref && window['_ie_firstload']) { 234 | currentHref = initialHref; 235 | return; 236 | } 237 | if ((!flexAppUrl || flexAppUrl == defaultHash) && window['_ie_firstload']) { 238 | newUrl = baseUrl + '#' + defaultHash; 239 | flexAppUrl = defaultHash; 240 | } else { 241 | // for IE, tell the history frame to go somewhere without a '#' 242 | // in order to get this entry into the browser history. 243 | getHistoryFrame().src = historyFrameSourcePrefix + flexAppUrl; 244 | } 245 | setHash(flexAppUrl); 246 | } else { 247 | 248 | //ADR 249 | if (backStack.length == 0 && initialState.flexAppUrl == flexAppUrl) { 250 | initialState = createState(baseUrl, newUrl, flexAppUrl); 251 | } else if(backStack.length > 0 && backStack[backStack.length - 1].flexAppUrl == flexAppUrl) { 252 | backStack[backStack.length - 1] = createState(baseUrl, newUrl, flexAppUrl); 253 | } 254 | 255 | if (browser.safari) { 256 | // for Safari, submit a form whose action points to the desired URL 257 | if (browser.version <= 419.3) { 258 | var file = window.location.pathname.toString(); 259 | file = file.substring(file.lastIndexOf("/")+1); 260 | getFormElement().innerHTML = '
'; 261 | //get the current elements and add them to the form 262 | var qs = window.location.search.substring(1); 263 | var qs_arr = qs.split("&"); 264 | for (var i = 0; i < qs_arr.length; i++) { 265 | var tmp = qs_arr[i].split("="); 266 | var elem = document.createElement("input"); 267 | elem.type = "hidden"; 268 | elem.name = tmp[0]; 269 | elem.value = tmp[1]; 270 | document.forms.historyForm.appendChild(elem); 271 | } 272 | document.forms.historyForm.submit(); 273 | } else { 274 | top.location.hash = flexAppUrl; 275 | } 276 | // We also have to maintain the history by hand for Safari 277 | historyHash[history.length] = flexAppUrl; 278 | _storeStates(); 279 | } else { 280 | // Otherwise, write an anchor into the page and tell the browser to go there 281 | addAnchor(flexAppUrl); 282 | setHash(flexAppUrl); 283 | 284 | // For IE8 we must restore full focus/activation to our invoking player instance. 285 | if (browser.ie8) 286 | getPlayer().focus(); 287 | } 288 | } 289 | backStack.push(createState(baseUrl, newUrl, flexAppUrl)); 290 | } 291 | 292 | function _storeStates() { 293 | if (browser.safari) { 294 | getRememberElement().value = historyHash.join(","); 295 | } 296 | } 297 | 298 | function handleBackButton() { 299 | //The "current" page is always at the top of the history stack. 300 | var current = backStack.pop(); 301 | if (!current) { return; } 302 | var last = backStack[backStack.length - 1]; 303 | if (!last && backStack.length == 0){ 304 | last = initialState; 305 | } 306 | forwardStack.push(current); 307 | } 308 | 309 | function handleForwardButton() { 310 | //summary: private method. Do not call this directly. 311 | 312 | var last = forwardStack.pop(); 313 | if (!last) { return; } 314 | backStack.push(last); 315 | } 316 | 317 | function handleArbitraryUrl() { 318 | //delete all the history entries 319 | forwardStack = []; 320 | } 321 | 322 | /* Called periodically to poll to see if we need to detect navigation that has occurred */ 323 | function checkForUrlChange() { 324 | 325 | if (browser.ie) { 326 | if (currentHref != document.location.href && currentHref + '#' != document.location.href) { 327 | //This occurs when the user has navigated to a specific URL 328 | //within the app, and didn't use browser back/forward 329 | //IE seems to have a bug where it stops updating the URL it 330 | //shows the end-user at this point, but programatically it 331 | //appears to be correct. Do a full app reload to get around 332 | //this issue. 333 | if (browser.version < 7) { 334 | currentHref = document.location.href; 335 | document.location.reload(); 336 | } else { 337 | if (getHash() != getIframeHash()) { 338 | // this.iframe.src = this.blankURL + hash; 339 | var sourceToSet = historyFrameSourcePrefix + getHash(); 340 | getHistoryFrame().src = sourceToSet; 341 | currentHref = document.location.href; 342 | } 343 | } 344 | } 345 | } 346 | 347 | if (browser.safari) { 348 | // For Safari, we have to check to see if history.length changed. 349 | if (currentHistoryLength >= 0 && history.length != currentHistoryLength) { 350 | //alert("did change: " + history.length + ", " + historyHash.length + "|" + historyHash[history.length] + "|>" + historyHash.join("|")); 351 | var flexAppUrl = getHash(); 352 | if (browser.version < 528.16 /* Anything earlier than Safari 4.0 */) 353 | { 354 | // If it did change and we're running Safari 3.x or earlier, 355 | // then we have to look the old state up in our hand-maintained 356 | // array since document.location.hash won't have changed, 357 | // then call back into BrowserManager. 358 | currentHistoryLength = history.length; 359 | flexAppUrl = historyHash[currentHistoryLength]; 360 | } 361 | 362 | //ADR: to fix multiple 363 | if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) { 364 | var pl = getPlayers(); 365 | for (var i = 0; i < pl.length; i++) { 366 | pl[i].browserURLChange(flexAppUrl); 367 | } 368 | } else { 369 | getPlayer().browserURLChange(flexAppUrl); 370 | } 371 | _storeStates(); 372 | } 373 | } 374 | if (browser.firefox) { 375 | if (currentHref != document.location.href) { 376 | var bsl = backStack.length; 377 | 378 | var urlActions = { 379 | back: false, 380 | forward: false, 381 | set: false 382 | } 383 | 384 | if ((window.location.hash == initialHash || window.location.href == initialHref) && (bsl == 1)) { 385 | urlActions.back = true; 386 | // FIXME: could this ever be a forward button? 387 | // we can't clear it because we still need to check for forwards. Ugg. 388 | // clearInterval(this.locationTimer); 389 | handleBackButton(); 390 | } 391 | 392 | // first check to see if we could have gone forward. We always halt on 393 | // a no-hash item. 394 | if (forwardStack.length > 0) { 395 | if (forwardStack[forwardStack.length-1].flexAppUrl == getHash()) { 396 | urlActions.forward = true; 397 | handleForwardButton(); 398 | } 399 | } 400 | 401 | // ok, that didn't work, try someplace back in the history stack 402 | if ((bsl >= 2) && (backStack[bsl - 2])) { 403 | if (backStack[bsl - 2].flexAppUrl == getHash()) { 404 | urlActions.back = true; 405 | handleBackButton(); 406 | } 407 | } 408 | 409 | if (!urlActions.back && !urlActions.forward) { 410 | var foundInStacks = { 411 | back: -1, 412 | forward: -1 413 | } 414 | 415 | for (var i = 0; i < backStack.length; i++) { 416 | if (backStack[i].flexAppUrl == getHash() && i != (bsl - 2)) { 417 | arbitraryUrl = true; 418 | foundInStacks.back = i; 419 | } 420 | } 421 | for (var i = 0; i < forwardStack.length; i++) { 422 | if (forwardStack[i].flexAppUrl == getHash() && i != (bsl - 2)) { 423 | arbitraryUrl = true; 424 | foundInStacks.forward = i; 425 | } 426 | } 427 | handleArbitraryUrl(); 428 | } 429 | 430 | // Firefox changed; do a callback into BrowserManager to tell it. 431 | currentHref = document.location.href; 432 | var flexAppUrl = getHash(); 433 | //ADR: to fix multiple 434 | if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) { 435 | var pl = getPlayers(); 436 | for (var i = 0; i < pl.length; i++) { 437 | pl[i].browserURLChange(flexAppUrl); 438 | } 439 | } else { 440 | getPlayer().browserURLChange(flexAppUrl); 441 | } 442 | } 443 | } 444 | //setTimeout(checkForUrlChange, 50); 445 | } 446 | 447 | /* Write an anchor into the page to legitimize it as a URL for Firefox et al. */ 448 | function addAnchor(flexAppUrl) 449 | { 450 | if (document.getElementsByName(flexAppUrl).length == 0) { 451 | getAnchorElement().innerHTML += "" + flexAppUrl + ""; 452 | } 453 | } 454 | 455 | var _initialize = function () { 456 | if (browser.ie) 457 | { 458 | var scripts = document.getElementsByTagName('script'); 459 | for (var i = 0, s; s = scripts[i]; i++) { 460 | if (s.src.indexOf("history.js") > -1) { 461 | var iframe_location = (new String(s.src)).replace("history.js", "historyFrame.html"); 462 | } 463 | } 464 | historyFrameSourcePrefix = iframe_location + "?"; 465 | var src = historyFrameSourcePrefix; 466 | 467 | var iframe = document.createElement("iframe"); 468 | iframe.id = 'ie_historyFrame'; 469 | iframe.name = 'ie_historyFrame'; 470 | iframe.src = 'javascript:false;'; 471 | 472 | try { 473 | document.body.appendChild(iframe); 474 | } catch(e) { 475 | setTimeout(function() { 476 | document.body.appendChild(iframe); 477 | }, 0); 478 | } 479 | } 480 | 481 | if (browser.safari) 482 | { 483 | var rememberDiv = document.createElement("div"); 484 | rememberDiv.id = 'safari_rememberDiv'; 485 | document.body.appendChild(rememberDiv); 486 | rememberDiv.innerHTML = ''; 487 | 488 | var formDiv = document.createElement("div"); 489 | formDiv.id = 'safari_formDiv'; 490 | document.body.appendChild(formDiv); 491 | 492 | var reloader_content = document.createElement('div'); 493 | reloader_content.id = 'safarireloader'; 494 | var scripts = document.getElementsByTagName('script'); 495 | for (var i = 0, s; s = scripts[i]; i++) { 496 | if (s.src.indexOf("history.js") > -1) { 497 | html = (new String(s.src)).replace(".js", ".html"); 498 | } 499 | } 500 | reloader_content.innerHTML = ''; 501 | document.body.appendChild(reloader_content); 502 | reloader_content.style.position = 'absolute'; 503 | reloader_content.style.left = reloader_content.style.top = '-9999px'; 504 | iframe = reloader_content.getElementsByTagName('iframe')[0]; 505 | 506 | if (document.getElementById("safari_remember_field").value != "" ) { 507 | historyHash = document.getElementById("safari_remember_field").value.split(","); 508 | } 509 | 510 | } 511 | 512 | if (browser.firefox || browser.ie8) 513 | { 514 | var anchorDiv = document.createElement("div"); 515 | anchorDiv.id = 'firefox_anchorDiv'; 516 | document.body.appendChild(anchorDiv); 517 | } 518 | 519 | if (browser.ie8) 520 | document.body.onhashchange = hashChangeHandler; 521 | //setTimeout(checkForUrlChange, 50); 522 | } 523 | 524 | return { 525 | historyHash: historyHash, 526 | backStack: function() { return backStack; }, 527 | forwardStack: function() { return forwardStack }, 528 | getPlayer: getPlayer, 529 | initialize: function(src) { 530 | _initialize(src); 531 | }, 532 | setURL: function(url) { 533 | document.location.href = url; 534 | }, 535 | getURL: function() { 536 | return document.location.href; 537 | }, 538 | getTitle: function() { 539 | return document.title; 540 | }, 541 | setTitle: function(title) { 542 | try { 543 | backStack[backStack.length - 1].title = title; 544 | } catch(e) { } 545 | //if on safari, set the title to be the empty string. 546 | if (browser.safari) { 547 | if (title == "") { 548 | try { 549 | var tmp = window.location.href.toString(); 550 | title = tmp.substring((tmp.lastIndexOf("/")+1), tmp.lastIndexOf("#")); 551 | } catch(e) { 552 | title = ""; 553 | } 554 | } 555 | } 556 | document.title = title; 557 | }, 558 | setDefaultURL: function(def) 559 | { 560 | defaultHash = def; 561 | def = getHash(); 562 | //trailing ? is important else an extra frame gets added to the history 563 | //when navigating back to the first page. Alternatively could check 564 | //in history frame navigation to compare # and ?. 565 | if (browser.ie) 566 | { 567 | window['_ie_firstload'] = true; 568 | var sourceToSet = historyFrameSourcePrefix + def; 569 | var func = function() { 570 | getHistoryFrame().src = sourceToSet; 571 | window.location.replace("#" + def); 572 | setInterval(checkForUrlChange, 50); 573 | } 574 | try { 575 | func(); 576 | } catch(e) { 577 | window.setTimeout(function() { func(); }, 0); 578 | } 579 | } 580 | 581 | if (browser.safari) 582 | { 583 | currentHistoryLength = history.length; 584 | if (historyHash.length == 0) { 585 | historyHash[currentHistoryLength] = def; 586 | var newloc = "#" + def; 587 | window.location.replace(newloc); 588 | } else { 589 | //alert(historyHash[historyHash.length-1]); 590 | } 591 | //setHash(def); 592 | setInterval(checkForUrlChange, 50); 593 | } 594 | 595 | 596 | if (browser.firefox || browser.opera) 597 | { 598 | var reg = new RegExp("#" + def + "$"); 599 | if (window.location.toString().match(reg)) { 600 | } else { 601 | var newloc ="#" + def; 602 | window.location.replace(newloc); 603 | } 604 | setInterval(checkForUrlChange, 50); 605 | //setHash(def); 606 | } 607 | 608 | }, 609 | 610 | /* Set the current browser URL; called from inside BrowserManager to propagate 611 | * the application state out to the container. 612 | */ 613 | setBrowserURL: function(flexAppUrl, objectId) { 614 | if (browser.ie && typeof objectId != "undefined") { 615 | currentObjectId = objectId; 616 | } 617 | //fromIframe = fromIframe || false; 618 | //fromFlex = fromFlex || false; 619 | //alert("setBrowserURL: " + flexAppUrl); 620 | //flexAppUrl = (flexAppUrl == "") ? defaultHash : flexAppUrl ; 621 | 622 | var pos = document.location.href.indexOf('#'); 623 | var baseUrl = pos != -1 ? document.location.href.substr(0, pos) : document.location.href; 624 | var newUrl = baseUrl + '#' + flexAppUrl; 625 | 626 | if (document.location.href != newUrl && document.location.href + '#' != newUrl) { 627 | currentHref = newUrl; 628 | addHistoryEntry(baseUrl, newUrl, flexAppUrl); 629 | currentHistoryLength = history.length; 630 | } 631 | }, 632 | 633 | browserURLChange: function(flexAppUrl) { 634 | var objectId = null; 635 | if (browser.ie && currentObjectId != null) { 636 | objectId = currentObjectId; 637 | } 638 | pendingURL = ''; 639 | 640 | if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) { 641 | var pl = getPlayers(); 642 | for (var i = 0; i < pl.length; i++) { 643 | try { 644 | pl[i].browserURLChange(flexAppUrl); 645 | } catch(e) { } 646 | } 647 | } else { 648 | try { 649 | getPlayer(objectId).browserURLChange(flexAppUrl); 650 | } catch(e) { } 651 | } 652 | 653 | currentObjectId = null; 654 | }, 655 | getUserAgent: function() { 656 | return navigator.userAgent; 657 | }, 658 | getPlatform: function() { 659 | return navigator.platform; 660 | } 661 | 662 | } 663 | 664 | })(); 665 | 666 | // Initialization 667 | 668 | // Automated unit testing and other diagnostics 669 | 670 | function setURL(url) 671 | { 672 | document.location.href = url; 673 | } 674 | 675 | function backButton() 676 | { 677 | history.back(); 678 | } 679 | 680 | function forwardButton() 681 | { 682 | history.forward(); 683 | } 684 | 685 | function goForwardOrBackInHistory(step) 686 | { 687 | history.go(step); 688 | } 689 | 690 | //BrowserHistoryUtils.addEvent(window, "load", function() { BrowserHistory.initialize(); }); 691 | (function(i) { 692 | var u =navigator.userAgent;var e=/*@cc_on!@*/false; 693 | var st = setTimeout; 694 | if(/webkit/i.test(u)){ 695 | st(function(){ 696 | var dr=document.readyState; 697 | if(dr=="loaded"||dr=="complete"){i()} 698 | else{st(arguments.callee,10);}},10); 699 | } else if((/mozilla/i.test(u)&&!/(compati)/.test(u)) || (/opera/i.test(u))){ 700 | document.addEventListener("DOMContentLoaded",i,false); 701 | } else if(e){ 702 | (function(){ 703 | var t=document.createElement('doc:rdy'); 704 | try{t.doScroll('left'); 705 | i();t=null; 706 | }catch(e){st(arguments.callee,0);}})(); 707 | } else{ 708 | window.onload=i; 709 | } 710 | })( function() {BrowserHistory.initialize();} ); 711 | -------------------------------------------------------------------------------- /html-template/history/historyFrame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 27 | Hidden frame for Browser History support. 28 | 29 | 30 | -------------------------------------------------------------------------------- /html-template/index.template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | ${title} 15 | 16 | 21 | 27 | 28 | 29 | 33 | 34 | 35 | 58 | 59 | 60 | 64 |
65 |

66 | To view this page ensure that Adobe Flash Player version 67 | ${version_major}.${version_minor}.${version_revision} or greater is installed. 68 |

69 | 74 |
75 | 76 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /html-template/playerProductInstall.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pixelrevision/texture_atlas_generator/bf13b9d3edc9dfcbcf509d914f1036f14037b4d3/html-template/playerProductInstall.swf -------------------------------------------------------------------------------- /src/com/pixelrevision/textureAtlas/LUAGenerator.as: -------------------------------------------------------------------------------- 1 | package com.pixelrevision.textureAtlas{ 2 | 3 | import com.pixelrevision.textureAtlas.Settings; 4 | 5 | public class LUAGenerator{ 6 | 7 | private var _settings:Settings; 8 | public function LUAGenerator(){ 9 | _settings = Settings.sharedInstance; 10 | } 11 | 12 | public function generate(items:Array):String{ 13 | var lua:String = ""; 14 | lua += generateClips(items); 15 | lua += addFramesToSprites(items); 16 | lua += generateSpriteSheetData(items); 17 | return lua; 18 | } 19 | 20 | private function generateClips(items:Array):String{ 21 | var i:int; 22 | var lua:String = "function getInstanceByName(name, fps)\n"; 23 | lua += "\tsprite = require(\"sprite\")\n"; 24 | lua += "\tspriteData = getSpriteSheetData(name)\n"; 25 | lua += "\tspriteSheet = sprite.newSpriteSheetFromData(\"" + _settings.textureName + ".png\", spriteData)\n"; 26 | lua += "\tspriteSet = registerSpriteSets(name, sprite, spriteSheet, fps)\n"; 27 | lua += "\tinstance = sprite.newSprite(spriteSet)\n"; 28 | lua += "\treturn instance\n"; 29 | lua += "end\n"; 30 | return lua; 31 | } 32 | 33 | private function addFramesToSprites(items:Array):String{ 34 | var lastName:String = ""; 35 | var lastFrame:String = ""; 36 | var i:int; 37 | var startSpriteSetFrame:int; 38 | var startTaggedFrame:int; 39 | var lua:String = "function registerSpriteSets(name, sprite, spriteSheet, fps)\n"; 40 | lua += "\tsecs = 1000/fps\n"; 41 | var sprData:Object = {}; 42 | lastName = ""; 43 | lastFrame = ""; 44 | var frameNumber:int = 1; 45 | var start:int = -1; 46 | var end:int; 47 | for(i=0; i _mask.width){ 57 | _hScrollBar.visible = true; 58 | }else{ 59 | _hScrollBar.visible = false; 60 | } 61 | if(_content.height > _mask.height){ 62 | _vScrollBar.visible = true; 63 | }else{ 64 | _vScrollBar.visible = false; 65 | } 66 | 67 | _vScrollBar.setThumbPercent(_mask.height/_content.height); 68 | _hScrollBar.setThumbPercent(_mask.width/_content.width); 69 | 70 | _vScrollBar.setSliderParams(0, -(_mask.height - _content.height)/SCROLL_SPEED, 0); 71 | _hScrollBar.setSliderParams(0, -(_mask.width - _content.width)/SCROLL_SPEED, 0); 72 | } 73 | 74 | 75 | private function scrollVert(e:Event):void{ 76 | _content.y = -_vScrollBar.value * SCROLL_SPEED; 77 | } 78 | 79 | private function scrollHoiz(e:Event):void{ 80 | _content.x = -_hScrollBar.value * SCROLL_SPEED; 81 | } 82 | } 83 | 84 | } -------------------------------------------------------------------------------- /src/com/pixelrevision/textureAtlas/Settings.as: -------------------------------------------------------------------------------- 1 | package com.pixelrevision.textureAtlas{ 2 | 3 | import com.pixelrevision.textureAtlas.events.TextureAtlasEvent; 4 | 5 | import flash.events.EventDispatcher; 6 | 7 | public class Settings extends EventDispatcher{ 8 | 9 | 10 | private static var _sharedInstance:Settings; 11 | 12 | private var _canvasWidth:Number = 1024; 13 | private var _canvasHeight:Number = 1024; 14 | private var _textureName:String = "sprite_sheet"; 15 | 16 | public static function get sharedInstance():Settings{ 17 | if(!_sharedInstance) _sharedInstance = new Settings(); 18 | return _sharedInstance; 19 | } 20 | 21 | public function Settings(){ 22 | 23 | } 24 | 25 | public function get textureName():String{ 26 | return _textureName; 27 | } 28 | public function set textureName(value:String):void{ 29 | _textureName = value; 30 | } 31 | 32 | 33 | public function get canvasWidth():Number{ 34 | return _canvasWidth; 35 | } 36 | public function set canvasWidth(value:Number):void{ 37 | _canvasWidth = value; 38 | dispatchEvent(new TextureAtlasEvent(TextureAtlasEvent.CANVAS_SIZE_CHANGED) ); 39 | } 40 | 41 | public function get canvasHeight():Number{ 42 | return _canvasHeight; 43 | } 44 | public function set canvasHeight(value:Number):void{ 45 | _canvasHeight = value; 46 | dispatchEvent(new TextureAtlasEvent(TextureAtlasEvent.CANVAS_SIZE_CHANGED) ); 47 | } 48 | 49 | 50 | } 51 | } -------------------------------------------------------------------------------- /src/com/pixelrevision/textureAtlas/TextureAtlas.as: -------------------------------------------------------------------------------- 1 | 2 | package com.pixelrevision.textureAtlas{ 3 | 4 | import com.pixelrevision.textureAtlas.events.TextureAtlasEvent; 5 | 6 | import flash.display.Sprite; 7 | import flash.display.StageAlign; 8 | import flash.display.StageScaleMode; 9 | import flash.events.Event; 10 | import flash.events.MouseEvent; 11 | 12 | [SWF(backgroundColor="0xEEEEEE", frameRate="60", width="800", height="600")] 13 | public class TextureAtlas extends Sprite{ 14 | 15 | public var menu:TextureAtlasMenu; 16 | public var textureLayout:TextureLayout; 17 | public var scrollWindow:ScrollWindow; 18 | private var _swfLoader:SWFFileLoader; 19 | private var _settings:Settings; 20 | 21 | public static const POW_2:Array = [32, 64, 128, 256, 512, 1024, 2048, 4096]; 22 | 23 | public function TextureAtlas(){ 24 | super(); 25 | setup(); 26 | } 27 | 28 | private function setup():void{ 29 | setupStage(); 30 | 31 | _settings = Settings.sharedInstance; 32 | 33 | _swfLoader = SWFFileLoader.sharedInstance; 34 | _swfLoader.addEventListener(TextureAtlasEvent.SWF_LOADED, newSWFLoaded); 35 | 36 | 37 | menu = new TextureAtlasMenu(); 38 | menu.saveSWFButton.addEventListener(MouseEvent.CLICK, saveFiles); 39 | addChild(menu); 40 | 41 | scrollWindow = new ScrollWindow(800, 600 - 40); 42 | scrollWindow.y = 40; 43 | addChild(scrollWindow); 44 | 45 | textureLayout = new TextureLayout(); 46 | textureLayout.addEventListener(TextureAtlasEvent.CANVAS_SIZE_CHANGED, checkScroll); 47 | 48 | } 49 | 50 | private function checkScroll(e:TextureAtlasEvent):void{ 51 | scrollWindow.checkLayout(); 52 | } 53 | 54 | private function newSWFLoaded(e:Event):void{ 55 | textureLayout.processSWF(_swfLoader.swf); 56 | scrollWindow.content = textureLayout; 57 | 58 | for(var i:uint=0; i _settings.canvasWidth){ 39 | xPos = 0; 40 | yPos += maxY; 41 | maxY = 0; 42 | } 43 | if(_items[i].height + 1 > maxY){ 44 | maxY = _items[i].height + 1; 45 | } 46 | _items[i].x = xPos; 47 | _items[i].y = yPos; 48 | xPos += _items[i].width + 1; 49 | } 50 | } 51 | 52 | private function drawBounds(e:TextureAtlasEvent):void{ 53 | graphics.clear(); 54 | graphics.lineStyle(1, 0x000000); 55 | graphics.drawRect(0, 0, _settings.canvasWidth-1, _settings.canvasHeight-1); 56 | layoutChildren(); 57 | dispatchEvent(new TextureAtlasEvent(TextureAtlasEvent.CANVAS_SIZE_CHANGED) ); 58 | } 59 | 60 | public function get withinBounds():Boolean{ 61 | trace(this.width, _settings.canvasWidth, this.height, _settings.canvasHeight); 62 | return (this.width <= _settings.canvasWidth && this.height <= _settings.canvasHeight); 63 | } 64 | 65 | public function addItem(item:TextureItem):void{ 66 | _items.push(item); 67 | addChild(item); 68 | } 69 | 70 | public function clear():void{ 71 | for(var i:uint=0; i<_items.length; i++){ 72 | removeChild(_items[i]); 73 | } 74 | _currentLab = ""; 75 | _items = []; 76 | } 77 | 78 | public function processSWF(swf:MovieClip):void{ 79 | clear(); 80 | var parseFrame:Boolean = false; 81 | var selected:MovieClip; 82 | var itemW:Number; 83 | var itemH:Number; 84 | var bounds:Rectangle; 85 | 86 | for(var i:uint=0; i 1){ 91 | for(var m:uint=0; m); 136 | xml.@imagePath = _settings.textureName + ".png"; 137 | 138 | 139 | // add a folder with all the images 140 | 141 | 142 | for(var i:uint=0; i<_items.length; i++){ 143 | 144 | var matrix:Matrix = new Matrix(); 145 | matrix.tx = _items[i].x; 146 | matrix.ty = _items[i].y; 147 | bmd.draw(_items[i], matrix); 148 | 149 | // xml 150 | var subText:XML = new XML(); 151 | subText.@x = _items[i].x; 152 | subText.@y = _items[i].y; 153 | subText.@width = _items[i].width; 154 | subText.@height = _items[i].height; 155 | subText.@name = _items[i].textureName; 156 | if(_items[i].frameName != "") subText.@frameLabel = _items[i].frameName; 157 | xml.appendChild(subText); 158 | 159 | // json 160 | var textureData:Object = new Object(); 161 | textureData.x = _items[i].x; 162 | textureData.y = _items[i].y; 163 | textureData.width = _items[i].width; 164 | textureData.height = _items[i].height; 165 | textureData.name = _items[i].textureName; 166 | if(_items[i].frameName != "") textureData.frameLabel = _items[i].frameName; 167 | json.textures.push(textureData); 168 | 169 | // make an item 170 | 171 | } 172 | 173 | var luaGenerator:LUAGenerator = new LUAGenerator(); 174 | var lua:String = luaGenerator.generate(_items); 175 | // trace(lua); 176 | 177 | // now setup zip 178 | var img:ByteArray = PNGEncoder.encode(bmd); 179 | var xmlString:String = xml.toString(); 180 | var jsonString:String = JSON.encode(json); 181 | var zip:FZip = new FZip(); 182 | zip.addFile(_settings.textureName + ".png", img); 183 | zip.addFileFromString(_settings.textureName + ".xml", xmlString); 184 | zip.addFileFromString(_settings.textureName + ".json", jsonString); 185 | zip.addFileFromString(_settings.textureName + ".lua", lua); 186 | 187 | for(i=0; i<_items.length; i++){ 188 | var ti:TextureItem = TextureItem(_items[i]); 189 | var encoded:ByteArray = PNGEncoder.encode(ti.graphic); 190 | zip.addFile("raw_images/" + ti.textureName + ".png", encoded); 191 | } 192 | 193 | // save 194 | var zipArray:ByteArray = new ByteArray(); 195 | zip.serialize(zipArray, true); 196 | var fr:FileReference = new FileReference(); 197 | fr.save(zipArray, _settings.textureName + ".zip"); 198 | 199 | 200 | 201 | 202 | 203 | 204 | drawBounds(null); 205 | } 206 | 207 | 208 | } 209 | } -------------------------------------------------------------------------------- /src/com/pixelrevision/textureAtlas/events/TextureAtlasEvent.as: -------------------------------------------------------------------------------- 1 | package com.pixelrevision.textureAtlas.events{ 2 | 3 | import flash.events.Event; 4 | 5 | public class TextureAtlasEvent extends Event{ 6 | 7 | public static const SWF_LOADED:String = "swfLoaded"; 8 | public static const CANVAS_SIZE_CHANGED:String = "canvasSizeChanged"; 9 | 10 | 11 | public function TextureAtlasEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false){ 12 | super(type, bubbles, cancelable); 13 | } 14 | 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /swc/MinimalComps.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pixelrevision/texture_atlas_generator/bf13b9d3edc9dfcbcf509d914f1036f14037b4d3/swc/MinimalComps.swc -------------------------------------------------------------------------------- /swc/as3corelib.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pixelrevision/texture_atlas_generator/bf13b9d3edc9dfcbcf509d914f1036f14037b4d3/swc/as3corelib.swc -------------------------------------------------------------------------------- /swc/fzip.swc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pixelrevision/texture_atlas_generator/bf13b9d3edc9dfcbcf509d914f1036f14037b4d3/swc/fzip.swc --------------------------------------------------------------------------------