15 /** |
15 /** |
16 * Helper function to correctly set up the prototype chain, for subclasses. |
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 |
17 * Similar to `goog.inherits`, but uses a hash of prototype properties and |
18 * class properties to be extended. |
18 * class properties to be extended. |
19 * |
19 * |
20 * @param object parent Parent class constructor to inherit from. |
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. |
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. |
22 * @param object staticProps Properties to apply directly to the class constructor. |
23 * @return child The subclassed constructor. |
23 * @return child The subclassed constructor. |
24 */ |
24 */ |
25 inherits = function( parent, protoProps, staticProps ) { |
25 inherits = function( parent, protoProps, staticProps ) { |
26 var child; |
26 var child; |
27 |
27 |
28 // The constructor function for the new subclass is either defined by you |
28 /* |
29 // (the "constructor" property in your `extend` definition), or defaulted |
29 * The constructor function for the new subclass is either defined by you |
30 // by us to simply call `super()`. |
30 * (the "constructor" property in your `extend` definition), or defaulted |
|
31 * by us to simply call `super()`. |
|
32 */ |
31 if ( protoProps && protoProps.hasOwnProperty( 'constructor' ) ) { |
33 if ( protoProps && protoProps.hasOwnProperty( 'constructor' ) ) { |
32 child = protoProps.constructor; |
34 child = protoProps.constructor; |
33 } else { |
35 } else { |
34 child = function() { |
36 child = function() { |
35 // Storing the result `super()` before returning the value |
37 /* |
36 // prevents a bug in Opera where, if the constructor returns |
38 * Storing the result `super()` before returning the value |
37 // a function, Opera will reject the return value in favor of |
39 * prevents a bug in Opera where, if the constructor returns |
38 // the original object. This causes all sorts of trouble. |
40 * a function, Opera will reject the return value in favor of |
|
41 * the original object. This causes all sorts of trouble. |
|
42 */ |
39 var result = parent.apply( this, arguments ); |
43 var result = parent.apply( this, arguments ); |
40 return result; |
44 return result; |
41 }; |
45 }; |
42 } |
46 } |
43 |
47 |
44 // Inherit class (static) properties from parent. |
48 // Inherit class (static) properties from parent. |
45 $.extend( child, parent ); |
49 $.extend( child, parent ); |
46 |
50 |
47 // Set the prototype chain to inherit from `parent`, without calling |
51 // Set the prototype chain to inherit from `parent`, |
48 // `parent`'s constructor function. |
52 // without calling `parent`'s constructor function. |
49 ctor.prototype = parent.prototype; |
53 ctor.prototype = parent.prototype; |
50 child.prototype = new ctor(); |
54 child.prototype = new ctor(); |
51 |
55 |
52 // Add prototype properties (instance properties) to the subclass, |
56 // Add prototype properties (instance properties) to the subclass, |
53 // if supplied. |
57 // if supplied. |
54 if ( protoProps ) |
58 if ( protoProps ) { |
55 $.extend( child.prototype, protoProps ); |
59 $.extend( child.prototype, protoProps ); |
|
60 } |
56 |
61 |
57 // Add static properties to the constructor function, if supplied. |
62 // Add static properties to the constructor function, if supplied. |
58 if ( staticProps ) |
63 if ( staticProps ) { |
59 $.extend( child, staticProps ); |
64 $.extend( child, staticProps ); |
|
65 } |
60 |
66 |
61 // Correctly set child's `prototype.constructor`. |
67 // Correctly set child's `prototype.constructor`. |
62 child.prototype.constructor = child; |
68 child.prototype.constructor = child; |
63 |
69 |
64 // Set a convenience property in case the parent's prototype is needed later. |
70 // Set a convenience property in case the parent's prototype is needed later. |
100 }; |
106 }; |
101 |
107 |
102 /** |
108 /** |
103 * Creates a subclass of the class. |
109 * Creates a subclass of the class. |
104 * |
110 * |
105 * @param object protoProps Properties to apply to the prototype. |
111 * @param object protoProps Properties to apply to the prototype. |
106 * @param object staticProps Properties to apply directly to the class. |
112 * @param object staticProps Properties to apply directly to the class. |
107 * @return child The subclass. |
113 * @return child The subclass. |
108 */ |
114 */ |
109 api.Class.extend = function( protoProps, classProps ) { |
115 api.Class.extend = function( protoProps, classProps ) { |
110 var child = inherits( this, protoProps, classProps ); |
116 var child = inherits( this, protoProps, classProps ); |
111 child.extend = this.extend; |
117 child.extend = this.extend; |
112 return child; |
118 return child; |
342 * the last to be a function callback that will be invoked when the requested |
352 * the last to be a function callback that will be invoked when the requested |
343 * items are available. |
353 * items are available. |
344 * |
354 * |
345 * @see {api.Values.when} |
355 * @see {api.Values.when} |
346 * |
356 * |
347 * @param {string} id ID of the item. |
357 * @param {string} id ID of the item. |
348 * @param {...} Zero or more IDs of items to wait for and a callback |
358 * @param {...} Zero or more IDs of items to wait for and a callback |
349 * function to invoke when they're available. Optional. |
359 * function to invoke when they're available. Optional. |
350 * @return {mixed} The item instance if only one ID was supplied. |
360 * @return {mixed} The item instance if only one ID was supplied. |
351 * A Deferred Promise object if a callback function is supplied. |
361 * A Deferred Promise object if a callback function is supplied. |
352 */ |
362 */ |
353 instance: function( id ) { |
363 instance: function( id ) { |
354 if ( arguments.length === 1 ) |
364 if ( arguments.length === 1 ) { |
355 return this.value( id ); |
365 return this.value( id ); |
|
366 } |
356 |
367 |
357 return this.when.apply( this, arguments ); |
368 return this.when.apply( this, arguments ); |
358 }, |
369 }, |
359 |
370 |
360 /** |
371 /** |
361 * Get the instance of an item. |
372 * Get the instance of an item. |
362 * |
373 * |
363 * @param {string} id The ID of the item. |
374 * @param {string} id The ID of the item. |
364 * @return {[type]} [description] |
375 * @return {[type]} [description] |
365 */ |
376 */ |
366 value: function( id ) { |
377 value: function( id ) { |
367 return this._value[ id ]; |
378 return this._value[ id ]; |
368 }, |
379 }, |
369 |
380 |
370 /** |
381 /** |
371 * Whether the collection has an item with the given ID. |
382 * Whether the collection has an item with the given ID. |
372 * |
383 * |
373 * @param {string} id The ID of the item to look for. |
384 * @param {string} id The ID of the item to look for. |
374 * @return {Boolean} |
385 * @return {boolean} |
375 */ |
386 */ |
376 has: function( id ) { |
387 has: function( id ) { |
377 return typeof this._value[ id ] !== 'undefined'; |
388 return typeof this._value[ id ] !== 'undefined'; |
378 }, |
389 }, |
379 |
390 |
422 |
433 |
423 /** |
434 /** |
424 * Create a new item of the collection using the collection's default constructor |
435 * Create a new item of the collection using the collection's default constructor |
425 * and store it in the collection. |
436 * and store it in the collection. |
426 * |
437 * |
427 * @param {string} id The ID of the item. |
438 * @param {string} id The ID of the item. |
428 * @param {mixed} value Any extra arguments are passed into the item's initialize method. |
439 * @param {mixed} value Any extra arguments are passed into the item's initialize method. |
429 * @return {mixed} The new item's instance. |
440 * @return {mixed} The new item's instance. |
430 */ |
441 */ |
431 create: function( id ) { |
442 create: function( id ) { |
432 return this.add( id, new this.defaultConstructor( api.Class.applicator, slice.call( arguments, 1 ) ) ); |
443 return this.add( id, new this.defaultConstructor( api.Class.applicator, slice.call( arguments, 1 ) ) ); |
433 }, |
444 }, |
434 |
445 |
435 /** |
446 /** |
436 * Iterate over all items in the collection invoking the provided callback. |
447 * Iterate over all items in the collection invoking the provided callback. |
437 * |
448 * |
438 * @param {Function} callback Function to invoke. |
449 * @param {Function} callback Function to invoke. |
439 * @param {object} context Object context to invoke the function with. Optional. |
450 * @param {Object} context Object context to invoke the function with. Optional. |
440 */ |
451 */ |
441 each: function( callback, context ) { |
452 each: function( callback, context ) { |
442 context = typeof context === 'undefined' ? this : context; |
453 context = typeof context === 'undefined' ? this : context; |
443 |
454 |
444 $.each( this._value, function( key, obj ) { |
455 $.each( this._value, function( key, obj ) { |
480 * when( ids*, [callback] ); |
491 * when( ids*, [callback] ); |
481 * |
492 * |
482 * For example: |
493 * For example: |
483 * when( id1, id2, id3, function( value1, value2, value3 ) {} ); |
494 * when( id1, id2, id3, function( value1, value2, value3 ) {} ); |
484 * |
495 * |
485 * @returns $.Deferred.promise(); |
496 * @return $.Deferred.promise(); |
486 */ |
497 */ |
487 when: function() { |
498 when: function() { |
488 var self = this, |
499 var self = this, |
489 ids = slice.call( arguments ), |
500 ids = slice.call( arguments ), |
490 dfd = $.Deferred(); |
501 dfd = $.Deferred(); |
491 |
502 |
492 // If the last argument is a callback, bind it to .done() |
503 // If the last argument is a callback, bind it to .done(). |
493 if ( $.isFunction( ids[ ids.length - 1 ] ) ) |
504 if ( $.isFunction( ids[ ids.length - 1 ] ) ) { |
494 dfd.done( ids.pop() ); |
505 dfd.done( ids.pop() ); |
|
506 } |
495 |
507 |
496 /* |
508 /* |
497 * Create a stack of deferred objects for each item that is not |
509 * Create a stack of deferred objects for each item that is not |
498 * yet available, and invoke the supplied callback when they are. |
510 * yet available, and invoke the supplied callback when they are. |
499 */ |
511 */ |
500 $.when.apply( $, $.map( ids, function( id ) { |
512 $.when.apply( $, $.map( ids, function( id ) { |
501 if ( self.has( id ) ) |
513 if ( self.has( id ) ) { |
502 return; |
514 return; |
|
515 } |
503 |
516 |
504 /* |
517 /* |
505 * The requested item is not available yet, create a deferred |
518 * The requested item is not available yet, create a deferred |
506 * object to resolve when it becomes available. |
519 * object to resolve when it becomes available. |
507 */ |
520 */ |
655 */ |
668 */ |
656 api.Messenger = api.Class.extend(/** @lends wp.customize.Messenger.prototype */{ |
669 api.Messenger = api.Class.extend(/** @lends wp.customize.Messenger.prototype */{ |
657 /** |
670 /** |
658 * Create a new Value. |
671 * Create a new Value. |
659 * |
672 * |
660 * @param {string} key Unique identifier. |
673 * @param {string} key Unique identifier. |
661 * @param {mixed} initial Initial value. |
674 * @param {mixed} initial Initial value. |
662 * @param {mixed} options Options hash. Optional. |
675 * @param {mixed} options Options hash. Optional. |
663 * @return {Value} Class instance of the Value. |
676 * @return {Value} Class instance of the Value. |
664 */ |
677 */ |
665 add: function( key, initial, options ) { |
678 add: function( key, initial, options ) { |
666 return this[ key ] = new api.Value( initial, options ); |
679 return this[ key ] = new api.Value( initial, options ); |
667 }, |
680 }, |
668 |
681 |
669 /** |
682 /** |
670 * Initialize Messenger. |
683 * Initialize Messenger. |
671 * |
684 * |
672 * @param {object} params - Parameters to configure the messenger. |
685 * @param {Object} params - Parameters to configure the messenger. |
673 * {string} params.url - The URL to communicate with. |
686 * {string} params.url - The URL to communicate with. |
674 * {window} params.targetWindow - The window instance to communicate with. Default window.parent. |
687 * {window} params.targetWindow - The window instance to communicate with. Default window.parent. |
675 * {string} params.channel - If provided, will send the channel with each message and only accept messages a matching channel. |
688 * {string} params.channel - If provided, will send the channel with each message and only accept messages a matching channel. |
676 * @param {object} options - Extend any instance parameter or method with this object. |
689 * @param {Object} options - Extend any instance parameter or method with this object. |
677 */ |
690 */ |
678 initialize: function( params, options ) { |
691 initialize: function( params, options ) { |
679 // Target the parent frame by default, but only if a parent frame exists. |
692 // Target the parent frame by default, but only if a parent frame exists. |
680 var defaultTarget = window.parent === window ? null : window.parent; |
693 var defaultTarget = window.parent === window ? null : window.parent; |
681 |
694 |
688 urlParser.href = to; |
701 urlParser.href = to; |
689 // Port stripping needed by IE since it adds to host but not to event.origin. |
702 // Port stripping needed by IE since it adds to host but not to event.origin. |
690 return urlParser.protocol + '//' + urlParser.host.replace( /:(80|443)$/, '' ); |
703 return urlParser.protocol + '//' + urlParser.host.replace( /:(80|443)$/, '' ); |
691 }); |
704 }); |
692 |
705 |
693 // first add with no value |
706 // First add with no value. |
694 this.add( 'targetWindow', null ); |
707 this.add( 'targetWindow', null ); |
695 // This avoids SecurityErrors when setting a window object in x-origin iframe'd scenarios. |
708 // This avoids SecurityErrors when setting a window object in x-origin iframe'd scenarios. |
696 this.targetWindow.set = function( to ) { |
709 this.targetWindow.set = function( to ) { |
697 var from = this._value; |
710 var from = this._value; |
698 |
711 |
708 |
721 |
709 this.callbacks.fireWith( this, [ to, from ] ); |
722 this.callbacks.fireWith( this, [ to, from ] ); |
710 |
723 |
711 return this; |
724 return this; |
712 }; |
725 }; |
713 // now set it |
726 // Now set it. |
714 this.targetWindow( params.targetWindow || defaultTarget ); |
727 this.targetWindow( params.targetWindow || defaultTarget ); |
715 |
728 |
716 |
729 |
717 // Since we want jQuery to treat the receive function as unique |
730 /* |
718 // to this instance, we give the function a new guid. |
731 * Since we want jQuery to treat the receive function as unique |
719 // |
732 * to this instance, we give the function a new guid. |
720 // This will prevent every Messenger's receive function from being |
733 * |
721 // unbound when calling $.off( 'message', this.receive ); |
734 * This will prevent every Messenger's receive function from being |
|
735 * unbound when calling $.off( 'message', this.receive ); |
|
736 */ |
722 this.receive = $.proxy( this.receive, this ); |
737 this.receive = $.proxy( this.receive, this ); |
723 this.receive.guid = $.guid++; |
738 this.receive.guid = $.guid++; |
724 |
739 |
725 $( window ).on( 'message', this.receive ); |
740 $( window ).on( 'message', this.receive ); |
726 }, |
741 }, |
742 if ( ! this.targetWindow || ! this.targetWindow() ) { |
757 if ( ! this.targetWindow || ! this.targetWindow() ) { |
743 return; |
758 return; |
744 } |
759 } |
745 |
760 |
746 // Check to make sure the origin is valid. |
761 // Check to make sure the origin is valid. |
747 if ( this.origin() && event.origin !== this.origin() ) |
762 if ( this.origin() && event.origin !== this.origin() ) { |
748 return; |
763 return; |
749 |
764 } |
750 // Ensure we have a string that's JSON.parse-able |
765 |
|
766 // Ensure we have a string that's JSON.parse-able. |
751 if ( typeof event.data !== 'string' || event.data[0] !== '{' ) { |
767 if ( typeof event.data !== 'string' || event.data[0] !== '{' ) { |
752 return; |
768 return; |
753 } |
769 } |
754 |
770 |
755 message = JSON.parse( event.data ); |
771 message = JSON.parse( event.data ); |
756 |
772 |
757 // Check required message properties. |
773 // Check required message properties. |
758 if ( ! message || ! message.id || typeof message.data === 'undefined' ) |
774 if ( ! message || ! message.id || typeof message.data === 'undefined' ) { |
759 return; |
775 return; |
|
776 } |
760 |
777 |
761 // Check if channel names match. |
778 // Check if channel names match. |
762 if ( ( message.channel || this.channel() ) && this.channel() !== message.channel ) |
779 if ( ( message.channel || this.channel() ) && this.channel() !== message.channel ) { |
763 return; |
780 return; |
|
781 } |
764 |
782 |
765 this.trigger( message.id, message.data ); |
783 this.trigger( message.id, message.data ); |
766 }, |
784 }, |
767 |
785 |
768 /** |
786 /** |
769 * Send data to the other window. |
787 * Send data to the other window. |
770 * |
788 * |
771 * @param {string} id The event name. |
789 * @param {string} id The event name. |
772 * @param {object} data Data. |
790 * @param {Object} data Data. |
773 */ |
791 */ |
774 send: function( id, data ) { |
792 send: function( id, data ) { |
775 var message; |
793 var message; |
776 |
794 |
777 data = typeof data === 'undefined' ? null : data; |
795 data = typeof data === 'undefined' ? null : data; |
778 |
796 |
779 if ( ! this.url() || ! this.targetWindow() ) |
797 if ( ! this.url() || ! this.targetWindow() ) { |
780 return; |
798 return; |
|
799 } |
781 |
800 |
782 message = { id: id, data: data }; |
801 message = { id: id, data: data }; |
783 if ( this.channel() ) |
802 if ( this.channel() ) { |
784 message.channel = this.channel(); |
803 message.channel = this.channel(); |
|
804 } |
785 |
805 |
786 this.targetWindow().postMessage( JSON.stringify( message ), this.origin() ); |
806 this.targetWindow().postMessage( JSON.stringify( message ), this.origin() ); |
787 } |
807 } |
788 }); |
808 }); |
789 |
809 |
840 * Initialize notification. |
860 * Initialize notification. |
841 * |
861 * |
842 * @since 4.9.0 |
862 * @since 4.9.0 |
843 * |
863 * |
844 * @param {string} code - Notification code. |
864 * @param {string} code - Notification code. |
845 * @param {object} params - Notification parameters. |
865 * @param {Object} params - Notification parameters. |
846 * @param {string} params.message - Message. |
866 * @param {string} params.message - Message. |
847 * @param {string} [params.type=error] - Type. |
867 * @param {string} [params.type=error] - Type. |
848 * @param {string} [params.setting] - Related setting ID. |
868 * @param {string} [params.setting] - Related setting ID. |
849 * @param {Function} [params.template] - Function for rendering template. If not provided, this will come from templateId. |
869 * @param {Function} [params.template] - Function for rendering template. If not provided, this will come from templateId. |
850 * @param {string} [params.templateId] - ID for template to render the notification. |
870 * @param {string} [params.templateId] - ID for template to render the notification. |
940 * @access public |
960 * @access public |
941 * |
961 * |
942 * @alias wp.customize.utils.parseQueryString |
962 * @alias wp.customize.utils.parseQueryString |
943 * |
963 * |
944 * @param {string} queryString Query string. |
964 * @param {string} queryString Query string. |
945 * @returns {object} Parsed query string. |
965 * @return {Object} Parsed query string. |
946 */ |
966 */ |
947 api.utils.parseQueryString = function parseQueryString( queryString ) { |
967 api.utils.parseQueryString = function parseQueryString( queryString ) { |
948 var queryParams = {}; |
968 var queryParams = {}; |
949 _.each( queryString.split( '&' ), function( pair ) { |
969 _.each( queryString.split( '&' ), function( pair ) { |
950 var parts, key, value; |
970 var parts, key, value; |