56 lines
18 KiB
JavaScript
56 lines
18 KiB
JavaScript
ips.templates.set('gallery.notes.wrapper'," <div class='cGalleryNote' data-controller='gallery.front.view.note' data-noteID='{{id}}' data-note=\"{{note}}\" {{#editable}}data-editable{{/editable}} data-posLeft='{{left}}' data-posTop='{{top}}' data-dimWidth='{{width}}' data-dimHeight='{{height}}'> <div class='cGalleryNote_border'></div> <div class='cGalleryNote_note' style='display: none'> <div>{{note}}</div> </div></div>");ips.templates.set('gallery.notes.delete'," <a href='#' data-action='delete' class='cGalleryNote_delete' data-ipsTooltip title='{{#lang}}delete_note{{/lang}}'>×</a>");ips.templates.set('gallery.notes.edit'," <textarea>{{note}}</textarea> <ul class='ipsButtons i-justify-content_start i-margin-top_2'> <li><button data-action='save' class='ipsButton ipsButton--positive'>{{#lang}}save_note{{/lang}}</button></li> <li><a href='#' class='ipsButton ipsButton--inherit' data-action='cancel'>{{#lang}}cancel_note{{/lang}}</a></li> </ul>");;
|
|
;(function($,_,undefined){"use strict";const selectorPropertyMap={comments:'[data-role="imageComments"]',image:'[data-role="imageFrame"]',info:'[data-role="imageInfo"]',breadcrumb_top:'nav.ipsBreadcrumb--top',breadcrumb_bottom:'nav.ipsBreadcrumb--bottom',breadcrumb_mobile:'nav.ipsBreadcrumb--mobile',breadcrumb_off_canvas:'nav.ipsOffCanvas__breadcrumb'};ips.controller.register('gallery.front.view.image',{initialize:function(){this.on('menuOpened',this.menuOpened);this.on('menuClosed',this.menuClosed);this.on(document,'keydown',this.keyDown);this.on('click','[data-action="setAsCover"]',this.setAsCover);this.on('click','[data-action="setAsProfile"]',this.setAsProfile);this.on('click','[data-action="rotateImage"]',this.rotateImage);this.on('click','[data-action="changeImage"]',this.changeImage);this._stateUpdate=e=>this.stateUpdate(e);ips.utils.history.replaceState({id:this.getCurrentImageId()},'gallery.view.image',window.location.href);window.addEventListener('historychange',this._stateUpdate);},destroy(){window.removeEventListener('historychange:gallery.view.image',this._stateUpdate);},menuOpened:function(){this.scope.find('.elGalleryImage').addClass('cGalleryImageHover');},menuClosed:function(e){this.scope.find('.elGalleryImage').removeClass('cGalleryImageHover');},keyDown:function(e){if($(e.target).closest('input, textarea, .ipsComposeArea, .ipsComposeArea_editor').length){return;}
|
|
switch(e.keyCode){case ips.ui.key.LEFT:this.scope.find('[data-action="changeImage"][data-direction="prev"]')[0].click();break;case ips.ui.key.RIGHT:this.scope.find('[data-action="changeImage"][data-direction="next"]')[0].click();break;}},setAsProfile:function(e){e.preventDefault();var url=$(e.currentTarget).attr('href');ips.ui.alert.show({type:'confirm',icon:'question',message:ips.getString('set_as_photo_confirm'),callbacks:{ok:function(){ips.getAjax()(url,{showLoading:true}).done(function(response){ips.ui.flashMsg.show(response.message);}).fail(function(){window.location=url;});}}});},setAsCover:function(e){e.preventDefault();var url=$(e.currentTarget).attr('href');ips.getAjax()(url,{showLoading:true}).done(function(response){ips.ui.flashMsg.show(response.message);}).fail(function(){window.location=url;});},rotateImage:function(e){e.preventDefault();var url=$(e.currentTarget).attr('href');var self=this;ips.getAjax()(url,{showLoading:true}).done(function(response){self.scope.find('[data-role="theImage"]')[0].src=response.src;self.scope.find('[data-role="theImage"]').css({'width':response.width+'px','height':response.height+'px'});self.scope.find('[data-role="theImage"]').closest('.cGalleryViewImage').css({'width':response.width+'px','height':response.height+'px'});ips.ui.flashMsg.show(response.message);}).fail(function(){window.location=url;});},changeImage:async function(e){e.preventDefault();let commentTab;const tabsContainer=this.elem.querySelector(`${selectorPropertyMap.comments} i-tabs`);if(tabsContainer){let tab=tabsContainer.querySelector(`[href][aria-selected="true"]`)?.href;if(tab&&tab.endsWith('comments')){commentTab='comments';}else if(tab){commentTab='reviews';}}
|
|
let url=$(e.currentTarget).attr('href');const currentId=this.getCurrentImageId();const urlObj=new URL(url,window.location.href);urlObj.updateSearchParams({param:'browse',value:'1'});try{let selectedId;if(urlObj.searchParams.get('do')==='previous'&¤tId&¤tId in this._prevIdCache){selectedId=this._prevIdCache[currentId];}else if(urlObj.searchParams.get('do')==='next'&¤tId&¤tId in this._nextIdCache){selectedId=this._nextIdCache[currentId];}else if(e.currentTarget.closest(`#gallery-image-thumbs > [data-image-id]`)){selectedId=e.currentTarget.closest(`#gallery-image-thumbs > [data-image-id]`).dataset.imageId;}
|
|
if(selectedId&&selectedId===currentId){Debug.log(`Not loading image ${selectedId} from ${urlObj} because it is the current image`);return;}
|
|
for(const selector of Object.values(selectorPropertyMap)){this.elem.querySelectorAll(`${selector}:not(${selector} *)`).forEach(el=>el.classList.add('ipsLoading'));}
|
|
const response=await this.fetchImageData(urlObj.toString(),commentTab,selectedId);url=new URL(response.url,window.location.href)
|
|
if(commentTab){url.updateSearchParams({param:"tab",value:commentTab});}
|
|
ips.utils.history.pushState({url:url.toString(),response,commentTab,id:response.id.toString()},`gallery.view.image`,url.toString(),e);if(this.historyPromise){await this.historyPromise;}
|
|
const currentThumbIDs=new Set([...this.elem.querySelectorAll("#gallery-image-thumbs [data-image-id]")].map(elem=>elem.dataset.imageId));let thumbsChanged=false;for(const thumb of this.elem.querySelectorAll("#gallery-image-thumbs [data-image-id]")){if(!currentThumbIDs.has(thumb.dataset.imageId)){thumbsChanged=true;break;}
|
|
currentThumbIDs.delete(thumb.dataset.imageId);}
|
|
if(currentThumbIDs.size&&!thumbsChanged){thumbsChanged=true;}
|
|
selectedId=this.getCurrentImageId();if(selectedId){if(thumbsChanged){this._prevIdCache={};this._nextIdCache={};}
|
|
const urlObj=new URL(response.url,window.location.href);if(urlObj.searchParams.get('do')==='previous'&¤tId){this._prevIdCache[currentId]=selectedId;this._nextIdCache[selectedId]=currentId;}else if(urlObj.searchParams.get('do')==='next'&¤tId){this._nextIdCache[currentId]=selectedId;this._prevIdCache[selectedId]=currentId;}}}catch(e){Debug.warn(e);}},async fetchImageData(url,commentTab,id){url=new URL(url,window.location.href).updateSearchParams({params:{tab:['comments','reviews'].includes(commentTab)?commentTab:null,browse:1,}}).toString();commentTab=commentTab||'reviews';const response=this._resultCache?.[commentTab]?.[id]||await ips.fetch(url,{bypassRedirect:'none'});if(typeof response!=='object'||['image','url','info','title','id'].some(prop=>!(prop in response))){throw new RangeError(`The response from the endpoint ${urlObj} is not a JSON object containing image, url, info and title properties.`);}
|
|
if(id){this._resultCache[commentTab]=this._resultCache[commentTab]||{};this._resultCache[commentTab][id]=response;}
|
|
return response;},async stateUpdate(e){if(e.detail.type==='replace'){return;}
|
|
let _resolve,_reject;let{response,commentTab,id}=e.detail.state['gallery.view.image'];this.historyPromise=new Promise(((resolve,reject)=>{_resolve=resolve;_reject=reject;}));if(!id||id===this.getCurrentImageId()){Debug.log(`Not handling a state update for the gallery view because the id has not changed`);_reject(`The view wasn't actually changed`);return;}
|
|
if(!response||!commentTab){let tab=this.elem.querySelector(`${selectorPropertyMap.comments} i-tabs [href][aria-selected="true"]`)?.href;if(tab&&tab.endsWith('comments')){commentTab='comments';}else if(tab){commentTab='reviews';}
|
|
response=await this.fetchImageData(window.location.href,commentTab,id);ips.utils.history.replaceState({...e.detail.state['gallery.view.image'],response,commentTab,id,url:response.url});}
|
|
for(const[property,selector]of Object.entries(selectorPropertyMap)){const root=['breadcrumb_top','breadcrumb_bottom','breadcrumb_mobile','breadcrumb_off_canvas'].includes(property)?document.body:this.elem;root.querySelectorAll(`${selector}:not(${selector} *)`).forEach(el=>{el.insertAdjacentHTML("afterend",response[property]||"");el.remove();});}
|
|
this.updateActiveThumb(response);document.title=response.title;$(document).trigger('contentChange',[$(this.elem)]);if(response.dataLayer){this.scope.trigger('ipsDataLayerProperties',{_properties:response.dataLayer});}
|
|
_resolve();},historyPromise:undefined,getCurrentImageId(){const id=this.elem.querySelector("[data-role='imageFrame'][data-image-id]")?.dataset.imageId;if(id===undefined){Debug.warn(new RangeError(`Could not determine the current image id from the image frame`));}
|
|
return id;},_nextIdCache:{},_prevIdCache:{},_resultCache:{},updateActiveThumb(response){if(response){const allImages=[...this.elem.querySelectorAll(`#gallery-image-thumbs > [data-image-id]`)];const remainingIds=new Set(allImages.map(img=>parseInt(img.dataset.imageId)));const toInsert=[...response.images_prev,{id:response.id,content:response.image_link_current},...response.images_next];const overlap=toInsert.findIndex(val=>remainingIds.has((parseInt(val.id))));if(overlap!==-1){const id=parseInt(toInsert[overlap].id);const overlapDOMIdx=allImages.findIndex(img=>parseInt(img.dataset.imageId)===id);const prevInDOM=allImages.slice(0,overlapDOMIdx).reverse();const prevIdsRemaining=new Set(prevInDOM.map(img=>parseInt(img.dataset.imageId)));const prevToInsert=toInsert.slice(0,overlap).reverse();for(let i=0;i<prevToInsert.length;i++){const id=parseInt(prevToInsert[i].id);if(!prevInDOM.length&&!remainingIds.has(id)){requestAnimationFrame(()=>{this.elem.querySelector(`#gallery-image-thumbs`).insertAdjacentHTML('afterbegin',prevToInsert[i].content);});continue;}
|
|
if(prevIdsRemaining.has(id)){prevIdsRemaining.delete(id);while(prevInDOM.length>1&&parseInt(prevInDOM[0].dataset.imageId)!==id){const skipped=prevInDOM.shift();prevIdsRemaining.delete(parseInt(skipped.dataset.imageId));}
|
|
continue;}
|
|
if(remainingIds.has(id)){continue;}
|
|
const chunk=[];while(i<prevToInsert.length&&!remainingIds.has(parseInt(prevToInsert[i].id))){chunk.unshift(prevToInsert[i].content);i++;}
|
|
requestAnimationFrame(()=>{prevInDOM[0].insertAdjacentHTML('beforebegin',chunk.join(''));});}
|
|
const nextToInsert=toInsert.slice(overlap+1);const nextInDOM=allImages.slice(overlapDOMIdx);const nextIdsRemaining=new Set(nextInDOM.map(img=>parseInt(img.dataset.imageId)));for(let i=0;i<nextToInsert.length;i++){const id=parseInt(nextToInsert[i].id);if(!nextInDOM.length){requestAnimationFrame(()=>{this.elem.querySelector(`#gallery-image-thumbs`).insertAdjacentHTML('beforeend',nextToInsert[i].content);});continue;}
|
|
if(nextIdsRemaining.has(id)){nextIdsRemaining.delete(id);while(nextInDOM.length>1&&parseInt(nextInDOM[0].dataset.imageId)!==id){const skipped=nextInDOM.shift();nextIdsRemaining.delete(parseInt(skipped.dataset.imageId));}
|
|
continue;}
|
|
if(remainingIds.has(id)){continue;}
|
|
let chunk=[];while(i<nextToInsert.length&&!remainingIds.has(parseInt(nextToInsert[i].id))){chunk.push(nextToInsert[i].content);i++;}
|
|
requestAnimationFrame(()=>{nextInDOM[0].insertAdjacentHTML('afterend',chunk.join(''));});}}else if(toInsert.length){requestAnimationFrame(()=>{this.elem.querySelector('#gallery-image-thumbs').innerHTML=toInsert.map(img=>img.content).join('\n');});}}
|
|
const currentlyActiveThumb=this.getCurrentImageId();requestAnimationFrame(()=>{this.elem.querySelectorAll(`#gallery-image-thumbs > [data-active]`).forEach(el=>delete el.dataset.active);});if(currentlyActiveThumb){let img;requestAnimationFrame(()=>{this.elem.querySelectorAll(`#gallery-image-thumbs > [data-image-id="${currentlyActiveThumb}"]`).forEach(el=>{el.dataset.active='';img=el;});if(img){requestAnimationFrame(()=>{const imgRect=img.getBoundingClientRect();const scroller=img.closest('#gallery-image-thumbs');const scrollerRect=scroller.getBoundingClientRect();if(imgRect.left<scrollerRect.left){scroller.scrollBy({left:imgRect.left-scrollerRect.left});}else if(imgRect.right>scrollerRect.right){scroller.scrollBy({left:imgRect.right-scrollerRect.right});}});}});}}});}(jQuery,_));;
|
|
;(function($,_,undefined){"use strict";ips.controller.register('gallery.front.view.note',{_editing:false,_editable:false,_draggingNotEditing:false,_hoverTimerOn:null,_hoverTimerOff:null,_note:'',initialize:function(){this.on('click','.cGalleryNote_border',this.startEditing);this.on('click','[data-action="save"]',this.saveNote);this.on('click','[data-action="cancel"]',this.cancelNote);this.on('click','[data-action="delete"]',this.deleteNote);this.on('mousedown','.cGalleryNote_note',this.mouseDown);this.on('mouseenter',this.mouseEnter);this.on('mouseleave',this.mouseLeave);this.setup();},setup:function(){var self=this;if(!_.isUndefined(this.scope.attr('data-editable'))&&!ips.utils.responsive.currentIs('phone')){this._editable=true;}
|
|
this._note=this.scope.attr('data-note');this._baseURL=ips.getSetting('baseURL')+'index.php?app=gallery&module=gallery&controller=notes&imageId='+this.scope.closest('.cGalleryViewImage').attr('data-imageID');this._buildNote();this._setUpEditable();this._initialPosition();if(this.scope.attr('data-noteID')=='new'){this.scope.find('.cGalleryNote_border').click();}},saveNote:function(e){e.preventDefault();var self=this;var note=this.scope.find('.cGalleryNote_note textarea').val();var savePosition=false;this.scope.draggable('enable');if(!note.trim()){return;}
|
|
if(this.scope.attr('data-noteID')=='new'){savePosition=true;}
|
|
this._saveNote(note,savePosition).done(function(){self._note=note;self._stopEditing();});},cancelNote:function(e){if(this.scope.attr('data-noteID')=='new'){this.deleteNote(e);return;}
|
|
e.preventDefault();this.scope.draggable('enable');this._stopEditing();},deleteNote:function(e){e.preventDefault();var self=this;ips.ui.alert.show({type:'confirm',icon:'question',message:ips.getString('delete_note_confirm'),callbacks:{ok:function(){self._doDeleteNote();}}});},mouseEnter:function(){var self=this;if(this._hoverTimerOn){clearTimeout(this._hoverTimerOn);}
|
|
if(!this._editing){this._hoverTimerOn=setTimeout(function(){if(!self.scope.find('.cGalleryNote_note').is(':visible')){ips.utils.anim.go('fadeIn fast',self.scope.find('.cGalleryNote_note'));}});}},mouseLeave:function(){var self=this;if(this._hoverTimerOff){clearTimeout(this._hoverTimerOff);}
|
|
if(!this._editing){this._hoverTimerOff=setTimeout(function(){if(self.scope.find('.cGalleryNote_note').is(':visible')){ips.utils.anim.go('fadeOut fast',self.scope.find('.cGalleryNote_note'));}});}},mouseDown:function(){},startEditing:function(){if(!this._editable||this._draggingNotEditing){return;}
|
|
if(this._editing===true){this.scope.find('.cGalleryNote_note > div textarea').focus();return;}
|
|
this._editing=true;this.scope.addClass('cGalleryNote_editing').append(ips.templates.render('gallery.notes.delete')).find('.cGalleryNote_note > div').html(ips.templates.render('gallery.notes.edit',{note:this._note})).find('textarea').focus();},_doDeleteNote:function(){var url=this._baseURL;var self=this;if(this.scope.attr('data-noteID')=='new'){ips.utils.anim.go('fadeOutDown',self.scope).done(function(){self.scope.remove();});return;}
|
|
ips.getAjax()(url+'&delete=1&id='+this.scope.attr('data-noteID')).done(function(){ips.utils.anim.go('fadeOutDown',self.scope).done(function(){self.scope.remove();});})},_saveNote:function(noteContent,savePosition){var deferred=$.Deferred();var self=this;var url=this._baseURL;var position='';var note='';if(this.scope.attr('data-noteID')=='new'){url+='&add=1';}else{url+='&edit=1&id='+this.scope.attr('data-noteID');}
|
|
if(savePosition){position=this._getPosition();}
|
|
if(noteContent){note=noteContent;}
|
|
if(this.scope.find('[data-action="save"]').length&¬e){this.scope.find('[data-action="save"]').prop('disabled',true).text(ips.getString('saving_note'));}
|
|
ips.getAjax()(url,{data:{note:note,position:position}}).done(function(response){if(self.scope.find('[data-action="save"]').length&¬e){self.scope.find('[data-action="save"]').prop('disabled',false).text('Save');}
|
|
if(_.isObject(response)&&response.id){self.scope.attr('data-noteID',response.id);}
|
|
deferred.resolve();}).fail(function(){deferred.reject();});return deferred.promise();},_getPosition:function(){var position=[];var parent=this.scope.closest('.cGalleryViewImage');var notePos=this.scope.position();position[0]=(notePos['left']/parent.width())*100;position[1]=(notePos['top']/parent.height())*100;position[2]=(this.scope.width()/parent.width())*100;position[3]=(this.scope.height()/parent.height())*100;return position.join(',');},_stopEditing:function(){this._editing=false;this._draggingNotEditing=false;this.scope.removeClass('cGalleryNote_editing').find('.cGalleryNote_note > div').text(this._note).end().find('.cGalleryNote_delete').remove();},_buildNote:function(){this.scope.find('.cGalleryNote_note > div').text(this._note);},_setUpEditable:function(){if(!this._editable){return;}
|
|
var self=this;ips.loader.get(['core/interface/jquery/jquery-ui.js']).then(function(){self.scope.resizable({containment:self.scope.closest('.cGalleryViewImage'),handles:'se',stop:self._updatePosition.bind(self)});self.scope.draggable({containment:self.scope.closest('.cGalleryViewImage'),start:self._startDragging.bind(self),stop:self._updatePosition.bind(self)});});},_startDragging:function(){if(!this._editing){this._draggingNotEditing=true;}},_updatePosition:function(){var self=this;if(this.scope.attr('data-noteID')=='new'){return;}
|
|
this._saveNote(false,true).done(function(){if(!self._editing){self._stopEditing();}});},_initialPosition:function(){var left=this.scope.attr('data-posLeft');var top=this.scope.attr('data-posTop');var width=this.scope.attr('data-dimWidth');var height=this.scope.attr('data-dimHeight');this.scope.css({left:left+'%',top:top+'%',width:width+'%',height:height+'%'});}});}(jQuery,_));;
|
|
;(function($,_,undefined){"use strict";ips.controller.register('gallery.front.view.notes',{_inAddingState:false,initialize:function(){this.on(document,'click','[data-action="addNote"]',this.startAddNote);this.setup();},setup:function(){var notes;try{notes=$.parseJSON(this.scope.attr('data-notesData'));}catch(err){}
|
|
if(notes&¬es.length){this._buildNotes(notes);}},startAddNote:function(e){e.preventDefault();this.scope.append(ips.templates.render('gallery.notes.wrapper',{id:'new',left:50,top:50,width:(100/this.scope.width())*100,height:(100/this.scope.height())*100,editable:true}));$(document).trigger('contentChange',[this.scope]);},_buildNotes:function(notes){if(notes.length){for(var i=0;i<notes.length;i++){this.scope.append(ips.templates.render('gallery.notes.wrapper',{id:notes[i].ID,left:notes[i].LEFT,top:notes[i].TOP,width:notes[i].WIDTH,height:notes[i].HEIGHT,note:notes[i].NOTE,editable:!_.isUndefined(this.scope.attr('data-editable'))?true:false}));}
|
|
$(document).trigger('contentChange',[this.scope]);}}});}(jQuery,_));; |