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