| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 /** 2 * @output wp-includes/js/customize-models.js 3 */ 4 5 /* global _wpCustomizeHeader */ 6 7 /** 8 * The WordPress Customizer models API. 9 * 10 * @param {JQueryStatic} $ The jQuery object. 11 * @param {Object} wp The WordPress global object. 12 */ 13 (function( $, wp ) { 14 var api = wp.customize; 15 /** @namespace wp.customize.HeaderTool */ 16 api.HeaderTool = {}; 17 18 19 /** 20 * wp.customize.HeaderTool.ImageModel 21 * 22 * A header image. This is where saves via the Customizer API are 23 * abstracted away, plus our own Ajax calls to add images to and remove 24 * images from the user's recently uploaded images setting on the server. 25 * These calls are made regardless of whether the user actually saves new 26 * Customizer settings. 27 * 28 * @memberOf wp.customize.HeaderTool 29 * @alias wp.customize.HeaderTool.ImageModel 30 * 31 * @class 32 * @augments Backbone.Model 33 */ 34 api.HeaderTool.ImageModel = Backbone.Model.extend(/** @lends wp.customize.HeaderTool.ImageModel.prototype */{ 35 /** 36 * Returns the default attributes for a header image. 37 * 38 * @return {Object} Default attributes. 39 */ 40 defaults: function() { 41 return { 42 header: { 43 attachment_id: 0, 44 url: '', 45 timestamp: _.now(), 46 thumbnail_url: '' 47 }, 48 choice: '', 49 selected: false, 50 random: false 51 }; 52 }, 53 54 /** 55 * Initializes the model, hiding the header when asked to. 56 */ 57 initialize: function() { 58 this.on('hide', this.hide, this); 59 }, 60 61 /** 62 * Hides the header image, removing it from the site. 63 */ 64 hide: function() { 65 this.set('choice', ''); 66 api('header_image').set('remove-header'); 67 api('header_image_data').set('remove-header'); 68 }, 69 70 /** 71 * Removes the image, hiding the header first if it is the current one. 72 */ 73 destroy: function() { 74 var data = this.get('header'), 75 curr = api.HeaderTool.currentHeader.get('header').attachment_id; 76 77 // If the image we're removing is also the current header, 78 // unset the latter. 79 if (curr && data.attachment_id === curr) { 80 api.HeaderTool.currentHeader.trigger('hide'); 81 } 82 83 wp.ajax.post( 'custom-header-remove', { 84 nonce: _wpCustomizeHeader.nonces.remove, 85 wp_customize: 'on', 86 theme: api.settings.theme.stylesheet, 87 attachment_id: data.attachment_id 88 }); 89 90 this.trigger('destroy', this, this.collection); 91 }, 92 93 /** 94 * Makes this image the current header image. 95 */ 96 save: function() { 97 if (this.get('random')) { 98 api('header_image').set(this.get('header').random); 99 api('header_image_data').set(this.get('header').random); 100 } else { 101 if (this.get('header').defaultName) { 102 api('header_image').set(this.get('header').url); 103 api('header_image_data').set(this.get('header').defaultName); 104 } else { 105 api('header_image').set(this.get('header').url); 106 api('header_image_data').set(this.get('header')); 107 } 108 } 109 110 api.HeaderTool.combinedList.trigger('control:setImage', this); 111 }, 112 113 /** 114 * Adds the image to the theme's uploaded headers. 115 */ 116 importImage: function() { 117 var data = this.get('header'); 118 if (data.attachment_id === undefined) { 119 return; 120 } 121 122 wp.ajax.post( 'custom-header-add', { 123 nonce: _wpCustomizeHeader.nonces.add, 124 wp_customize: 'on', 125 theme: api.settings.theme.stylesheet, 126 attachment_id: data.attachment_id 127 } ); 128 }, 129 130 /** 131 * Returns whether the image needs cropping for this theme. 132 * 133 * @return {boolean} Whether the image should be cropped. 134 */ 135 shouldBeCropped: function() { 136 if (this.get('themeFlexWidth') === true && 137 this.get('themeFlexHeight') === true) { 138 return false; 139 } 140 141 if (this.get('themeFlexWidth') === true && 142 this.get('themeHeight') === this.get('imageHeight')) { 143 return false; 144 } 145 146 if (this.get('themeFlexHeight') === true && 147 this.get('themeWidth') === this.get('imageWidth')) { 148 return false; 149 } 150 151 if (this.get('themeWidth') === this.get('imageWidth') && 152 this.get('themeHeight') === this.get('imageHeight')) { 153 return false; 154 } 155 156 if (this.get('imageWidth') <= this.get('themeWidth')) { 157 return false; 158 } 159 160 return true; 161 } 162 }); 163 164 165 /** 166 * wp.customize.HeaderTool.ChoiceList 167 * 168 * @memberOf wp.customize.HeaderTool 169 * @alias wp.customize.HeaderTool.ChoiceList 170 * 171 * @class 172 * @augments Backbone.Collection 173 */ 174 api.HeaderTool.ChoiceList = Backbone.Collection.extend({ 175 model: api.HeaderTool.ImageModel, 176 177 /** 178 * Orders the collection from most recently used to least. 179 * 180 * @param {Backbone.Model} model The model to sort. 181 * @return {number} The sort order. 182 */ 183 comparator: function(model) { 184 return -model.get('header').timestamp; 185 }, 186 187 /** 188 * Initializes the collection from the uploaded header images. 189 */ 190 initialize: function() { 191 var current = api.HeaderTool.currentHeader.get('choice').replace(/^https?:\/\//, ''), 192 isRandom = this.isRandomChoice(api.get().header_image); 193 194 // Overridable by an extending class. 195 if (!this.type) { 196 this.type = 'uploaded'; 197 } 198 199 // Overridable by an extending class. 200 if (typeof this.data === 'undefined') { 201 this.data = _wpCustomizeHeader.uploads; 202 } 203 204 if (isRandom) { 205 // So that when adding data we don't hide regular images. 206 current = api.get().header_image; 207 } 208 209 this.on('control:setImage', this.setImage, this); 210 this.on('control:removeImage', this.removeImage, this); 211 this.on('add', this.maybeRemoveOldCrop, this); 212 this.on('add', this.maybeAddRandomChoice, this); 213 214 _.each(this.data, function(elt, index) { 215 if (!elt.attachment_id) { 216 elt.defaultName = index; 217 } 218 219 if (typeof elt.timestamp === 'undefined') { 220 elt.timestamp = 0; 221 } 222 223 this.add({ 224 header: elt, 225 choice: elt.url.split('/').pop(), 226 selected: current === elt.url.replace(/^https?:\/\//, '') 227 }, { silent: true }); 228 }, this); 229 230 if (this.size() > 0) { 231 this.addRandomChoice(current); 232 } 233 }, 234 235 /** 236 * Removes an image's previous crop once it has been replaced. 237 * 238 * @param {Backbone.Model} model Model. 239 */ 240 maybeRemoveOldCrop: function( model ) { 241 var newID = model.get( 'header' ).attachment_id || false, 242 oldCrop; 243 244 // Bail early if we don't have a new attachment ID. 245 if ( ! newID ) { 246 return; 247 } 248 249 oldCrop = this.find( function( item ) { 250 return ( item.cid !== model.cid && item.get( 'header' ).attachment_id === newID ); 251 } ); 252 253 // If we found an old crop, remove it from the collection. 254 if ( oldCrop ) { 255 this.remove( oldCrop ); 256 } 257 }, 258 259 /** 260 * Adds the random choice once a single image is left. 261 */ 262 maybeAddRandomChoice: function() { 263 if (this.size() === 1) { 264 this.addRandomChoice(); 265 } 266 }, 267 268 /** 269 * Adds the random image choice to the collection. 270 * 271 * @param {string} initialChoice Initial choice. 272 */ 273 addRandomChoice: function(initialChoice) { 274 var isRandomSameType = RegExp(this.type).test(initialChoice), 275 randomChoice = 'random-' + this.type + '-image'; 276 277 this.add({ 278 header: { 279 timestamp: 0, 280 random: randomChoice, 281 width: 245, 282 height: 41 283 }, 284 choice: randomChoice, 285 random: true, 286 selected: isRandomSameType 287 }); 288 }, 289 290 /** 291 * Returns whether a choice is one of the random image choices. 292 * 293 * @param {string} choice Choice. 294 * @return {boolean} Whether the choice is random. 295 */ 296 isRandomChoice: function(choice) { 297 return (/^random-(uploaded|default)-image$/).test(choice); 298 }, 299 300 /** 301 * Returns whether the list title should be hidden. 302 * 303 * @return {boolean} Whether the title should be hidden. 304 */ 305 shouldHideTitle: function() { 306 return this.size() < 2; 307 }, 308 309 /** 310 * Marks a single image as the selected one. 311 * 312 * @param {Backbone.Model} model Model. 313 */ 314 setImage: function(model) { 315 this.each(function(m) { 316 m.set('selected', false); 317 }); 318 319 if (model) { 320 model.set('selected', true); 321 } 322 }, 323 324 /** 325 * Clears the selection. 326 */ 327 removeImage: function() { 328 this.each(function(m) { 329 m.set('selected', false); 330 }); 331 } 332 }); 333 334 335 /** 336 * wp.customize.HeaderTool.DefaultsList 337 * 338 * @memberOf wp.customize.HeaderTool 339 * @alias wp.customize.HeaderTool.DefaultsList 340 * 341 * @class 342 * @augments wp.customize.HeaderTool.ChoiceList 343 * @augments Backbone.Collection 344 */ 345 api.HeaderTool.DefaultsList = api.HeaderTool.ChoiceList.extend({ 346 /** 347 * Initializes the collection from the theme's default header images. 348 */ 349 initialize: function() { 350 this.type = 'default'; 351 this.data = _wpCustomizeHeader.defaults; 352 api.HeaderTool.ChoiceList.prototype.initialize.apply(this); 353 } 354 }); 355 356 })( jQuery, window.wp );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Sun Sep 13 08:20:28 2026 | Cross-referenced by PHPXref |