PageRenderTime 33ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/t/upfront/elements/upfront-slider/js/uslider.js

https://bitbucket.org/matthewselby/wpdev
JavaScript | 1643 lines | 1200 code | 253 blank | 190 comment | 200 complexity | 94d898b3927bc2c7db50affcf0d379fb 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

Large files files are truncated, but you can click here to view the full file

  1. (function ($) {
  2. define([
  3. 'text!elements/upfront-slider/tpl/uslider.html',
  4. 'text!elements/upfront-slider/tpl/backend.html',
  5. 'elements/upfront-slider/js/settings',
  6. 'scripts/upfront/preset-settings/util',
  7. "scripts/upfront/link-model",
  8. 'text!elements/upfront-slider/tpl/preset-style.html'
  9. ], function(sliderTpl, editorTpl, SliderSettings, PresetUtil, LinkModel, settingsStyleTpl){
  10. var l10n = Upfront.Settings.l10n.slider_element;
  11. //Slide Model
  12. var Uslider_Slide = Backbone.Model.extend({
  13. //See library to know the defaults
  14. defaults: Upfront.data.uslider.slideDefaults,
  15. get_breakpoint_attr: function (attr, breakpoint_id) {
  16. var data = this.get('breakpoint') || {},
  17. breakpoint = Upfront.Views.breakpoints_storage.get_breakpoints().get_active().toJSON()
  18. ;
  19. if ( !breakpoint_id ) breakpoint_id = breakpoint.id;
  20. if ( !(breakpoint_id in data) || (!(attr in data[breakpoint_id])) ) return false;
  21. return data[breakpoint_id][attr];
  22. },
  23. set_breakpoint_attr: function (attr, value, breakpoint_id) {
  24. var data = Upfront.Util.clone(this.get('breakpoint') || {}),
  25. breakpoint = Upfront.Views.breakpoints_storage.get_breakpoints().get_active().toJSON()
  26. ;
  27. if ( !breakpoint_id ) breakpoint_id = breakpoint.id;
  28. if ( !_.isObject(data) || _.isArray(data) ) data = {};
  29. if ( !(breakpoint_id in data) ) data[breakpoint_id] = {};
  30. data[breakpoint_id][attr] = value;
  31. return this.set('breakpoint', data);
  32. },
  33. is_theme_image: function () {
  34. return this.get('srcFull') && this.get('srcFull').match(Upfront.mainData.currentThemePath);
  35. }
  36. });
  37. //Slide Collection
  38. var Uslider_Slides = Backbone.Collection.extend({
  39. model: Uslider_Slide
  40. });
  41. /**
  42. * Define the model - initialize properties to their default values.
  43. * @type {Upfront.Models.ObjectModel}
  44. */
  45. var USliderModel = Upfront.Models.ObjectModel.extend({
  46. /**
  47. * A quasi-constructor, called after actual constructor *and* the built-in `initialize()` method.
  48. * Used for setting up instance defaults, initialization and the like.
  49. */
  50. init: function () {
  51. var properties = _.clone(Upfront.data.uslider.defaults);
  52. properties.element_id = Upfront.Util.get_unique_id(properties.id_slug + "-object");
  53. this.init_properties(properties);
  54. }
  55. });
  56. /**
  57. * View instance - what the element looks like.
  58. * @type {Upfront.Views.ObjectView}
  59. */
  60. var USliderView = Upfront.Views.ObjectView.extend({
  61. self: {},
  62. module_settings: {},
  63. tpl: Upfront.Util.template(sliderTpl),
  64. startingTpl: _.template($(editorTpl).find('#startingTpl').html()),
  65. initialize: function(options){
  66. var me = this;
  67. if(! (this.model instanceof USliderModel)){
  68. this.model = new USliderModel({properties: this.model.get('properties')});
  69. }
  70. this.first_time_opening_slider = false;
  71. this.presets = new Backbone.Collection(Upfront.mainData['sliderPresets'] || []);
  72. this.model.view = this;
  73. this.constructor.__super__.initialize.call(this, [options]);
  74. this.events = _.extend({}, this.events, {
  75. 'click .upfront-image-select': 'firstImageSelection',
  76. 'click .upfront-icon-next': 'nextSlide',
  77. 'click .upfront-icon-prev': 'prevSlide',
  78. 'change .uslider-starting-options input[type="radio"]': 'setSliderType'
  79. // 'click .uslider-starting-options': 'checkStartingInputClick'
  80. });
  81. //Update slide defaults to match preset settings
  82. this.updateSlideDefaults();
  83. this.model.slideCollection = new Uslider_Slides(this.property('slides'));
  84. this.listenTo(this.model.slideCollection, 'add remove reset change', this.onSlidesCollectionChange);
  85. this.listenTo(this.model, 'change', this.onModelChange);
  86. this.listenTo(this.model, 'addRequest', this.openImageSelector);
  87. this.lastStyle = this.get_preset_properties().primaryStyle;
  88. this.listenTo(this.model, 'background', function(rgba){
  89. me.model.slideCollection.each(function(slide){
  90. slide.set('captionBackground', rgba);
  91. });
  92. });
  93. this.listenTo(Upfront.Events, "theme_colors:update", this.update_colors, this);
  94. this.listenTo(Upfront.Events, "preset:slider:updated", this.caption_updated, this);
  95. this.listenTo(this.model, "preset:updated", this.preset_updated);
  96. this.listenTo(Upfront.Events, 'upfront:import_image:populate_theme_images', this.populate_theme_images);
  97. this.listenTo(Upfront.Events, 'upfront:import_image:imported', this.imported_theme_image);
  98. this.listenTo(Upfront.Events, 'upfront:layout_size:change_breakpoint', this.updateSliderHeight);
  99. this.listenTo(Upfront.Events, 'command:layout:save', this.saveResizing);
  100. this.listenTo(Upfront.Events, 'command:layout:save_as', this.saveResizing);
  101. //Temporary props for image resizing and cropping
  102. this.imageProps = {};
  103. this.cropHeight = false;
  104. this.cropTimer = false;
  105. this.cropTimeAfterResize = 500;
  106. //Current Slide index
  107. this.setCurrentSlide(0);
  108. var saveSliderPreset = function(properties) {
  109. if (!Upfront.Application.user_can("MODIFY_PRESET")) {
  110. // me.model.trigger("preset:updated", properties.id);
  111. me.preset_updated(properties.id);
  112. return false;
  113. }
  114. Upfront.Util.post({
  115. action: 'upfront_save_slider_preset',
  116. data: properties
  117. }).done( function() {
  118. me.preset_updated(properties.id);
  119. });
  120. };
  121. // Let's not flood server on some nuber property firing changes like crazy
  122. this.debouncedSavePreset = _.debounce(saveSliderPreset, 1000);
  123. this.delegateEvents();
  124. },
  125. updateSlideDefaults: function() {
  126. var primary = this.get_preset_properties().primaryStyle,
  127. defaults = {
  128. below: 'below',
  129. over: 'bottomOver',
  130. side: 'right',
  131. notext: 'nocaption'
  132. }
  133. ;
  134. Upfront.data.uslider.slideDefaults.style = defaults[primary];
  135. },
  136. get_preset_properties: function() {
  137. var preset = this.model.get_property_value_by_name("preset"),
  138. props = PresetUtil.getPresetProperties('slider', preset) || {};
  139. return props;
  140. },
  141. /**
  142. * Returns preset propery value
  143. * @param key
  144. * @returns {boolean}
  145. */
  146. get_preset_property: function(key){
  147. var preset_props = this.get_preset_properties();
  148. return preset_props[key] ? preset_props[key] : false;
  149. },
  150. preset_updated: function(preset) {
  151. this.updateSlideDefaults();
  152. //this.render();
  153. Upfront.Events.trigger('preset:slider:updated', preset);
  154. },
  155. caption_updated: function(preset) {
  156. var currentPreset = this.model.get_property_value_by_name("preset");
  157. //If element use updated preset re-render
  158. if(currentPreset === preset && this.lastStyle != this.get_preset_property('primaryStyle')) {
  159. this.render();
  160. }
  161. },
  162. update_colors: function () {
  163. var props = this.get_preset_properties();
  164. if (_.size(props) <= 0) return false; // No properties, carry on
  165. PresetUtil.updatePresetStyle('slider', props, settingsStyleTpl);
  166. },
  167. on_edit: function(){
  168. return false;
  169. },
  170. populate_theme_images: function (image_list) {
  171. this.model.slideCollection.each(function(slide){
  172. if ( slide.is_theme_image() ) image_list.push(slide.get('srcFull'));
  173. });
  174. },
  175. imported_theme_image: function (image) {
  176. this.model.slideCollection.each(function(slide){
  177. var src = slide.get('srcFull');
  178. if ( slide.is_theme_image() && image.filepath === src ) {
  179. slide.set('id', image.id);
  180. slide.set('srcFull', image.src);
  181. }
  182. });
  183. },
  184. get_content_markup: function() {
  185. var me = this,
  186. props,
  187. rendered = {},
  188. breakpoints = Upfront.Views.breakpoints_storage.get_breakpoints().get_enabled(),
  189. breakpoint = Upfront.Views.breakpoints_storage.get_breakpoints().get_active().toJSON()
  190. ;
  191. this.checkStyles();
  192. props = this.extract_properties();
  193. if (Upfront.Application.user_can_modify_layout()) {
  194. if(!this.model.slideCollection.length){
  195. this.startingHeight = this.startingHeight || 225;
  196. return this.startingTpl({startingHeight: this.startingHeight, l10n: l10n});
  197. }
  198. } else {
  199. return '';
  200. }
  201. props.properties = this.get_preset_properties();
  202. // Overwrite properties with preset properties
  203. if (this.property('usingNewAppearance')) {
  204. if (props.properties.primaryStyle) {
  205. props.primaryStyle = props.properties.primaryStyle;
  206. }
  207. if (props.properties.captionBackground) {
  208. props.captionBackground = props.properties.captionBackground;
  209. }
  210. }
  211. //Stop autorotate
  212. props.rotate = false;
  213. props.dots = _.indexOf(['dots', 'both'], props.controls) != -1;
  214. props.arrows = _.indexOf(['arrows', 'both'], props.controls) != -1;
  215. props.slides = this.model.slideCollection.toJSON();
  216. _.each(props.slides, function (slide) {
  217. slide.breakpoint_map = JSON.stringify(slide.breakpoint);
  218. if ( slide.breakpoint && slide.breakpoint[breakpoint.id] && slide.breakpoint[breakpoint.id]['style'] ) {
  219. slide.style = slide.breakpoint[breakpoint.id]['style'];
  220. }
  221. });
  222. props.slidesLength = props.slides.length;
  223. props.imageWidth = '100%';
  224. props.textWidth = '100%';
  225. if(props.primaryStyle == 'side') {
  226. var imgPercent = Math.round(props.rightImageWidth / props.rightWidth * 100)
  227. textPercent = Math.round((props.rightWidth - props.rightImageWidth) / props.rightWidth * 100)
  228. ;
  229. props.imageWidth = imgPercent + '%';
  230. props.textWidth = textPercent + '%';
  231. // If total is 101 because of the round we decrease textWidth with 1%
  232. if((imgPercent + textPercent) > 100) {
  233. props.textWidth = (textPercent - 1) + '%';
  234. }
  235. }
  236. props.imageHeight = '100%';
  237. if (props.slides.length) {
  238. var imageProps = me.imageProps[props.slides[0].id];
  239. if (imageProps) {
  240. props.imageHeight = imageProps.cropSize.height;
  241. } else {
  242. props.imageHeight = props.slides[0].cropSize.height;
  243. }
  244. }
  245. props.production = false;
  246. props.startingSlide = this.getCurrentSlide();
  247. props.l10 = l10n;
  248. props.usingNewAppearance = props.usingNewAppearance || false;
  249. rendered = this.tpl(props);
  250. var $rendered = $('<div></div>').append(rendered);
  251. this.model.slideCollection.each(function(slide){
  252. if(!me.imageProps[slide.id]){
  253. me.imageProps[slide.id] = {
  254. size: slide.get('size'),
  255. cropOffset: slide.get('cropOffset'),
  256. cropSize: slide.get('cropSize')
  257. };
  258. }
  259. var props = me.imageProps[slide.id],
  260. img = $rendered.find('.uslide[rel=' + slide.id + ']').height(props.size.height).find('img')
  261. ;
  262. img.attr('src', slide.get('srcFull'))
  263. .css({
  264. position: 'absolute',
  265. width: props.size.width,
  266. height: props.size.height,
  267. top: 0-props.cropOffset.top,
  268. left: 0-props.cropOffset.left,
  269. 'max-width': 'none',
  270. 'max-height': 'none'
  271. })
  272. .parent().css({
  273. position: 'relative',
  274. height: me.cropHeight || slide.get('cropSize').height,
  275. overflow: 'hidden'
  276. })
  277. ;
  278. });
  279. return $rendered.html();
  280. },
  281. on_render: function() {
  282. var me = this;
  283. setTimeout( function() {
  284. var slider = me.$el.find('.upfront-output-uslider'),
  285. options = slider.find('.uslider').data();
  286. slider.find('.uslides').on('rendered', function(){
  287. me.trigger('rendered');
  288. Upfront.Events.trigger('entity:object:refresh', me);
  289. });
  290. slider.find('.uslides').upfront_default_slider(options);
  291. slider.find('.uslide-above').each(function(){
  292. var slide = $(this);
  293. slide.find('.uslide-caption').remove().prependTo(slide);
  294. });
  295. slider.find('.uslide-left').each(function(){
  296. var slide = $(this);
  297. slide.find('.uslide-caption').remove().prependTo(slide);
  298. });
  299. slider.find('.uslide-bottomOver, .uslide-middleCover, .uslide-bottomCover, .uslide-topCover').each(function() {
  300. var slide = $(this);
  301. slide.find('.uslide-caption').remove().prependTo(slide.find('.uslide-image'));
  302. });
  303. me.prepareSlider();
  304. }, 100);
  305. if(!me.parent_module_view)
  306. return;
  307. if(!this.model.slideCollection.length)
  308. return;
  309. if(!this.$el.parent().length) {
  310. setTimeout(function(){
  311. me.on_render();
  312. }, 100);
  313. }
  314. this.update_caption_controls();
  315. },
  316. update_caption_controls: function(){
  317. if (!Upfront.Application.user_can_modify_layout()) return false;
  318. var me = this,
  319. panel = new Upfront.Views.Editor.InlinePanels.Panel()
  320. ;
  321. panel.items = this.getControlItems();
  322. panel.render();
  323. _.delay( function(){
  324. me.controls.$el.html( panel.$el );
  325. me.controls.$el.css("width", "auto");
  326. me.updateSlideControls();
  327. }, 400);
  328. },
  329. hideSliderNavigation: function(){
  330. this.$('.upfront-default-slider-nav').hide();
  331. this.$('.upfront-default-slider-nav-prev').hide();
  332. this.$('.upfront-default-slider-nav-next').hide();
  333. this
  334. .listenTo(Upfront.Events, 'csseditor:open', function(elementId){
  335. if(elementId == this.property('element_id')){
  336. this.$('.upfront-default-slider-nav').show();
  337. this.$('.upfront-default-slider-nav-prev').show();
  338. this.$('.upfront-default-slider-nav-next').show();
  339. }
  340. })
  341. .listenTo(Upfront.Events, 'csseditor:closed', function(elementId){
  342. if(elementId == this.property('element_id')){
  343. this.$('.upfront-default-slider-nav').hide();
  344. this.$('.upfront-default-slider-nav-prev').hide();
  345. this.$('.upfront-default-slider-nav-next').hide();
  346. }
  347. })
  348. ;
  349. },
  350. prepareSlider: function(){
  351. var me = this,
  352. wrapper = me.$('.uslide-image'),
  353. //controls = me.createSlideControls(),
  354. text = me.$('.uslide-editable-text'),
  355. currentSlide = this.model.slideCollection.at(this.getCurrentSlide())
  356. ;
  357. // controls.setWidth(wrapper.width());
  358. // controls.render();
  359. // if(typeof(currentSlide) != 'undefined') {
  360. // me.$('.uslides').append(
  361. // $('<div class="uimage-controls upfront-ui" rel="' + currentSlide.id + '"></div>').append(controls.$el)
  362. // );
  363. // }
  364. me.onSlideShow();
  365. // this.controls = controls;
  366. me.$('.uslide').css({height: 'auto'});
  367. //Enable text editors
  368. text.each(function () {
  369. var text = $(this); // Re-bind to local
  370. if (text.data('ueditor')) return true; // If ueditor is already up, carry on
  371. text.ueditor({
  372. autostart: false,
  373. upfrontMedia: false,
  374. upfrontImages: false,
  375. placeholder: '<p>' + l10n.slide_desc + '</p>',
  376. linebreaks: false,
  377. inserts: []
  378. })
  379. .on('start', function() {
  380. var id = $(this).closest('.uslide').attr('rel'),
  381. slide = me.model.slideCollection.get(id)
  382. ;
  383. me.$el.addClass('upfront-editing');
  384. Upfront.Events.trigger('upfront:element:edit:start', 'text');
  385. $(this).on('syncAfter', function(){
  386. slide.set('text', $(this).html(), {silent: true});
  387. })
  388. .on('stop', function(){
  389. slide.set('text', $(this).html());
  390. me.property('slides', me.model.slideCollection.toJSON());
  391. me.$el.removeClass('upfront-editing');
  392. Upfront.Events.trigger('upfront:element:edit:stop');
  393. // Trigger cleanup if possible
  394. var ed = $(this).data('ueditor');
  395. if (ed.redactor) ed.redactor.events.trigger('cleanUpListeners');
  396. me.render();
  397. });
  398. })
  399. ;
  400. });
  401. if(me.get_preset_properties().primaryStyle == 'side'){
  402. me.setImageResizable();
  403. }
  404. me.updateSliderHeight();
  405. },
  406. updateSliderHeight: function () {
  407. var wrapper = this.$('.uslide-image'),
  408. currentSlide = this.model.slideCollection.at(this.getCurrentSlide())
  409. ;
  410. //Adapt slider height to the image crop
  411. if(typeof(currentSlide) != 'undefined') {
  412. var textHeight = this.get_preset_properties().primaryStyle == 'below'
  413. ? this.$('.uslide[rel=' + currentSlide.id + ']').find('.uslide-caption').outerHeight(true)
  414. : 0
  415. ;
  416. this.$('.uslides').css({ 'padding-top' : wrapper.outerHeight(true) + textHeight});
  417. }
  418. },
  419. updateSlideControls: function(){
  420. // if(typeof(this.controls) !== 'undefined') {
  421. // this.controls.remove();
  422. // }
  423. // var controls = this.createSlideControls();
  424. // controls.render();
  425. // this.$('.uimage-controls').append(controls.$el);
  426. // if(typeof(this.model.slideCollection.at(this.getCurrentSlide())) !== 'undefined') {
  427. // this.$('.uimage-controls').attr('rel', this.model.slideCollection.at(this.getCurrentSlide()).id);
  428. // }
  429. // this.controls = controls;
  430. if(typeof(this.$control_el) !== 'undefined') {
  431. this.$control_el.find('.upfront-element-controls').remove();
  432. }
  433. if(typeof(this.controls) !== 'undefined') {
  434. this.controls = undefined;
  435. }
  436. this.updateControls();
  437. },
  438. nextSlide: function(e){
  439. e.preventDefault();
  440. this.$('.uslides').upfront_default_slider('next');
  441. },
  442. prevSlide: function(e){
  443. e.preventDefault();
  444. this.$('.uslides').upfront_default_slider('prev');
  445. },
  446. checkStyles: function() {
  447. var me = this,
  448. breakpoint = Upfront.Views.breakpoints_storage.get_breakpoints().get_active().toJSON(),
  449. primary = this.get_preset_properties().primaryStyle,
  450. defaults = {
  451. below: 'below',
  452. over: 'bottomOver',
  453. side: 'right',
  454. notxt: 'nocaption'
  455. }
  456. ;
  457. if (primary != this.lastStyle) {
  458. this.model.slideCollection.each(function(slide){
  459. var style = breakpoint['default'] ? slide.get('style') : slide.get_breakpoint_attr('style', breakpoint.id);
  460. if(
  461. primary == 'below' && _.indexOf(['below', 'above'], style) == -1
  462. ||
  463. primary == 'over' && _.indexOf(['topOver', 'bottomOver', 'topCover', 'middleCover', 'bottomCover'], style) == -1
  464. ||
  465. primary == 'side' && _.indexOf(['right', 'left'], style) == -1
  466. ) {
  467. if ( breakpoint['default'] ) {
  468. slide.set('style', defaults[primary]);
  469. }
  470. else {
  471. slide.set_breakpoint_attr('style', defaults[primary], breakpoint.id);
  472. }
  473. }
  474. if ( primary == 'side' ) return;
  475. me.once('rendered', function () {
  476. var wrap = me.$('.uslide[rel=' + slide.id + ']').find('.uslide-image');
  477. me.imageProps[slide.id] = me.calculateImageResize({width: wrap.width(), height:wrap.height()}, slide);
  478. });
  479. });
  480. this.setTimer();
  481. this.lastStyle = primary;
  482. this.onSlidesCollectionChange();
  483. }
  484. },
  485. /* checkStartingInputClick: function(e){
  486. //Hack to make the radio buttons work in the starting layout
  487. e.stopPropagation(); //This is not a good practice
  488. }, */
  489. setSliderType: function (e) {
  490. var primaryStyle = $(e.currentTarget).val(),
  491. style = 'default'
  492. ;
  493. if (primaryStyle == 'over') {
  494. style = 'bottomOver';
  495. }
  496. else if (primaryStyle == 'below') {
  497. style = 'below';
  498. }
  499. else if(primaryStyle == 'side') {
  500. style = 'right';
  501. }
  502. else if(primaryStyle == 'notxt') {
  503. style = 'nocaption';
  504. }
  505. this.model.set_property('primaryStyle', primaryStyle, true);
  506. this.property('style', style);
  507. },
  508. firstImageSelection: function(e){
  509. e.preventDefault();
  510. this.first_time_opening_slider = true;
  511. return this.openImageSelector();
  512. },
  513. setImageResizable: function(){
  514. if(!this.model.slideCollection.length) return;
  515. var me = this,
  516. current = this.$('.upfront-default-slider-item-current'),
  517. $slide = current.find('.uslide-image'),
  518. elementWidth = me.$('.upfront-object').outerWidth(),
  519. elementCols, colWidth,
  520. text = current.find('.uslide-caption'),
  521. id = current.attr('rel'),
  522. slide = this.model.slideCollection.get(id) || this.model.slideCollection.at(this.getCurrentSlide()),
  523. height = false,
  524. style = slide.get('style')
  525. ;
  526. //Stop any other resizable slide
  527. this.$('.ui-resizable').resizable('destroy');
  528. if(style == 'nocaption')
  529. return;
  530. $slide.resizable({
  531. handles: style == 'right' ? 'e' : 'w',
  532. helper: 'uslider-resize-handler',
  533. start: function(e, ui){
  534. if(!ui.element.hasClass('uslide-image'))
  535. return;
  536. elementWidth = me.$('.upfront-object').outerWidth();
  537. elementCols = me.get_element_columns();
  538. colWidth = me.get_element_max_columns_px() / me.get_element_max_columns();
  539. height = $slide.height();
  540. ui.element.parent().closest('.ui-resizable').resizable('disable');
  541. $slide.resizable('option', {
  542. minWidth: colWidth * 3,
  543. maxWidth: (elementCols - 3) * colWidth,
  544. grid: [colWidth, 100], //Second number is never used (fixed height)
  545. handles: style == 'right' ? 'e' : 'w',
  546. helper: 'uslider-resize-handler',
  547. minHeigth: height,
  548. maxHeight: height
  549. });
  550. },
  551. resize: function(e, ui){
  552. if(!ui.element.hasClass('uslide-image'))
  553. return;
  554. var padding_left = parseInt( me.model.get_breakpoint_property_value("left_padding_use", true) ? me.model.get_breakpoint_property_value('left_padding_num', true) : 0, 10 ),
  555. padding_right = parseInt( me.model.get_breakpoint_property_value("right_padding_use", true) ? me.model.get_breakpoint_property_value('right_padding_num', true) : 0, 10 ),
  556. newElementWidth = parseInt( elementWidth - ( padding_left + padding_right ) ),
  557. imageWidth = ui.helper.width(),
  558. textWidth = newElementWidth - imageWidth - 20,
  559. textCss = {width: textWidth},
  560. imgCss = {width: imageWidth}
  561. ;
  562. me.calculateImageResize({width: imageWidth, height: ui.element.height()}, slide);
  563. if(style == 'right')
  564. textCss['margin-left'] = imageWidth;
  565. else
  566. imgCss['margin-left'] = textWidth;
  567. text.css(textCss);
  568. $slide.css(imgCss);
  569. },
  570. stop: function(e, ui){
  571. if(!ui.element.hasClass('uslide-image'))
  572. return;
  573. var helperWidth = ui.helper.width(),
  574. imageWidth = helperWidth > (elementCols - 3) * colWidth ? (elementCols - 3) * colWidth : (helperWidth < 3 * colWidth ? 3 * colWidth : helperWidth),
  575. imageCols = Math.round((imageWidth - (colWidth - 15))/ colWidth) + 1,
  576. percentage = Math.floor(imageCols / elementCols * 100)
  577. ;
  578. $slide.css({width: percentage + '%'});
  579. me.model.slideCollection.each(function(slide){
  580. if(slide.get('style') != 'nocaption')
  581. me.imageProps[slide.id] = me.calculateImageResize({width: $slide.width(), height: ui.element.height()}, slide);
  582. });
  583. me.cropHeight = ui.element.height();
  584. me.property('rightWidth', elementCols, true);
  585. me.property('rightImageWidth', imageCols, false);
  586. me.setTimer();
  587. me.parent_module_view.$el.children('.upfront-module').resizable('enable');
  588. }
  589. });
  590. },
  591. setTimer: function(){
  592. var me = this;
  593. if(me.cropTimer){
  594. clearTimeout(me.cropTimer);
  595. me.cropTimer = false;
  596. }
  597. me.cropTimer = setTimeout(function() {
  598. var slide = me.model.slideCollection.at(me.getCurrentSlide()),
  599. editor = me.$('.uslide[rel=' + slide.id + ']').find('.uslide-editable-text');
  600. if (editor.length && editor.data('redactor')) {
  601. editor.on('stop', function(){
  602. me.saveTemporaryResizing();
  603. });
  604. } else {
  605. me.saveTemporaryResizing();
  606. }
  607. }, me.cropTimeAfterResize);
  608. },
  609. onSlideShow: function(){
  610. var me = this;
  611. this.$('.uslides').on('slidein', function(e, slide, index){
  612. if(slide){
  613. me.setCurrentSlide(index);
  614. me.updateSlideControls();
  615. me.$('.uimage-controls').attr('rel', slide.attr('rel'));
  616. if(me.get_preset_properties().primaryStyle == 'side')
  617. me.setImageResizable();
  618. if(me.get_preset_properties().primaryStyle == 'below'){
  619. //Adapt the height to take care of the caption
  620. me.$('.uslides').css({ 'padding-top' : slide.find('.uslide-image').outerHeight() + slide.find('.uslide-caption').outerHeight()});
  621. }
  622. }
  623. });
  624. },
  625. // createSlideControls: function() {
  626. // var me = this,
  627. // panel = new Upfront.Views.Editor.InlinePanels.ControlPanel(),
  628. // multiBelow = {
  629. // above: ['above', l10n.above_img],
  630. // below: ['below', l10n.below_img],
  631. // nocaption: ['nocaption', l10n.no_text]
  632. // },
  633. // multiOver = {
  634. // topOver: ['topOver', l10n.over_top],
  635. // bottomOver: ['bottomOver', l10n.over_bottom],
  636. // topCover: ['topCover', l10n.cover_top],
  637. // middleCover: ['middleCover', l10n.cover_mid],
  638. // bottomCover: ['bottomCover', l10n.cover_bottom],
  639. // nocaption: ['nocaption', l10n.no_text]
  640. // },
  641. // multiSide = {
  642. // right: ['right', l10n.at_right],
  643. // left: ['left', l10n.at_left],
  644. // nocaption: ['nocaption', l10n.no_text]
  645. // },
  646. // primaryStyle = this.get_preset_properties().primaryStyle,
  647. // multiControls = {},
  648. // captionControl = new Upfront.Views.Editor.InlinePanels.TooltipControl(),
  649. // panelItems = [],
  650. // slide = this.model.slideCollection.at(this.getCurrentSlide())
  651. // ;
  652. // captionControl.sub_items = {};
  653. // if(primaryStyle == 'below')
  654. // multiControls = multiBelow;
  655. // else if(primaryStyle == 'over')
  656. // multiControls = multiOver;
  657. // else if(primaryStyle == 'side')
  658. // multiControls = multiSide;
  659. // else
  660. // multiControls = false;
  661. // if(multiControls){
  662. // _.each(multiControls, function(opts, key){
  663. // captionControl.sub_items[key] = me.createControl(opts[0], opts[1]);
  664. // });
  665. // captionControl.icon = 'caption';
  666. // captionControl.tooltip = l10n.cap_position;
  667. // captionControl.selected = multiControls[slide.get('style')] ? slide.get('style') : 'nocaption';
  668. // this.listenTo(captionControl, 'select', function(item){
  669. // var previousStyle = slide.get('style');
  670. // slide.set('style', item);
  671. // me.onSlidesCollectionChange();
  672. // if(primaryStyle == 'side' && previousStyle == 'nocaption' || item == 'nocaption'){
  673. // //give time to the element to render
  674. // setTimeout(function(){
  675. // var wrap = me.$('.upfront-default-slider-item-current').find('.uslide-image');
  676. // me.imageProps[slide.id] = me.calculateImageResize({width: wrap.width(), height: wrap.height()}, slide);
  677. // me.setTimer();
  678. // }, 100);
  679. // }
  680. // });
  681. // }
  682. // panelItems.push(this.createControl('crop', l10n.edit_img, 'imageEditMask'));
  683. // // panelItems.push(this.createLinkControl(slide));
  684. // panelItems.push(this.createControl('remove', l10n.remove_slide, 'onRemoveSlide'));
  685. // panel.items = _(panelItems);
  686. // return panel;
  687. // },
  688. createControl: function(icon, tooltip, click){
  689. var me = this,
  690. item = new Upfront.Views.Editor.InlinePanels.Control();
  691. item.icon = icon;
  692. item.tooltip = tooltip;
  693. if(click){
  694. item.on('click', function(e){
  695. me[click](e);
  696. });
  697. }
  698. return item;
  699. },
  700. createLinkControl: function() {
  701. var me = this,
  702. slide = this.model.slideCollection.at(this.getCurrentSlide()),
  703. control = new Upfront.Views.Editor.InlinePanels.LinkControl(),
  704. link;
  705. if (this.currentSlideLink) {
  706. this.stopListening(this.currentSlideLink);
  707. }
  708. if (typeof(slide) !== 'undefined' && typeof(slide.get('link')) !== 'undefined') {
  709. link = new LinkModel(slide.get('link'));
  710. } else {
  711. link = new LinkModel({
  712. type: slide?slide.get('urlType'):'',
  713. url: slide?slide.get('url'):'',
  714. target: slide?slide.get('linkTarget'):''
  715. });
  716. }
  717. control.view = linkPanel = new Upfront.Views.Editor.LinkPanel({
  718. model: link,
  719. linkTypes: { image: true },
  720. imageUrl: slide?slide.get('srcFull'):''
  721. });
  722. this.listenTo(control, 'panel:ok', function(){
  723. control.close();
  724. });
  725. me.listenTo(control, 'panel:open', function(){
  726. control.$el
  727. .closest('.uimage-controls')
  728. .addClass('upfront-control-visible').end()
  729. .closest('.uslider-link')
  730. .removeAttr('href') //Deactivate link when the panel is open
  731. ;
  732. me.$el.closest('.ui-draggable').draggable('disable');
  733. me.$('.uimage').sortable('disable');
  734. });
  735. me.listenTo(control, 'panel:close', function(){
  736. control.$el
  737. .closest('.uimage-controls')
  738. .removeClass('upfront-control-visible').end()
  739. .closest('.uslider-link')
  740. .attr('href', typeof(slide) !== 'undefined' ? slide.get('url') : '')
  741. ;
  742. me.$el.closest('.ui-draggable').draggable('enable');
  743. });
  744. me.listenTo(link, 'change', function(data) {
  745. // If we have boolean type return
  746. if(data === true) return;
  747. slide.set({link: data.toJSON()}, {silent:true});
  748. // Rather than changing template rendering set properties that tempalte uses also
  749. slide.set({
  750. urlType: data.get('type'),
  751. url: data.get('url'),
  752. linkTarget: data.get('target')
  753. }, {silent:true});
  754. me.property('slides', me.model.slideCollection.toJSON(), true);
  755. });
  756. me.listenTo(link, 'change:target', function(data) {
  757. slide.set({link: data.toJSON()}, {silent:true});
  758. // Rather than changing template rendering set properties that tempalte uses also
  759. slide.set({
  760. urlType: data.get('type'),
  761. url: data.get('url'),
  762. linkTarget: data.get('target')
  763. }, {silent:true});
  764. me.property('slides', me.model.slideCollection.toJSON(), true);
  765. me.$el.find('.upfront-default-slider-item-current a')
  766. .attr('target', data.get('target'));
  767. });
  768. // Update wrapper size
  769. me.listenTo(linkPanel, 'linkpanel:update:wrapper', function() {
  770. control.updateWrapperSize();
  771. });
  772. this.currentSlideLink = link;
  773. control.icon = 'link';
  774. control.tooltip = l10n.img_link;
  775. control.id = 'link';
  776. return control;
  777. },
  778. getElementColumns: function(){
  779. var module = this.$el.closest('.upfront-module'),
  780. classes,
  781. found = false
  782. ;
  783. if(!module.length)
  784. return -1;
  785. classes = module.attr('class').split(' ');
  786. _.each(classes, function(c){
  787. if(c.match(/^c\d+$/))
  788. found = c.replace('c', '');
  789. });
  790. return found || -1;
  791. },
  792. onSlidesCollectionChange: function(){
  793. //console.log(this.model.slideCollection.toJSON())
  794. this.property('slides', this.model.slideCollection.toJSON(), false);
  795. },
  796. onModelChange: function() {
  797. if (this.stopListeningTo) {
  798. this.stopListeningTo(this.model.slideCollection);
  799. this.model.slideCollection = new Uslider_Slides(this.property('slides'));
  800. this.listenTo(this.model.slideCollection, 'add remove reset change', this.onSlidesCollectionChange);
  801. }
  802. this.render();
  803. },
  804. openImageSelector: function(e, replaceId){
  805. //Update slide defaults to match preset settings
  806. this.updateSlideDefaults();
  807. var me = this,
  808. sizer = this.model.slideCollection.length ? this.$('.upfront-default-slider-item-current').find('.uslide-image') : this.$('.upfront-object-content'),
  809. baseline = Upfront.Settings.LayoutEditor.Grid.baseline,
  810. row = this.model.get_breakpoint_property_value('row', true),
  811. height = row * baseline,
  812. padding_top = parseInt( this.model.get_breakpoint_property_value("top_padding_use", true) ? this.model.get_breakpoint_property_value('top_padding_num', true) : 0, 10 ),
  813. padding_bottom = parseInt( this.model.get_breakpoint_property_value("bottom_padding_use", true) ? this.model.get_breakpoint_property_value('bottom_padding_num', true) : 0, 10 ),
  814. selectorOptions = {
  815. multiple: true,
  816. preparingText: l10n.preparing_img,
  817. element_id: this.model.get_property_value_by_name("element_id"),
  818. customImageSize: {
  819. width: sizer.width(),
  820. height: height - padding_top - padding_bottom
  821. }
  822. }
  823. ;
  824. if(e)
  825. e.preventDefault();
  826. Upfront.Views.Editor.ImageSelector.open(selectorOptions).done(function(images, response){
  827. me.addSlides(images, replaceId);
  828. if ( me.first_time_opening_slider ) {
  829. me.addSliderPreset();
  830. me.first_time_opening_slider = false;
  831. setTimeout(function(){
  832. // we have to wait for adding preset to finish
  833. Upfront.Views.Editor.ImageSelector.close();
  834. }, 1500);
  835. } else {
  836. Upfront.Views.Editor.ImageSelector.close();
  837. }
  838. });
  839. },
  840. addSliderPreset: function () {
  841. var style = this.model.get_property_value_by_name('primaryStyle'),
  842. element_id = this.model.get_property_value_by_name("element_id")
  843. ;
  844. // Skip if default
  845. if(style === "default") return false;
  846. var defaultPreset = PresetUtil.getPresetProperties('slider', 'default') || {},
  847. presetDefaults = !_.isEmpty(defaultPreset) ? defaultPreset : Upfront.mainData.presetDefaults.slider,
  848. presetStyle = presetDefaults.preset_style || '',
  849. presetName = element_id + ' preset',
  850. presetID = presetName.toLowerCase().replace(/ /g, '-'),
  851. preset = _.extend(presetDefaults, {
  852. id: presetID,
  853. name: presetName,
  854. primaryStyle: style,
  855. preset_style: presetStyle.replace(/ .default/g, ' .' + presetID + ' '),
  856. theme_preset: false
  857. })
  858. ;
  859. this.presets.add(preset);
  860. this.model.set_property('preset', preset.id, true);
  861. this.updateSliderPreset(preset);
  862. // Make sure we don't lose our current preset
  863. this.model.encode_preset(preset.id);
  864. },
  865. updateSliderPreset: function(properties) {
  866. PresetUtil.updatePresetStyle('slider', properties, settingsStyleTpl);
  867. this.debouncedSavePreset(properties);
  868. Upfront.mainData['sliderPresets'] = [];
  869. _.each(this.presets.models, function(preset, presetIndex) {
  870. Upfront.mainData['sliderPresets'].push(preset.attributes);
  871. });
  872. },
  873. addSlides: function(images, replaceId){
  874. var slides = [];
  875. _.each(images, function(image, id){
  876. var data = {sizes: image, id: id, srcFull: image.full[0], status: 'ok'};
  877. if(image.custom && !image.custom.error){
  878. data.src = image.custom.url;
  879. data.size = image.custom.editdata.resize;
  880. data.cropSize = image.custom.crop;
  881. data.cropOffset = image.custom.editdata.crop;
  882. }
  883. else{
  884. data.src = image.full[0];
  885. data.size = {width: image.full[1], height: image.full[2]};
  886. }
  887. slides.push(data);
  888. });
  889. if(replaceId){
  890. this.model.slideCollection.get(replaceId).set(slides[0]);
  891. this.onSlidesCollectionChange();
  892. }
  893. else
  894. this.model.slideCollection.add(slides);
  895. },
  896. calculateColumnWidth: function(){
  897. return (this.colWidth = Upfront.Behaviors.GridEditor.col_size);
  898. },
  899. /***************************************************************************/
  900. /* Handling element resize events (jQuery resizeable) */
  901. /***************************************************************************/
  902. on_element_resize_start: function(attr) {
  903. var properties = this.get_preset_properties(),
  904. style = this.property('style'),
  905. me = this
  906. ;
  907. if(typeof properties !== "undefined" && properties.primaryStyle === "side") return;
  908. if(_.indexOf(['nocaption', 'below', 'above', 'right', 'left'], style) == -1)
  909. this.$('.uslider-caption').fadeOut('fast');
  910. else if(style == 'right' || style == 'left'){
  911. this.$('.uslide').css({height: '100%'});
  912. }
  913. },
  914. on_element_resizing: function(attr) {
  915. if( !this.model.slideCollection.length ) return;
  916. var properties = this.get_preset_properties();
  917. if(typeof properties !== "undefined" && properties.primaryStyle === "side") return;
  918. var me = this,
  919. current = this.$('.upfront-default-slider-item-current'),
  920. text = this.get_preset_properties().primaryStyle == 'below' ? current.find('.uslide-caption') : [],
  921. textHeight = text.length ? text.height() : 0,
  922. column_padding = Upfront.Settings.LayoutEditor.Grid.column_padding,
  923. vPadding = parseInt( this.model.get_breakpoint_property_value('top_padding_num') || column_padding, 10 ) + parseInt( this.model.get_breakpoint_property_value('bottom_padding_num') || column_padding, 10 ),
  924. newElementSize = {width: parseInt( attr.width, 10 ), height: parseInt( attr.height, 10 ) - ( vPadding * 2 ) - textHeight},
  925. imageWrapper = current.find('.uslide-image'),
  926. style = this.get_preset_properties().primaryStyle,
  927. wrapperSize = {width: style == 'side' ? imageWrapper.width() : newElementSize.width, height: newElementSize.height},
  928. wrapperCss = {height: wrapperSize.height}
  929. ;
  930. if(style == 'side') {
  931. current.find('.uslide-caption').height(newElementSize.height);
  932. } else {
  933. wrapperCss.width = wrapperSize.width;
  934. }
  935. imageWrapper.css(wrapperCss)
  936. .closest('.uslide').height(newElementSize.height)
  937. .closest('.uslides').css({'padding-top' : newElementSize.height})
  938. ;
  939. //We should resize all slides
  940. this.model.slideCollection.each(function (slide) {
  941. me.calculateImageResize(wrapperSize, slide);
  942. });
  943. // Update Resize Hint.
  944. this.update_size_hint();
  945. },
  946. on_element_resize: function(attr) {
  947. // Add/remove multiple module class.
  948. $object = this.$el.find('.upfront-editable_entity:first');
  949. this.add_multiple_module_class($object);
  950. if( !this.model.slideCollection.length ) return;
  951. var properties = this.get_preset_properties();
  952. if(typeof properties !== "undefined" && properties.primaryStyle === "side") return;
  953. var me = this,
  954. mask = this.$('.upfront-default-slider-item-current').find('.uslide-image'),
  955. text = this.get_preset_properties().primaryStyle == 'below' ? mask.find('.uslide-caption') : [],
  956. textHeight = text.length ? text.height() : 0,
  957. column_padding = Upfront.Settings.LayoutEditor.Grid.column_padding,
  958. vPadding = parseInt( this.model.get_breakpoint_property_value('top_padding_num') || column_padding, 10 ) + parseInt( this.model.get_breakpoint_property_value('bottom_padding_num') || column_padding, 10 ),
  959. newElementSize = {width: parseInt( attr.width, 10 ), height: parseInt( attr.height, 10 ) - ( vPadding * 2 ) - textHeight},
  960. elementColumns = attr.col,
  961. imageColumns = Math.max(3, Math.round(this.property('rightImageWidth') * elementColumns / this.property('rightWidth'))),
  962. sideImageWidth = imageColumns * this.calculateColumnWidth()
  963. ;
  964. this.model.slideCollection.each(function (slide) {
  965. var imageSize = {height: newElementSize.height};
  966. imageSize.width = me.get_preset_properties().primaryStyle == 'side' && slide.get('style') != 'nocaption' ? sideImageWidth : newElementSize.width;
  967. me.imageProps[slide.id] = me.calculateImageResize(imageSize, slide);
  968. });
  969. me.cropHeight = newElementSize.height;
  970. me.setTimer();
  971. },
  972. calculateImageResize: function(wrapperSize, slide){
  973. var breakpoint = Upfront.Views.breakpoints_storage.get_breakpoints().get_active().toJSON(),
  974. defaults = {
  975. size: slide.get('size'),
  976. cropOffset: slide.get('cropOffset'),
  977. cropSize: slide.get('cropSize')
  978. }
  979. ;
  980. if ( !breakpoint.default ) { // No resizing on responsive, return default
  981. return defaults;
  982. }
  983. var img = this.$('.uslide[rel=' + slide.id + ']').find('img'),
  984. currentPosition = img.position(),
  985. imgSize = slide.get('size'),
  986. imgMargins = slide.get('cropOffset'),
  987. imgPosition = {top: - imgMargins.top, left: - imgMargins.left},
  988. imgRatio = imgSize.width / imgSize.height,
  989. wrapperRatio = wrapperSize.width / wrapperSize.height,
  990. pivot = imgSize.width / imgSize.height > wrapperSize.width / wrapperSize.height ? 'height' : 'width',
  991. other = pivot == 'height' ? 'width' : 'height',
  992. final_width, final_height
  993. ;
  994. if (pivot == 'height' && wrapperSize.height > imgSize.height) {
  995. // Old style, using CSS
  996. //img.css({width: 'auto', height: '100%', top: 0, left: Math.min(0, Math.max(imgPosition.left, wrapperSize.width - imgSize.width))});
  997. final_width = wrapperSize.height / imgSize.height * imgSize.width;
  998. img.css({width: final_width, height: wrapperSize.height, top: 0, left: Math.min(0, Math.max(imgPosition.left, wrapperSize.width - imgSize.width))});
  999. } else if (pivot == 'width' && wrapperSize.width > imgSize.width) {
  1000. // Old style, using CSS
  1001. //img.css({width: '100%', height: 'auto', left: 0, top: Math.min(0, Math.max(imgPosition.top, wrapperSize.height - imgSize.height))});
  1002. final_height = wrapperSize.width / imgSize.width * imgSize.height;
  1003. img.css({width: wrapperSize.width, height: final_height, left: 0, top: Math.min(0, Math.max(imgPosition.top, wrapperSize.height - imgSize.height))});
  1004. } else {
  1005. if (pivot == 'height') {
  1006. final_width = wrapperSize.height / imgSize.height * imgSize.width;
  1007. img.css({width: final_width, height: wrapperSize.height, top: 0, left: Math.min(0, Math.max(imgPosition.left, wrapperSize.width - imgSize.width))});
  1008. } else {
  1009. final_height = wrapperSize.width / imgSize.width * imgSize.height;
  1010. img.css({width: wrapperSize.width, height: final_height, left: 0, top: Math.min(0, Math.max(imgPosition.top, wrapperSize.height - imgSize.height))});
  1011. }
  1012. /*
  1013. img.css({
  1014. height: imgSize.height,
  1015. width: imgSize.width,
  1016. top: Math.max(imgPosition.top, wrapperSize.height - imgSize.height),
  1017. left: Math.max(imgPosition.left, wrapperSize.width - imgSize.width)
  1018. });
  1019. */
  1020. }
  1021. // Re-adjust wrappers! They're only being adjusted for the currently active slide
  1022. img.closest(".uslide-image")
  1023. .width(Math.min(img.width(), wrapperSize.width))
  1024. .height(Math.min(img.height(), wrapperSize.height))
  1025. ;
  1026. return {
  1027. size: {width: img.width(), height: img.height()},
  1028. cropOffset: {left: 0-img.position().left, top: 0-img.position().top},
  1029. cropSize: wrapperSize
  1030. };
  1031. },
  1032. saveTemporaryResizing: function(){
  1033. var me = this,
  1034. imagesData = [],
  1035. editOptions = {action: 'upfront-media-image-create-size'},
  1036. sentData = {},
  1037. element_id = this.model.get_property_value_by_name("element_id")
  1038. ;
  1039. this.model.slideCollection.each(function(slide){
  1040. var imageProps = me.imageProps[slide.id],
  1041. crop = imageProps.cropOffset,
  1042. data
  1043. ;
  1044. crop.width = imageProps.cropSize.width;
  1045. crop.height = imageProps.cropSize.height;
  1046. data = {
  1047. id: slide.id,
  1048. element_id: element_id,
  1049. rotate: slide.get('rotation'),
  1050. resize: imageProps.size,
  1051. crop: crop
  1052. };
  1053. imagesData.push(data);
  1054. sentData[slide.id] = data;
  1055. });
  1056. editOptions.images = imagesData;
  1057. return Upfront.Util.post(editOptions).done(function(response){
  1058. var images = response.data.images;
  1059. _.each(images, function(data, id){
  1060. if ( true === data.error ) return; // error, ignore this
  1061. var slide = me.model.slideCollection.get(id),
  1062. imageData = sentData[id]
  1063. ;
  1064. slide.set({
  1065. src: data.url,
  1066. srcFull: data.urlOriginal,
  1067. size: imageData.resize,
  1068. cropSize: {width: imageData.crop.width, height: imageData.crop.height},
  1069. cropOffset: {left: imageData.crop.left, top: imageData.crop.top}
  1070. }, {silent: true});
  1071. });
  1072. //Clear the timeout
  1073. clearTimeout(me.cropTimer);
  1074. me.cropTimer = false;
  1075. me.imageProps = {};
  1076. me.onSlidesCollectionChange();
  1077. });
  1078. },
  1079. saveResizing: function(){
  1080. var me = this,
  1081. post_id = ( typeof _upfront_post_data.post_id !== 'undefined' ) ? _upfront_post_data.post_id : false,
  1082. layout_ids = ( typeof _upfront_post_data.layout !== 'undefined' ) ? _upfront_post_data.layout : '',
  1083. load_dev = ( _upfront_storage_key != _upfront_save_storage_key ? 1 : 0 )
  1084. ;
  1085. if (this.cropTimer) {
  1086. this.saveTemporaryResizing().done(function(){
  1087. var saveData = {
  1088. element: JSON.stringify(Upfront.Util.model_to_json(me.model)),
  1089. post_id: post_id,
  1090. layout_ids: layout_ids,
  1091. load_dev: load_dev,
  1092. action: 'upfront_update_layout_element'
  1093. };
  1094. Upfront.Util.post(saveData).done();
  1095. });
  1096. }
  1097. },
  1098. onRemoveSlide: function(e) {
  1099. // var item = $(e.target).closest('.uimage-controls');
  1100. this.removeSlide(/*item*/);
  1101. },
  1102. // removeSlide: function(item) {
  1103. removeSlide: function() {
  1104. this.startingHeight = this.$('.upfront-slider').height();
  1105. if (confirm(l10n.delete_slide_confirm)) {
  1106. // It's very important that next line goes before removing slide from collection
  1107. var currentSlide = this.getCurrentSlide();
  1108. this.setCurrentSlide( currentSlide > 0 ? currentSlide - 1 : 0 );
  1109. this.model.slideCollection.remove(this.model.slideCollection.at(currentSlide).id);
  1110. }
  1111. },
  1112. getCurrentSlide: function() {
  1113. return this.currentSlide;
  1114. },
  1115. setCurrentSlide: function(number) {
  1116. this.currentSlide = number;
  1117. },
  1118. imageEditMask: function(e) {
  1119. var me = this,
  1120. item = $(e.target).closest('.uimage-controls'),
  1121. currentSlide = this.model.slideCollection.at(this.getCurrentSlide()),
  1122. slide = this.model.slideCollection.get(currentSlide.id),
  1123. editorOpts = this.getEditorOptions(slide)
  1124. ;
  1125. if(slide.get('status') != 'ok'){
  1126. var selectorOptions = {
  1127. multiple: false,
  1128. preparingText: l10n.preparing_slides,
  1129. element_id: me.model.get_property_value_by_name("element_id")
  1130. };
  1131. return Upfront.Views.Editor.ImageSelector.open(selectorOptions).done(function(images, response){
  1132. me.addSlides(images);
  1133. var index = me.model.slideCollection.indexOf(slide);
  1134. me.model.slideCollection.remove(slide, {silent:true});
  1135. var newSlide = me.model.slideCollection.at(me.model.slideCollection.length -1);
  1136. me.model.slideCollection.remove(newSlide, {silent:true});
  1137. me.model.slideCollection.add(newSlide, {at: index});
  1138. Upfront.Views.Editor.ImageSelector.close();
  1139. });
  1140. }
  1141. e.preventDefault();
  1142. Upfront.Views.Editor.ImageEditor.open(editorOpts)
  1143. .done(function(result){
  1144. slide.set({
  1145. src: result.src,
  1146. srcFull: result.srcFull,
  1147. cropSize: result.cropSize,
  1148. size: result.imageSize,
  1149. cropOffset: result.imageOffset,
  1150. margin: {left: Math.max(0-result.imageOffset.left, 0), top: Math.max(0-result.imageOffset.top, 0)},
  1151. rotation: result.rotation,
  1152. id: result.imageId
  1153. });
  1154. me.imageProps[slide.id] = {
  1155. cropOffset: result.imageOffset,
  1156. size: result.imageSize,
  1157. cropSize: result.cropSize
  1158. };
  1159. me.render();
  1160. })
  1161. .fail(function(data){
  1162. if(data && data.reason == 'changeImage')
  1163. me.openImageSelector(null, data.id);
  1164. })
  1165. ;
  1166. },
  1167. getEditorOptions: function(image){
  1168. var me = this,
  1169. mask = this.$('.uslide[rel=' + image.id + ']').find('.uslide-image'),
  1170. img = mask.find('img'),
  1171. full = image.get('sizes').full,
  1172. size = {width: img.width(), height: img.height()},
  1173. position = {left: 0 - img.position().left, top: 0 - img.position().top},
  1174. element_id = this.model.get_property_value_by_name("element_id")
  1175. ;
  1176. return {
  1177. id: image.id,
  1178. element_id: element_id,
  1179. element_cols: Upfront.Util.grid.width_to_col(mask.width(), true),
  1180. maskSize: {width: mask.width(), height: mask.height()},
  1181. maskOffset: mask.offset(),
  1182. position: position,
  1183. size: size,
  1184. fullSize: {width: full[1], height: full[2]},
  1185. src: image.get('src'),
  1186. srcOriginal: full[0],
  1187. rotation: image.get('rotation')
  1188. };
  1189. },
  1190. postTypes: function(){
  1191. var types = [];
  1192. _.each(Upfront.data.ugallery.postTypes, function(type){
  1193. if(type.name != 'attachment')
  1194. types.push({name: type.name, label: type.label});
  1195. });
  1196. return types;
  1197. },
  1198. cleanup: function(){
  1199. if(this.controls){
  1200. this.controls.remove();
  1201. this.controls = false;
  1202. }
  1203. },
  1204. /*
  1205. Returns an object with the properties of the model in the form {name:value}
  1206. */
  1207. extract_properties: function() {
  1208. var model = this.model.get('properties').toJSON(),
  1209. props = {}
  1210. ;
  1211. _.each(model, function(prop){
  1212. props[prop.name] = prop.value;
  1213. });
  1214. props.preset = props.preset || 'default';
  1215. return props;
  1216. },
  1217. /*
  1218. Shorcut to set and get model's properties.
  1219. */
  1220. property: function(name, value, silent) {
  1221. if(typeof value != "undefined"){
  1222. if(typeof silent == "undefined")
  1223. silent = true;
  1224. return this.model.set_property(name, value, silent);
  1225. }
  1226. return this.model.get_property_value_by_name(name);
  1227. },
  1228. getControlItems: function(){
  1229. if( !this.model.slideCollection.length ) return _([]); // We need no controls when there is no slide
  1230. var me = this,
  1231. moreOptions = new Upfront.Views.Editor.InlinePanels.SubControl(),
  1232. slideCollection = this.model.slideCollection,
  1233. multiBelow = {
  1234. back: ['back', l10n.back_button],
  1235. above: ['above', l10n.above_img],
  1236. below: ['below', l10n.below_img],
  1237. nocaption: ['nocaption', l10n.no_text]
  1238. },
  1239. multiOver = {
  1240. back: ['back', l10n.back_button],
  1241. topOver: ['topOver', l10n.over_top],
  1242. bottomOver: ['bottomOver', l10n.over_bottom],
  1243. topCover: ['topCover', l10n.cover_top],
  1244. middleCover: ['middleCover', l10n.cover_mid],
  1245. bottomCover: ['bottomCover', l10n.cover_bottom],
  1246. nocaption: ['nocaption', l10n.no_text]
  1247. },
  1248. multiSide = {
  1249. back: ['back', l10n.back_button],
  1250. right: ['right', l10n.at_right],
  1251. left: ['left', l10n.at_left],
  1252. nocaption: ['nocaption', l10n.no_text]
  1253. },
  1254. primaryStyle = this.get_preset_property('primaryStyle'),
  1255. multiControls = {},
  1256. captionControl = new Upfront.Views.Editor.InlinePanels.TooltipControl(),
  1257. slide = slideCollection.at(this.getCurrentSlide())
  1258. ;
  1259. captionControl.sub_items = {};
  1260. captionControl.wrapperClass = 'slider-caption-second-level';
  1261. if(primaryStyle == 'below')
  1262. multiControls = multiBelow;
  1263. else if(primaryStyle == 'over')
  1264. multiControls = multiOver;
  1265. else if(primaryStyle == 'side')
  1266. multiControls = multiSide;
  1267. else
  1268. multiControls = false;
  1269. if(multiControls){
  1270. _.each(multiControls, function(opts, key){
  1271. captionControl.sub_items[key] = me.createControl(opts[0], opts[1]);
  1272. });
  1273. captionControl.icon = 'caption';
  1274. captionControl.tooltip = l10n.cap_position;
  1275. captionControl.selected = multiControls[slide.get('style')] ? slide.get('style') : 'nocaption';
  1276. this.listenTo(captionControl, 'select', function(item) {
  1277. if(item === "back") {
  1278. return;
  1279. }
  1280. var breakpoint = Upfront.Views.breakpoints_storage.get_breakpoints().get_active().toJSON(),
  1281. previousStyle = breakpoint['default'] ? slide.get('style') : slide.get_breakpoint_attr('style', breakpoint.id)
  1282. ;
  1283. if ( breakpoint['default'] ) {
  1284. slide.set('style', item);
  1285. }
  1286. else {
  1287. slide.set_breakpoint_attr('style', item, breakpoint.id);
  1288. }
  1289. me.onSlidesCollectionChange();
  1290. /*if(primaryStyle == 'side' && previousStyle == 'nocaption' || item == 'nocaption'){
  1291. //give time t…

Large files files are truncated, but you can click here to view the full file