* @output wp-includes/js/customize-models.js
/* global _wpCustomizeHeader */
/** @namespace wp.customize.HeaderTool */
* wp.customize.HeaderTool.ImageModel
* A header image. This is where saves via the Customizer API are
* abstracted away, plus our own Ajax calls to add images to and remove
* images from the user's recently uploaded images setting on the server.
* These calls are made regardless of whether the user actually saves new
* @memberOf wp.customize.HeaderTool
* @alias wp.customize.HeaderTool.ImageModel
* @augments Backbone.Model
api.HeaderTool.ImageModel = Backbone.Model.extend(/** @lends wp.customize.HeaderTool.ImageModel.prototype */{
this.on('hide', this.hide, this);
api('header_image').set('remove-header');
api('header_image_data').set('remove-header');
var data = this.get('header'),
curr = api.HeaderTool.currentHeader.get('header').attachment_id;
// If the image we're removing is also the current header,
if (curr && data.attachment_id === curr) {
api.HeaderTool.currentHeader.trigger('hide');
wp.ajax.post( 'custom-header-remove', {
nonce: _wpCustomizeHeader.nonces.remove,
theme: api.settings.theme.stylesheet,
attachment_id: data.attachment_id
this.trigger('destroy', this, this.collection);
if (this.get('random')) {
api('header_image').set(this.get('header').random);
api('header_image_data').set(this.get('header').random);
if (this.get('header').defaultName) {
api('header_image').set(this.get('header').url);
api('header_image_data').set(this.get('header').defaultName);
api('header_image').set(this.get('header').url);
api('header_image_data').set(this.get('header'));
api.HeaderTool.combinedList.trigger('control:setImage', this);
importImage: function() {
var data = this.get('header');
if (data.attachment_id === undefined) {
wp.ajax.post( 'custom-header-add', {
nonce: _wpCustomizeHeader.nonces.add,
theme: api.settings.theme.stylesheet,
attachment_id: data.attachment_id
shouldBeCropped: function() {
if (this.get('themeFlexWidth') === true &&
this.get('themeFlexHeight') === true) {
if (this.get('themeFlexWidth') === true &&
this.get('themeHeight') === this.get('imageHeight')) {
if (this.get('themeFlexHeight') === true &&
this.get('themeWidth') === this.get('imageWidth')) {
if (this.get('themeWidth') === this.get('imageWidth') &&
this.get('themeHeight') === this.get('imageHeight')) {
if (this.get('imageWidth') <= this.get('themeWidth')) {
* wp.customize.HeaderTool.ChoiceList
* @memberOf wp.customize.HeaderTool
* @alias wp.customize.HeaderTool.ChoiceList
* @augments Backbone.Collection
api.HeaderTool.ChoiceList = Backbone.Collection.extend({
model: api.HeaderTool.ImageModel,
// Ordered from most recently used to least.
comparator: function(model) {
return -model.get('header').timestamp;
var current = api.HeaderTool.currentHeader.get('choice').replace(/^https?:\/\//, ''),
isRandom = this.isRandomChoice(api.get().header_image);
// Overridable by an extending class.
// Overridable by an extending class.
if (typeof this.data === 'undefined') {
this.data = _wpCustomizeHeader.uploads;
// So that when adding data we don't hide regular images.
current = api.get().header_image;
this.on('control:setImage', this.setImage, this);
this.on('control:removeImage', this.removeImage, this);
this.on('add', this.maybeRemoveOldCrop, this);
this.on('add', this.maybeAddRandomChoice, this);
_.each(this.data, function(elt, index) {
if (!elt.attachment_id) {
if (typeof elt.timestamp === 'undefined') {
choice: elt.url.split('/').pop(),
selected: current === elt.url.replace(/^https?:\/\//, '')
this.addRandomChoice(current);
maybeRemoveOldCrop: function( model ) {
var newID = model.get( 'header' ).attachment_id || false,
// Bail early if we don't have a new attachment ID.
oldCrop = this.find( function( item ) {
return ( item.cid !== model.cid && item.get( 'header' ).attachment_id === newID );
// If we found an old crop, remove it from the collection.
maybeAddRandomChoice: function() {
addRandomChoice: function(initialChoice) {
var isRandomSameType = RegExp(this.type).test(initialChoice),
randomChoice = 'random-' + this.type + '-image';
selected: isRandomSameType
isRandomChoice: function(choice) {
return (/^random-(uploaded|default)-image$/).test(choice);
shouldHideTitle: function() {
setImage: function(model) {
m.set('selected', false);
model.set('selected', true);
removeImage: function() {
m.set('selected', false);
* wp.customize.HeaderTool.DefaultsList
* @memberOf wp.customize.HeaderTool
* @alias wp.customize.HeaderTool.DefaultsList
* @augments wp.customize.HeaderTool.ChoiceList
* @augments Backbone.Collection
api.HeaderTool.DefaultsList = api.HeaderTool.ChoiceList.extend({
this.data = _wpCustomizeHeader.defaults;
api.HeaderTool.ChoiceList.prototype.initialize.apply(this);