PageRenderTime 66ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/t/upfront/scripts/upfront/upfront-media.js

https://bitbucket.org/matthewselby/wpdev
JavaScript | 2868 lines | 2558 code | 158 blank | 152 comment | 275 complexity | 8799fe65b60e14287bb765d5bd21c8a9 MD5 | raw file
Possible License(s): Apache-2.0, GPL-2.0, LGPL-3.0, LGPL-2.1, AGPL-1.0, BSD-3-Clause, MIT, GPL-3.0, MPL-2.0-no-copyleft-exception
  1. (function ($, undefined) {
  2. define([
  3. 'scripts/upfront/upfront-media/insert-options-item-control',
  4. 'scripts/perfect-scrollbar/perfect-scrollbar'
  5. ], function(InsertOptions, perfectScrollbar) {
  6. var MEDIA_SIZES = {
  7. FULL: "full",
  8. to_size: function (size) {
  9. return size.width + 'x' + size.height;
  10. }
  11. };
  12. var l10n = Upfront.Settings.l10n.media;
  13. var INSERT_OPTIONS = InsertOptions.INSERT_OPTIONS;
  14. // ----- Models -----
  15. var MediaItem_Model = Backbone.Model.extend({
  16. defaults: {
  17. thumbnail: "<span class='upfront-image-upload-placeholder'></span>",
  18. insert_option: "image_insert"
  19. }
  20. });
  21. var MediaCollection_Model = Backbone.Collection.extend({
  22. defaults:{
  23. thumbnail: '',
  24. title: ''
  25. }
  26. });
  27. var MediaCollection_Selection = Backbone.Collection.extend({
  28. model: MediaItem_Model,
  29. initialize: function () {
  30. this.listenTo(Upfront.Events, "media_manager:media:labels_loaded", this.global_labels_loaded);
  31. },
  32. get_shared_labels: function () {
  33. var known_labels = ActiveFilters.get("label"),
  34. selected_labels = [],
  35. shared_labels = [],
  36. tmp_shared = {}
  37. ;
  38. this.each(function (item) {
  39. var labels = item.get("labels") || [];
  40. labels = _.map(labels, function(each){ return parseInt(each, 10); });
  41. tmp_shared[item.get("ID")] = labels;
  42. });
  43. selected_labels = _.intersection.apply(this, _(tmp_shared).values());
  44. known_labels.each(function (label) {
  45. if (
  46. selected_labels.indexOf(label.get("value")) >= 0
  47. ||
  48. selected_labels.indexOf(parseInt(label.get("value"), 10)) >= 0
  49. ) shared_labels.push(label);
  50. });
  51. return shared_labels;
  52. },
  53. get_additional_sizes: function () {
  54. if (!ActiveFilters.multiple_sizes) return false; // Do not use multiple sizes if we're told not to
  55. var all_item_sizes = this.invoke("get", "additional_sizes"),
  56. item_sizes = []
  57. ;
  58. _(all_item_sizes).each(function (item, idx) {
  59. var tmp_sizes = [];
  60. if (!idx) item_sizes = _(item).map(function (size) { return MEDIA_SIZES.to_size(size);});
  61. _(item).each(function (size) {
  62. tmp_sizes.push(MEDIA_SIZES.to_size(size));
  63. });
  64. item_sizes = _.intersection(item_sizes, tmp_sizes);
  65. });
  66. item_sizes.push(MEDIA_SIZES.FULL);
  67. return item_sizes;
  68. },
  69. is_used_label: function (label) {
  70. return (_(this.get_shared_labels()).invoke("get", "value").indexOf(label.get("value")) >= 0);
  71. },
  72. update_label_state: function (label) {
  73. return this.is_used_label(label)
  74. ? this.disassociate_label(label)
  75. : this.associate_label(label)
  76. ;
  77. },
  78. associate_label: function (label) {
  79. this._update_label('', label);
  80. },
  81. disassociate_label: function (label) {
  82. this._update_label('dis', label);
  83. },
  84. _update_label: function (pfx, label) {
  85. pfx = pfx || '';
  86. var me = this,
  87. idx = label.get("value"),
  88. data = {
  89. action: "upfront-media-" + pfx + "associate_label",
  90. term: idx,
  91. post_ids: this.invoke("get", "ID")
  92. }
  93. ;
  94. Upfront.Util.post(data)
  95. .success(function (response) {
  96. me.each(function (model) {
  97. var labels = response.data[model.get("ID")];
  98. if (labels) model.set({labels: labels}, {silent: true});
  99. });
  100. me.trigger("change");
  101. })
  102. ;
  103. },
  104. add_new_label: function (label) {
  105. var me = this,
  106. data = {
  107. "action": "upfront-media-add_label",
  108. "term": label,
  109. "post_ids": this.invoke("get", "ID")
  110. }
  111. ;
  112. return Upfront.Util.post(data)
  113. .success(function (response) {
  114. me.each(function (model) {
  115. var labels = response.data[model.get("ID")];
  116. if (labels) model.set({labels: labels}, {silent: true});
  117. });
  118. Upfront.Events.trigger("media_manager:media:labels_updated");
  119. me.trigger("change");
  120. })
  121. ;
  122. },
  123. delete_media_items: function () {
  124. var me = this,
  125. data = {
  126. "action": "upfront-media-remove_item",
  127. "post_ids": this.invoke("get", "ID")
  128. }
  129. ;
  130. Upfront.Util.post(data)
  131. .success(function (response) {
  132. me.reset([]);
  133. Upfront.Events.trigger("media_manager:media:list", ActiveFilters);
  134. })
  135. ;
  136. },
  137. // Same as delete_media_items except for theme/UI images.
  138. delete_theme_items: function () {
  139. var me = this,
  140. data = {
  141. "action": "upfront-media-remove_theme_item",
  142. // Theme images use file names rather than post IDs.
  143. "post_ids": this.invoke("get", "post_title")
  144. }
  145. ;
  146. Upfront.Util.post(data)
  147. .success(function (response) {
  148. me.reset([]);
  149. Upfront.Events.trigger("media_manager:media:list", ActiveFilters);
  150. })
  151. ;
  152. },
  153. global_labels_loaded: function () {
  154. this.trigger("change");
  155. }
  156. });
  157. var MediaFilter_Item = Backbone.Model.extend({
  158. });
  159. var MediaFilter_Collection = Backbone.Collection.extend({
  160. model: MediaFilter_Item
  161. });
  162. var ActiveMediaFilter_Collection = Backbone.Model.extend({
  163. CONST: {
  164. CUTOFF_SIZE: 8,
  165. CUTOFF_BIT: 3
  166. },
  167. labels_cache: false,
  168. default_media_types: ['images', 'videos', 'audios', 'other'],
  169. allowed_media_types: [],
  170. image_sizes: true,
  171. showing_titles: true,
  172. current_keys: [],
  173. current_models: [],
  174. current_page: 1,
  175. max_pages: 1,
  176. max_items: 1,
  177. media_limit: 60,
  178. current_filter_control: 0,
  179. initialize: function () {
  180. this.to_defaults();
  181. this.listenTo(Upfront.Events, "media_manager:media:filters_updated", this.update_active_filters);
  182. this.listenTo(Upfront.Events, "media_manager:media:labels_updated", this.reload_labels);
  183. this.listenTo(Upfront.Events, "media_manager:media:toggle_titles", this.toggle_titles);
  184. },
  185. to_defaults: function () {
  186. var types = new MediaFilter_Collection([]),
  187. has_all = (this.allowed_media_types.indexOf('other') >= 0)
  188. ;
  189. if (!this.allowed_media_types.length) this.allowed_media_types = this.default_media_types;
  190. if (this.allowed_media_types.indexOf('images') >= 0) types.add(new MediaFilter_Item({filter: l10n.filter.images, value: 'images', state: !has_all}), {silent: true});
  191. if (this.allowed_media_types.indexOf('videos') >= 0) types.add(new MediaFilter_Item({filter: l10n.filter.videos, value: 'videos', state: !has_all}), {silent: true});
  192. if (this.allowed_media_types.indexOf('audios') >= 0) types.add(new MediaFilter_Item({filter: l10n.filter.audios, value: 'audios', state: !has_all}), {silent: true});
  193. if (this.allowed_media_types.indexOf('other') >= 0) types.add(new MediaFilter_Item({filter: l10n.filter.all, value: 'other', state: has_all}), {silent: true});
  194. this.set("type", types, {silent: true});
  195. this.set("recent", new MediaFilter_Collection([
  196. new MediaFilter_Item({filter: "5", value: 5, state: false}),
  197. new MediaFilter_Item({filter: "10", value: 10, state: false}),
  198. new MediaFilter_Item({filter: "20", value: 20, state: false}),
  199. new MediaFilter_Item({filter: "40", value: 40, state: false}),
  200. new MediaFilter_Item({filter: "100", value: 100, state: false})
  201. ]), {silent: true});
  202. this.set("order", new MediaFilter_Collection([
  203. new MediaFilter_Item({filter: l10n.filter.newest, value: 'date_desc', state: true}),
  204. new MediaFilter_Item({filter: l10n.filter.oldest, value: 'date_asc', state: false}),
  205. new MediaFilter_Item({filter: l10n.filter.a_z, value: 'title_asc', state: false}),
  206. new MediaFilter_Item({filter: l10n.filter.z_a, value: 'title_desc', state: false})
  207. ]), {silent: true});
  208. this.set({"search": new MediaFilter_Collection([])}, {silent: true});
  209. this.themeImages =false;
  210. this.current_page = 1;
  211. this.current_filter_control = 0;
  212. this.set_labels_to_defaults();
  213. },
  214. set_max_pages: function (max) {
  215. this.max_pages = !_.isUndefined(max) ? max : 1;
  216. },
  217. set_max_items: function (max) {
  218. this.max_items = !_.isUndefined(max) ? max : 1;
  219. },
  220. prev_page: function () {
  221. if (this.current_page > 1) return this.set_page(this.current_page-1);
  222. },
  223. next_page: function () {
  224. if (this.current_page < this.max_pages) return this.set_page(this.current_page+1);
  225. },
  226. set_page: function (page) {
  227. if (!page) return false;
  228. if (page >= 1 && page < this.max_pages) {
  229. if (page == this.current_page) return false; // Already here.
  230. this.current_page = page;
  231. return true;
  232. } else return false;
  233. },
  234. toggle_titles: function () {
  235. this.showing_titles = !this.showing_titles;
  236. },
  237. set_labels_to_defaults: function () {
  238. if (this.labels_cache) {
  239. var arr = [];
  240. _(this.labels_cache).each(function (item) {
  241. arr.push(new MediaFilter_Item({filter: item.name, value: item.term_id, state: false}));
  242. });
  243. this.set("label", new MediaFilter_Collection(arr), {silent: true});
  244. Upfront.Events.trigger("media_manager:media:labels_loaded");
  245. } else this.reload_labels();
  246. },
  247. reload_labels: function () {
  248. var me = this;
  249. Upfront.Util.post({action: "upfront-media-get_labels"})
  250. .success(function (response) {
  251. var arr = [];
  252. if (response.data) {
  253. me.labels_cache = response.data;
  254. me.set_labels_to_defaults();
  255. }
  256. })
  257. ;
  258. },
  259. update_active_filters: function (filter, data) {
  260. if (!filter || !this.get(filter)) {
  261. this.to_defaults();
  262. Upfront.Events.trigger("media_manager:media:filters_reset");
  263. } else {
  264. var collection = data && data.get ? data.get(filter).toArray() : data,
  265. me = this.get(filter)
  266. ;
  267. _(collection).each(function (item) {
  268. if (item.get("state")) {
  269. var has = me.where({filter: item.get("filter")});
  270. if (has.length) {
  271. has[0].set({state: item.get("state")}, {silent: true});
  272. }
  273. }
  274. });
  275. // Reset page to 1
  276. this.set_page(1);
  277. }
  278. Upfront.Events.trigger("media_manager:media:list", this);
  279. },
  280. to_request_json: function () {
  281. var data = {},
  282. me = this
  283. ;
  284. _(this.attributes).each(function (collection, idx) {
  285. var active = me.get(idx).where({state:true});
  286. data[idx] = _(active).invoke("get", "value");
  287. });
  288. data.page = this.current_page;
  289. return data;
  290. },
  291. to_list: function () {
  292. var data = {},
  293. me = this
  294. ;
  295. _(this.attributes).each(function (collection, idx) {
  296. var active = me.get(idx).where({state:true}),
  297. active_non_defaults = []
  298. ;
  299. active_non_defaults = _(active).filter(function (filter) {
  300. var value = filter.get("value");
  301. return "other" !== value && "date_desc" !== value;
  302. });
  303. data[idx] = _(active_non_defaults).invoke("get", "filter");
  304. });
  305. return data;
  306. },
  307. has_upload: function () {
  308. if ( Upfront.Settings.Application.PERMS.UPLOAD ) {
  309. if (!this.themeImages) return true; // Allow when not looking into theme images
  310. return true === Upfront.plugins.isRequiredByPlugin('media filter upload');
  311. } else {
  312. return false; // disabling upload when user role has no permission
  313. }
  314. }
  315. });
  316. var ActiveFilters = new ActiveMediaFilter_Collection();
  317. // ----- Views -----
  318. var MediaManager_Controls_View = Backbone.View.extend({
  319. className: "upfront-media-controls",
  320. is_search_active: false,
  321. initialize: function (args) {
  322. this.listenTo(Upfront.Events, "media:item:selection_changed", this.switch_controls);
  323. this.listenTo(Upfront.Events, "media:search:requested", this.switch_to_search);
  324. this.listenTo(Upfront.Events, "media_manager:load:done", this.render_filters);
  325. this.options = args.options;
  326. },
  327. render: function () {
  328. if (!this.options.show_insert) {
  329. this.$el.addClass('upfront-media-controls-no-insert');
  330. }
  331. this.render_filters();
  332. },
  333. render_filters: function () {
  334. if (this.search) this.search.remove();
  335. this.search = new MediaManager_SearchControl();
  336. if (this.control) this.control.remove();
  337. this.control = this.is_search_active ? new MediaManager_SearchFiltersControl() : new MediaManager_FiltersControl();
  338. this.search.render();
  339. this.control.render();
  340. this.$el.empty().append(this.search.$el).append(this.control.$el);
  341. if ( this.is_search_active ) this.$el.removeClass('upfront-media-controls-search-selected').addClass('upfront-media-controls-search');
  342. else this.$el.removeClass('upfront-media-controls-search');
  343. },
  344. render_media: function (selected) {
  345. var item_control = new MediaManager_ItemControl({model: new MediaCollection_Selection(selected), options: this.options});
  346. item_control.render();
  347. this.$el.empty();
  348. if (this.is_search_active) {
  349. this.control = new MediaManager_SearchFiltersControl();
  350. this.control.render();
  351. this.$el.append(this.control.$el);
  352. this.$el.removeClass('upfront-media-controls-search').addClass('upfront-media-controls-search-selected');
  353. }
  354. else
  355. this.$el.removeClass('upfront-media-controls-search-selected');
  356. this.$el.append(item_control.$el);
  357. },
  358. switch_controls: function (media_collection) {
  359. var positive = media_collection.where({selected: true});
  360. if (positive.length) this.render_media(positive);
  361. else this.render_filters();
  362. },
  363. switch_to_search: function (search) {
  364. this.is_search_active = search && search.get("state");
  365. //this.render_filters(); // This will be rendered later in another event to prevent double rendering in a row
  366. },
  367. remove: function() {
  368. if (this.control) this.control.remove();
  369. Backbone.View.prototype.remove.call(this);
  370. }
  371. });
  372. var MediaManager_AuxControls_View = Backbone.View.extend({
  373. className: "upfront-media-aux_controls",
  374. initialize: function () {
  375. this.listenTo(Upfront.Events, "media:item:selection_changed", this.switch_controls);
  376. },
  377. render: function () {
  378. //this.render_selection();
  379. },
  380. /*render_selection: function () {
  381. var selection_control = new MediaManager_SelectionControl({model: this.model});
  382. selection_control.render();
  383. this.$el.empty().append(selection_control.$el);
  384. this.$el.removeClass('upfront-media-aux_controls-has-select');
  385. },*/
  386. render_delete: function (selected) {
  387. var delete_control = new MediaManager_DeleteControl({model: new MediaCollection_Selection(selected)});
  388. delete_control.render();
  389. //this.render_selection();
  390. this.$el.empty().append(delete_control.$el);
  391. this.$el.addClass('upfront-media-aux_controls-has-select');
  392. },
  393. switch_controls: function (media_collection) {
  394. var positive = media_collection && media_collection.where ? media_collection.where({selected: true}) : [];
  395. if (positive.length) this.render_delete(positive);
  396. //else this.render_selection();
  397. }
  398. });
  399. var MediaManager_SelectionControl = Backbone.View.extend({
  400. className: "select_control_container",
  401. events: {
  402. "click a.none": "select_none",
  403. "click a.all": "select_all"
  404. },
  405. initialize: function () {
  406. this.display_values = [
  407. {label: '20', value: 20},
  408. {label: '40', value: 40},
  409. {label: '60', value: 60},
  410. {label: '80', value: 80},
  411. {label: '100', value: 100}
  412. ];
  413. },
  414. render: function () {
  415. var me = this;
  416. me.$el.empty().append(l10n.select + ' <a href="#all" class="all">' + l10n.all + '</a>&nbsp;|&nbsp;<a href="#none" class="none">' + l10n.none + '</a>');
  417. me.select_display_field = new Upfront.Views.Editor.Field.Select({
  418. label: l10n.display+":",
  419. className: "upfront-field-wrap upfront-field-wrap-select upfront-filter_display_control",
  420. name: "display-selection",
  421. width: '70px',
  422. values: me.display_values,
  423. multiple: false,
  424. default_value: ActiveFilters.media_limit,
  425. change: function(){
  426. me.select_display(this.get_value());
  427. }
  428. });
  429. me.select_display_field.render();
  430. me.$el.append(me.select_display_field.$el);
  431. },
  432. select_display: function (limit) {
  433. ActiveFilters.media_limit = limit;
  434. Upfront.Events.trigger("media_manager:media:list", ActiveFilters);
  435. },
  436. select_none: function (e) {
  437. e.preventDefault();
  438. e.stopPropagation();
  439. var positive = this.model.where({selected: true});
  440. if ( positive.length ) {
  441. this.model.each(function (item) {
  442. item.set({selected: false}, {silent: true});
  443. });
  444. this.model.trigger("change");
  445. Upfront.Events.trigger("media:item:selection_changed", this.model);
  446. // run again to apply the new list
  447. var selected_model = new MediaCollection_Selection(ActiveFilters.current_models);
  448. Upfront.Events.trigger("media:item:selection_changed", selected_model);
  449. }
  450. },
  451. select_all: function (e) {
  452. e.preventDefault();
  453. e.stopPropagation();
  454. var all = [];
  455. this.model.each(function (item) {
  456. item.set({selected: true}, {silent: true});
  457. all.push(item);
  458. });
  459. this.model.trigger("change");
  460. Upfront.Events.trigger("media:item:selection_changed", this.model);
  461. // run again to apply the new list
  462. var selected_model = new MediaCollection_Selection(ActiveFilters.current_models);
  463. Upfront.Events.trigger("media:item:selection_changed", selected_model);
  464. }
  465. });
  466. var MediaManager_DeleteControl = Backbone.View.extend({
  467. className: "delete_control_container upfront-icon upfront-icon-trash",
  468. events: {
  469. click: "delete_selection"
  470. },
  471. render: function () {
  472. this.$el.empty().append('<a href="#delete">' + l10n.del_command + '</a>');
  473. },
  474. delete_selection: function (e) {
  475. e.preventDefault();
  476. e.stopPropagation();
  477. if ( confirm(l10n.confirm_delete_items) ) {
  478. var show_nag = false;
  479. this.model.each(function (item) {
  480. if (item.get("parent")) show_nag = true;
  481. });
  482. if (!show_nag || (show_nag && confirm(l10n.item_in_use_nag))) {
  483. ActiveFilters.current_keys = [];
  484. ActiveFilters.current_models = [];
  485. // If theme image, delete via proper deletion method.
  486. if (ActiveFilters.themeImages) {
  487. return this.model.delete_theme_items();
  488. }
  489. // Otherwise delete media item.
  490. return this.model.delete_media_items();
  491. }
  492. }
  493. }
  494. });
  495. var MediaManager_ItemControl = Backbone.View.extend({
  496. className: "upfront-item-control",
  497. options: {
  498. insert_options: false,
  499. hide_sizes: false
  500. },
  501. templates: {
  502. caption: _.template('<label class="upfront-field-label upfront-field-label-block">{{title}}</label>'),
  503. shared_label: _.template('<a href="#remove" class="upfront-icon upfront-icon-media-label-delete" data-idx="{{value}}">{{filter}}</a>'),
  504. additional_size: _.template('<option value="{{size}}">{{size}}</option>')
  505. },
  506. events: {
  507. //"change .change_title :text": "change_title",
  508. "click .existing_labels a": "drop_label"//,
  509. //"change .additional_sizes select": "select_size"
  510. },
  511. initialize: function ( opts ) {
  512. this.listenTo(this.model, "change", this.render);
  513. this.options = _.extend( this.options, opts.options );
  514. },
  515. render: function () {
  516. var self = this,
  517. sections = _([
  518. 'size_hints',
  519. 'change_title',
  520. 'change_alt',
  521. 'copy_url',
  522. //'existing_labels',
  523. 'add_labels',
  524. 'insert_options',
  525. 'additional_sizes'
  526. ]),
  527. renderers = _([
  528. 'render_size_hint',
  529. 'render_title',
  530. 'render_alt',
  531. 'render_copy_url',
  532. //'render_shared_labels',
  533. 'render_labels_adding',
  534. 'render_insert_options',
  535. 'render_additional_sizes'
  536. ]);
  537. // remove prev sections
  538. this.$el.empty();
  539. // if insert_options is false remove insert options section
  540. if( !this.options.insert_options ){
  541. sections = _( sections.reject(function(section){
  542. return section === "insert_options";
  543. }) );
  544. renderers = _( renderers.reject(function(renderer){
  545. return renderer === "render_insert_options";
  546. }) );
  547. }
  548. if (_.indexOf(this.options.media_type, 'videos') !== -1) {
  549. sections = _( sections.reject(function(section){
  550. return section === "additional_sizes";
  551. }) );
  552. renderers = _( renderers.reject(function(renderer){
  553. return renderer === "render_additional_sizes";
  554. }) );
  555. }
  556. // add sections
  557. sections.each(function(section){
  558. self.$el.append( '<div class="' + section + '" />' );
  559. });
  560. // render sections
  561. renderers.each(function(renderer){
  562. self[renderer]();
  563. });
  564. },
  565. _find_gcd: function (a, b) {
  566. return (b == 0) ? a : this._find_gcd(b, a%b);
  567. },
  568. render_size_hint: function() {
  569. var me = this,
  570. $hub = this.$el.find('.size_hints'),
  571. sizeWidth,
  572. sizeHeight;
  573. $hub.empty();
  574. if(this.model.length === 1) {
  575. var image = this.model.at(0).get('image'),
  576. $container = $('<div class="upfront-size-hints upfront-field-wrap upfront-field-wrap-text"><label class="upfront-field-label upfront-field-label-block">'+ l10n.information +'</label></div>')
  577. ;
  578. if ( image !== undefined ) {
  579. var iwidth = parseInt((image || {}).width, 10),
  580. iheight = parseInt((image || {}).height, 10),
  581. gcd = me._find_gcd(iwidth, iheight)
  582. ;
  583. // Only render size hint if we're actually able to
  584. if (iwidth && iheight) {
  585. $container.append(
  586. '<span class="upfront-size-hint-ratio">' +
  587. (iwidth/gcd) +
  588. ':' +
  589. (iheight/gcd) +
  590. '</span>'
  591. );
  592. $container.append(
  593. '<span class="upfront-size-hint-width">' +
  594. l10n.width_label +
  595. ': <span>' +
  596. image.width + l10n.px_label +
  597. '</span></span>'
  598. );
  599. $container.append(
  600. '<span class="upfront-size-hint-height">' +
  601. l10n.height_label +
  602. ': <span>' +
  603. image.height + l10n.px_label +
  604. '</span></span>'
  605. );
  606. $hub.append($container);
  607. }
  608. }
  609. }
  610. },
  611. render_alt: function () {
  612. var me = this,
  613. $hub = this.$el.find(".change_alt"),
  614. image = this.model.at(0).get('image');
  615. $hub.empty();
  616. if (this.model.length === 1) {
  617. this.alt_field = new Upfront.Views.Editor.Field.Text({
  618. model: this.model.at(0),
  619. label: l10n.media_alt,
  620. name: 'alt',
  621. change: function(){
  622. me.change_alt();
  623. }
  624. });
  625. this.alt_field.render();
  626. $hub.append(this.alt_field.$el);
  627. }
  628. },
  629. render_title: function () {
  630. var me = this,
  631. $hub = this.$el.find(".change_title")
  632. ;
  633. $hub.empty();
  634. if (this.model.length > 1) {
  635. var files = '<span class="selected_files">' + l10n.files.replace(/%d/, this.model.length) + '</span>',
  636. shared_labels = this.model.get_shared_labels()
  637. ;
  638. $hub.append('<label class="upfront-field-label upfront-field-label-block">'+ l10n.information +'</label>');
  639. $hub.append('<span class="selected_length">' + ( shared_labels.length > 0 ? l10n.selected.replace(/%s/, files) : l10n.selected_no_label.replace(/%s/, files) ) + '</span>');
  640. } else {
  641. this.title_field = new Upfront.Views.Editor.Field.Text({
  642. model: this.model.at(0),
  643. label: l10n.media_title,
  644. compact: true,
  645. name: 'post_title',
  646. change: function(){
  647. me.change_title();
  648. }
  649. });
  650. this.title_field.render();
  651. $hub.append(this.title_field.$el);
  652. }
  653. },
  654. render_copy_url: function () {
  655. var $hub = this.$el.find(".copy_url");
  656. if (this.model.length > 1) return false;
  657. this.copy_url = new Upfront.Views.Editor.Field.Button({
  658. model: this.model.at(0),
  659. label: l10n.copy_url,
  660. compact: true,
  661. name: "document_url",
  662. on_click: function () {
  663. Upfront.Util.add_to_clipboard(this.model.get('document_url'));
  664. }
  665. });
  666. this.copy_url.render();
  667. $hub.append(this.copy_url.$el);
  668. },
  669. render_labels_adding: function () {
  670. var me = this,
  671. $hub = this.$el.find(".add_labels"),
  672. container = new MediaManager_ItemControl_LabelsContainer({model: this.model})
  673. ;
  674. $hub.empty().append(this.templates.caption({title: l10n.media_labels}));
  675. container.render();
  676. $hub.append(container.$el);
  677. this.$el.on("click", function (e) {
  678. e.stopPropagation();
  679. container.trigger("filters:selection:click");
  680. });
  681. },
  682. render_shared_labels: function () {
  683. var me = this,
  684. $hub = this.$el.find(".existing_labels"),
  685. shared_labels = this.model.get_shared_labels(),
  686. title = (shared_labels.length > 1 ? l10n.current_labels : '')
  687. ;
  688. $hub.empty()
  689. .append(this.templates.caption({title: title}))
  690. ;
  691. _(shared_labels).each(function (label) {
  692. $hub.append(me.templates.shared_label(label.toJSON()));
  693. });
  694. },
  695. render_additional_sizes: function () {
  696. var me = this,
  697. $hub = this.$el.find(".additional_sizes"),
  698. additional_sizes = this.model.get_additional_sizes(),
  699. title = l10n.additional_sizes,
  700. sizes = []
  701. ;
  702. $hub.empty();
  703. if( ( this.options.insert_options && this.model.at(0).get("insert_option") === INSERT_OPTIONS.wp_insert) || ( !this.options.hide_sizes && !this.options.insert_options ) ) {
  704. if (!additional_sizes.length) return false;
  705. _(additional_sizes).each(function (size) {
  706. if (size === MEDIA_SIZES.FULL) return;
  707. sizes.push({ label: size, value: size });
  708. });
  709. this.size_field = new Upfront.Views.Editor.Field.Radios({
  710. model: this.model.at(0),
  711. name: 'selected_size',
  712. width: '100%',
  713. values: sizes,
  714. default_value: additional_sizes[0],
  715. change: function(){
  716. me.select_size();
  717. }
  718. });
  719. this.size_field.render();
  720. $hub.append(this.size_field.$el);
  721. this.size_field.$el.on("click", function (e) {
  722. e.stopPropagation();
  723. });
  724. }
  725. },
  726. select_size: function (e) {
  727. //e.stopPropagation();
  728. var size = this.size_field.get_value() || MEDIA_SIZES.FULL;
  729. this.model.each(function (model) {
  730. model.set({selected_size: size}, {silent: true});
  731. });
  732. },
  733. change_title: function (e) {
  734. //e.stopPropagation();
  735. var model = this.model.at(0);
  736. model.set({post_title: this.title_field.get_value()});
  737. var me = this,
  738. data = {
  739. action: "upfront-media-update_media_item",
  740. data: model.toJSON()
  741. }
  742. ;
  743. Upfront.Util.post(data)
  744. .done(function () {
  745. model.trigger("change");
  746. })
  747. ;
  748. model.trigger("appearance:update");
  749. },
  750. change_alt: function (e) {
  751. //e.stopPropagation();
  752. var model = this.model.at(0);
  753. model.set({alt: this.alt_field.get_value()});
  754. var me = this,
  755. data = {
  756. action: "upfront-media-update_media_item",
  757. data: model.toJSON()
  758. }
  759. ;
  760. Upfront.Util.post(data)
  761. .done(function () {
  762. model.trigger("change");
  763. })
  764. ;
  765. model.trigger("appearance:update");
  766. },
  767. drop_label: function (e) {
  768. e.preventDefault();
  769. e.stopPropagation();
  770. var $label = $(e.target),
  771. idx = $label.attr("data-idx"),
  772. shared = this.model.get_shared_labels(),
  773. label_idx = _(shared).invoke("get", "value").indexOf(idx),
  774. label = label_idx >= 0 && shared[label_idx] ? shared[label_idx] : false
  775. ;
  776. if (label) this.model.update_label_state(label);
  777. },
  778. render_insert_options: function(){
  779. var $this_section = this.$(".insert_options"),
  780. view = new InsertOptions.Options_Control( {model: this.model} );
  781. view.render();
  782. $this_section.html(view.el);
  783. }
  784. });
  785. var MediaManager_ItemControl_LabelsContainer = Backbone.View.extend({
  786. className: "upfront-additive_multiselection",
  787. selection: '',
  788. events: {
  789. "click .labels_filter": "stop_prop",
  790. "keyup .labels_filter :text.filter": "update_selection",
  791. "click .new_labels .toggle-add-label": "show_add_label",
  792. "click .new_labels .submit-label": "add_new_labels",
  793. "focus :text.filter": "add_focus_state",
  794. "blur :text.filter": "remove_focus_state",
  795. "keyup .new_labels :text.add-label": "enter_new_labels"
  796. },
  797. initialize: function () {
  798. this.listenTo(Upfront.Events, "media_manager:media:labels_updated", this.render);
  799. this._adding_label = false;
  800. },
  801. stop_prop: function (e) {
  802. e.stopPropagation();
  803. // Also let's focus the text field
  804. this.$el.find(":text.filter").focus();
  805. },
  806. add_focus_state: function (e) {
  807. this.$el.addClass('focus');
  808. },
  809. remove_focus_state: function (e) {
  810. this.$el.removeClass('focus');
  811. },
  812. render: function () {
  813. var sel = this.selection || '';
  814. this.$el.empty()
  815. .append('<div class="title">' + l10n.assigned_labels + '</div>')
  816. .append('<div class="labels_filter"><ul></ul><input type="text" class="filter upfront-field upfront-field-text" value="' + sel + '" placeholder="' + l10n.type_labels_pick + '" /></div>')
  817. .append('<div class="labels_list"><ul></ul></div>')
  818. .append('<div class="title">' + l10n.create_new_label + '</div>')
  819. .append('<div class="new_labels"><a class="toggle-add-label upfront-icon-control upfront-icon-label-add"></a><input type="text" class="add-label upfront-field upfront-field-text" placeholder="' + l10n.type_labels_add + '" /><a class="submit-label upfront-icon-control upfront-icon-label-add-alt"></a></div>')
  820. ;
  821. this.render_existing_labels();
  822. this.render_labels();
  823. },
  824. render_existing_labels: function () {
  825. var me = this,
  826. $hub = this.$el.find("div.labels_filter ul"),
  827. count = 0
  828. ;
  829. $hub.empty();
  830. _.each(this.model.get_shared_labels(), function (label) {
  831. var item = new MediaManager_ItemControl_LabelItem({model: label});
  832. item.media_items = me.model;
  833. item.render();
  834. $hub.append(item.$el);
  835. count++;
  836. });
  837. if (count > 0) {
  838. // Remove placeholder
  839. this.$el.find(".labels_filter :text.filter").attr('placeholder', '');
  840. }
  841. },
  842. render_labels: function () {
  843. var me = this,
  844. $hub = this.$el.find(".labels_list ul"),
  845. known_labels = ActiveFilters.get("label"),
  846. shared_labels = this.model.get_shared_labels(),
  847. has_selection = false,
  848. match = 0
  849. ;
  850. $hub.empty();
  851. if (!this.selection) return false;
  852. known_labels.each(function (label) {
  853. if (me.model.is_used_label(label)) return;
  854. var item = new MediaManager_ItemControl_LabelItem({model: label});
  855. item.shared = shared_labels;
  856. item.media_items = me.model;
  857. item.selection = me.selection;
  858. item.render();
  859. if (item.matched) {
  860. $hub.append(item.$el);
  861. match++;
  862. }
  863. });
  864. if (match > 0) this.$el.addClass('has_match');
  865. else this.$el.removeClass('has_match');
  866. },
  867. update_selection: function (e) {
  868. e.preventDefault();
  869. e.stopPropagation();
  870. var $text = this.$el.find(".labels_filter :text.filter"),
  871. selection = $text.val()
  872. ;
  873. this.selection = selection;
  874. this.render_labels();
  875. },
  876. show_add_label: function (e) {
  877. e.preventDefault();
  878. e.stopPropagation();
  879. var $hub = this.$el.find(".new_labels"),
  880. $text = this.$el.find(".new_labels :text.add-label")
  881. ;
  882. $hub.addClass('active');
  883. $text.focus();
  884. },
  885. enter_new_labels: function (e) {
  886. if (e.which == 13) {
  887. this.add_new_labels();
  888. }
  889. },
  890. add_new_labels: function (e) {
  891. if (e) {
  892. e.preventDefault();
  893. e.stopPropagation();
  894. }
  895. if (this._adding_label) return;
  896. var me = this,
  897. $hub = this.$el.find(".new_labels"),
  898. $text = this.$el.find(".new_labels :text.add-label"),
  899. selection = $text.val()
  900. ;
  901. this._adding_label = true;
  902. $text.attr('disabled', true);
  903. this.model.add_new_label(selection)
  904. .always(function(){
  905. me._adding_label = false;
  906. $text.val('').attr('disabled', false);
  907. })
  908. .fail(function(jqxhr){
  909. var response = jqxhr.responseJSON;
  910. if (response && response.error) {
  911. Upfront.Views.Editor.notify(response.error, 'error');
  912. }
  913. });
  914. }
  915. });
  916. var MediaManager_ItemControl_LabelItem = Backbone.View.extend({
  917. tagName: 'li',
  918. events: {
  919. click: "toggle_label_assignment"
  920. },
  921. render: function () {
  922. var me = this,
  923. is_used = this.media_items.is_used_label(this.model),
  924. used = _.template('<input type="checkbox" id="{{id}}" class="upfront-field-checkbox" value="{{value}}" checked />'),
  925. free = _.template('<input type="checkbox" id="{{id}}" class="upfront-field-checkbox" value="{{value}}" />'),
  926. label = _.template('<label for="{{id}}">{{name}}</label>'),
  927. name = this.model.get("filter") || '',
  928. match_rx = this.selection ? new RegExp('(' + this.selection + ')', 'i') : false,
  929. obj = this.model.toJSON()
  930. ;
  931. this.matched = false;
  932. this.$el.empty();
  933. if (match_rx && !name.match(match_rx)) return false;
  934. this.matched = true;
  935. obj.id = this.cid;
  936. obj.name = name.replace(match_rx, '<span class="selection">$1</span>');
  937. this.$el
  938. .append(label(obj))
  939. .append((is_used ? used : free)(obj))
  940. ;
  941. },
  942. toggle_label_assignment: function (e) {
  943. e.preventDefault();
  944. e.stopPropagation();
  945. this.media_items.update_label_state(this.model);
  946. }
  947. });
  948. var MediaManager_SearchFiltersControl = Backbone.View.extend({
  949. className: "upfront-search_filter-control",
  950. events: {
  951. "click a": "clear_search"
  952. },
  953. render: function () {
  954. var search = ActiveFilters.get("search").first(),
  955. obj = search.toJSON();
  956. obj.total = ActiveFilters.max_items;
  957. this.$el.empty().append(
  958. _.template(l10n.showing_total_results + ' <b class="search-text">{{value}}</b> <a href="#clear" class="clear_search">' + l10n.clear_search + '</a>', obj)
  959. );
  960. },
  961. clear_search: function (e) {
  962. e.preventDefault();
  963. e.stopPropagation();
  964. var search = new MediaFilter_Item({filter: false, value: false, state: false});
  965. ActiveFilters.set({search: new MediaFilter_Collection([search])});
  966. Upfront.Events.trigger("media_manager:media:list", ActiveFilters);
  967. Upfront.Events.trigger("media:search:requested", search);
  968. }
  969. });
  970. var MediaManager_FiltersControl = Backbone.View.extend({
  971. className: "upfront-filter-control",
  972. events: {
  973. "click": "stop_prop"
  974. },
  975. stop_prop: function (e) {
  976. e.stopPropagation();
  977. if (this.filter_selection) this.filter_selection.trigger("filters:outside_click");
  978. },
  979. initialize: function () {
  980. this.filter_selection = new MediaManager_FiltersSelectionControl();
  981. //this.filters_selected = new MediaManager_FiltersSelectedControl({model: ActiveFilters});
  982. },
  983. render: function () {
  984. this.filter_selection.render();
  985. //this.filters_selected.render();
  986. this.$el.empty()
  987. .append(this.filter_selection.$el)
  988. //.append(this.filters_selected.$el)
  989. ;
  990. },
  991. toggle_titles: function (e) {
  992. e.stopPropagation();
  993. Upfront.Events.trigger("media_manager:media:toggle_titles");
  994. },
  995. remove: function() {
  996. this.filter_selection.remove();
  997. //this.filters_selected.remove();
  998. Backbone.View.prototype.remove.call(this);
  999. }
  1000. });
  1001. var MediaManager_FiltersSelectedControl = Backbone.View.extend({
  1002. className: "upfront-filter_selected-control",
  1003. events: {
  1004. "click a.filter": "drop_filter",
  1005. "click a.all_filters": "drop_all"
  1006. },
  1007. initialize: function () {
  1008. this.listenTo(Upfront.Events, "media_manager:media:list", this.set_filters);
  1009. },
  1010. render: function () {
  1011. this.$el.empty();
  1012. var me = this,
  1013. _list = _(this.model.to_list()),
  1014. _to_render = _([]),
  1015. tpl = _.template(' <a href="#" class="filter upfront-icon upfront-icon-media-label-delete" data-type="{{type}}" data-filter="{{filter}}">{{filter}}</a>')
  1016. ;
  1017. _list.each(function (filters, type) {
  1018. _(filters).each(function (filter) {
  1019. _to_render.push({filter: filter, type: type});
  1020. });
  1021. });
  1022. if (!_to_render.size()) return false; // Do not render the empty filter array (ie. only defaults)
  1023. this.$el.append('<label class="upfront-field-label upfront-field-label-block">' + l10n.active_filters + '</label>');
  1024. _to_render.each(function (item) {
  1025. me.$el.append(tpl(item));
  1026. });
  1027. this.$el.append(" <a href='#' class='all_filters'>" + l10n.clear_all_filters + "</a>");
  1028. },
  1029. set_filters: function (filters) {
  1030. this.model = filters;
  1031. this.render();
  1032. },
  1033. drop_filter: function (e) {
  1034. e.preventDefault();
  1035. e.stopPropagation();
  1036. var $el = $(e.target),
  1037. all = this.model,
  1038. type = $el.attr("data-type"),
  1039. filter = $el.attr("data-filter")
  1040. ;
  1041. if (type && all.get(type)) {
  1042. var has = all.get(type).where({filter: filter});
  1043. if (has && has.length) _(has).invoke("set", {state: false}, {silent: true});
  1044. } else {
  1045. _(this.model.attributes).each(function (collection, idx) {
  1046. var has = all.get(idx).where({filter: filter});
  1047. if (has.length) {
  1048. type = idx;
  1049. _(has).invoke("set", {state: false}, {silent: true});
  1050. }
  1051. });
  1052. }
  1053. Upfront.Events.trigger("media_manager:media:filters_updated", type, this.model);
  1054. },
  1055. drop_all: function (e) {
  1056. e.preventDefault();
  1057. e.stopPropagation();
  1058. Upfront.Events.trigger("media_manager:media:filters_updated", false, false);
  1059. }
  1060. });
  1061. var MediaManager_FiltersSelectionControl = Backbone.View.extend({
  1062. className: "upfront-filter_selection-control clearfix",
  1063. initialize: function () {
  1064. this.controls = _([
  1065. new Control_MediaType(),
  1066. //new Control_MediaDate(),
  1067. //new Control_MediaFileName(),
  1068. //new Control_MediaRecent(),
  1069. new Control_MediaLabels()
  1070. ]);
  1071. this.on("filters:outside_click", function () {
  1072. this.controls.each(function (ctrl) {
  1073. ctrl.trigger("filters:selection:click");
  1074. });
  1075. }, this);
  1076. },
  1077. render: function () {
  1078. var me = this,
  1079. tpl = _.template("<li style='display:none'><a href='#' data-idx='{{idx}}'>{{name}}</a></li>"),
  1080. values = []
  1081. ;
  1082. this.controls.each(function (ctl, idx) {
  1083. values.push({label: ctl.get_name(), value: idx});
  1084. });
  1085. this.$el.empty();
  1086. this.$el.append('<div class="upfront-filter_control" />');
  1087. this.$control = this.$el.find("div.upfront-filter_control");
  1088. this.control_field = new Upfront.Views.Editor.Field.Radios({
  1089. label: l10n.filter_label,
  1090. name: "filter-selection",
  1091. className: "upfront-field-wrap upfront-field-wrap-multiple upfront-field-wrap-radios upfront-filter_selection-tab",
  1092. values: values,
  1093. multiple: false,
  1094. default_value: ActiveFilters.current_filter_control,
  1095. change: function(){
  1096. me.select_control(this.get_value());
  1097. }
  1098. });
  1099. this.control_field.render();
  1100. this.$el.prepend(this.control_field.$el);
  1101. this.control_field.trigger('changed');
  1102. },
  1103. select_control: function (idx) {
  1104. this.$control.empty();
  1105. if ('false' === idx) return false;
  1106. ActiveFilters.current_filter_control = idx;
  1107. var control = this.controls.toArray()[idx];
  1108. control.render();
  1109. this.$control.append(control.$el);
  1110. return false;
  1111. },
  1112. remove: function () {
  1113. this.controls.each(function (ctrl) {
  1114. ctrl.remove();
  1115. });
  1116. Backbone.View.prototype.remove.call(this);
  1117. }
  1118. });
  1119. var Media_FilterSelection_Multiselection = Backbone.View.extend({
  1120. tagName: "ul",
  1121. get_name: function () {
  1122. return this.filter_name;
  1123. },
  1124. initialize_model: function () {
  1125. this.model = ActiveFilters.get(this.filter_type);
  1126. this.listenTo(this.model, "change", this.apply_changes);
  1127. },
  1128. render: function () {
  1129. var me = this;
  1130. this.$el.empty();
  1131. this.model.each(function (model) {
  1132. if (me.allowed_values && me.allowed_values.indexOf(model.get("value")) < 0) return false;
  1133. var item = new Media_FilterSelection_Multiselection_Item({model: model});
  1134. item.render();
  1135. me.$el.append(item.$el);
  1136. });
  1137. },
  1138. apply_changes: function () {
  1139. var data = {},
  1140. values = []
  1141. ;
  1142. data = this.model.where({state:true});
  1143. Upfront.Events.trigger("media_manager:media:filters_updated", this.filter_type, data);
  1144. },
  1145. update_selection: function () {
  1146. var active = ActiveFilters.get(this.filter_type);
  1147. if (!active) {
  1148. this.model.invoke("set", {state: false});
  1149. } else {
  1150. this.model.each(function (model) {
  1151. var has = active.where({filter: model.get("filter"), state: true});
  1152. model.set({state: !!has.length});
  1153. });
  1154. }
  1155. this.render();
  1156. return false;
  1157. }
  1158. });
  1159. var Media_FilterSelection_AdditiveMultiselection = Media_FilterSelection_Multiselection.extend({
  1160. tagName: "div",
  1161. className: "upfront-additive_multiselection",
  1162. events: {
  1163. click: "stop_prop",
  1164. "keyup :text.filter": "show_matching_labels",
  1165. "focus :text.filter": "add_focus_state",
  1166. "blur :text.filter": "remove_focus_state"
  1167. },
  1168. stop_prop: function (e) {
  1169. e.stopPropagation();
  1170. // Also let's focus the text field
  1171. this.$el.find(":text.filter").focus();
  1172. },
  1173. add_focus_state: function (e) {
  1174. this.$el.addClass('focus');
  1175. },
  1176. remove_focus_state: function (e) {
  1177. this.$el.removeClass('focus');
  1178. },
  1179. render: function () {
  1180. var me = this,
  1181. sel = this.selection || ''
  1182. ;
  1183. this.$el
  1184. .empty()
  1185. .append('<div class="title">' + l10n.filter_by_labels + '</div>')
  1186. .append('<div class="labels_filter"><ul></ul><input type="text" class="filter upfront-field upfront-field-text" value="' + sel + '" placeholder="' + l10n.type_labels + '" /></div>')
  1187. .append('<div class="labels_list"><ul></ul></div>')
  1188. ;
  1189. this.render_filtered_items();
  1190. this.render_items();
  1191. },
  1192. render_filtered_items: function () {
  1193. var me = this,
  1194. $hub = this.$el.find("div.labels_filter ul"),
  1195. count = 0
  1196. ;
  1197. $hub.empty();
  1198. this.model.each(function (model) {
  1199. if (me.allowed_values && me.allowed_values.indexOf(model.get("value")) < 0) return false;
  1200. if (!model.get("state")) return false;
  1201. var item = new Media_FilterSelection_AdditiveMultiselection_Item({model: model});
  1202. item.render();
  1203. $hub.append(item.$el);
  1204. count++;
  1205. });
  1206. if (count > 0) {
  1207. // Remove placeholder
  1208. this.$el.find(":text.filter").attr('placeholder', '');
  1209. }
  1210. },
  1211. render_items: function () {
  1212. var me = this,
  1213. $hub = this.$el.find("div.labels_list ul"),
  1214. match = 0
  1215. ;
  1216. $hub.empty();
  1217. if (!this.selection) {
  1218. this.$el.removeClass('has_match');
  1219. return false;
  1220. }
  1221. //if (!this.$el.is(".active")) return false; // Only actually render this if we can see it - it takes *a while* to do so
  1222. this.model.each(function (model) {
  1223. if (me.allowed_values && me.allowed_values.indexOf(model.get("value")) < 0) return false;
  1224. if (model.get("state")) return false;
  1225. var item = new Media_FilterSelection_AdditiveMultiselection_Item({model: model});
  1226. item.selection = me.selection;
  1227. item.render();
  1228. if (item.matched) {
  1229. $hub.append(item.$el);
  1230. match++;
  1231. }
  1232. });
  1233. if (match > 0) this.$el.addClass('has_match');
  1234. else this.$el.removeClass('has_match');
  1235. },
  1236. show_matching_labels: function (e) {
  1237. var $text = this.$el.find(":text.filter"),
  1238. selection = $text.val()
  1239. ;
  1240. this.selection = selection;
  1241. this.render_items();
  1242. }
  1243. });
  1244. var Media_FilterSelection_Uniqueselection = Media_FilterSelection_Multiselection.extend({
  1245. render: function () {
  1246. var me = this;
  1247. this.$el.empty();
  1248. this.model.each(function (model) {
  1249. if (me.allowed_values && me.allowed_values.indexOf(model.get("value")) < 0) return false;
  1250. var item = new Media_FilterSelection_Uniqueselection_Item({model: model});
  1251. item.render();
  1252. me.$el.append(item.$el);
  1253. me.listenTo(item, "model:unique_state:change", me.change_state);
  1254. });
  1255. },
  1256. change_state: function (model) {
  1257. this.model.each(function (item) {
  1258. if (item.get("value") != model.get("value")) item.set({state: false}, {silent: true});
  1259. });
  1260. model.set({state: true}, {silent: true});
  1261. this.apply_changes(model);
  1262. this.render();
  1263. }
  1264. });
  1265. var Media_FilterSelection_Multiselection_Item = Backbone.View.extend({
  1266. tagName: "li",
  1267. events: {
  1268. "click": "on_click"
  1269. },
  1270. initialize: function () {
  1271. this.listenTo(this.model, "change", this.render);
  1272. },
  1273. render: function () {
  1274. var name = this.model.get("filter");
  1275. if ("other" === this.model.get("value")) return false; // DO NOT RENDER "ALL", special case
  1276. if (this.model.get("state")) name = '<b>' + name + '</b>';
  1277. this.$el.empty().append(name);
  1278. },
  1279. on_click: function (e) {
  1280. e.preventDefault();
  1281. e.stopPropagation();
  1282. this.model.set({state: !this.model.get("state")});
  1283. }
  1284. });
  1285. var Media_FilterSelection_Uniqueselection_Item = Media_FilterSelection_Multiselection_Item.extend({
  1286. on_click: function (e) {
  1287. e.preventDefault();
  1288. e.stopPropagation();
  1289. this.model.set({state: !this.model.get("state")}, {silent: true});
  1290. this.trigger("model:unique_state:change", this.model);
  1291. }
  1292. });
  1293. var Media_FilterSelection_AdditiveMultiselection_Item = Media_FilterSelection_Multiselection_Item.extend({
  1294. render: function () {
  1295. var checked = _.template('<input type="checkbox" for="{{id}}" class="upfront-field-checkbox" name="{{filter}}" value="{{value}}" checked />'),
  1296. unchecked = _.template('<input type="checkbox" for="{{id}}" class="upfront-field-checkbox" name="{{filter}}" value="{{value}}" />'),
  1297. label = _.template('<label for="{{id}}">{{name}}</label>'),
  1298. name = this.model.get("filter") || '',
  1299. match_rx = this.selection ? new RegExp('(' + this.selection + ')', 'i') : false,
  1300. obj = this.model.toJSON()
  1301. ;
  1302. this.matched = false;
  1303. this.$el.empty();
  1304. if (match_rx && !name.match(match_rx)) return false;
  1305. this.matched = true;
  1306. obj.id = this.cid;
  1307. obj.name = name.replace(match_rx, '<span class="selection">$1</span>');
  1308. this.$el
  1309. .append(label(obj))
  1310. .append((this.model.get("state") ? checked : unchecked)(obj))
  1311. ;
  1312. }
  1313. });
  1314. var Media_FilterCollection = Backbone.View.extend({
  1315. render: function () {
  1316. var me = this;
  1317. this.$el.empty();
  1318. this.model.each(function (model) {
  1319. var item = new Media_FilterItem({model: model});
  1320. item.render();
  1321. me.$el.append(item.$el);
  1322. });
  1323. }
  1324. });
  1325. var Media_FilterItem = Backbone.View.extend({
  1326. render: function () {
  1327. this.$el.empty().append(this.model.get("filter"));
  1328. }
  1329. });
  1330. var Control_MediaType = Media_FilterSelection_Uniqueselection.extend({
  1331. initialize: function () {
  1332. this.filter_name = l10n.by_type;
  1333. this.filter_type = "type";
  1334. this.initialize_model();
  1335. this.listenTo(Upfront.Events, "media_manager:media:filters_updated", this.update_selection);
  1336. this.listenTo(Upfront.Events, "media_manager:media:filters_reset", this.initialize_model);
  1337. },
  1338. render: function () {
  1339. var me = this,
  1340. values = [],
  1341. has_all = (this.model.indexOf("other") >= 0)
  1342. ;
  1343. this.$el.empty();
  1344. this.model.each(function (model) {
  1345. if (me.allowed_values && me.allowed_values.indexOf(model.get("value")) < 0) return false;
  1346. values.push({label: model.get("filter"), value: model.get("value")});
  1347. });
  1348. this.select_field = new Upfront.Views.Editor.Field.Select({
  1349. name: "filter-type",
  1350. values: values,
  1351. multiple: false,
  1352. default_value: has_all ? "other" : this.model.findWhere({state: true}).get("value"),
  1353. change: function(){
  1354. var model = me.model.findWhere({value: this.get_value()});
  1355. model.set({state: !model.get("state")}, {silent: true});
  1356. me.change_state(model);
  1357. }
  1358. });
  1359. this.select_field.render();
  1360. this.$el.append(this.select_field.$el);
  1361. },
  1362. /*apply_changes: function (model) {
  1363. return;
  1364. var all = this.model.where({state: true}),
  1365. other = this.model.where({value: 'other'}),
  1366. edited = model.previousAttributes()
  1367. ;
  1368. if (other.length) other = other[0]; // Do the model
  1369. else return;
  1370. if (edited && edited.value && "other" === edited.value) {
  1371. var no_other = !!edited.state;
  1372. this.model.each(function (mod) {
  1373. mod.set({state: no_other}, {silent: true});
  1374. });
  1375. other.set({state: !no_other}, {silent: true});
  1376. } else if (other.get("state")) other.set({state: false}, {silent: true});
  1377. Media_FilterSelection_Uniqueselection.prototype.apply_changes.call(this);
  1378. }*/
  1379. });
  1380. var Control_MediaFileName = Media_FilterSelection_Uniqueselection.extend({
  1381. allowed_values: ['title_desc', 'title_asc'],
  1382. initialize: function () {
  1383. this.filter_name = l10n.file_name;
  1384. this.filter_type = "order";
  1385. this.initialize_model();
  1386. this.listenTo(Upfront.Events, "media_manager:media:filters_updated", this.update_selection);
  1387. this.listenTo(Upfront.Events, "media_manager:media:filters_reset", this.initialize_model);
  1388. }
  1389. });
  1390. var Control_MediaLabels = Media_FilterSelection_AdditiveMultiselection.extend({
  1391. initialize: function () {
  1392. this.filter_name = l10n.by_labels;
  1393. this.filter_type = "label";
  1394. this.initialize_model();
  1395. this.listenTo(Upfront.Events, "media_manager:media:filters_updated", this.update_selection);
  1396. this.listenTo(Upfront.Events, "media_manager:media:filters_reset", this.initialize_model);
  1397. this.listenTo(Upfront.Events, "media_manager:media:labels_loaded", this.reinitialize_model);
  1398. },
  1399. reinitialize_model: function () {
  1400. this.initialize_model();
  1401. this.render();
  1402. }
  1403. });
  1404. var MediaManager_SearchControl = Backbone.View.extend({
  1405. className: "upfront-search-control",
  1406. events: {
  1407. "click .clear": "clear_search",
  1408. "keyup :text": "on_keyup"
  1409. },
  1410. render: function () {
  1411. var me = this,
  1412. active = ActiveFilters.get("search"),
  1413. search = !!active.length ? active.first() : false,
  1414. has_search = !!search && search.get("state")
  1415. ;
  1416. if ( _.isUndefined(this.search_field) ) {
  1417. this.search_field = new Upfront.Views.Editor.Field.Text({
  1418. label: l10n.search_media,
  1419. name: 'search',
  1420. placeholder: l10n.search_placeholder,
  1421. default_value: has_search && search ? search.get("value") : ''
  1422. });
  1423. }
  1424. if ( _.isUndefined(this.search_button) ) {
  1425. this.search_button = new Upfront.Views.Editor.Field.Button({
  1426. label: l10n.search,
  1427. classname: 'upfront-media-search-button',
  1428. compact: true,
  1429. on_click: function(e) {
  1430. e.preventDefault();
  1431. e.stopPropagation();
  1432. me.do_search();
  1433. }
  1434. });
  1435. }
  1436. this.search_field.render();
  1437. this.search_button.render();
  1438. this.$el.empty()
  1439. .append(this.search_field.$el)
  1440. .append(this.search_button.$el)
  1441. ;
  1442. if (has_search) {
  1443. this.$el.addClass("has_search");
  1444. }
  1445. else {
  1446. this.$el.removeClass("has_search");
  1447. }
  1448. },
  1449. do_search: function () {
  1450. var text = this.search_field.get_value(),
  1451. search = new MediaFilter_Item({filter: text, value: text, state: true})
  1452. ;
  1453. if (!text) {
  1454. search = new MediaFilter_Item({filter: false, value: false, state: false});
  1455. }
  1456. ActiveFilters.to_defaults();
  1457. ActiveFilters.current_keys = [];
  1458. ActiveFilters.current_models = [];
  1459. ActiveFilters.set("search", new MediaFilter_Collection([search]));
  1460. Upfront.Events.trigger("media_manager:media:list", ActiveFilters);
  1461. Upfront.Events.trigger("media:search:requested", search);
  1462. this.render();
  1463. var selected_model = new MediaCollection_Selection(ActiveFilters.current_models);
  1464. Upfront.Events.trigger("media:item:selection_changed", selected_model);
  1465. },
  1466. clear_search: function (e) {
  1467. e.preventDefault();
  1468. e.stopPropagation();
  1469. this.search_field.set_value('');
  1470. this.do_search(e);
  1471. },
  1472. on_keyup: function (e) {
  1473. if ( e.keyCode == 13 )
  1474. this.search_button.$el.trigger('click');
  1475. //else if ( e.keyCode == 27 )
  1476. // this.$el.find('.clear').trigger('click');
  1477. }
  1478. });
  1479. /**
  1480. * Top-level controls
  1481. */
  1482. var MediaManager_Switcher = Backbone.View.extend({
  1483. events: {
  1484. "click .media-upload": "switch_to_upload",
  1485. "click .media-info": "switch_controls"
  1486. },
  1487. info_template: _.template(
  1488. '<button type="button" class="media-info upfront-icon-control upfront-icon-media-info">' + l10n.info + '</button>'
  1489. ),
  1490. upload_template: _.template(
  1491. '<button type="button" class="media-upload upfront-icon-control upfront-icon-media-upload">' + l10n.upload + '</button>'
  1492. ),
  1493. initialize: function (options) {
  1494. this.options = options;
  1495. this.listenTo(Upfront.Events, "media:item:selection_changed", this.switch_delete);
  1496. },
  1497. render: function () {
  1498. this.$el.empty().append(
  1499. this.info_template({}) +
  1500. (ActiveFilters.has_upload() ? this.upload_template({}) : '')
  1501. );
  1502. this.$el.addClass('upfront-no-select clearfix');
  1503. },
  1504. remove: function () {
  1505. this.undelegateEvents();
  1506. if (this.delete_control) {
  1507. this.delete_control.remove();
  1508. this.delete_control = false;
  1509. }
  1510. // We don't want to remove this element as it belongs to popup, so just empty it out and remove bound events
  1511. this.$el.empty();
  1512. this.stopListening();
  1513. },
  1514. switch_to_upload: function (e) {
  1515. e.preventDefault();
  1516. e.stopPropagation();
  1517. this.trigger("media_manager:switcher:to_upload");
  1518. },
  1519. switch_controls: function (e) {
  1520. if (e) {
  1521. e.preventDefault();
  1522. e.stopPropagation();
  1523. }
  1524. if (!this.options.can_toggle_control) return;
  1525. this.$el.find('.media-info').toggleClass('media-info-active');
  1526. this.trigger("media_manager:switcher:toggle_controls");
  1527. },
  1528. show_controls: function () {
  1529. this.$el.find('.media-info').addClass('media-info-active');
  1530. this.trigger("media_manager:switcher:toggle_controls", true);
  1531. },
  1532. switch_delete: function (media_collection) {
  1533. var positive = media_collection && media_collection.where ? media_collection.where({selected: true}) : [];
  1534. if (positive.length) {
  1535. this.render_delete(positive);
  1536. }
  1537. else {
  1538. if (this.delete_control) {
  1539. this.delete_control.remove();
  1540. this.delete_control = false;
  1541. }
  1542. }
  1543. },
  1544. render_delete: function (selected) {
  1545. if ( this.delete_control ) this.delete_control.remove();
  1546. this.delete_control = new MediaManager_DeleteControl({model: new MediaCollection_Selection(selected)});
  1547. this.delete_control.render();
  1548. //this.render_selection();
  1549. this.$el.append(this.delete_control.$el);
  1550. this.$el.addClass('upfront-media-manager-has-select');
  1551. },
  1552. /**
  1553. * Boolean helper for determining if we're in some sort of a free-form or text editing mode
  1554. */
  1555. is_in_editing_mode: function () {
  1556. var type = Upfront.Application.sidebar.prevented_usage_type;
  1557. return !(type.match(/media/));
  1558. }
  1559. });
  1560. /**
  1561. * Main media dispatcher, has main level views.
  1562. */
  1563. var MediaManager_View = Backbone.View.extend({
  1564. _request_in_progress: false,
  1565. initialize: function (data) {
  1566. data = _.extend({
  1567. type: "PostImage",
  1568. multiple_selection: false,
  1569. can_toggle_control: false,
  1570. show_control: true,
  1571. show_insert: true
  1572. }, data);
  1573. var type = data.type,
  1574. multiple_selection = data.multiple_selection,
  1575. button_text = data.button_text,
  1576. button_text_multiple = data.button_text_multiple
  1577. ;
  1578. this.popup_data = data.data;
  1579. this.can_toggle_control = data.can_toggle_control;
  1580. this.show_control = data.show_control;
  1581. ActiveFilters.to_defaults();
  1582. this.switcher_view = new MediaManager_Switcher({
  1583. el: this.popup_data.$top,
  1584. can_toggle_control: this.can_toggle_control,
  1585. show_control: this.show_control
  1586. });
  1587. this.listenTo(this.switcher_view, "media_manager:switcher:to_upload", this.render_upload, this);
  1588. this.listenTo(this.switcher_view, "media_manager:switcher:toggle_controls", this.toggle_controls, this);
  1589. this.command_view = new MediaManager_BottomCommand({
  1590. el: this.popup_data.$bottom,
  1591. button_text: button_text,
  1592. button_text_multiple: button_text_multiple,
  1593. ck_insert: data.ck_insert,
  1594. show_insert: data.show_insert
  1595. });
  1596. this.library_view = new MediaManager_PostImage_View(data.collection, data);
  1597. //this.embed_view = new MediaManager_EmbedMedia({});
  1598. this.library_view.multiple_selection = multiple_selection;
  1599. if(data.themeImages){
  1600. ActiveFilters.themeImages = true;
  1601. this.library_view.multiple_selection = false;
  1602. }
  1603. this.listenTo(Upfront.Events, "media:item:selection_changed", this.update_model);
  1604. },
  1605. remove: function() {
  1606. this.library_view.remove();
  1607. this.switcher_view.remove();
  1608. this.command_view.remove();
  1609. //this.library_view = new MediaManager_PostImage_View(this.collection);
  1610. // We don't want to remove this element as it belongs to popup, so just empty it out and remove bound events
  1611. this.$el.empty();
  1612. this.stopListening();
  1613. },
  1614. render: function () {
  1615. this.switcher_view.render();
  1616. this.command_view.render();
  1617. this.render_library();
  1618. this.listenTo(Upfront.Events, "media_manager:media:list", this.switch_media_type);
  1619. },
  1620. render_library: function () {
  1621. this.load();
  1622. //this.embed_view.model.clear({silent:true});
  1623. this.library_view.render();
  1624. this.$el.empty().append(this.library_view.$el);
  1625. },
  1626. render_embed: function () {
  1627. return false;
  1628. /*
  1629. this.embed_view.model.clear({silent:true});
  1630. this.embed_view.render();
  1631. this.embed_view.$el.css({
  1632. 'max-height': this.popup_data.height,
  1633. 'overflow-y': 'scroll'
  1634. });
  1635. this.$el.empty().append(this.embed_view.$el);
  1636. */
  1637. },
  1638. render_upload: function (e) {
  1639. if (!this.library_view.$el.is(":visible")) this.render_library();
  1640. // Check if we're actually allowing uploads
  1641. if (!(window._upfront_media_upload && _upfront_media_upload.image_ref)) {
  1642. alert(l10n.disabled);
  1643. return false;
  1644. }
  1645. var me = this,
  1646. uploaded = 0,
  1647. progressing = 0,
  1648. done = 0,
  1649. processed = 0,
  1650. new_media = [],
  1651. media_library_view = me.library_view._subviews.media,
  1652. uploadUrl = ActiveFilters.themeImages ? _upfront_media_upload.theme : _upfront_media_upload.normal
  1653. ;
  1654. this.$("#fileupload").remove();
  1655. this.$el.append('<input id="fileupload" type="file" style="display:none" name="media" data-url="' + uploadUrl + '" multiple >');
  1656. this.$("#fileupload").off("click").on("click", function (e) { e.stopPropagation(); }).fileupload({
  1657. dataType: 'json',
  1658. add: function (e, data) {
  1659. var media = data.files[0],
  1660. count = uploaded,
  1661. name = media.name || 'tmp'
  1662. ;
  1663. uploaded++;
  1664. new_media[count] = new MediaItem_Model({progress: 0});
  1665. new_media[count].set({post_title: name});
  1666. media_library_view.model.add(new_media[count], {at: 0});
  1667. data.submit();
  1668. new_media[count].on("upload:abort", function () {
  1669. data.abort();
  1670. // If normal Media.
  1671. if (new_media[count].get("ID") && !ActiveFilters.themeImages) {
  1672. // Already uploaded this file, remove on the server side
  1673. Upfront.Util.post({
  1674. action: "upfront-media-remove_item",
  1675. item_id: new_media[count].get("ID")
  1676. }).always(function () {
  1677. media_library_view.model.trigger("change");
  1678. });
  1679. }
  1680. media_library_view.model.remove(new_media[count]);
  1681. media_library_view.model.trigger("change");
  1682. });
  1683. new_media[count].trigger("upload:start", media);
  1684. },
  1685. progressall: function (e, data) {
  1686. var count = progressing;
  1687. progressing++;
  1688. var progress = parseInt(data.loaded / data.total * 100, 10);
  1689. if (new_media[count]) new_media[count].trigger("upload:progress", progress);
  1690. },
  1691. done: function (e, data) {
  1692. var count = done;
  1693. done++;
  1694. processed++;
  1695. if(ActiveFilters.themeImages){
  1696. new_media[count].set(data.result.data, {silent: true});
  1697. new_media[count].trigger("upload:finish", me);
  1698. if (processed == uploaded) { // Refresh when all images has processed
  1699. ActiveFilters.to_defaults();
  1700. Upfront.Events.trigger("media_manager:media:list", ActiveFilters);
  1701. }
  1702. return;
  1703. }
  1704. var result = data.result.data || [],
  1705. uploaded_id = result[0]
  1706. ;
  1707. new_media[count].set({ID: uploaded_id}, {silent:true});
  1708. Upfront.Util.post({
  1709. action: "upfront-media-get_item",
  1710. item_id: uploaded_id
  1711. }).done(function (response) {
  1712. new_media[count].set(response.data, {silent:true});
  1713. new_media[count].trigger("upload:finish", me);
  1714. }).always(function () {
  1715. if (processed == uploaded) { // Refresh when all images has processed
  1716. ActiveFilters.to_defaults();
  1717. Upfront.Events.trigger("media_manager:media:list", ActiveFilters);
  1718. }
  1719. });
  1720. },
  1721. fail: function (e, data) {
  1722. processed++;
  1723. if (data.jqXHR.responseJSON && data.jqXHR.responseJSON.error) Upfront.Views.Editor.notify(data.jqXHR.responseJSON.error, 'error');
  1724. if (processed == uploaded) { // Refresh when all images has processed
  1725. ActiveFilters.to_defaults();
  1726. Upfront.Events.trigger("media_manager:media:list", ActiveFilters);
  1727. }
  1728. }
  1729. }).trigger("click");
  1730. },
  1731. render_shortcode: function () {
  1732. //console.log("SHORTCODE YAY");
  1733. },
  1734. render_markup: function () {
  1735. //console.log("MARKUP YAY");
  1736. },
  1737. toggle_controls: function (show) {
  1738. if (!this.library_view) return false;
  1739. this.library_view.toggle_controls(show);
  1740. this.show_control = false;
  1741. },
  1742. load: function (data) {
  1743. Upfront.Events.trigger("media_manager:load:start", data);
  1744. this._request_in_progress = true;
  1745. data = data && data.type ? data : ActiveFilters.to_request_json();
  1746. data.media_limit = ActiveFilters.media_limit;
  1747. data.action = ActiveFilters.themeImages ? 'upfront-media-list_theme_images' : "upfront-media-list_media";
  1748. var me = this;
  1749. if (this.library_view.media_view && this.library_view.media_view.start_loading) this.library_view.media_view.start_loading();
  1750. Upfront.Util.post(data)
  1751. .done(function (response) {
  1752. ActiveFilters.set_max_pages(response.data.meta.max_pages);
  1753. ActiveFilters.set_max_items(response.data.meta.max_items);
  1754. me.library_view.update(response.data.items);
  1755. me.command_view.render();
  1756. if (me.show_control) me.switcher_view.show_controls();
  1757. Upfront.Events.trigger("media_manager:load:done", response);
  1758. })
  1759. .fail(function (response) {
  1760. me.library_view.update([]);
  1761. me.command_view.render();
  1762. Upfront.Events.trigger("media_manager:load:fail", response);
  1763. })
  1764. .always(function () {
  1765. me._request_in_progress = false;
  1766. })
  1767. ;
  1768. },
  1769. switch_media_type: function (what) {
  1770. if (this._request_in_progress) return false;
  1771. this.load(what.to_request_json());
  1772. },
  1773. update_model: function (selected) {
  1774. // checking on all models on current page
  1775. for ( var key in selected.models ) {
  1776. var model = selected.models[key],
  1777. modelAttributes = ((model || {}).attributes || {})
  1778. index = ActiveFilters.current_keys.indexOf(modelAttributes.ID)
  1779. ;
  1780. if( index == -1 ) {
  1781. // inserting selected media models on the list
  1782. if( modelAttributes.selected ) {
  1783. ActiveFilters.current_keys.push(modelAttributes.ID);
  1784. ActiveFilters.current_models.push(model);
  1785. }
  1786. } else {
  1787. // removing media models on the list
  1788. if( !modelAttributes.selected || modelAttributes.selected === undefined ) {
  1789. ActiveFilters.current_keys.splice(index, 1);
  1790. ActiveFilters.current_models.splice(index, 1);
  1791. }
  1792. }
  1793. }
  1794. Upfront.Events.trigger("media_manager:active_filters:updated");
  1795. }
  1796. });
  1797. /**
  1798. * Bottom commands view (search etc)
  1799. */
  1800. var MediaManager_BottomCommand = Backbone.View.extend({
  1801. initialize: function(opts){
  1802. this.options = opts;
  1803. },
  1804. render: function () {
  1805. var button_text = this.options.button_text,
  1806. button_text_multiple = this.options.button_text_multiple,
  1807. pagination = new MediaManager_Pagination(),
  1808. use = false
  1809. ;
  1810. pagination.render();
  1811. if (this.options.show_insert) {
  1812. use = this.options.ck_insert
  1813. ? new MediaManager_BottomCommand_UseSelection_MultiDialog({
  1814. button_text: button_text,
  1815. button_text_multiple: button_text_multiple
  1816. })
  1817. : new MediaManager_BottomCommand_UseSelection({
  1818. button_text: button_text,
  1819. button_text_multiple: button_text_multiple
  1820. })
  1821. use.render();
  1822. }
  1823. this.$el.empty()
  1824. .append(pagination.$el)
  1825. .append(use !== false ? use.$el : '')
  1826. .addClass('upfront-no-select')
  1827. ;
  1828. },
  1829. switch_to_upload: function (e) {
  1830. this.trigger("media_manager:switcher:to_upload");
  1831. },
  1832. remove: function () {
  1833. // We don't want to remove this element as it belongs to popup, so just empty it out and remove bound events
  1834. this.$el.empty();
  1835. this.stopListening();
  1836. }
  1837. });
  1838. var MediaManager_Pagination = Backbone.View.extend({
  1839. events: {
  1840. "click .upfront-pagination_item-prev": "prev_page",
  1841. "click .upfront-pagination_item-next": "next_page",
  1842. "click .upfront-pagination_page-item": "set_page",
  1843. "click .upfront-pagination_page-current": "stop_prop",
  1844. "keypress .upfront-pagination_page-current": "set_page_keypress"
  1845. },
  1846. stop_prop: function (e) { e.stopPropagation(); },
  1847. render: function () {
  1848. var markup = '';
  1849. if (ActiveFilters.max_pages > 1) {
  1850. markup += '<div id="upfront-entity_list-pagination">';
  1851. markup += '<a class="upfront-pagination_item upfront-pagination_item-skip upfront-pagination_item-prev"></a>';
  1852. // Input
  1853. markup += '<div class="upfront-pagination_navigation">';
  1854. markup += '<input type="text" class="upfront-pagination_page-current" value="' + ActiveFilters.current_page + '" />';
  1855. markup += '&nbsp;' + l10n.n_of_x + '&nbsp;';
  1856. markup += '<a class="upfront-pagination_page-item" data-idx="' + (ActiveFilters.max_pages - 1) + '">' + (ActiveFilters.max_pages - 1) + '</a>';
  1857. markup += '</div>';
  1858. markup += '<a class="upfront-pagination_item upfront-pagination_item-skip upfront-pagination_item-next"></a>';
  1859. // Add max items
  1860. markup += '<small>(' + _.template(l10n.entity_list_info, {items: ActiveFilters.max_items, pages: ActiveFilters.max_pages - 1}) + ')</small>';
  1861. markup += '</div>';
  1862. }
  1863. this.$el.empty().append(markup);
  1864. },
  1865. prev_page: function (e) {
  1866. e.preventDefault();
  1867. e.stopPropagation();
  1868. if (ActiveFilters.prev_page()) Upfront.Events.trigger("media_manager:media:list", ActiveFilters);
  1869. },
  1870. next_page: function (e) {
  1871. e.preventDefault();
  1872. e.stopPropagation();
  1873. if (ActiveFilters.next_page()) Upfront.Events.trigger("media_manager:media:list", ActiveFilters);
  1874. },
  1875. set_page: function (e) {
  1876. e.preventDefault();
  1877. e.stopPropagation();
  1878. if (ActiveFilters.set_page($(e.target).data("idx"))) Upfront.Events.trigger("media_manager:media:list", ActiveFilters);
  1879. },
  1880. set_page_keypress: function (e) {
  1881. e.stopPropagation();
  1882. //e.preventDefault();
  1883. if (13 !== e.which) return true;
  1884. var string = $.trim($(e.target).val()),
  1885. num = parseInt(string, 10)
  1886. ;
  1887. if (!num) return false;
  1888. if (num > ActiveFilters.max_pages) num = ActiveFilters.max_pages;
  1889. if (ActiveFilters.set_page(num)) Upfront.Events.trigger("media_manager:media:list", ActiveFilters);
  1890. }
  1891. });
  1892. var MediaManager_BottomCommand_UseSelection = Backbone.View.extend({
  1893. className: "use_selection_container",
  1894. events: {
  1895. "click a": "use_selection"
  1896. },
  1897. initialize: function (opts) {
  1898. this.options = opts;
  1899. this.listenTo(Upfront.Events, "media_manager:active_filters:updated", this.render);
  1900. },
  1901. render: function () {
  1902. this.$el.empty();
  1903. if ( ActiveFilters.current_models.length == 1 ) {
  1904. this.$el.append('<a href="#use" class="use">' + ( this.options.button_text || l10n.ok )+ '</a>');
  1905. }
  1906. else if ( ActiveFilters.current_models.length > 1 ) {
  1907. this.$el.append('<a href="#use" class="use">' + ( this.options.button_text_multiple || l10n.ok ) + '</a>');
  1908. }
  1909. },
  1910. use_selection: function (e) {
  1911. e.preventDefault();
  1912. e.stopPropagation();
  1913. // using the persistent list instead of current page media collection
  1914. var model = new MediaCollection_Selection(ActiveFilters.current_models);
  1915. Upfront.Popup.close(model);
  1916. }
  1917. });
  1918. var MediaManager_BottomCommand_UseSelection_MultiDialog = MediaManager_BottomCommand_UseSelection.extend({
  1919. use_selection: function (e) {
  1920. e.preventDefault();
  1921. e.stopPropagation();
  1922. if ( this.model && this.model.length > 1 )
  1923. this.open_dialog();
  1924. else
  1925. Upfront.Popup.close(this.model);
  1926. },
  1927. open_dialog: function () {
  1928. var $dialog = $('<div id="media-manager-multi-dialog" class="upfront-ui" />');
  1929. $dialog.append('<h3 class="multi-dialog-title">' + l10n.insertion_question + '</h3>');
  1930. $dialog.append(
  1931. '<ul class="multi-dialog-choices">' +
  1932. '<li class="multi-dialog-choice upfront-icon upfront-icon-media-insert-multi-plain" data-choice="plain">' + l10n.plain_images + '</li>' +
  1933. '<li class="multi-dialog-choice upfront-icon upfront-icon-media-insert-multi-slider" data-choice="slider">' + l10n.image_slider + '</li>' +
  1934. '<li class="multi-dialog-choice upfront-icon upfront-icon-media-insert-multi-gallery" data-choice="gallery">' + l10n.image_gallery + '</li>' +
  1935. '</ul>'
  1936. );
  1937. Upfront.Popup.$popup.find("#upfront-popup-content").append($dialog);
  1938. $dialog.on('click', '.multi-dialog-choice', this, this.select_dialog);
  1939. },
  1940. select_dialog: function (e) {
  1941. e.preventDefault();
  1942. e.stopPropagation();
  1943. var $dialog = $('#media-manager-multi-dialog'),
  1944. choice = $(this).attr('data-choice') || 'plain',
  1945. obj = e.data;
  1946. obj.model.type = choice;
  1947. $dialog.remove();
  1948. Upfront.Popup.close(obj.model);
  1949. }
  1950. });
  1951. /**
  1952. * Embed media from URL
  1953. */
  1954. var MediaManager_EmbedMedia = Backbone.View.extend({
  1955. className: "upfront-embed_media clearifx",
  1956. initialize: function () {
  1957. this.model = new MediaItem_Model();
  1958. },
  1959. render: function () {
  1960. this.embed_pane = new MediaManager_Embed_DetailsPane({model: this.model});
  1961. this.embed_pane.on("embed:editable:updated", this.embed_updated, this);
  1962. this.preview_pane = new MediaManager_Embed_PreviewPane({model: this.model});
  1963. this.embed_pane.render();
  1964. this.preview_pane.render();
  1965. this.$el.empty()
  1966. .append(this.embed_pane.$el)
  1967. .append(this.preview_pane.$el)
  1968. ;
  1969. },
  1970. embed_updated: function () {
  1971. this.preview_pane.render_progress();
  1972. var me = this;
  1973. Upfront.Util.post(_.extend({
  1974. action: "upfront-media-embed",
  1975. media: this.model.get("original_url")
  1976. }, _upfront_media_upload.embed_ref)).done(function (response) {
  1977. me.model.set(response.data, {silent:true});
  1978. me.preview_pane.trigger("embed:media:imported");
  1979. me.embed_pane.clear_updating_flag();
  1980. me.embed_pane.render();
  1981. me.preview_pane.render();
  1982. });
  1983. }
  1984. });
  1985. var MediaManager_Embed_DetailsPane = Backbone.View.extend({
  1986. className: "upfront-pane",
  1987. embed_is_being_updated: false,
  1988. events: {
  1989. "click button": "save"
  1990. },
  1991. initialize: function () {
  1992. this.editables = _([
  1993. new MediaItem_EmbedableUrl({model: this.model}),
  1994. new MediaItem_EditableTitle({model: this.model}),
  1995. new MediaItem_EditableLabels({model: this.model})
  1996. ]);
  1997. },
  1998. render: function () {
  1999. this.$el.empty();
  2000. var me = this;
  2001. this.editables.each(function (editable) {
  2002. editable.render();
  2003. editable.on("embed:updated", me.editable_updated, me);
  2004. me.$el.append(editable.$el);
  2005. });
  2006. this.$el.append('<button type="button">' + l10n.ok + '</button>');
  2007. },
  2008. editable_updated: function () {
  2009. this.embed_is_being_updated = true;
  2010. this.trigger("embed:editable:updated");
  2011. },
  2012. clear_updating_flag: function () {
  2013. this.embed_is_being_updated = false;
  2014. },
  2015. save: function () {
  2016. if (!this.model) return false;
  2017. var me = this;
  2018. if (!this.model.get("ID") && this.embed_is_being_updated) {
  2019. // A case when an embed is still being fetched but OK is clicked
  2020. setTimeout(function () {
  2021. me.save();
  2022. }, 500);
  2023. return false;
  2024. }
  2025. //this.editables.invoke("update"); // Do NOT!! invoke the update
  2026. var data = {
  2027. action: "upfront-media-update_media_item",
  2028. data: this.model.toJSON()
  2029. };
  2030. Upfront.Util.post(data)
  2031. .done(function () {
  2032. me.model.trigger("change");
  2033. // Swap back to media
  2034. Upfront.Events.trigger("media_manager:media:show_library", data.data);
  2035. })
  2036. ;
  2037. }
  2038. });
  2039. var MediaManager_Embed_PreviewPane = Backbone.View.extend({
  2040. className: "upfront-pane",
  2041. initialize: function () {
  2042. },
  2043. render: function () {
  2044. this.preview_view = new MediaManager_Embed_Preview({model: this.model});
  2045. this.labels_view = new MediaItem_Labels({model: this.model});
  2046. this.on("embed:media:imported", this.update_media_preview, this);
  2047. this.preview_view.render();
  2048. //this.labels_view.render();
  2049. this.$el.empty()
  2050. .append(this.preview_view.$el)
  2051. //.append(this.labels_view.$el)
  2052. ;
  2053. },
  2054. render_progress: function () {
  2055. this.$el.empty().append('<div class="preview_loader" />');
  2056. var $loader = this.$el.find(".preview_loader");
  2057. $loader.css({
  2058. position: "relative",
  2059. minHeight: "250px", // Ugh...
  2060. width: "100%"
  2061. });
  2062. this.loading = new Upfront.Views.Editor.Loading({
  2063. loading: l10n.loading_embeddable_preview,
  2064. done: 'Loaded'
  2065. });
  2066. this.loading.render();
  2067. $loader.append(this.loading.$el);
  2068. },
  2069. update_media_preview: function () {
  2070. this.preview_view.render();
  2071. this.labels_view.render();
  2072. this.labels_view.delegateEvents();
  2073. }
  2074. });
  2075. var MediaManager_Embed_Preview = Backbone.View.extend({
  2076. className: "upfront-media_manager-embed-preview",
  2077. template: _.template('{{thumbnail}} <div class="progress"></div>'),
  2078. render: function () {
  2079. if (!this.model.get("original_url")) return this.$el.empty();
  2080. var me = this,
  2081. is_image = this.is_image(),
  2082. thumbnail = is_image ? this.model.get("thumbnail") : this.get_media_thumbnail()
  2083. ;
  2084. this.$el.empty().append(this.template({thumbnail: thumbnail}));
  2085. },
  2086. is_image: function () {
  2087. return (this.model.get("original_url") || "").match(/\.(jpe?g|gif|png)$/i);
  2088. },
  2089. get_media_thumbnail: function () {
  2090. return this.model.get("thumbnail");
  2091. }
  2092. });
  2093. /**
  2094. * Post images library implementation.
  2095. */
  2096. var MediaManager_PostImage_View = MediaManager_View.extend({
  2097. className: "upfront-media_manager upfront-media_manager-post_image upfront-no-select clearfix",
  2098. _subviews: {
  2099. media: false,
  2100. aux: false,
  2101. controls: false
  2102. },
  2103. show_controls: false,
  2104. initialize: function (collection, opts) {
  2105. var data = data || {};
  2106. if((collection || {}).models)
  2107. collection = new MediaCollection_Model(collection);
  2108. else
  2109. collection = new MediaCollection_Model();
  2110. this.media_collection = collection;
  2111. this.options = opts;
  2112. },
  2113. render: function () {
  2114. if (!this._subviews.media) {
  2115. this._subviews.media = new MediaCollection_View({model: this.media_collection});
  2116. }
  2117. var media = this._subviews.media;
  2118. /*if (!this._subviews.aux) {
  2119. this._subviews.aux = new MediaManager_AuxControls_View({model: this.media_collection});
  2120. }
  2121. var aux = this._subviews.aux;*/
  2122. if (!this._subviews.controls) {
  2123. this._subviews.controls = new MediaManager_Controls_View({model: this.media_collection, options: this.options });
  2124. }
  2125. var controls = this._subviews.controls;
  2126. media.multiple_selection = this.multiple_selection;
  2127. controls.render();
  2128. //aux.render();
  2129. media.render();
  2130. this.$el
  2131. .empty()
  2132. .append(controls.$el)
  2133. //.append(aux.$el)
  2134. .append(media.$el)
  2135. ;
  2136. controls.$el.hide(); // Hide controls by default
  2137. this.media_view = media;
  2138. this.media_view.start_loading();
  2139. },
  2140. update: function (collection) {
  2141. var me = this;
  2142. this.media_view.model.reset(collection);
  2143. this.media_view.end_loading(function(){
  2144. me.media_view.render();
  2145. });
  2146. },
  2147. toggle_controls: function (show) {
  2148. this.show_controls = _.isUndefined(show) ? !this.show_controls : show;
  2149. this._subviews.controls.$el.toggle(show);
  2150. this.$el.toggleClass('upfront-media_manager-show_controls', show);
  2151. },
  2152. remove: function() {
  2153. _.each(this._subviews, function(subview, idx) {
  2154. if (!subview) return true;
  2155. subview.remove();
  2156. this._subviews[idx] = false;
  2157. }, this);
  2158. Backbone.View.prototype.remove.call(this);
  2159. }
  2160. });
  2161. var MediaCollection_View = Backbone.View.extend({
  2162. tagName: 'ul',
  2163. className: 'upfront-media_collection',
  2164. initialize: function () {
  2165. this.listenTo(this.model, "add", this.render);
  2166. this.listenTo(this.model, "remove", this.render);
  2167. this.listenTo(this.model, "change", this.update);
  2168. this.listenTo(this.model, "change:selected", this.propagate_selection);
  2169. },
  2170. render: function () {
  2171. this.subviews = [];
  2172. var me = this;
  2173. this.$el.empty();
  2174. if (!this.model.length) {
  2175. this.$el.append('&nbsp;');
  2176. } else {
  2177. this.model.each(function (model) {
  2178. var view = new MediaItem_View({model: model});
  2179. me.subviews.push(view);
  2180. view.parent_view = me;
  2181. view.render();
  2182. me.$el.append(view.$el);
  2183. // preserving selected media
  2184. if( ActiveFilters.current_keys.length ) {
  2185. var target_index = ActiveFilters.current_keys.indexOf(((model || {}).attributes || {}).ID);
  2186. if( target_index != -1 ) {
  2187. model.set({selected: true}, {silent: true});
  2188. model.trigger("appearance:update");
  2189. }
  2190. }
  2191. });
  2192. // running change event to apply persistent list
  2193. var selected_model = new MediaCollection_Selection(ActiveFilters.current_models);
  2194. Upfront.Events.trigger("media:item:selection_changed", selected_model);
  2195. // Add JS Scrollbar.
  2196. perfectScrollbar.withDebounceUpdate(
  2197. // Element.
  2198. this.el,
  2199. // Run First.
  2200. true,
  2201. // Event.
  2202. false,
  2203. // Initialize.
  2204. true
  2205. );
  2206. }
  2207. },
  2208. update: function () {
  2209. if (this.model.length) {
  2210. this.model.each(function (model) {
  2211. model.trigger("appearance:update");
  2212. });
  2213. }
  2214. },
  2215. start_loading: function () {
  2216. this.loading = new Upfront.Views.Editor.Loading({
  2217. loading: l10n.loading_media_files,
  2218. timeout: 500,
  2219. done: 'Loaded'
  2220. });
  2221. this.loading.render();
  2222. this.loading.$el.insertAfter(this.$el);
  2223. },
  2224. end_loading: function (callback) {
  2225. if (this.loading && this.loading.done) this.loading.done(callback);
  2226. else callback();
  2227. },
  2228. propagate_selection: function (model) {
  2229. if (!this.multiple_selection) {
  2230. var has = this.model.where({selected: true}),
  2231. selected = true === model.get("selected")
  2232. ;
  2233. if (has.length) _(has).each(function (item) {
  2234. item.set({selected: false}, {silent: true});
  2235. item.trigger("appearance:update");
  2236. });
  2237. // Persistent list also need to be unselected in this case
  2238. _.each(ActiveFilters.current_models, function(item){
  2239. item.set({selected: false}, {silent: true});
  2240. item.trigger("appearance:update");
  2241. });
  2242. if (selected) model.set({selected: true}, {silent: true});
  2243. model.trigger("appearance:update");
  2244. }
  2245. Upfront.Events.trigger("media:item:selection_changed", this.model);
  2246. // running again change event to apply persistent list
  2247. var selected_model = new MediaCollection_Selection(ActiveFilters.current_models);
  2248. Upfront.Events.trigger("media:item:selection_changed", selected_model);
  2249. },
  2250. remove: function() {
  2251. _.each(this.subviews, function(subview) {
  2252. subview.remove();
  2253. });
  2254. Backbone.View.prototype.remove.call(this);
  2255. }
  2256. });
  2257. var MediaItem_View = Backbone.View.extend({
  2258. tagName: 'li',
  2259. className: 'upfront-media_item',
  2260. events: {
  2261. click: "toggle_item_selection"
  2262. },
  2263. initialize: function () {
  2264. var cls = '';
  2265. // Detect the default WP video icon being used as thumb
  2266. // It's fugly, so let's add class so we can override
  2267. if ((this.model.get("thumbnail") || '').match(/wp-includes\/images\/media\/video/i)) {
  2268. cls += "override";
  2269. }
  2270. this.template = _.template("<div class='thumbnail " + cls + "'>{{thumbnail}}</div> <div class='title'>{{post_title}}</div> <div class='upfront-media_item-editor-container' />");
  2271. this.listenTo(Upfront.Events, "media_manager:media:toggle_titles", this.toggle_title);
  2272. this.listenTo(this.model, "appearance:update", this.update);
  2273. this.listenTo(this.model, "upload:start", this.upload_start);
  2274. this.listenTo(this.model, "upload:progress", this.upload_progress);
  2275. this.listenTo(this.model, "upload:finish", this.upload_finish);
  2276. },
  2277. render: function () {
  2278. this.$el.empty().append(
  2279. this.template(this.model.toJSON())
  2280. );
  2281. this.update();
  2282. this.toggle_title();
  2283. },
  2284. update: function () {
  2285. if (this.model.get("parent")) this.$el.addClass("has-parent");
  2286. else this.$el.removeClass("has-parent");
  2287. if (this.model.get("selected") && !this.$el.hasClass("selected")) {
  2288. this.$el.addClass("selected");
  2289. }
  2290. else if (!this.model.get("selected")) {
  2291. this.$el.removeClass("selected");
  2292. }
  2293. this.$el.find(".title").text(this.model.get('post_title'));
  2294. },
  2295. toggle_title: function () {
  2296. var state = ActiveFilters.showing_titles,
  2297. $el = this.$el.find(".title")
  2298. ;
  2299. if (state && !$el.is(":visible")) $el.show();
  2300. else $el.hide();
  2301. },
  2302. toggle_item_selection: function (e) {
  2303. e.stopPropagation();
  2304. e.preventDefault();
  2305. this.model.set({selected: !this.model.get("selected")});
  2306. },
  2307. upload_start: function (media) {
  2308. /*$(".upfront-media_item-editor").remove();
  2309. var editor = new MediaItem_EditorView({
  2310. model: this.model,
  2311. media: media
  2312. });
  2313. editor.render();
  2314. this.$el.find(".upfront-media_item-editor-container").append(editor.$el);*/
  2315. this.parent_view.$el.scrollTop(0);
  2316. this.$el.find('.thumbnail').append('<div class="upfront-media-progress-bar" />');
  2317. },
  2318. upload_progress: function (progress) {
  2319. //Upfront.Util.log(_.template("{{post.post_title}} progress changed to {{progress}}", {post:this.model.toJSON(), progress:progress}));
  2320. this.$el.find('.upfront-media-progress-bar').css('width', progress+'%');
  2321. },
  2322. upload_finish: function (manager) {
  2323. this.$el.find(".thumbnail .upfront-image-upload-placeholder").replaceWith(this.model.get("thumbnail"));
  2324. this.$el.find('.upfront-media-progress-bar').remove();
  2325. this.model.set({selected: true});
  2326. // adding it on persistent list
  2327. ActiveFilters.current_models.push(this.model);
  2328. // Only do if regular media.
  2329. if (!ActiveFilters.themeImages) {
  2330. // Add as current keys so uploads are selected.
  2331. ActiveFilters.current_keys.push(this.model.attributes.ID);
  2332. // redraw media gallery
  2333. //manager.render_library();
  2334. }
  2335. }
  2336. });
  2337. // ----- Editor -----
  2338. var MediaItem_EditorView = Backbone.View.extend({
  2339. className: "upfront-media_item-editor",
  2340. events: {
  2341. "click button": "save"
  2342. },
  2343. initialize: function (data) {
  2344. this.editables = _([
  2345. new MediaItem_EditableTitle({model: this.model})
  2346. ]);
  2347. if (data && data.media) this.media = data.media;
  2348. },
  2349. render: function () {
  2350. this.$el.empty();
  2351. var me = this;
  2352. this.editables.each(function (editable) {
  2353. editable.render();
  2354. me.$el.append(editable.$el);
  2355. });
  2356. var labels = new MediaItem_Labels({model: this.model});
  2357. labels.render();
  2358. this.$el.append(labels.$el);
  2359. this.$el.append('<button type="button">' + l10n.ok + '</button>');
  2360. if (!this.media) return true;
  2361. var type = this.media.type || 'application/octet-stream',
  2362. is_image = type.match(/^image/i)
  2363. ;
  2364. if (is_image) return true;
  2365. var nag = new MediaItem_UploadNag({model: this.model, media:this.media});
  2366. nag.render();
  2367. this.$el.append(nag.$el);
  2368. },
  2369. save: function () {
  2370. this.editables.invoke("update");
  2371. var me = this,
  2372. data = {
  2373. action: "upfront-media-update_media_item",
  2374. data: this.model.toJSON()
  2375. }
  2376. ;
  2377. Upfront.Util.post(data)
  2378. .done(function () {
  2379. //Upfront.Util.log('successfully saved data');
  2380. me.model.trigger("change");
  2381. })
  2382. ;
  2383. }
  2384. });
  2385. var MediaItem_Labels = Backbone.View.extend({
  2386. className: "upfront-media_labels",
  2387. events: {
  2388. "click button": "create_label",
  2389. "click a.own_label": "drop_label",
  2390. "click a.all_label": "add_label"
  2391. },
  2392. initialize: function () {
  2393. this.labels = ActiveFilters.get("label");
  2394. Upfront.Events.on("media_manager:media:labels_loaded", this.reset_labels, this);
  2395. },
  2396. reset_labels: function () {
  2397. this.labels = ActiveFilters.get("label");
  2398. this.render();
  2399. },
  2400. render: function () {
  2401. var own_labels_template = _.template('<a class="own_label" href="#" data-idx="{{value}}">{{filter}}</a> '),
  2402. all_labels_template = _.template('<a class="all_label" href="#" data-idx="{{value}}">{{filter}}</a> '),
  2403. me = this,
  2404. model_labels = this.model.get("labels"),
  2405. own_labels = [],
  2406. all_labels = []
  2407. ;
  2408. this.$el.empty();
  2409. if (this.labels) this.labels.each(function (item) {
  2410. if (model_labels && model_labels.length && model_labels.indexOf(item.get("value")) >= 0) own_labels.push(own_labels_template(item.toJSON()));
  2411. else all_labels.push(all_labels_template(item.toJSON()));
  2412. });
  2413. me.$el.append(l10n.applied_labels + "&nbsp;");
  2414. _(own_labels).each(function (item) {
  2415. me.$el.append(item);
  2416. });
  2417. this.$el.append(
  2418. '<input type="text" placeholder="label..." />' +
  2419. '<button type="button">' + l10n.add + '</button>'
  2420. );
  2421. me.$el.append("All labels: ");
  2422. _(all_labels).each(function (item) {
  2423. me.$el.append(item);
  2424. });
  2425. },
  2426. create_label: function (e) {
  2427. e.preventDefault();
  2428. e.stopPropagation();
  2429. var label = this.$el.find(":text").val(),
  2430. data = {
  2431. "action": "upfront-media-add_label",
  2432. "term": label,
  2433. "post_id": this.model.get("ID")
  2434. }
  2435. ;
  2436. Upfront.Util.post(data)
  2437. .success(function (response) {
  2438. Upfront.Events.trigger("media_manager:media:labels_updated");
  2439. })
  2440. ;
  2441. },
  2442. add_label: function (e) {
  2443. e.preventDefault();
  2444. e.stopPropagation();
  2445. this._update_labels(e);
  2446. },
  2447. drop_label: function (e) {
  2448. e.preventDefault();
  2449. e.stopPropagation();
  2450. this._update_labels(e, 'dis');
  2451. },
  2452. _update_labels: function (e, pfx) {
  2453. pfx = pfx || '';
  2454. e.preventDefault();
  2455. e.stopPropagation();
  2456. var me = this,
  2457. $label = $(e.target),
  2458. idx = $label.attr("data-idx"),
  2459. data = {
  2460. action: "upfront-media-" + pfx + "associate_label",
  2461. term: idx,
  2462. post_id: this.model.get("ID")
  2463. }
  2464. ;
  2465. Upfront.Util.post(data)
  2466. .success(function (response) {
  2467. var id = me.model.get("ID"),
  2468. data = response.data || {},
  2469. labels = data[id] || data
  2470. ;
  2471. me.model.set("labels", labels, {silent: true});
  2472. me.render();
  2473. })
  2474. ;
  2475. }
  2476. });
  2477. var MediaItem_UploadNag = Backbone.View.extend({
  2478. className: "upload_type-nag",
  2479. events: {
  2480. "click .keep": "keep_file",
  2481. "click .remove": "remove_file"
  2482. },
  2483. render: function () {
  2484. this.$el.empty()
  2485. .append(l10n.video_recommendation_nag)
  2486. .append('<a href="#" class="button keep">' + l10n.keep_file + '</a>')
  2487. .append('<a href="#" class="button remove">' + l10n.remove_file + '</a>')
  2488. ;
  2489. },
  2490. keep_file: function (e) {
  2491. e.preventDefault();
  2492. e.stopPropagation();
  2493. },
  2494. remove_file: function (e) {
  2495. e.preventDefault();
  2496. e.stopPropagation();
  2497. this.model.trigger("upload:abort");
  2498. }
  2499. });
  2500. var MediaItem_EditorEditable = Backbone.View.extend({
  2501. className: "upfront-media_item-editable",
  2502. events:{
  2503. change: "update"
  2504. },
  2505. template: _.template(
  2506. "<label>{{label}}<input type='text' name='{{name}}' value='{{value}}' placeholder='{{placeholder}}' /></label>"
  2507. ),
  2508. get_name: function () {},
  2509. get_label: function () {},
  2510. get_placeholder: function () {},
  2511. get_value: function () {
  2512. return this.$el.find('[name="' + this.get_name() + '"]:first').val();
  2513. },
  2514. render: function () {
  2515. var name = this.get_name() || '',
  2516. label = this.get_label() || '',
  2517. placeholder = this.get_placeholder() || '',
  2518. value = this.model.get(this.get_name()) || '',
  2519. data = {
  2520. name: name,
  2521. label: label,
  2522. placeholder: placeholder,
  2523. value: value
  2524. }
  2525. ;
  2526. this.$el.empty().append(
  2527. this.template(data)
  2528. );
  2529. },
  2530. update: function () {
  2531. var obj = {};
  2532. obj[this.get_name()] = this.get_value();
  2533. this.model.set(obj, {silent: true});
  2534. }
  2535. });
  2536. var MediaItem_EditorEmbedableEditable = MediaItem_EditorEditable.extend({
  2537. update: function () {
  2538. var obj = {};
  2539. obj[this.get_name()] = this.get_value();
  2540. this.model.set(obj, {silent: true});
  2541. this.trigger("embed:updated");
  2542. }
  2543. });
  2544. var MediaItem_EmbedableUrl = MediaItem_EditorEmbedableEditable.extend({
  2545. get_name: function () { return "original_url"; },
  2546. get_label: function () { return l10n.media_url; },
  2547. get_placeholder: function () { return "http://sample.com/path-to-image/image.jpg"; }
  2548. });
  2549. var MediaItem_EditableTitle = MediaItem_EditorEditable.extend({
  2550. get_name: function () { return "post_title"; },
  2551. get_label: function () { return l10n.image_title; },
  2552. get_placeholder: function () { return l10n.your_image_title; }
  2553. });
  2554. var MediaItem_EditableLabels = MediaItem_EditorEditable.extend({
  2555. get_label: function () { return l10n.labels; },
  2556. render: function () {
  2557. var collection = new MediaCollection_Selection([this.model]),
  2558. view = new MediaManager_ItemControl_LabelsContainer({model: collection})
  2559. ;
  2560. view.render();
  2561. collection.on("change", view.render_labels, view);
  2562. this.$el.empty()
  2563. .append('<label>' + this.get_label() + '</label>')
  2564. .append(view.$el)
  2565. ;
  2566. }
  2567. });
  2568. // ----- Interface -----
  2569. var ContentEditorUploader = Backbone.View.extend({
  2570. initialize: function (opts) {
  2571. this.options = opts;
  2572. },
  2573. open: function (options) {
  2574. options = _.extend({
  2575. media_type: ["images"],
  2576. multiple_sizes: true,
  2577. multiple_selection: true,
  2578. button_text: l10n.insert_media_file,
  2579. button_text_multiple: l10n.insert_media_files,
  2580. ck_insert: false,
  2581. hold_editor: false
  2582. }, options);
  2583. var me = this,
  2584. popup = false,
  2585. media_type = options.media_type,
  2586. multiple_selection = options.multiple_selection
  2587. ;
  2588. ActiveFilters.allowed_media_types = media_type;
  2589. ActiveFilters.multiple_sizes = options.multiple_sizes;
  2590. popup = Upfront.Popup.open(function (data, $top, $bottom) {
  2591. me.out = this;
  2592. me.popup_data = data;
  2593. me.popup_data.$top = $top;
  2594. me.popup_data.$bottom = $bottom;
  2595. me.load(options);
  2596. }, {width: 800, hold_editor: options.hold_editor}, 'media-manager');
  2597. popup.always(_.bind(this.cleanup_active_filters, this));
  2598. popup.progress($.proxy(this.clean_up, this));
  2599. Upfront.Events.trigger('upfront:element:edit:start', 'media-upload');
  2600. return popup;
  2601. },
  2602. /**
  2603. * Ensure everything is off when popup is closed.
  2604. */
  2605. clean_up: function(flag) {
  2606. if (flag === 'before_close') {
  2607. Upfront.Events.trigger('upfront:element:edit:stop', 'media-upload');
  2608. }
  2609. },
  2610. cleanup_active_filters: function () {
  2611. ActiveFilters.allowed_media_types = [];
  2612. ActiveFilters.current_keys = [];
  2613. ActiveFilters.current_models = [];
  2614. this.cleanup_manager_view();
  2615. },
  2616. cleanup_manager_view: function () {
  2617. if (this.media_manager) {
  2618. this.media_manager.undelegateEvents();
  2619. this.media_manager.remove();
  2620. this.media_manage_options = undefined;
  2621. }
  2622. },
  2623. load: function (options) {
  2624. this.cleanup_manager_view();
  2625. if (_.isUndefined(this.media_manage_options)) {
  2626. this.media_manage_options = _.extend({
  2627. el: this.out,
  2628. data: this.popup_data
  2629. }, options);
  2630. this.media_manager = new MediaManager_View(this.media_manage_options);
  2631. } else if(!_.isEqual(this.media_manage_options, _.extend({ el: this.out, data: this.popup_data }, options))) {
  2632. this.media_manage_options = _.extend({
  2633. el: this.out,
  2634. data: this.popup_data
  2635. }, options);
  2636. this.media_manager = new MediaManager_View(this.media_manage_options);
  2637. }
  2638. this.media_manager.render();
  2639. return false;
  2640. },
  2641. results_html: function (result) {
  2642. var html = '';
  2643. if (result && result.each) result.each(function (item) {
  2644. var data = item.toJSON(),
  2645. selected_size = item.get("selected_size") || MEDIA_SIZES.FULL,
  2646. all_sizes = item.get("additional_sizes")
  2647. ;
  2648. if (selected_size && MEDIA_SIZES.FULL != selected_size) {
  2649. _(all_sizes).each(function (size) {
  2650. if (MEDIA_SIZES.to_size(size) != selected_size) return true;
  2651. data.image = size;
  2652. });
  2653. }
  2654. if ( result.type == 'gallery' )
  2655. data.link = {
  2656. href: '#',
  2657. "class": 'popup'
  2658. };
  2659. data.type = result.type;
  2660. html += _.template( (data.link ? Upfront.Media.Templates.image_link : Upfront.Media.Templates.image), data);
  2661. });
  2662. if (result && result.length && result.length > 1) {
  2663. if ( result.type == 'plain' )
  2664. html = _.template(
  2665. Upfront.Media.Templates.multiple,
  2666. {content: html}
  2667. );
  2668. else if ( result.type == 'gallery' )
  2669. html = _.template(
  2670. Upfront.Media.Templates.gallery,
  2671. {content: html}
  2672. );
  2673. else if ( result.type == 'slider' )
  2674. html = _.template(
  2675. Upfront.Media.Templates.slider,
  2676. {content: html}
  2677. );
  2678. }
  2679. return html;
  2680. }
  2681. });
  2682. Upfront.Media = {
  2683. Manager: new ContentEditorUploader(),
  2684. Templates: {
  2685. image: '<p class="upfront-inserted_image-wrapper upfront-inserted_image-{{type}}"><img src="{{image.src}}" title="{{post_title}}" alt="{{post_title}}" height="{{image.height}}" width="{{image.width}}" /></p>',
  2686. image_link: '<p class="upfront-inserted_image-wrapper upfront-inserted_image-{{type}}"><a href="{{link.href}}" class="{{link.class}}"><img src="{{image.src}}" title="{{post_title}}" alt="{{post_title}}" height="{{image.height}}" width="{{image.width}}" /></a></p>',
  2687. embeddable: '<div>{{post_content}}<br />{{post_title}}</div>',
  2688. gallery: '[upfront-gallery]{{content}}[/upfront-gallery]',
  2689. slider: '[upfront-slider]{{content}}[/upfront-slider]',
  2690. multiple: '{{content}}'
  2691. },
  2692. Transformations: {
  2693. _transformations: _([]),
  2694. add: function (f) {
  2695. this._transformations.push(f);
  2696. },
  2697. apply: function (content) {
  2698. this._transformations.each(function (t) {
  2699. content = t.apply(this, [content]);
  2700. });
  2701. return content;
  2702. }
  2703. },
  2704. Ref: (window._upfront_media_upload || {image_ref: ''}).image_ref
  2705. };
  2706. });
  2707. })(jQuery);