1 2 3(function($) { 4 'use strict'; 5 /** 6 * All of the code for your admin-facing JavaScript source 7 * should reside in this file. 8 * 9 * Note: It has been assumed you will write jQuery code here, so the 10 * $ function reference has been prepared for usage within the scope 11 * of this function. 12 * 13 * This enables you to define handlers, for when the DOM is ready: 14 * 15 * $(function() { 16 * 17 * }); 18 * 19 * When the window is loaded: 20 * 21 * $( window ).load(function() { 22 * 23 * }); 24 * 25 * ...and/or other possibilities. 26 * 27 * Ideally, it is not considered best practise to attach more than a 28 * single DOM-ready or window-load handler for a particular page. 29 * Although scripts in the WordPress core, Plugins and Themes may be 30 * practising this, we should strive to set a better example in our own work. 31 */ 32 /** 33 * StencilWordPressAdmin 34 * 35 * @abstract 36 */ 37 var StencilWordPressAdmin = (function() { 38 /** 39 * Properties 40 * 41 */ 42 /** 43 * __browseRouterChangeDetectionInterval 44 * 45 * @access private 46 * @var Number (default: 1500) 47 */ 48 var __browseRouterChangeDetectionInterval = 1500; 49 /** 50 * __compiledWordPressPath 51 * 52 * @access private 53 * @var String (default: '/stencil/app/static/compiled/wordPress.js') 54 */ 55 var __compiledWordPressPath = '/stencil/app/static/compiled/wordPress.js'; 56 /** 57 * __filenames 58 * 59 * @access private 60 * @var Object 61 */ 62 var __filenames = { 63 admin: 'stencil-admin.js', 64 wordPressUtils: 'WordPressUtils.js' 65 }; 66 /** 67 * __hosts 68 * 69 * @access private 70 * @var Object 71 */ 72 var __hosts = { 73 local: 'local.getstencil.com', 74 dev: 'dev.getstencil.com', 75 prod: 'getstencil.com' 76 }; 77 /** 78 * __mediaFramePostBrowserRouterOverrideMethod 79 * 80 * @notes 'extend' or 'overwrite' 81 * @access private 82 * @var String (default: 'overwrite') 83 */ 84 var __mediaFramePostBrowserRouterOverrideMethod = 'overwrite'; 85 /** 86 * __mediaFrameSelectBrowserRouterOverrideMethod 87 * 88 * @notes 'extend' or 'overwrite' 89 * @access private 90 * @var String (default: 'overwrite') 91 */ 92 var __mediaFrameSelectBrowserRouterOverrideMethod = 'overwrite'; 93 /** 94 * __messages 95 * 96 * @access private 97 * @var Object 98 */ 99 var __messages = { 100 failed: 'Could not load Stencil. Please contact ' + 101 '[email protected] for help.' 102 }; 103 /** 104 * __overrideIntervalCheckDuration 105 * 106 * @access private 107 * @var Number (default: 10) 108 */ 109 var __overrideIntervalCheckDuration = 10; 110 /** 111 * __timeout 112 * 113 * @access private 114 * @var Number (default: 5000) 115 */ 116 var __timeout = 5000; 117 /** 118 * Methods 119 * 120 */ 121 /** 122 * __attempt 123 * 124 * @access private 125 * @param Function closure 126 * @return mixed|null 127 */ 128 var __attempt = function(closure) { 129 try { 130 var response = closure(); 131 return response; 132 } catch (err) { 133 } 134 return null; 135 }; 136 /** 137 * __callbacks 138 * 139 * @access private 140 * @var Object 141 */ 142 var __callbacks = { 143 /** 144 * error 145 * 146 * @access private 147 * @return Boolean 148 */ 149 error: function() { 150 var editPostPage = window.location.pathname.indexOf('wp-admin/post.php') !== -1; 151 if (editPostPage === false) { 152 return false;
153 } 154 var msg = __messages.failed; 155 alert(msg); 156 return true; 157 }, 158 /** 159 * success 160 * 161 * @access private 162 * @return void 163 */ 164 success: function() { 165 window.StencilWordPressUtils.init($); 166 } 167 }; 168 /** 169 * __extendMediaFramePostBrowseRouterClosure 170 * 171 * @access private 172 * @return void 173 */ 174 var __extendMediaFramePostBrowseRouterClosure = function() { 175 var callback = function() { 176 if (__mediaFramePostBrowseRouterProxied() === false) { 177 var originalReference = window.wp.media.view.MediaFrame.Post; 178 window.wp.media.view.MediaFrame.Post = originalReference.extend({ 179 browseRouter: function(routerView) { 180 StencilWordPressUtils; 181 var args = arguments; 182 args = [].slice.call(args); 183 originalReference.prototype.browseRouter.apply(this, args); 184 __handleMediaFramePostBrowserRouterCallback.apply(window, args); 185 } 186 }); 187 } 188 }, 189 period = __browseRouterChangeDetectionInterval, 190 reference = setInterval(callback, period); 191 callback(); 192 }; 193 /** 194 * __extendMediaFrameSelectBrowseRouterClosure 195 * 196 * @access private 197 * @return void 198 */ 199 var __extendMediaFrameSelectBrowseRouterClosure = function() { 200 var callback = function() { 201 if (__mediaFrameSelectBrowseRouterProxied() === false) { 202 var originalReference = window.wp.media.view.MediaFrame.Select; 203 window.wp.media.view.MediaFrame.Select = originalReference.extend({ 204 browseRouter: function(routerView) { 205 StencilWordPressUtils; 206 var args = arguments; 207 args = [].slice.call(args); 208 originalReference.prototype.browseRouter.apply(this, args); 209 __handleMediaFrameSelectBrowserRouterCallback.apply(window, args); 210 } 211 }); 212 } 213 }, 214 period = __browseRouterChangeDetectionInterval, 215 reference = setInterval(callback, period); 216 callback(); 217 }; 218 /** 219 * __getHost 220 * 221 * @access private 222 * @return String 223 */ 224 var __getHost = function() { 225 var role = __getRole(), 226 hosts = __hosts, 227 host = hosts[role]; 228 return host; 229 }; 230 /** 231 * __getHour 232 * 233 * @access private 234 * @return String 235 */ 236 var __getHour = function() { 237 var currentDate = new Date(), 238 hour = currentDate.getDate() + '/' 239 + (currentDate.getMonth() + 1) + '/' 240 + currentDate.getFullYear() + '@' 241 + currentDate.getHours() + ':' 242 + '00:' 243 + '00'; 244 return hour; 245 }; 246 /** 247 * __getLocalWordPressScriptPath 248 * 249 * @access private 250 * @return null|String 251 */ 252 var __getLocalWordPressScriptPath = function() { 253 var role = __getRole(), 254 path = __attempt(__getPluginWordPressUtilsPath); 255 if (path === null) { 256 return null; 257 } 258 if (role === 'local') { 259 path = __compiledWordPressPath; 260 } 261 var queryString = __getQueryString(); 262 path = (path) + '?' + (queryString); 263 return path; 264 }; 265 /** 266 * __getPluginVersion 267 * 268 * @access private 269 * @return null|String 270 */ 271 var __getPluginVersion = function() { 272 var adminFilename = __filenames.admin, 273 src = $('script[src*="' + (adminFilename) + '"]').first().attr('src'), 274 matches = src.match(/ver=([0-9\.]+)/); 275 if (matches === null) { 276 return null; 277 } 278 var version = matches.pop(); 279 return version; 280 }; 281 /** 282 * __getPluginWordPressUtilsPath 283 * 284 * @access private 285 * @return String 286 */ 287 var __getPluginWordPressUtilsPath = function() { 288 var adminFilename = __filenames.admin, 289 wordPressUtilsFilename = __filenames.wordPressUtils, 290 src = $('script[src*="' + (adminFilename) + '"]').first().attr('src'); 291 src = src.replace(adminFilename, wordPressUtilsFilename); 292 var host = window.location.host; 293 src = src.split(host).pop(); 294 return src; 295 }; 296 /** 297 * __getQueryData 298 * 299 * @access private 300 * @return Object 301 */ 302 var __getQueryData = function() {
303 var queryData = { 304 hour: __getHour(), 305 timezone: __getTimezone(), 306 version: __getPluginVersion() 307 }; 308 if (queryData.version === null) { 309 delete queryData.version; 310 } 311 return queryData; 312 }; 313 /** 314 * __getQueryString 315 * 316 * @access private 317 * @return String 318 */ 319 var __getQueryString = function() { 320 var queryData = __getQueryData(), 321 queryString = jQuery.param(queryData); 322 return queryString; 323 }; 324 /** 325 * __getRemoteWordPressScriptURL 326 * 327 * @access private 328 * @return String 329 */ 330 var __getRemoteWordPressScriptURL = function() { 331 var host = __getHost(), 332 path = __compiledWordPressPath, 333 queryString = __getQueryString(), 334 url = 'https://' + (host) + (path) + '?' + (queryString); 335 return url; 336 }; 337 /** 338 * __getRole 339 * 340 * @access private 341 * @return String 342 */ 343 var __getRole = function() { 344 if (window.location.host === 'local.getstencil.com') { 345 var role = 'local'; 346 return role; 347 } 348 if (window.location.host === 'dev.getstencil.com') { 349 var role = 'dev'; 350 return role; 351 } 352 var role = 'prod'; 353 return role; 354 }; 355 /** 356 * __getTimezone 357 * 358 * @see https://stackoverflow.com/questions/1954397/detect-timezone-abbreviation-using-javascript 359 * @see https://stackoverflow.com/a/34405528/115025 360 * @access private 361 * @return String 362 */ 363 var __getTimezone = function() { 364 var currentDate = new Date(), 365 lang = 'en-us', 366 localeTimeString = currentDate.toLocaleTimeString(lang, { 367 timeZoneName: 'short' 368 }), 369 pieces = localeTimeString.split(' '), 370 timezone = 'unknown'; 371 if (pieces.length > 2) { 372 timezone = pieces[2]; 373 } 374 return timezone; 375 }; 376 /** 377 * __handleMediaFramePostBrowserRouterCallback 378 * 379 * @access private 380 * @param Object routerView 381 * @return void 382 */ 383 var __handleMediaFramePostBrowserRouterCallback = function(routerView) { 384 StencilWordPressUtils.manage.browseRouter(routerView); 385 }; 386 /** 387 * __handleMediaFrameSelectBrowserRouterCallback 388 * 389 * @access private 390 * @param Object routerView 391 * @return void 392 */ 393 var __handleMediaFrameSelectBrowserRouterCallback = function(routerView) { 394 StencilWordPressUtils.manage.browseRouter(routerView); 395 }; 396 /** 397 * __loadLocalWordPressScript 398 * 399 * @access private 400 * @param Function error 401 * @return void 402 */ 403 var __loadLocalWordPressScript = function(error) { 404 var path = __getLocalWordPressScriptPath(), 405 url = path, 406 success = __callbacks.success; 407 if (path === null) { 408 error(); 409 } else { 410 __loadScript(url, success, error); 411 } 412 }; 413 /** 414 * __loadRemoteWordPressScript 415 * 416 * @access private 417 * @param Function error 418 * @return void 419 */ 420 var __loadRemoteWordPressScript = function(error) { 421 var url = __getRemoteWordPressScriptURL(), 422 success = __callbacks.success; 423 __loadScript(url, success, error); 424 }; 425 /** 426 * __loadScript 427 * 428 * @see https://api.jquery.com/jquery.getscript/ 429 * @access private 430 * @param String url 431 * @param Function success 432 * @param Function error 433 * @return void 434 */ 435 var __loadScript = function(url, success, error) { 436 $.ajax({ 437 cache: true,
438 dataType: 'script', 439 error: error, 440 success: success, 441 timeout: __timeout, 442 url: url 443 }); 444 }; 445 /** 446 * __loadWordPressScript 447 * 448 * @access private 449 * @return void 450 */ 451 var __loadWordPressScript = function() { 452 var error = function() { 453 var error = __callbacks.error; 454 __loadLocalWordPressScript(error); 455 }; 456 __loadRemoteWordPressScript(error); 457 }; 458 /** 459 * __mediaFramePostBrowseRouterProxied 460 * 461 * @access private 462 * @return Boolean 463 */ 464 var __mediaFramePostBrowseRouterProxied = function() { 465 var callback = window.wp.media.view.MediaFrame.Post.prototype.browseRouter, 466 str = callback.toString(); 467 if (str.match(/StencilWordPressUtils/) === null) { 468 return false; 469 } 470 return true; 471 }; 472 /** 473 * __mediaFrameSelectBrowseRouterProxied 474 * 475 * @access private 476 * @return Boolean 477 */ 478 var __mediaFrameSelectBrowseRouterProxied = function() { 479 var callback = window.wp.media.view.MediaFrame.Select.prototype.browseRouter, 480 str = callback.toString(); 481 if (str.match(/StencilWordPressUtils/) === null) { 482 return false; 483 } 484 return true; 485 }; 486 /** 487 * __override 488 * 489 * @access private 490 * @var Object 491 */ 492 var __override = { 493 /** 494 * mediaFramePostBrowseRouter 495 * 496 * @access private 497 * @return void 498 */ 499 mediaFramePostBrowseRouter: function() { 500 var scope = 'window.wp.media.view.MediaFrame.Post.prototype.browseRouter', 501 callback = function() { 502 __setMediaFramePostBrowseRouterChangeDetectionInterval(); 503 }; 504 __override.reference(scope, callback); 505 }, 506 /** 507 * mediaFrameSelectBrowseRouter 508 * 509 * @access private 510 * @return void 511 */ 512 mediaFrameSelectBrowseRouter: function() { 513 var scope = 'window.wp.media.view.MediaFrame.Select.prototype.browseRouter', 514 callback = function() { 515 __setMediaFrameSelectBrowseRouterChangeDetectionInterval(); 516 }; 517 __override.reference(scope, callback); 518 }, 519 /** 520 * modalOpen 521 * 522 * @access private 523 * @return void 524 */ 525 modalOpen: function() { 526 var scope = 'window.wp.media.view.Modal.prototype.on', 527 callback = function() { 528 var openModalCallback = function() { 529 StencilWordPressUtils.manage.modalOpen(this); 530 }; 531 window.wp.media.view.Modal.prototype.on( 532 'open', 533 openModalCallback 534 ); 535 }; 536 __override.reference(scope, callback); 537 }, 538 /** 539 * reference 540 * 541 * @access private 542 * @param String scope 543 * @param Function callback 544 * @return void 545 */ 546 reference: function(scope, callback) { 547 var interval, 548 check = function() { 549 if (__validReference(scope) === true) { 550 clearInterval(interval); 551 callback(); 552 } 553 }, 554 intervalCheckDuration = __overrideIntervalCheckDuration; 555 interval = setInterval(check, intervalCheckDuration); 556 } 557 }; 558 /**
559 * __overwriteMediaFramePostBrowseRouterClosure 560 * 561 * @access private 562 * @return void 563 */ 564 var __overwriteMediaFramePostBrowseRouterClosure = function() { 565 var callback = function() { 566 if (__mediaFramePostBrowseRouterProxied() === false) { 567 var originalCall = window.wp.media.view.MediaFrame.Post.prototype.browseRouter; 568 window.wp.media.view.MediaFrame.Post.prototype.browseRouter = function() { 569 StencilWordPressUtils; 570 var args = arguments; 571 args = [].slice.call(args); 572 originalCall.apply(window, args); 573 __handleMediaFramePostBrowserRouterCallback.apply(window, args); 574 }; 575 } 576 }, 577 period = __browseRouterChangeDetectionInterval, 578 reference = setInterval(callback, period); 579 callback(); 580 }; 581 /** 582 * __overwriteMediaFrameSelectBrowseRouterClosure 583 * 584 * @access private 585 * @return void 586 */ 587 var __overwriteMediaFrameSelectBrowseRouterClosure = function() { 588 var callback = function() { 589 if (__mediaFrameSelectBrowseRouterProxied() === false) { 590 var originalCall = window.wp.media.view.MediaFrame.Select.prototype.browseRouter; 591 window.wp.media.view.MediaFrame.Select.prototype.browseRouter = function() { 592 StencilWordPressUtils; 593 var args = arguments; 594 args = [].slice.call(args); 595 originalCall.apply(window, args); 596 __handleMediaFrameSelectBrowserRouterCallback.apply(window, args); 597 }; 598 } 599 }, 600 period = __browseRouterChangeDetectionInterval, 601 reference = setInterval(callback, period); 602 callback(); 603 }; 604 /** 605 * __setMediaFramePostBrowseRouterChangeDetectionInterval 606 * 607 * @access private 608 * @return void 609 */ 610 var __setMediaFramePostBrowseRouterChangeDetectionInterval = function() { 611 var method = __mediaFramePostBrowserRouterOverrideMethod; 612 if (method === 'extend') { 613 __extendMediaFramePostBrowseRouterClosure(); 614 } 615 if (method === 'overwrite') { 616 __overwriteMediaFramePostBrowseRouterClosure(); 617 } 618 }; 619 /** 620 * __setMediaFrameSelectBrowseRouterChangeDetectionInterval 621 * 622 * This method exists because while debugging why a specific WordPress 623 * website wasn't working, I found out that certain plugins may also 624 * take over the browseRouter function. 625 * 626 * The specific example I found was Envato Elements (v1.0.2), whereby it 627 * would override the browseRouter callback I specified. 628 * 629 * So to deal with this, I run an interval, and if it's found that the 630 * browseRouter callback does not conclusively contain Stencil logic, I 631 * create a wrapper of that new callback, and then add the 632 * browseRouterCallback value I need for the Stencil WordPress Plugin to 633 * work properly. 634 * 635 * @access private 636 * @return void 637 */ 638 var __setMediaFrameSelectBrowseRouterChangeDetectionInterval = function() { 639 var method = __mediaFrameSelectBrowserRouterOverrideMethod; 640 if (method === 'extend') { 641 __extendMediaFrameSelectBrowseRouterClosure(); 642 } 643 if (method === 'overwrite') { 644 __overwriteMediaFrameSelectBrowseRouterClosure(); 645 } 646 }; 647 /** 648 * _validReference 649 * 650 * @access private 651 * @param String str 652 * @return Boolean 653 */ 654 var __validReference = function(str) { 655 var pieces = str.split('.'), 656 index, 657 reference = window; 658 for (index in pieces) { 659 if (isNaN(index) === true) { 660 continue; 661 } 662 reference = reference[pieces[index]]; 663 if (reference === undefined) { 664 return false;
665 } 666 if (reference === null) { 667 return false; 668 } 669 } 670 return true; 671 }; 672 return { 673 /** 674 * Methods 675 * 676 */ 677 /** 678 * init 679 * 680 * @note The override methods are required to be called in this 681 * (stencil-admin.js) file rather than the loaded 682 * WordPressUtils.js file because in the newest WordPress 683 * (5.0.3), the "Set featured image" in the right column 684 * of a post/page is actually instantiated before the 685 * WordPressUtils.js file is loaded. 686 * This means that the prototype objects/references aren't 687 * overridden at the time that specific MediaFrame view 688 * objects are made, which results in the code not properly 689 * running in time. 690 * @access public 691 * @return void 692 */ 693 init: function() { 694 __override.mediaFrameSelectBrowseRouter(); 695 __override.modalOpen(); 696 $(document).ready(function($) { 697 __loadWordPressScript(); 698 }); 699 } 700 }; 701 })(); 702 StencilWordPressAdmin.init(); 703})(jQuery); 704;
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.