[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[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. 395 * When an ID string is supplied, then itemObject must be provided. 396 * @param {wp.customize.Class} [itemObject] - The item instance when the first argument is an ID string. 397 * @return {wp.customize.Class} The new item's instance, or an existing instance if already added. 398 */ 399 add: function( item, itemObject ) { 400 var collection = this, id, instance; 401 if ( 'string' === typeof item ) { 402 id = item; 403 instance = itemObject; 404 } else { 405 if ( 'string' !== typeof item.id ) { 406 throw new Error( 'Unknown key' ); 407 } 408 id = item.id; 409 instance = item; 410 } 411 412 if ( collection.has( id ) ) { 413 return collection.value( id ); 414 } 415 416 collection._value[ id ] = instance; 417 instance.parent = collection; 418 419 // Propagate a 'change' event on an item up to the collection. 420 if ( instance.extended( api.Value ) ) { 421 instance.bind( collection._change ); 422 } 423 424 collection.trigger( 'add', instance ); 425 426 // If a deferred object exists for this item, 427 // resolve it. 428 if ( collection._deferreds[ id ] ) { 429 collection._deferreds[ id ].resolve(); 430 } 431 432 return collection._value[ id ]; 433 }, 434 435 /** 436 * Create a new item of the collection using the collection's default constructor 437 * and store it in the collection. 438 * 439 * @param {string} id The ID of the item. 440 * @param {mixed} value Any extra arguments are passed into the item's initialize method. 441 * @return {mixed} The new item's instance. 442 */ 443 create: function( id ) { 444 return this.add( id, new this.defaultConstructor( api.Class.applicator, slice.call( arguments, 1 ) ) ); 445 }, 446 447 /** 448 * Iterate over all items in the collection invoking the provided callback. 449 * 450 * @param {Function} callback Function to invoke. 451 * @param {Object} context Object context to invoke the function with. Optional. 452 */ 453 each: function( callback, context ) { 454 context = typeof context === 'undefined' ? this : context; 455 456 $.each( this._value, function( key, obj ) { 457 callback.call( context, obj, key ); 458 }); 459 }, 460 461 /** 462 * Remove an item from the collection. 463 * 464 * @param {string} id The ID of the item to remove. 465 */ 466 remove: function( id ) { 467 var value = this.value( id ); 468 469 if ( value ) { 470 471 // Trigger event right before the element is removed from the collection. 472 this.trigger( 'remove', value ); 473 474 if ( value.extended( api.Value ) ) { 475 value.unbind( this._change ); 476 } 477 delete value.parent; 478 } 479 480 delete this._value[ id ]; 481 delete this._deferreds[ id ]; 482 483 // Trigger removed event after the item has been eliminated from the collection. 484 if ( value ) { 485 this.trigger( 'removed', value ); 486 } 487 }, 488 489 /** 490 * Runs a callback once all requested values exist. 491 * 492 * when( ids*, [callback] ); 493 * 494 * For example: 495 * when( id1, id2, id3, function( value1, value2, value3 ) {} ); 496 * 497 * @return $.Deferred.promise(); 498 */ 499 when: function() { 500 var self = this, 501 ids = slice.call( arguments ), 502 dfd = $.Deferred(); 503 504 // If the last argument is a callback, bind it to .done(). 505 if ( typeof ids[ ids.length - 1 ] === 'function' ) { 506 dfd.done( ids.pop() ); 507 } 508 509 /* 510 * Create a stack of deferred objects for each item that is not 511 * yet available, and invoke the supplied callback when they are. 512 */ 513 $.when.apply( $, $.map( ids, function( id ) { 514 if ( self.has( id ) ) { 515 return; 516 } 517 518 /* 519 * The requested item is not available yet, create a deferred 520 * object to resolve when it becomes available. 521 */ 522 return self._deferreds[ id ] = self._deferreds[ id ] || $.Deferred(); 523 })).done( function() { 524 var values = $.map( ids, function( id ) { 525 return self( id ); 526 }); 527 528 // If a value is missing, we've used at least one expired deferred. 529 // Call Values.when again to generate a new deferred. 530 if ( values.length !== ids.length ) { 531 // ids.push( callback ); 532 self.when.apply( self, ids ).done( function() { 533 dfd.resolveWith( self, values ); 534 }); 535 return; 536 } 537 538 dfd.resolveWith( self, values ); 539 }); 540 541 return dfd.promise(); 542 }, 543 544 /** 545 * A helper function to propagate a 'change' event from an item 546 * to the collection itself. 547 */ 548 _change: function() { 549 this.parent.trigger( 'change', this ); 550 } 551 }); 552 553 // Create a global events bus on the Customizer. 554 $.extend( api.Values.prototype, api.Events ); 555 556 557 /** 558 * Cast a string to a jQuery collection if it isn't already. 559 * 560 * @param {string|jQuery collection} element 561 */ 562 api.ensure = function( element ) { 563 return typeof element === 'string' ? $( element ) : element; 564 }; 565 566 /** 567 * An observable value that syncs with an element. 568 * 569 * Handles inputs, selects, and textareas by default. 570 * 571 * @memberOf wp.customize 572 * @alias wp.customize.Element 573 * 574 * @constructor 575 * @augments wp.customize.Value 576 * @augments wp.customize.Class 577 */ 578 api.Element = api.Value.extend(/** @lends wp.customize.Element */{ 579 initialize: function( element, options ) { 580 var self = this, 581 synchronizer = api.Element.synchronizer.html, 582 type, update, refresh; 583 584 this.element = api.ensure( element ); 585 this.events = ''; 586 587 if ( this.element.is( 'input, select, textarea' ) ) { 588 type = this.element.prop( 'type' ); 589 this.events += ' change input'; 590 synchronizer = api.Element.synchronizer.val; 591 592 if ( this.element.is( 'input' ) && api.Element.synchronizer[ type ] ) { 593 synchronizer = api.Element.synchronizer[ type ]; 594 } 595 } 596 597 api.Value.prototype.initialize.call( this, null, $.extend( options || {}, synchronizer ) ); 598 this._value = this.get(); 599 600 update = this.update; 601 refresh = this.refresh; 602 603 this.update = function( to ) { 604 if ( to !== refresh.call( self ) ) { 605 update.apply( this, arguments ); 606 } 607 }; 608 this.refresh = function() { 609 self.set( refresh.call( self ) ); 610 }; 611 612 this.bind( this.update ); 613 this.element.on( this.events, this.refresh ); 614 }, 615 616 find: function( selector ) { 617 return $( selector, this.element ); 618 }, 619 620 refresh: function() {}, 621 622 update: function() {} 623 }); 624 625 api.Element.synchronizer = {}; 626 627 $.each( [ 'html', 'val' ], function( index, method ) { 628 api.Element.synchronizer[ method ] = { 629 update: function( to ) { 630 this.element[ method ]( to ); 631 }, 632 refresh: function() { 633 return this.element[ method ](); 634 } 635 }; 636 }); 637 638 api.Element.synchronizer.checkbox = { 639 update: function( to ) { 640 this.element.prop( 'checked', to ); 641 }, 642 refresh: function() { 643 return this.element.prop( 'checked' ); 644 } 645 }; 646 647 api.Element.synchronizer.radio = { 648 update: function( to ) { 649 this.element.filter( function() { 650 return this.value === to; 651 }).prop( 'checked', true ); 652 }, 653 refresh: function() { 654 return this.element.filter( ':checked' ).val(); 655 } 656 }; 657 658 $.support.postMessage = !! window.postMessage; 659 660 /** 661 * A communicator for sending data from one window to another over postMessage. 662 * 663 * @memberOf wp.customize 664 * @alias wp.customize.Messenger 665 * 666 * @constructor 667 * @augments wp.customize.Class 668 * @mixes wp.customize.Events 669 */ 670 api.Messenger = api.Class.extend(/** @lends wp.customize.Messenger.prototype */{ 671 /** 672 * Create a new Value. 673 * 674 * @param {string} key Unique identifier. 675 * @param {mixed} initial Initial value. 676 * @param {mixed} options Options hash. Optional. 677 * @return {Value} Class instance of the Value. 678 */ 679 add: function( key, initial, options ) { 680 return this[ key ] = new api.Value( initial, options ); 681 }, 682 683 /** 684 * Initialize Messenger. 685 * 686 * @param {Object} params - Parameters to configure the messenger. 687 * {string} params.url - The URL to communicate with. 688 * {window} params.targetWindow - The window instance to communicate with. Default window.parent. 689 * {string} params.channel - If provided, will send the channel with each message and only accept messages a matching channel. 690 * @param {Object} options - Extend any instance parameter or method with this object. 691 */ 692 initialize: function( params, options ) { 693 // Target the parent frame by default, but only if a parent frame exists. 694 var defaultTarget = window.parent === window ? null : window.parent; 695 696 $.extend( this, options || {} ); 697 698 this.add( 'channel', params.channel ); 699 this.add( 'url', params.url || '' ); 700 this.add( 'origin', this.url() ).link( this.url ).setter( function( to ) { 701 var urlParser = document.createElement( 'a' ); 702 urlParser.href = to; 703 // Port stripping needed by IE since it adds to host but not to event.origin. 704 return urlParser.protocol + '//' + urlParser.host.replace( /:(80|443)$/, '' ); 705 }); 706 707 // First add with no value. 708 this.add( 'targetWindow', null ); 709 // This avoids SecurityErrors when setting a window object in x-origin iframe'd scenarios. 710 this.targetWindow.set = function( to ) { 711 var from = this._value; 712 713 to = this._setter.apply( this, arguments ); 714 to = this.validate( to ); 715 716 if ( null === to || from === to ) { 717 return this; 718 } 719 720 this._value = to; 721 this._dirty = true; 722 723 this.callbacks.fireWith( this, [ to, from ] ); 724 725 return this; 726 }; 727 // Now set it. 728 this.targetWindow( params.targetWindow || defaultTarget ); 729 730 731 /* 732 * Since we want jQuery to treat the receive function as unique 733 * to this instance, we give the function a new guid. 734 * 735 * This will prevent every Messenger's receive function from being 736 * unbound when calling $.off( 'message', this.receive ); 737 */ 738 this.receive = this.receive.bind( this ); 739 this.receive.guid = $.guid++; 740 741 $( window ).on( 'message', this.receive ); 742 }, 743 744 destroy: function() { 745 $( window ).off( 'message', this.receive ); 746 }, 747 748 /** 749 * Receive data from the other window. 750 * 751 * @param {jQuery.Event} event Event with embedded data. 752 */ 753 receive: function( event ) { 754 var message; 755 756 event = event.originalEvent; 757 758 if ( ! this.targetWindow || ! this.targetWindow() ) { 759 return; 760 } 761 762 // Check to make sure the origin is valid. 763 if ( this.origin() && event.origin !== this.origin() ) { 764 return; 765 } 766 767 // Ensure we have a string that's JSON.parse-able. 768 if ( typeof event.data !== 'string' || event.data[0] !== '{' ) { 769 return; 770 } 771 772 message = JSON.parse( event.data ); 773 774 // Check required message properties. 775 if ( ! message || ! message.id || typeof message.data === 'undefined' ) { 776 return; 777 } 778 779 // Check if channel names match. 780 if ( ( message.channel || this.channel() ) && this.channel() !== message.channel ) { 781 return; 782 } 783 784 this.trigger( message.id, message.data ); 785 }, 786 787 /** 788 * Send data to the other window. 789 * 790 * @param {string} id The event name. 791 * @param {Object} data Data. 792 */ 793 send: function( id, data ) { 794 var message; 795 796 data = typeof data === 'undefined' ? null : data; 797 798 if ( ! this.url() || ! this.targetWindow() ) { 799 return; 800 } 801 802 message = { id: id, data: data }; 803 if ( this.channel() ) { 804 message.channel = this.channel(); 805 } 806 807 this.targetWindow().postMessage( JSON.stringify( message ), this.origin() ); 808 } 809 }); 810 811 // Add the Events mixin to api.Messenger. 812 $.extend( api.Messenger.prototype, api.Events ); 813 814 /** 815 * Notification. 816 * 817 * @class 818 * @augments wp.customize.Class 819 * @since 4.6.0 820 * 821 * @memberOf wp.customize 822 * @alias wp.customize.Notification 823 * 824 * @param {string} code - The error code. 825 * @param {object} params - Params. 826 * @param {string} params.message=null - The error message. 827 * @param {string} [params.type=error] - The notification type. 828 * @param {boolean} [params.fromServer=false] - Whether the notification was server-sent. 829 * @param {string} [params.setting=null] - The setting ID that the notification is related to. 830 * @param {*} [params.data=null] - Any additional data. 831 */ 832 api.Notification = api.Class.extend(/** @lends wp.customize.Notification.prototype */{ 833 834 /** 835 * Template function for rendering the notification. 836 * 837 * This will be populated with template option or else it will be populated with template from the ID. 838 * 839 * @since 4.9.0 840 * @var {Function} 841 */ 842 template: null, 843 844 /** 845 * ID for the template to render the notification. 846 * 847 * @since 4.9.0 848 * @var {string} 849 */ 850 templateId: 'customize-notification', 851 852 /** 853 * Additional class names to add to the notification container. 854 * 855 * @since 4.9.0 856 * @var {string} 857 */ 858 containerClasses: '', 859 860 /** 861 * Initialize notification. 862 * 863 * @since 4.9.0 864 * 865 * @param {string} code - Notification code. 866 * @param {Object} params - Notification parameters. 867 * @param {string} params.message - Message. 868 * @param {string} [params.type=error] - Type. 869 * @param {string} [params.setting] - Related setting ID. 870 * @param {Function} [params.template] - Function for rendering template. If not provided, this will come from templateId. 871 * @param {string} [params.templateId] - ID for template to render the notification. 872 * @param {string} [params.containerClasses] - Additional class names to add to the notification container. 873 * @param {boolean} [params.dismissible] - Whether the notification can be dismissed. 874 */ 875 initialize: function( code, params ) { 876 var _params; 877 this.code = code; 878 _params = _.extend( 879 { 880 message: null, 881 type: 'error', 882 fromServer: false, 883 data: null, 884 setting: null, 885 template: null, 886 dismissible: false, 887 containerClasses: '' 888 }, 889 params 890 ); 891 delete _params.code; 892 _.extend( this, _params ); 893 }, 894 895 /** 896 * Render the notification. 897 * 898 * @since 4.9.0 899 * 900 * @return {jQuery} Notification container element. 901 */ 902 render: function() { 903 var notification = this, container, data; 904 if ( ! notification.template ) { 905 notification.template = wp.template( notification.templateId ); 906 } 907 data = _.extend( {}, notification, { 908 alt: notification.parent && notification.parent.alt 909 } ); 910 container = $( notification.template( data ) ); 911 912 if ( notification.dismissible ) { 913 container.find( '.notice-dismiss' ).on( 'click keydown', function( event ) { 914 if ( 'keydown' === event.type && 13 !== event.which ) { 915 return; 916 } 917 918 if ( notification.parent ) { 919 notification.parent.remove( notification.code ); 920 } else { 921 container.remove(); 922 } 923 }); 924 } 925 926 return container; 927 } 928 }); 929 930 // The main API object is also a collection of all customizer settings. 931 api = $.extend( new api.Values(), api ); 932 933 /** 934 * Get all customize settings. 935 * 936 * @alias wp.customize.get 937 * 938 * @return {Object} 939 */ 940 api.get = function() { 941 var result = {}; 942 943 this.each( function( obj, key ) { 944 result[ key ] = obj.get(); 945 }); 946 947 return result; 948 }; 949 950 /** 951 * Utility function namespace 952 * 953 * @namespace wp.customize.utils 954 */ 955 api.utils = {}; 956 957 /** 958 * Parse query string. 959 * 960 * @since 4.7.0 961 * @access public 962 * 963 * @alias wp.customize.utils.parseQueryString 964 * 965 * @param {string} queryString Query string. 966 * @return {Object} Parsed query string. 967 */ 968 api.utils.parseQueryString = function parseQueryString( queryString ) { 969 var queryParams = {}; 970 _.each( queryString.split( '&' ), function( pair ) { 971 var parts, key, value; 972 parts = pair.split( '=', 2 ); 973 if ( ! parts[0] ) { 974 return; 975 } 976 key = decodeURIComponent( parts[0].replace( /\+/g, ' ' ) ); 977 key = key.replace( / /g, '_' ); // What PHP does. 978 if ( _.isUndefined( parts[1] ) ) { 979 value = null; 980 } else { 981 value = decodeURIComponent( parts[1].replace( /\+/g, ' ' ) ); 982 } 983 queryParams[ key ] = value; 984 } ); 985 return queryParams; 986 }; 987 988 /** 989 * Expose the API publicly on window.wp.customize 990 * 991 * @namespace wp.customize 992 */ 993 exports.customize = api; 994 })( wp, jQuery );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Wed Dec 25 08:20:01 2024 | Cross-referenced by PHPXref |