customize-models.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /* global _wpCustomizeHeader */
  2. (function( $, wp ) {
  3. var api = wp.customize;
  4. /** @namespace wp.customize.HeaderTool */
  5. api.HeaderTool = {};
  6. /**
  7. * wp.customize.HeaderTool.ImageModel
  8. *
  9. * A header image. This is where saves via the Customizer API are
  10. * abstracted away, plus our own AJAX calls to add images to and remove
  11. * images from the user's recently uploaded images setting on the server.
  12. * These calls are made regardless of whether the user actually saves new
  13. * Customizer settings.
  14. *
  15. * @memberOf wp.customize.HeaderTool
  16. * @alias wp.customize.HeaderTool.ImageModel
  17. *
  18. * @constructor
  19. * @augments Backbone.Model
  20. */
  21. api.HeaderTool.ImageModel = Backbone.Model.extend(/** @lends wp.customize.HeaderTool.ImageModel.prototype */{
  22. defaults: function() {
  23. return {
  24. header: {
  25. attachment_id: 0,
  26. url: '',
  27. timestamp: _.now(),
  28. thumbnail_url: ''
  29. },
  30. choice: '',
  31. selected: false,
  32. random: false
  33. };
  34. },
  35. initialize: function() {
  36. this.on('hide', this.hide, this);
  37. },
  38. hide: function() {
  39. this.set('choice', '');
  40. api('header_image').set('remove-header');
  41. api('header_image_data').set('remove-header');
  42. },
  43. destroy: function() {
  44. var data = this.get('header'),
  45. curr = api.HeaderTool.currentHeader.get('header').attachment_id;
  46. // If the image we're removing is also the current header, unset
  47. // the latter
  48. if (curr && data.attachment_id === curr) {
  49. api.HeaderTool.currentHeader.trigger('hide');
  50. }
  51. wp.ajax.post( 'custom-header-remove', {
  52. nonce: _wpCustomizeHeader.nonces.remove,
  53. wp_customize: 'on',
  54. theme: api.settings.theme.stylesheet,
  55. attachment_id: data.attachment_id
  56. });
  57. this.trigger('destroy', this, this.collection);
  58. },
  59. save: function() {
  60. if (this.get('random')) {
  61. api('header_image').set(this.get('header').random);
  62. api('header_image_data').set(this.get('header').random);
  63. } else {
  64. if (this.get('header').defaultName) {
  65. api('header_image').set(this.get('header').url);
  66. api('header_image_data').set(this.get('header').defaultName);
  67. } else {
  68. api('header_image').set(this.get('header').url);
  69. api('header_image_data').set(this.get('header'));
  70. }
  71. }
  72. api.HeaderTool.combinedList.trigger('control:setImage', this);
  73. },
  74. importImage: function() {
  75. var data = this.get('header');
  76. if (data.attachment_id === undefined) {
  77. return;
  78. }
  79. wp.ajax.post( 'custom-header-add', {
  80. nonce: _wpCustomizeHeader.nonces.add,
  81. wp_customize: 'on',
  82. theme: api.settings.theme.stylesheet,
  83. attachment_id: data.attachment_id
  84. } );
  85. },
  86. shouldBeCropped: function() {
  87. if (this.get('themeFlexWidth') === true &&
  88. this.get('themeFlexHeight') === true) {
  89. return false;
  90. }
  91. if (this.get('themeFlexWidth') === true &&
  92. this.get('themeHeight') === this.get('imageHeight')) {
  93. return false;
  94. }
  95. if (this.get('themeFlexHeight') === true &&
  96. this.get('themeWidth') === this.get('imageWidth')) {
  97. return false;
  98. }
  99. if (this.get('themeWidth') === this.get('imageWidth') &&
  100. this.get('themeHeight') === this.get('imageHeight')) {
  101. return false;
  102. }
  103. if (this.get('imageWidth') <= this.get('themeWidth')) {
  104. return false;
  105. }
  106. return true;
  107. }
  108. });
  109. /**
  110. * wp.customize.HeaderTool.ChoiceList
  111. *
  112. * @memberOf wp.customize.HeaderTool
  113. * @alias wp.customize.HeaderTool.ChoiceList
  114. *
  115. * @constructor
  116. * @augments Backbone.Collection
  117. */
  118. api.HeaderTool.ChoiceList = Backbone.Collection.extend({
  119. model: api.HeaderTool.ImageModel,
  120. // Ordered from most recently used to least
  121. comparator: function(model) {
  122. return -model.get('header').timestamp;
  123. },
  124. initialize: function() {
  125. var current = api.HeaderTool.currentHeader.get('choice').replace(/^https?:\/\//, ''),
  126. isRandom = this.isRandomChoice(api.get().header_image);
  127. // Overridable by an extending class
  128. if (!this.type) {
  129. this.type = 'uploaded';
  130. }
  131. // Overridable by an extending class
  132. if (typeof this.data === 'undefined') {
  133. this.data = _wpCustomizeHeader.uploads;
  134. }
  135. if (isRandom) {
  136. // So that when adding data we don't hide regular images
  137. current = api.get().header_image;
  138. }
  139. this.on('control:setImage', this.setImage, this);
  140. this.on('control:removeImage', this.removeImage, this);
  141. this.on('add', this.maybeRemoveOldCrop, this);
  142. this.on('add', this.maybeAddRandomChoice, this);
  143. _.each(this.data, function(elt, index) {
  144. if (!elt.attachment_id) {
  145. elt.defaultName = index;
  146. }
  147. if (typeof elt.timestamp === 'undefined') {
  148. elt.timestamp = 0;
  149. }
  150. this.add({
  151. header: elt,
  152. choice: elt.url.split('/').pop(),
  153. selected: current === elt.url.replace(/^https?:\/\//, '')
  154. }, { silent: true });
  155. }, this);
  156. if (this.size() > 0) {
  157. this.addRandomChoice(current);
  158. }
  159. },
  160. maybeRemoveOldCrop: function( model ) {
  161. var newID = model.get( 'header' ).attachment_id || false,
  162. oldCrop;
  163. // Bail early if we don't have a new attachment ID.
  164. if ( ! newID ) {
  165. return;
  166. }
  167. oldCrop = this.find( function( item ) {
  168. return ( item.cid !== model.cid && item.get( 'header' ).attachment_id === newID );
  169. } );
  170. // If we found an old crop, remove it from the collection.
  171. if ( oldCrop ) {
  172. this.remove( oldCrop );
  173. }
  174. },
  175. maybeAddRandomChoice: function() {
  176. if (this.size() === 1) {
  177. this.addRandomChoice();
  178. }
  179. },
  180. addRandomChoice: function(initialChoice) {
  181. var isRandomSameType = RegExp(this.type).test(initialChoice),
  182. randomChoice = 'random-' + this.type + '-image';
  183. this.add({
  184. header: {
  185. timestamp: 0,
  186. random: randomChoice,
  187. width: 245,
  188. height: 41
  189. },
  190. choice: randomChoice,
  191. random: true,
  192. selected: isRandomSameType
  193. });
  194. },
  195. isRandomChoice: function(choice) {
  196. return (/^random-(uploaded|default)-image$/).test(choice);
  197. },
  198. shouldHideTitle: function() {
  199. return this.size() < 2;
  200. },
  201. setImage: function(model) {
  202. this.each(function(m) {
  203. m.set('selected', false);
  204. });
  205. if (model) {
  206. model.set('selected', true);
  207. }
  208. },
  209. removeImage: function() {
  210. this.each(function(m) {
  211. m.set('selected', false);
  212. });
  213. }
  214. });
  215. /**
  216. * wp.customize.HeaderTool.DefaultsList
  217. *
  218. * @memberOf wp.customize.HeaderTool
  219. * @alias wp.customize.HeaderTool.DefaultsList
  220. *
  221. * @constructor
  222. * @augments wp.customize.HeaderTool.ChoiceList
  223. * @augments Backbone.Collection
  224. */
  225. api.HeaderTool.DefaultsList = api.HeaderTool.ChoiceList.extend({
  226. initialize: function() {
  227. this.type = 'default';
  228. this.data = _wpCustomizeHeader.defaults;
  229. api.HeaderTool.ChoiceList.prototype.initialize.apply(this);
  230. }
  231. });
  232. })( jQuery, window.wp );