[ Index ] |
PHP Cross Reference of WordPress |
[Summary view] [Print] [Text view]
1 /** 2 * @output wp-includes/js/customize-base.js 3 */ 4 5 /** @namespace wp */ 6 window.wp = window.wp || {}; 7 8 (function( exports, $ ){ 9 var api = {}, ctor, inherits, 10 slice = Array.prototype.slice; 11 12 // Shared empty constructor function to aid in prototype-chain creation. 13 ctor = function() {}; 14 15 /** 16 * Helper function to correctly set up the prototype chain, for subclasses. 17 * Similar to `goog.inherits`, but uses a hash of prototype properties and 18 * class properties to be extended. 19 * 20 * @param object parent Parent class constructor to inherit from. 21 * @param object protoProps Properties to apply to the prototype for use as class instance properties. 22 * @param object staticProps Properties to apply directly to the class constructor. 23 * @return child The subclassed constructor. 24 */ 25 inherits = function( parent, protoProps, staticProps ) { 26 var child; 27 28 /* 29 * The constructor function for the new subclass is either defined by you 30 * (the "constructor" property in your `extend` definition), or defaulted 31 * by us to simply call `super()`. 32 */ 33 if ( protoProps && protoProps.hasOwnProperty( 'constructor' ) ) { 34 child = protoProps.constructor; 35 } else { 36 child = function() { 37 /* 38 * Storing the result `super()` before returning the value 39 * prevents a bug in Opera where, if the constructor returns 40 * a function, Opera will reject the return value in favor of 41 * the original object. This causes all sorts of trouble. 42 */ 43 var result = parent.apply( this, arguments ); 44 return result; 45 }; 46 } 47 48 // Inherit class (static) properties from parent. 49 $.extend( child, parent ); 50 51 // Set the prototype chain to inherit from `parent`, 52 // without calling `parent`'s constructor function. 53 ctor.prototype = parent.prototype; 54 child.prototype = new ctor(); 55 56 // Add prototype properties (instance properties) to the subclass, 57 // if supplied. 58 if ( protoProps ) { 59 $.extend( child.prototype, protoProps ); 60 } 61 62 // Add static properties to the constructor function, if supplied. 63 if ( staticProps ) { 64 $.extend( child, staticProps ); 65 } 66 67 // Correctly set child's `prototype.constructor`. 68 child.prototype.constructor = child; 69 70 // Set a convenience property in case the parent's prototype is needed later. 71 child.__super__ = parent.prototype; 72 73 return child; 74 }; 75 76 /** 77 * Base class for object inheritance. 78 */ 79 api.Class = function( applicator, argsArray, options ) { 80 var magic, args = arguments; 81 82 if ( applicator && argsArray && api.Class.applicator === applicator ) { 83 args = argsArray; 84 $.extend( this, options || {} ); 85 } 86 87 magic = this; 88 89 /* 90 * If the class has a method called "instance", 91 * the return value from the class' constructor will be a function that 92 * calls the "instance" method. 93 * 94 * It is also an object that has properties and methods inside it. 95 */ 96 if ( this.instance ) { 97 magic = function() { 98 return magic.instance.apply( magic, arguments ); 99 }; 100 101 $.extend( magic, this ); 102 } 103 104 magic.initialize.apply( magic, args ); 105 return magic; 106 }; 107 108 /** 109 * Creates a subclass of the class. 110 * 111 * @param object protoProps Properties to apply to the prototype. 112 * @param object staticProps Properties to apply directly to the class. 113 * @return child The subclass. 114 */ 115 api.Class.extend = function( protoProps, staticProps ) { 116 var child = inherits( this, protoProps, staticProps ); 117 child.extend = this.extend; 118 return child; 119 }; 120 121 api.Class.applicator = {}; 122 123 /** 124 * Initialize a class instance. 125 * 126 * Override this function in a subclass as needed. 127 */ 128 api.Class.prototype.initialize = function() {}; 129 130 /* 131 * Checks whether a given instance extended a constructor. 132 * 133 * The magic surrounding the instance parameter causes the instanceof 134 * keyword to return inaccurate results; it defaults to the function's 135 * prototype instead of the constructor chain. Hence this function. 136 */ 137 api.Class.prototype.extended = function( constructor ) { 138 var proto = this; 139 140 while ( typeof proto.constructor !== 'undefined' ) { 141 if ( proto.constructor === constructor ) { 142 return true; 143 } 144 if ( typeof proto.constructor.__super__ === 'undefined' ) { 145 return false; 146 } 147 proto = proto.constructor.__super__; 148 } 149 return false; 150 }; 151 152 /** 153 * An events manager object, offering the ability to bind to and trigger events. 154 * 155 * Used as a mixin. 156 */ 157 api.Events = { 158 trigger: function( id ) { 159 if ( this.topics && this.topics[ id ] ) { 160 this.topics[ id ].fireWith( this, slice.call( arguments, 1 ) ); 161 } 162 return this; 163 }, 164 165 bind: function( id ) { 166 this.topics = this.topics || {}; 167 this.topics[ id ] = this.topics[ id ] || $.Callbacks(); 168 this.topics[ id ].add.apply( this.topics[ id ], slice.call( arguments, 1 ) ); 169 return this; 170 }, 171 172 unbind: function( id ) { 173 if ( this.topics && this.topics[ id ] ) { 174 this.topics[ id ].remove.apply( this.topics[ id ], slice.call( arguments, 1 ) ); 175 } 176 return this; 177 } 178 }; 179 180 /** 181 * Observable values that support two-way binding. 182 * 183 * @memberOf wp.customize 184 * @alias wp.customize.Value 185 * 186 * @constructor 187 */ 188 api.Value = api.Class.extend(/** @lends wp.customize.Value.prototype */{ 189 /** 190 * @param {mixed} initial The initial value. 191 * @param {Object} options 192 */ 193 initialize: function( initial, options ) { 194 this._value = initial; // @todo Potentially change this to a this.set() call. 195 this.callbacks = $.Callbacks(); 196 this._dirty = false; 197 198 $.extend( this, options || {} ); 199 200 this.set = this.set.bind( this ); 201 }, 202 203 /* 204 * Magic. Returns a function that will become the instance. 205 * Set to null to prevent the instance from extending a function. 206 */ 207 instance: function() { 208 return arguments.length ? this.set.apply( this, arguments ) : this.get(); 209 }, 210 211 /** 212 * Get the value. 213 * 214 * @return {mixed} 215 */ 216 get: function() { 217 return this._value; 218 }, 219 220 /** 221 * Set the value and trigger all bound callbacks. 222 * 223 * @param {Object} to New value. 224 */ 225 set: function( to ) { 226 var from = this._value; 227 228 to = this._setter.apply( this, arguments ); 229 to = this.validate( to ); 230 231 // Bail if the sanitized value is null or unchanged. 232 if ( null === to || _.isEqual( from, to ) ) { 233 return this; 234 } 235 236 this._value = to; 237 this._dirty = true; 238 239 this.callbacks.fireWith( this, [ to, from ] ); 240 241 return this; 242 }, 243 244 _setter: function( to ) { 245 return to; 246 }, 247 248 setter: function( callback ) { 249 var from = this.get(); 250 this._setter = callback; 251 // Temporarily clear value so setter can decide if it's valid. 252 this._value = null; 253 this.set( from ); 254 return this; 255 }, 256 257 resetSetter: function() { 258 this._setter = this.constructor.prototype._setter; 259 this.set( this.get() ); 260 return this; 261 }, 262 263 validate: function( value ) { 264 return value; 265 }, 266 267 /** 268 * Bind a function to be invoked whenever the value changes. 269 * 270 * @param {...Function} A function, or multiple functions, to add to the callback stack. 271 */ 272 bind: function() { 273 this.callbacks.add.apply( this.callbacks, arguments ); 274 return this; 275 }, 276 277 /** 278 * Unbind a previously bound function. 279 * 280 * @param {...Function} A function, or multiple functions, to remove from the callback stack. 281 */ 282 unbind: function() { 283 this.callbacks.remove.apply( this.callbacks, arguments ); 284 return this; 285 }, 286 287 link: function() { // values* 288 var set = this.set; 289 $.each( arguments, function() { 290 this.bind( set ); 291 }); 292 return this; 293 }, 294 295 unlink: function() { // values* 296 var set = this.set; 297 $.each( arguments, function() { 298 this.unbind( set ); 299 }); 300 return this; 301 }, 302 303 sync: function() { // values* 304 var that = this; 305 $.each( arguments, function() { 306 that.link( this ); 307 this.link( that ); 308 }); 309 return this; 310 }, 311 312 unsync: function() { // values* 313 var that = this; 314 $.each( arguments, function() { 315 that.unlink( this ); 316 this.unlink( that ); 317 }); 318 return this; 319 } 320 }); 321 322 /** 323 * A collection of observable values. 324 * 325 * @memberOf wp.customize 326 * @alias wp.customize.Values 327 * 328 * @constructor 329 * @augments wp.customize.Class 330 * @mixes wp.customize.Events 331 */ 332 api.Values = api.Class.extend(/** @lends wp.customize.Values.prototype */{ 333 334 /** 335 * The default constructor for items of the collection. 336 * 337 * @type {object} 338 */ 339 defaultConstructor: api.Value, 340 341 initialize: function( options ) { 342 $.extend( this, options || {} ); 343 344 this._value = {}; 345 this._deferreds = {}; 346 }, 347 348 /** 349 * Get the instance of an item from the collection if only ID is specified. 350 * 351 * If more than one argument is supplied, all are expected to be IDs and 352 * the last to be a function callback that will be invoked when the requested 353 * items are available. 354 * 355 * @see {api.Values.when} 356 * 357 * @param {string} id ID of the item. 358 * @param {...} Zero or more IDs of items to wait for and a callback 359 * function to invoke when they're available. Optional. 360 * @return {mixed} The item instance if only one ID was supplied. 361 * A Deferred Promise object if a callback function is supplied. 362 */ 363 instance: function( id ) { 364 if ( arguments.length === 1 ) { 365 return this.value( id ); 366 } 367 368 return this.when.apply( this, arguments ); 369 }, 370 371 /** 372 * Get the instance of an item. 373 * 374 * @param {string} id The ID of the item. 375 * @return {[type]} [description] 376 */ 377 value: function( id ) { 378 return this._value[ id ]; 379 }, 380 381 /** 382 * Whether the collection has an item with the given ID. 383 * 384 * @param {string} id The ID of the item to look for. 385 * @return {boolean} 386 */ 387 has: function( id ) { 388 return typeof this._value[ id ] !== 'undefined'; 389 }, 390 391 /** 392 * Add an item to the collection. 393 * 394 * @param {string|wp.customize.Class} item - The item instance to add, or the ID for the instance to add. When an ID string is supplied, then itemObject must be provided. 395 * @param {wp.customize.Class} [itemObject] - The item instance when the first argument is a ID string. 396 * @return {wp.customize.Class} The new item's instance, or an existing instance if already added. 397 */ 398 add: function( item, itemObject ) { 399 var collection = this, id, instance; 400 if ( 'string' === typeof item ) { 401 id = item; 402 instance = itemObject; 403 } else { 404 if ( 'string' !== typeof item.id ) { 405 throw new Error( 'Unknown key' ); 406 } 407 id = item.id; 408 instance = item; 409 } 410 411 if ( collection.has( id ) ) { 412 return collection.value( id ); 413 } 414 415 collection._value[ id ] = instance; 416 instance.parent = collection; 417 418 // Propagate a 'change' event on an item up to the collection. 419 if ( instance.extended( api.Value ) ) { 420 instance.bind( collection._change ); 421 } 422 423 collection.trigger( 'add', instance ); 424 425 // If a deferred object exists for this item, 426 // resolve it. 427 if ( collection._deferreds[ id ] ) { 428 collection._deferreds[ id ].resolve(); 429 } 430 431 return collection._value[ id ]; 432 }, 433 434 /** 435 * Create a new item of the collection using the collection's default constructor 436 * and store it in the collection. 437 * 438 * @param {string} id The ID of the item. 439 * @param {mixed} value Any extra arguments are passed into the item's initialize method. 440 * @return {mixed} The new item's instance. 441 */ 442 create: function( id ) { 443 return this.add( id, new this.defaultConstructor( api.Class.applicator, slice.call( arguments, 1 ) ) ); 444 }, 445 446 /** 447 * Iterate over all items in the collection invoking the provided callback. 448 * 449 * @param {Function} callback Function to invoke. 450 * @param {Object} context Object context to invoke the function with. Optional. 451 */ 452 each: function( callback, context ) { 453 context = typeof context === 'undefined' ? this : context; 454 455 $.each( this._value, function( key, obj ) { 456 callback.call( context, obj, key ); 457 }); 458 }, 459 460 /** 461 * Remove an item from the collection. 462 * 463 * @param {string} id The ID of the item to remove. 464 */ 465 remove: function( id ) { 466 var value = this.value( id ); 467 468 if ( value ) { 469 470 // Trigger event right before the element is removed from the collection. 471 this.trigger( 'remove', value ); 472 473 if ( value.extended( api.Value ) ) { 474 value.unbind( this._change ); 475 } 476 delete value.parent; 477 } 478 479 delete this._value[ id ]; 480 delete this._deferreds[ id ]; 481 482 // Trigger removed event after the item has been eliminated from the collection. 483 if ( value ) { 484 this.trigger( 'removed', value ); 485 } 486 }, 487 488 /** 489 * Runs a callback once all requested values exist. 490 * 491 * when( ids*, [callback] ); 492 * 493 * For example: 494 * when( id1, id2, id3, function( value1, value2, value3 ) {} ); 495 * 496 * @return $.Deferred.promise(); 497 */ 498 when: function() { 499 var self = this, 500 ids = slice.call( arguments ), 501 dfd = $.Deferred(); 502 503 // If the last argument is a callback, bind it to .done(). 504 if ( typeof ids[ ids.length - 1 ] === 'function' ) { 505 dfd.done( ids.pop() ); 506 } 507 508 /* 509 * Create a stack of deferred objects for each item that is not 510 * yet available, and invoke the supplied callback when they are. 511 */ 512 $.when.apply( $, $.map( ids, function( id ) { 513 if ( self.has( id ) ) { 514 return; 515 } 516 517 /* 518 * The requested item is not available yet, create a deferred 519 * object to resolve when it becomes available. 520 */ 521 return self._deferreds[ id ] = self._deferreds[ id ] || $.Deferred(); 522 })).done( function() { 523 var values = $.map( ids, function( id ) { 524 return self( id ); 525 }); 526 527 // If a value is missing, we've used at least one expired deferred. 528 // Call Values.when again to generate a new deferred. 529 if ( values.length !== ids.length ) { 530 // ids.push( callback ); 531 self.when.apply( self, ids ).done( function() { 532 dfd.resolveWith( self, values ); 533 }); 534 return; 535 } 536 537 dfd.resolveWith( self, values ); 538 }); 539 540 return dfd.promise(); 541 }, 542 543 /** 544 * A helper function to propagate a 'change' event from an item 545 * to the collection itself. 546 */ 547 _change: function() { 548 this.parent.trigger( 'change', this ); 549 } 550 }); 551 552 // Create a global events bus on the Customizer. 553 $.extend( api.Values.prototype, api.Events ); 554 555 556 /** 557 * Cast a string to a jQuery collection if it isn't already. 558 * 559 * @param {string|jQuery collection} element 560 */ 561 api.ensure = function( element ) { 562 return typeof element === 'string' ? $( element ) : element; 563 }; 564 565 /** 566 * An observable value that syncs with an element. 567 * 568 * Handles inputs, selects, and textareas by default. 569 * 570 * @memberOf wp.customize 571 * @alias wp.customize.Element 572 * 573 * @constructor 574 * @augments wp.customize.Value 575 * @augments wp.customize.Class 576 */ 577 api.Element = api.Value.extend(/** @lends wp.customize.Element */{ 578 initialize: function( element, options ) { 579 var self = this, 580 synchronizer = api.Element.synchronizer.html, 581 type, update, refresh; 582 583 this.element = api.ensure( element ); 584 this.events = ''; 585 586 if ( this.element.is( 'input, select, textarea' ) ) { 587 type = this.element.prop( 'type' ); 588 this.events += ' change input'; 589 synchronizer = api.Element.synchronizer.val; 590 591 if ( this.element.is( 'input' ) && api.Element.synchronizer[ type ] ) { 592 synchronizer = api.Element.synchronizer[ type ]; 593 } 594 } 595 596 api.Value.prototype.initialize.call( this, null, $.extend( options || {}, synchronizer ) ); 597 this._value = this.get(); 598 599 update = this.update; 600 refresh = this.refresh; 601 602 this.update = function( to ) { 603 if ( to !== refresh.call( self ) ) { 604 update.apply( this, arguments ); 605 } 606 }; 607 this.refresh = function() { 608 self.set( refresh.call( self ) ); 609 }; 610 611 this.bind( this.update ); 612 this.element.on( this.events, this.refresh ); 613 }, 614 615 find: function( selector ) { 616 return $( selector, this.element ); 617 }, 618 619 refresh: function() {}, 620 621 update: function() {} 622 }); 623 624 api.Element.synchronizer = {}; 625 626 $.each( [ 'html', 'val' ], function( index, method ) { 627 api.Element.synchronizer[ method ] = { 628 update: function( to ) { 629 this.element[ method ]( to ); 630 }, 631 refresh: function() { 632 return this.element[ method ](); 633 } 634 }; 635 }); 636 637 api.Element.synchronizer.checkbox = { 638 update: function( to ) { 639 this.element.prop( 'checked', to ); 640 }, 641 refresh: function() { 642 return this.element.prop( 'checked' ); 643 } 644 }; 645 646 api.Element.synchronizer.radio = { 647 update: function( to ) { 648 this.element.filter( function() { 649 return this.value === to; 650 }).prop( 'checked', true ); 651 }, 652 refresh: function() { 653 return this.element.filter( ':checked' ).val(); 654 } 655 }; 656 657 $.support.postMessage = !! window.postMessage; 658 659 /** 660 * A communicator for sending data from one window to another over postMessage. 661 * 662 * @memberOf wp.customize 663 * @alias wp.customize.Messenger 664 * 665 * @constructor 666 * @augments wp.customize.Class 667 * @mixes wp.customize.Events 668 */ 669 api.Messenger = api.Class.extend(/** @lends wp.customize.Messenger.prototype */{ 670 /** 671 * Create a new Value. 672 * 673 * @param {string} key Unique identifier. 674 * @param {mixed} initial Initial value. 675 * @param {mixed} options Options hash. Optional. 676 * @return {Value} Class instance of the Value. 677 */ 678 add: function( key, initial, options ) { 679 return this[ key ] = new api.Value( initial, options ); 680 }, 681 682 /** 683 * Initialize Messenger. 684 * 685 * @param {Object} params - Parameters to configure the messenger. 686 * {string} params.url - The URL to communicate with. 687 * {window} params.targetWindow - The window instance to communicate with. Default window.parent. 688 * {string} params.channel - If provided, will send the channel with each message and only accept messages a matching channel. 689 * @param {Object} options - Extend any instance parameter or method with this object. 690 */ 691 initialize: function( params, options ) { 692 // Target the parent frame by default, but only if a parent frame exists. 693 var defaultTarget = window.parent === window ? null : window.parent; 694 695 $.extend( this, options || {} ); 696 697 this.add( 'channel', params.channel ); 698 this.add( 'url', params.url || '' ); 699 this.add( 'origin', this.url() ).link( this.url ).setter( function( to ) { 700 var urlParser = document.createElement( 'a' ); 701 urlParser.href = to; 702 // Port stripping needed by IE since it adds to host but not to event.origin. 703 return urlParser.protocol + '//' + urlParser.host.replace( /:(80|443)$/, '' ); 704 }); 705 706 // First add with no value. 707 this.add( 'targetWindow', null ); 708 // This avoids SecurityErrors when setting a window object in x-origin iframe'd scenarios. 709 this.targetWindow.set = function( to ) { 710 var from = this._value; 711 712 to = this._setter.apply( this, arguments ); 713 to = this.validate( to ); 714 715 if ( null === to || from === to ) { 716 return this; 717 } 718 719 this._value = to; 720 this._dirty = true; 721 722 this.callbacks.fireWith( this, [ to, from ] ); 723 724 return this; 725 }; 726 // Now set it. 727 this.targetWindow( params.targetWindow || defaultTarget ); 728 729 730 /* 731 * Since we want jQuery to treat the receive function as unique 732 * to this instance, we give the function a new guid. 733 * 734 * This will prevent every Messenger's receive function from being 735 * unbound when calling $.off( 'message', this.receive ); 736 */ 737 this.receive = this.receive.bind( this ); 738 this.receive.guid = $.guid++; 739 740 $( window ).on( 'message', this.receive ); 741 }, 742 743 destroy: function() { 744 $( window ).off( 'message', this.receive ); 745 }, 746 747 /** 748 * Receive data from the other window. 749 * 750 * @param {jQuery.Event} event Event with embedded data. 751 */ 752 receive: function( event ) { 753 var message; 754 755 event = event.originalEvent; 756 757 if ( ! this.targetWindow || ! this.targetWindow() ) { 758 return; 759 } 760 761 // Check to make sure the origin is valid. 762 if ( this.origin() && event.origin !== this.origin() ) { 763 return; 764 } 765 766 // Ensure we have a string that's JSON.parse-able. 767 if ( typeof event.data !== 'string' || event.data[0] !== '{' ) { 768 return; 769 } 770 771 message = JSON.parse( event.data ); 772 773 // Check required message properties. 774 if ( ! message || ! message.id || typeof message.data === 'undefined' ) { 775 return; 776 } 777 778 // Check if channel names match. 779 if ( ( message.channel || this.channel() ) && this.channel() !== message.channel ) { 780 return; 781 } 782 783 this.trigger( message.id, message.data ); 784 }, 785 786 /** 787 * Send data to the other window. 788 * 789 * @param {string} id The event name. 790 * @param {Object} data Data. 791 */ 792 send: function( id, data ) { 793 var message; 794 795 data = typeof data === 'undefined' ? null : data; 796 797 if ( ! this.url() || ! this.targetWindow() ) { 798 return; 799 } 800 801 message = { id: id, data: data }; 802 if ( this.channel() ) { 803 message.channel = this.channel(); 804 } 805 806 this.targetWindow().postMessage( JSON.stringify( message ), this.origin() ); 807 } 808 }); 809 810 // Add the Events mixin to api.Messenger. 811 $.extend( api.Messenger.prototype, api.Events ); 812 813 /** 814 * Notification. 815 * 816 * @class 817 * @augments wp.customize.Class 818 * @since 4.6.0 819 * 820 * @memberOf wp.customize 821 * @alias wp.customize.Notification 822 * 823 * @param {string} code - The error code. 824 * @param {object} params - Params. 825 * @param {string} params.message=null - The error message. 826 * @param {string} [params.type=error] - The notification type. 827 * @param {boolean} [params.fromServer=false] - Whether the notification was server-sent. 828 * @param {string} [params.setting=null] - The setting ID that the notification is related to. 829 * @param {*} [params.data=null] - Any additional data. 830 */ 831 api.Notification = api.Class.extend(/** @lends wp.customize.Notification.prototype */{ 832 833 /** 834 * Template function for rendering the notification. 835 * 836 * This will be populated with template option or else it will be populated with template from the ID. 837 * 838 * @since 4.9.0 839 * @var {Function} 840 */ 841 template: null, 842 843 /** 844 * ID for the template to render the notification. 845 * 846 * @since 4.9.0 847 * @var {string} 848 */ 849 templateId: 'customize-notification', 850 851 /** 852 * Additional class names to add to the notification container. 853 * 854 * @since 4.9.0 855 * @var {string} 856 */ 857 containerClasses: '', 858 859 /** 860 * Initialize notification. 861 * 862 * @since 4.9.0 863 * 864 * @param {string} code - Notification code. 865 * @param {Object} params - Notification parameters. 866 * @param {string} params.message - Message. 867 * @param {string} [params.type=error] - Type. 868 * @param {string} [params.setting] - Related setting ID. 869 * @param {Function} [params.template] - Function for rendering template. If not provided, this will come from templateId. 870 * @param {string} [params.templateId] - ID for template to render the notification. 871 * @param {string} [params.containerClasses] - Additional class names to add to the notification container. 872 * @param {boolean} [params.dismissible] - Whether the notification can be dismissed. 873 */ 874 initialize: function( code, params ) { 875 var _params; 876 this.code = code; 877 _params = _.extend( 878 { 879 message: null, 880 type: 'error', 881 fromServer: false, 882 data: null, 883 setting: null, 884 template: null, 885 dismissible: false, 886 containerClasses: '' 887 }, 888 params 889 ); 890 delete _params.code; 891 _.extend( this, _params ); 892 }, 893 894 /** 895 * Render the notification. 896 * 897 * @since 4.9.0 898 * 899 * @return {jQuery} Notification container element. 900 */ 901 render: function() { 902 var notification = this, container, data; 903 if ( ! notification.template ) { 904 notification.template = wp.template( notification.templateId ); 905 } 906 data = _.extend( {}, notification, { 907 alt: notification.parent && notification.parent.alt 908 } ); 909 container = $( notification.template( data ) ); 910 911 if ( notification.dismissible ) { 912 container.find( '.notice-dismiss' ).on( 'click keydown', function( event ) { 913 if ( 'keydown' === event.type && 13 !== event.which ) { 914 return; 915 } 916 917 if ( notification.parent ) { 918 notification.parent.remove( notification.code ); 919 } else { 920 container.remove(); 921 } 922 }); 923 } 924 925 return container; 926 } 927 }); 928 929 // The main API object is also a collection of all customizer settings. 930 api = $.extend( new api.Values(), api ); 931 932 /** 933 * Get all customize settings. 934 * 935 * @alias wp.customize.get 936 * 937 * @return {Object} 938 */ 939 api.get = function() { 940 var result = {}; 941 942 this.each( function( obj, key ) { 943 result[ key ] = obj.get(); 944 }); 945 946 return result; 947 }; 948 949 /** 950 * Utility function namespace 951 * 952 * @namespace wp.customize.utils 953 */ 954 api.utils = {}; 955 956 /** 957 * Parse query string. 958 * 959 * @since 4.7.0 960 * @access public 961 * 962 * @alias wp.customize.utils.parseQueryString 963 * 964 * @param {string} queryString Query string. 965 * @return {Object} Parsed query string. 966 */ 967 api.utils.parseQueryString = function parseQueryString( queryString ) { 968 var queryParams = {}; 969 _.each( queryString.split( '&' ), function( pair ) { 970 var parts, key, value; 971 parts = pair.split( '=', 2 ); 972 if ( ! parts[0] ) { 973 return; 974 } 975 key = decodeURIComponent( parts[0].replace( /\+/g, ' ' ) ); 976 key = key.replace( / /g, '_' ); // What PHP does. 977 if ( _.isUndefined( parts[1] ) ) { 978 value = null; 979 } else { 980 value = decodeURIComponent( parts[1].replace( /\+/g, ' ' ) ); 981 } 982 queryParams[ key ] = value; 983 } ); 984 return queryParams; 985 }; 986 987 /** 988 * Expose the API publicly on window.wp.customize 989 * 990 * @namespace wp.customize 991 */ 992 exports.customize = api; 993 })( wp, jQuery );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Dec 25 01:00:02 2024 | Cross-referenced by PHPXref 0.7.1 |